Revision: 45973
Author:   skizzerz
Date:     2009-01-21 20:42:32 +0000 (Wed, 21 Jan 2009)

Log Message:
-----------
Redirect-related bugfixes/features:
* (bug 11644) Add $wgMaxRedirects variable to control how many redirects are 
recursed through until the "destination" page is reached.
** update redirect page UI to show each step down to the destination page
** rdfrom text still links to original page visited
** pages still show up in DoubleRedirects
** setting to 1 (default) is current behavior of only going 1 step down. 
Setting to 0 disables automatic redirects.
** arrow image needs to be smoothed, couldn't figure out how to do it myself 
while keeping the image in indexed mode
* (bug 10569) Redirects to Special:Mypage and Special:Mytalk are no longer 
allowed to prevent redirect loops
** can be re-enabled by changing the $wgInvalidRedirectTargets array

Modified Paths:
--------------
    trunk/phase3/RELEASE-NOTES
    trunk/phase3/includes/Article.php
    trunk/phase3/includes/DefaultSettings.php
    trunk/phase3/includes/EditPage.php
    trunk/phase3/includes/Title.php

Added Paths:
-----------
    trunk/phase3/skins/common/images/nextredirectltr.png
    trunk/phase3/skins/common/images/nextredirectrtl.png

Modified: trunk/phase3/RELEASE-NOTES
===================================================================
--- trunk/phase3/RELEASE-NOTES  2009-01-21 20:30:14 UTC (rev 45972)
+++ trunk/phase3/RELEASE-NOTES  2009-01-21 20:42:32 UTC (rev 45973)
@@ -48,7 +48,10 @@
 * (bugs 16957/16969) Add show/hide to preferences for RC patrol options on
   specialpages
 * (bug 11443) Auto-noindex user/user talk pages for blocked user
-
+* (bug 11644) Add $wgMaxRedirects variable to control how many redirects are 
recursed
+  through until the "destination" page is reached.
+* Add $wgInvalidRedirectTargets variable to prevent redirects to certain 
special pages.
+  
 === Bug fixes in 1.15 ===
 * (bug 16968) Special:Upload no longer throws useless warnings.
 * (bug 17000) Special:RevisionDelete now checks if the database is locked 
before
@@ -66,6 +69,8 @@
 * (bug 11527) Diff on page with one revision shows "Next" link to same diff
 * (bug 15936) New page's patrol button should always be visible
 * (bug 8065) Fix summary forcing for new pages
+* (bug 10569) redirects to Special:Mypage and Special:Mytalk are no longer 
allowed
+  by default. Change $wgInvalidRedirectTargets to re-enable.
 
 == API changes in 1.15 ==
 * (bug 16858) Revamped list=deletedrevs to make listing deleted contributions

Modified: trunk/phase3/includes/Article.php
===================================================================
--- trunk/phase3/includes/Article.php   2009-01-21 20:30:14 UTC (rev 45972)
+++ trunk/phase3/includes/Article.php   2009-01-21 20:42:32 UTC (rev 45973)
@@ -103,7 +103,8 @@
         * @return Title object
         */
        public function insertRedirect() {
-               $retval = Title::newFromRedirect( $this->getContent() );
+               // set noRecurse so that we always get an entry even if 
redirects are "disabled"
+               $retval = Title::newFromRedirect( $this->getContent(), false, 
true );
                if( !$retval ) {
                        return null;
                }
@@ -135,7 +136,7 @@
         * @return mixed false, Title of in-wiki target, or string with URL
         */
        public function followRedirectText( $text ) {
-               $rt = Title::newFromRedirect( $text );
+               $rt = Title::newFromRedirect( $text ); // only get the final 
target
                # process if title object is valid and not special:userlogout
                if( $rt ) {
                        if( $rt->getInterwiki() != '' ) {
@@ -584,9 +585,10 @@
                        }
                        // Apparently loadPageData was never called
                        $this->loadContent();
-                       $titleObj = Title::newFromRedirect( 
$this->fetchContent() );
+                       // Only get the next target to reduce load times
+                       $titleObj = Title::newFromRedirect( 
$this->fetchContent(), false, true );
                } else {
-                       $titleObj = Title::newFromRedirect( $text );
+                       $titleObj = Title::newFromRedirect( $text, false, true 
);
                }
                return $titleObj !== NULL;
        }
@@ -919,7 +921,7 @@
                                        $wgOut->addHTML( htmlspecialchars( 
$this->mContent ) );
                                        $wgOut->addHTML( "\n</pre>\n" );
                                }
-                       } else if( $rt = Title::newFromRedirect( $text ) ) {
+                       } else if( $rt = Title::newFromRedirect( $text, true ) 
) { # get an array of redirect targets
                                # Don't append the subtitle if this was an old 
revision
                                $wgOut->addHTML( $this->viewRedirect( $rt, 
!$wasRedirected && $this->isCurrent() ) );
                                $parseout = $wgParser->parse($text, 
$this->mTitle, ParserOptions::newFromUser($wgUser));
@@ -1039,25 +1041,42 @@
 
        /**
         * View redirect
-        * @param $target Title object of destination to redirect
+        * @param $target Title object or Array of destination(s) to redirect
         * @param $appendSubtitle Boolean [optional]
         * @param $forceKnown Boolean: should the image be shown as a bluelink 
regardless of existence?
         */
        public function viewRedirect( $target, $appendSubtitle = true, 
$forceKnown = false ) {
                global $wgParser, $wgOut, $wgContLang, $wgStylePath, $wgUser;
                # Display redirect
+               if( !is_array( $target ) ) {
+                       $target = array( $target );
+               }
                $imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
-               $imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir 
. '.png';
-
+               $imageUrl = $wgStylePath . '/common/images/redirect' . 
$imageDir . '.png';
+               $imageUrl2 = $wgStylePath . '/common/images/nextredirect' . 
$imageDir . '.png';
+               $alt2 = $wgContLang->isRTL() ? '&larr;' : '&rarr;'; // should 
-> and <- be used instead of entities?
+               
                if( $appendSubtitle ) {
                        $wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) 
);
                }
                $sk = $wgUser->getSkin();
+               // the loop prepends the arrow image before the link, so the 
first case needs to be outside
+               $title = array_shift( $target );
                if( $forceKnown ) {
-                       $link = $sk->makeKnownLinkObj( $target, 
htmlspecialchars( $target->getFullText() ) );
+                       $link = $sk->makeKnownLinkObj( $title, 
htmlspecialchars( $title->getFullText() ) );
                } else {
-                       $link = $sk->makeLinkObj( $target, htmlspecialchars( 
$target->getFullText() ) );
+                       $link = $sk->makeLinkObj( $title, htmlspecialchars( 
$title->getFullText() ) );
                }
+               // automatically append redirect=no to each link, since most of 
them are redirect pages themselves
+               foreach( $target as $rt ) {
+                       if( $forceKnown ) {
+                               $link .= '<img src="'.$imageUrl2.'" 
alt="'.$alt2.' " />'
+                                       . $sk->makeKnownLinkObj( $rt, 
htmlspecialchars( $rt->getFullText() ) );
+                       } else {
+                               $link .= '<img src="'.$imageUrl2.'" 
alt="'.$alt2.' " />'
+                                       . $sk->makeLinkObj( $rt, 
htmlspecialchars( $rt->getFullText() ) );
+                       }
+               }
                return '<img src="'.$imageUrl.'" alt="#REDIRECT " />' .
                        '<span class="redirectText">'.$link.'</span>';
 
@@ -3428,9 +3447,9 @@
        public static function getAutosummary( $oldtext, $newtext, $flags ) {
                # Decide what kind of autosummary is needed.
 
-               # Redirect autosummaries
-               $ot = Title::newFromRedirect( $oldtext );
-               $rt = Title::newFromRedirect( $newtext );
+               # Redirect autosummaries -- should only get the next target and 
not recurse
+               $ot = Title::newFromRedirect( $oldtext, false, true );
+               $rt = Title::newFromRedirect( $newtext, false, true );
                if( is_object( $rt ) && ( !is_object( $ot ) || !$rt->equals( 
$ot ) || $ot->getFragment() != $rt->getFragment() ) ) {
                        return wfMsgForContent( 'autoredircomment', 
$rt->getFullText() );
                }

Modified: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php   2009-01-21 20:30:14 UTC (rev 
45972)
+++ trunk/phase3/includes/DefaultSettings.php   2009-01-21 20:42:32 UTC (rev 
45973)
@@ -3612,6 +3612,25 @@
 $wgFixDoubleRedirects = false;
 
 /**
+ * Max number of redirects to follow when resolving redirects.
+ * 1 means only the first redirect is followed (default behavior).
+ * 0 or less means no redirects are followed.
+ */
+$wgMaxRedirects = 1;
+
+/**
+ * Array of invalid page redirect targets.
+ * Attempting to create a redirect to any of the pages in this array
+ * will make the redirect fail.
+ * Userlogout is hard-coded, so it does not need to be listed here.
+ * (bug 10569) Disallow Mypage and Mytalk as well.
+ *
+ * As of now, this only checks special pages. Redirects to pages in
+ * other namespaces cannot be invalidated by this variable.
+ */
+$wgInvalidRedirectTargets = array( 'Filepath', 'Mypage', 'Mytalk' );
+ 
+/**
  * Array of namespaces to generate a sitemap for when the
  * maintenance/generateSitemap.php script is run, or false if one is to be ge-
  * nerated for all namespaces.

Modified: trunk/phase3/includes/EditPage.php
===================================================================
--- trunk/phase3/includes/EditPage.php  2009-01-21 20:30:14 UTC (rev 45972)
+++ trunk/phase3/includes/EditPage.php  2009-01-21 20:42:32 UTC (rev 45973)
@@ -1687,7 +1687,7 @@
                        $parserOptions->setTidy(true);
                        $parserOutput = $wgParser->parse( $previewtext, 
$this->mTitle, $parserOptions );
                        $previewHTML = $parserOutput->mText;
-               } elseif ( $rt = Title::newFromRedirect( $this->textbox1 ) ) {
+               } elseif ( $rt = Title::newFromRedirect( $this->textbox1, true 
) ) {
                        $previewHTML = $this->mArticle->viewRedirect( $rt, 
false );
                } else {
                        $toparse = $this->textbox1;

Modified: trunk/phase3/includes/Title.php
===================================================================
--- trunk/phase3/includes/Title.php     2009-01-21 20:30:14 UTC (rev 45972)
+++ trunk/phase3/includes/Title.php     2009-01-21 20:42:32 UTC (rev 45973)
@@ -295,10 +295,20 @@
         * Extract a redirect destination from a string and return the
         * Title, or null if the text doesn't contain a valid redirect
         *
-        * @param $text \type{String} Text with possible redirect
+        * @param $text \type{\string} Text with possible redirect
+        * @param $getAllTargets \type{\bool} Should we get an array of every 
target or just the final one?
+        * @param $noRecurse \type{\bool} This will prevent any and all 
recursion, only getting the very next target
+        *      This is mainly meant for Article::insertRedirect so that the 
redirect table still works properly
+        *      (makes double redirect and broken redirect reports display 
accurate results).
         * @return \type{Title} The corresponding Title
+        * @return \type{\array} Array of redirect targets (Title objects), 
with the destination being last
         */
-       public static function newFromRedirect( $text ) {
+       public static function newFromRedirect( $text, $getAllTargets = false, 
$noRecurse = false ) {
+               global $wgMaxRedirects;
+               // are redirects disabled?
+               // Note that we should get a Title object if possible if 
$noRecurse is true so that the redirect table functions properly
+               if( !$noRecurse && $wgMaxRedirects < 1 )
+                       return null;
                $redir = MagicWord::get( 'redirect' );
                $text = trim($text);
                if( $redir->matchStartAndRemove( $text ) ) {
@@ -316,13 +326,38 @@
                                        $m[1] = urldecode( ltrim( $m[1], ':' ) 
);
                                }
                                $title = Title::newFromText( $m[1] );
-                               // Redirects to some special pages are not 
permitted
-                               if( $title instanceof Title 
-                                               && !$title->isSpecial( 
'Userlogout' )
-                                               && !$title->isSpecial( 
'Filepath' ) ) 
-                               {
+                               // If the initial title is a redirect to bad 
special pages or is invalid, quit early
+                               if( !$title instanceof Title || 
!$title->isValidRedirectTarget() ) {
+                                       return null;
+                               }
+                               // If $noRecurse is true, simply return here
+                               if( $noRecurse ) {
                                        return $title;
                                }
+                               // recursive check to follow double redirects
+                               $recurse = $wgMaxRedirects;
+                               $targets = array();
+                               while( --$recurse >= 0 ) {
+                                       // Redirects to some special pages are 
not permitted
+                                       if( $title instanceof Title && 
$title->isValidRedirectTarget() ) {
+                                               $targets[] = $title;
+                                               if( $title->isRedirect() ) {
+                                                       $article = new Article( 
$title, 0 );
+                                                       $title = 
$article->getRedirectTarget();
+                                               } else {
+                                                       break;
+                                               }
+                                       } else {
+                                               break;
+                                       }
+                               }
+                               if( $getAllTargets ) {
+                                       // return every target or null if no 
targets due to invalid title or whatever
+                                       return ( $targets === array() ) ? null 
: $targets;
+                               } else {
+                                       // return the final destination -- 
invalid titles are checked earlier
+                                       return $title;
+                               }
                        }
                }
                return null;
@@ -3426,4 +3461,26 @@
                }
                return $redirs;
        }
+       
+       /**
+        * Check if this Title is a valid redirect target
+        *
+        * @return \type{\bool} TRUE or FALSE
+        */
+       public function isValidRedirectTarget() {
+               global $wgInvalidRedirectTargets;
+               
+               // invalid redirect targets are stored in a global array, but 
explicity disallow Userlogout here
+               if( $this->isSpecial( 'Userlogout' ) ) {
+                       return false;
+               }
+               
+               foreach( $wgInvalidRedirectTargets as $target ) {
+                       if( $this->isSpecial( $target ) ) {
+                               return false;
+                       }
+               }
+               
+               return true;
+       }
 }

Added: trunk/phase3/skins/common/images/nextredirectltr.png
===================================================================
(Binary files differ)


Property changes on: trunk/phase3/skins/common/images/nextredirectltr.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: trunk/phase3/skins/common/images/nextredirectrtl.png
===================================================================
(Binary files differ)


Property changes on: trunk/phase3/skins/common/images/nextredirectrtl.png
___________________________________________________________________
Added: svn:mime-type
   + image/png



_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to