Follow-up r84814: revert redundant summary message addition.
[lhc/web/wiklou.git] / includes / SpecialPage.php
index 97b3c05..89a015b 100644 (file)
@@ -73,6 +73,22 @@ class SpecialPage {
         * Query parameteres added by redirects
         */
        var $mAddedRedirectParams = array();
+       /**
+        * Current request
+        * @var WebRequest 
+        */
+       protected $mRequest;
+       /**
+        * Current output page
+        * @var OutputPage
+        */
+       protected $mOutput;
+       /**
+        * Full title including $par
+        * @var Title
+        */
+       protected $mFullTitle;
+               
        /**
         * List of special pages, followed by parameters.
         * If the only parameter is a string, that is the page name.
@@ -84,71 +100,74 @@ class SpecialPage {
         */
        static public $mList = array(
                # Maintenance Reports
-               'BrokenRedirects'           => array( 'SpecialPage', 'BrokenRedirects' ),
-               'Deadendpages'              => array( 'SpecialPage', 'Deadendpages' ),
-               'DoubleRedirects'           => array( 'SpecialPage', 'DoubleRedirects' ),
-               'Longpages'                 => array( 'SpecialPage', 'Longpages' ),
-               'Ancientpages'              => array( 'SpecialPage', 'Ancientpages' ),
-               'Lonelypages'               => array( 'SpecialPage', 'Lonelypages' ),
-               'Fewestrevisions'           => array( 'SpecialPage', 'Fewestrevisions' ),
-               'Withoutinterwiki'          => array( 'SpecialPage', 'Withoutinterwiki' ),
+               'BrokenRedirects'           => 'BrokenRedirectsPage',
+               'Deadendpages'              => 'DeadendpagesPage',
+               'DoubleRedirects'           => 'DoubleRedirectsPage',
+               'Longpages'                 => 'LongpagesPage',
+               'Ancientpages'              => 'AncientpagesPage',
+               'Lonelypages'               => 'LonelypagesPage',
+               'Fewestrevisions'           => 'FewestrevisionsPage',
+               'Withoutinterwiki'          => 'WithoutinterwikiPage',
                'Protectedpages'            => 'SpecialProtectedpages',
                'Protectedtitles'           => 'SpecialProtectedtitles',
-               'Shortpages'                => array( 'SpecialPage', 'Shortpages' ),
-               'Uncategorizedcategories'   => array( 'SpecialPage', 'Uncategorizedcategories' ),
-               'Uncategorizedimages'       => array( 'SpecialPage', 'Uncategorizedimages' ),
-               'Uncategorizedpages'        => array( 'SpecialPage', 'Uncategorizedpages' ),
-               'Uncategorizedtemplates'    => array( 'SpecialPage', 'Uncategorizedtemplates' ),
-               'Unusedcategories'          => array( 'SpecialPage', 'Unusedcategories' ),
-               'Unusedimages'              => array( 'SpecialPage', 'Unusedimages' ),
-               'Unusedtemplates'           => array( 'SpecialPage', 'Unusedtemplates' ),
-               'Unwatchedpages'            => array( 'SpecialPage', 'Unwatchedpages', 'unwatchedpages' ),
-               'Wantedcategories'          => array( 'SpecialPage', 'Wantedcategories' ),
-               'Wantedfiles'               => array( 'SpecialPage', 'Wantedfiles' ),
-               'Wantedpages'               => array( 'IncludableSpecialPage', 'Wantedpages' ),
-               'Wantedtemplates'           => array( 'SpecialPage', 'Wantedtemplates' ),
+               'Shortpages'                => 'ShortpagesPage',
+               'Uncategorizedcategories'   => 'UncategorizedcategoriesPage',
+               'Uncategorizedimages'       => 'UncategorizedimagesPage',
+               'Uncategorizedpages'        => 'UncategorizedpagesPage',
+               'Uncategorizedtemplates'    => 'UncategorizedtemplatesPage',
+               'Unusedcategories'          => 'UnusedcategoriesPage',
+               'Unusedimages'              => 'UnusedimagesPage',
+               'Unusedtemplates'           => 'UnusedtemplatesPage',
+               'Unwatchedpages'            => 'UnwatchedpagesPage',
+               'Wantedcategories'          => 'WantedcategoriesPage',
+               'Wantedfiles'               => 'WantedfilesPage',
+               'Wantedpages'               => 'WantedpagesPage',
+               'Wantedtemplates'           => 'WantedtemplatesPage',
 
                # List of pages
                'Allpages'                  => 'SpecialAllpages',
                'Prefixindex'               => 'SpecialPrefixindex',
-               'Categories'                => array( 'SpecialPage', 'Categories' ),
-               'Disambiguations'           => array( 'SpecialPage', 'Disambiguations' ),
-               'Listredirects'             => array( 'SpecialPage', 'Listredirects' ),
+               'Categories'                => 'SpecialCategories',
+               'Disambiguations'           => 'DisambiguationsPage',
+               'Listredirects'             => 'ListredirectsPage',
 
                # Login/create account
-               'Userlogin'                 => array( 'SpecialPage', 'Userlogin' ),
+               'Userlogin'                 => 'LoginForm',
                'CreateAccount'             => array( 'SpecialRedirectToSpecial', 'CreateAccount', 'Userlogin', 'signup', array( 'uselang' ) ),
 
                # Users and rights
-               'Blockip'                   => 'IPBlockForm',
-               'Ipblocklist'               => 'IPUnblockForm',
-               'Unblock'                   => array( 'SpecialRedirectToSpecial', 'Unblock', 'Ipblocklist', false, array( 'uselang', 'ip', 'id' ), array( 'action' => 'unblock' ) ),
+               'Block'                     => 'SpecialBlock',
+               'Unblock'                   => 'SpecialUnblock',
+               'BlockList'                 => 'SpecialBlockList',
                'Resetpass'                 => 'SpecialResetpass',
                'DeletedContributions'      => 'DeletedContributionsPage',
                'Preferences'               => 'SpecialPreferences',
                'Contributions'             => 'SpecialContributions',
                'Listgrouprights'           => 'SpecialListGroupRights',
-               'Listusers'                 => array( 'SpecialPage', 'Listusers' ),
+               'Listusers'                 => 'SpecialListusers',
                'Listadmins'                => array( 'SpecialRedirectToSpecial', 'Listadmins', 'Listusers', 'sysop' ),
                'Listbots'                  => array( 'SpecialRedirectToSpecial', 'Listbots', 'Listusers', 'bot' ),
                'Activeusers'               => 'SpecialActiveUsers',
                'Userrights'                => 'UserrightsPage',
+               'DisableAccount'            => 'SpecialDisableAccount',
+               'EditWatchlist'             => 'SpecialEditWatchlist',
 
                # Recent changes and logs
-               'Newimages'                 => array( 'IncludableSpecialPage', 'Newimages' ),
+               'Newimages'                 => 'SpecialNewFiles',
                'Log'                       => 'SpecialLog',
-               'Watchlist'                 => array( 'SpecialPage', 'Watchlist' ),
+               'Watchlist'                 => 'SpecialWatchlist',
                'Newpages'                  => 'SpecialNewpages',
                'Recentchanges'             => 'SpecialRecentchanges',
                'Recentchangeslinked'       => 'SpecialRecentchangeslinked',
                'Tags'                      => 'SpecialTags',
 
                # Media reports and uploads
-               'Listfiles'                 => array( 'SpecialPage', 'Listfiles' ),
+               'Listfiles'                 => 'SpecialListFiles',
                'Filepath'                  => 'SpecialFilepath',
-               'MIMEsearch'                => array( 'SpecialPage', 'MIMEsearch' ),
-               'FileDuplicateSearch'       => array( 'SpecialPage', 'FileDuplicateSearch' ),
+               'MIMEsearch'                => 'MIMEsearchPage',
+               'FileDuplicateSearch'       => 'FileDuplicateSearchPage',
                'Upload'                    => 'SpecialUpload',
+               'UploadStash'               => 'SpecialUploadStash',
 
                # Wiki data and tools
                'Statistics'                => 'SpecialStatistics',
@@ -158,23 +177,23 @@ class SpecialPage {
                'Unlockdb'                  => 'SpecialUnlockdb',
 
                # Redirecting special pages
-               'LinkSearch'                => array( 'SpecialPage', 'LinkSearch' ),
+               'LinkSearch'                => 'LinkSearchPage',
                'Randompage'                => 'Randompage',
                'Randomredirect'            => 'SpecialRandomredirect',
 
                # High use pages
-               'Mostlinkedcategories'      => array( 'SpecialPage', 'Mostlinkedcategories' ),
-               'Mostimages'                => array( 'SpecialPage', 'Mostimages' ),
-               'Mostlinked'                => array( 'SpecialPage', 'Mostlinked' ),
-               'Mostlinkedtemplates'       => array( 'SpecialPage', 'Mostlinkedtemplates' ),
-               'Mostcategories'            => array( 'SpecialPage', 'Mostcategories' ),
-               'Mostrevisions'             => array( 'SpecialPage', 'Mostrevisions' ),
+               'Mostlinkedcategories'      => 'MostlinkedCategoriesPage',
+               'Mostimages'                => 'MostimagesPage',
+               'Mostlinked'                => 'MostlinkedPage',
+               'Mostlinkedtemplates'       => 'MostlinkedTemplatesPage',
+               'Mostcategories'            => 'MostcategoriesPage',
+               'Mostrevisions'             => 'MostrevisionsPage',
 
                # Page tools
                'ComparePages'              => 'SpecialComparePages',
                'Export'                    => 'SpecialExport',
                'Import'                    => 'SpecialImport',
-               'Undelete'                  => 'UndeleteForm',
+               'Undelete'                  => 'SpecialUndelete',
                'Whatlinkshere'             => 'SpecialWhatlinkshere',
                'MergeHistory'              => 'SpecialMergeHistory',
 
@@ -189,6 +208,8 @@ class SpecialPage {
                'Mycontributions'           => 'SpecialMycontributions',
                'Mypage'                    => 'SpecialMypage',
                'Mytalk'                    => 'SpecialMytalk',
+               'Myuploads'                 => 'SpecialMyuploads',
+               'PermanentLink'             => 'SpecialPermanentLink',
                'Revisiondelete'            => 'SpecialRevisionDelete',
                'RevisionMove'              => 'SpecialRevisionMove',
                'Specialpages'              => 'SpecialSpecialpages',
@@ -207,7 +228,6 @@ class SpecialPage {
        static function initList() {
                global $wgSpecialPages;
                global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
-               global $wgEnableSelenium;
 
                if ( self::$mListInitialised ) {
                        return;
@@ -218,11 +238,11 @@ class SpecialPage {
                self::$mListInitialised = true;
 
                if( !$wgDisableCounters ) {
-                       self::$mList['Popularpages'] = array( 'SpecialPage', 'Popularpages' );
+                       self::$mList['Popularpages'] = 'PopularpagesPage';
                }
 
                if( !$wgDisableInternalSearch ) {
-                       self::$mList['Search'] = array( 'SpecialPage', 'Search' );
+                       self::$mList['Search'] = 'SpecialSearch';
                }
 
                if( $wgEmailAuthentication ) {
@@ -230,10 +250,6 @@ class SpecialPage {
                        self::$mList['Invalidateemail'] = 'EmailInvalidation';
                }
 
-               if ( $wgEnableSelenium ) {
-                       self::$mList['Selenium'] = 'SpecialSelenium';
-               }
-
                # Add extension special pages
                self::$mList = array_merge( self::$mList, $wgSpecialPages );
 
@@ -276,6 +292,7 @@ class SpecialPage {
                if ( !self::$mListInitialised ) self::initList();
                if ( is_null( self::$mAliases ) ) self::initAliasList();
                $caseFoldedAlias = $wgContLang->caseFold( $alias );
+               $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
                if ( isset( self::$mAliases[$caseFoldedAlias] ) ) {
                        return self::$mAliases[$caseFoldedAlias];
                } else {
@@ -341,9 +358,10 @@ class SpecialPage {
                if( isset($specialPageGroupsCache[$page->mName]) ) {
                        return $specialPageGroupsCache[$page->mName];
                }
-               $group = wfMsg('specialpages-specialpagegroup-'.strtolower($page->mName));
-               if( $group == ''
-                || wfEmptyMsg('specialpages-specialpagegroup-'.strtolower($page->mName), $group ) ) {
+               $msg = wfMessage('specialpages-specialpagegroup-'.strtolower($page->mName));
+               if ( !$msg->isBlank() ) {
+                       $group = $msg->text();
+               } else {
                        $group = isset($wgSpecialPageGroups[$page->mName])
                                ? $wgSpecialPageGroups[$page->mName]
                                : '-';
@@ -407,7 +425,7 @@ class SpecialPage {
                                self::$mList[$name] = new $className;
                        } elseif ( is_array( $rec ) ) {
                                $className = array_shift( $rec );
-                               self::$mList[$name] = wfCreateObject( $className, $rec );
+                               self::$mList[$name] = MWFunction::newObj( $className, $rec );
                        }
                        return self::$mList[$name];
                } else {
@@ -505,7 +523,7 @@ class SpecialPage {
 
        /**
         * Execute a special page path.
-        * The path     may contain parameters, e.g. Special:Name/Params
+        * The path may contain parameters, e.g. Special:Name/Params
         * Extracts the special page name and call the execute method, passing the parameters
         *
         * Returns a title object if the page is redirected, false if there was no such special
@@ -538,16 +556,25 @@ class SpecialPage {
                        wfProfileOut( __METHOD__ );
                        return false;
                }
+               
+               # Page exists, set the context
+               $page->setContext( $wgRequest, $wgOut );
 
                # Check for redirect
                if ( !$including ) {
                        $redirect = $page->getRedirect( $par );
-                       if ( $redirect ) {
-                               $query = $page->getRedirectQuery();
+                       $query = $page->getRedirectQuery();
+                       if ( $redirect instanceof Title ) {
                                $url = $redirect->getFullUrl( $query );
                                $wgOut->redirect( $url );
                                wfProfileOut( __METHOD__ );
                                return $redirect;
+                       } elseif( $redirect === true ) {
+                               global $wgScript;
+                               $url = $wgScript . '?' . wfArrayToCGI( $query );
+                               $wgOut->redirect( $url );
+                               wfProfileOut( __METHOD__ );
+                               return $redirect;
                        }
                }
 
@@ -576,7 +603,7 @@ class SpecialPage {
                $page->including( $including );
 
                // Execute special page
-               $profName = 'Special:' . $page->getName();
+               $profName = 'Special:' . $page->name();
                wfProfileIn( $profName );
                $page->execute( $par );
                wfProfileOut( $profName );
@@ -626,7 +653,7 @@ class SpecialPage {
                        $found = false;
                        foreach ( $aliases as $n => $values ) {
                                if ( strcasecmp( $name, $n ) === 0 ) {
-                                       wfWarn( "Found alias defined for $n when searching for" .
+                                       wfWarn( "Found alias defined for $n when searching for " .
                                                "special page aliases for $name. Case mismatch?" );
                                        $name = $values[0];
                                        $found = true;
@@ -634,7 +661,7 @@ class SpecialPage {
                                }
                        }
                        if ( !$found ) {
-                               wfWarn( "Did not find alias for special page '$name'." . 
+                               wfWarn( "Did not find alias for special page '$name'. " .
                                        "Perhaps no aliases are defined for it?" );
                        }
                }
@@ -703,7 +730,16 @@ class SpecialPage {
         * @param $file String: file which is included by execute(). It is also constructed from $name by default
         * @param $includable Boolean: whether the page can be included in normal pages
         */
-       function SpecialPage( $name = '', $restriction = '', $listed = true, $function = false, $file = 'default', $includable = false ) {
+       public function __construct( $name = '', $restriction = '', $listed = true, $function = false, $file = 'default', $includable = false ) {
+               $this->init( $name, $restriction, $listed, $function, $file, $includable );
+       }
+
+       /**
+        * Do the real work for the constructor, mainly so __call() can intercept
+        * calls to SpecialPage()
+        * @see __construct() for param docs
+        */
+       private function init( $name, $restriction, $listed, $function, $file, $includable ) {
                $this->mName = $name;
                $this->mRestriction = $restriction;
                $this->mListed = $listed;
@@ -720,6 +756,32 @@ class SpecialPage {
                }
        }
 
+       /**
+        * Use PHP's magic __call handler to get calls to the old PHP4 constructor
+        * because PHP E_STRICT yells at you for having __construct() and SpecialPage()
+        *
+        * @param $fName String Name of called method
+        * @param $a Array Arguments to the method
+        * @deprecated Call isn't deprecated, but SpecialPage::SpecialPage() is
+        */
+       public function __call( $fName, $a ) {
+               // Sometimes $fName is SpecialPage, sometimes it's specialpage. <3 PHP
+               if( strtolower( $fName ) == 'specialpage' ) {
+                       // Debug messages now, warnings in 1.19 or 1.20?
+                       wfDebug( "Deprecated SpecialPage::SpecialPage() called, use __construct();\n" );
+                       $name = isset( $a[0] ) ? $a[0] : '';
+                       $restriction = isset( $a[1] ) ? $a[1] : '';
+                       $listed = isset( $a[2] ) ? $a[2] : true;
+                       $function = isset( $a[3] ) ? $a[3] : false;
+                       $file = isset( $a[4] ) ? $a[4] : 'default';
+                       $includable = isset( $a[5] ) ? $a[5] : false;
+                       $this->init( $name, $restriction, $listed, $function, $file, $includable );
+               } else {
+                       $className = get_class( $this );
+                       throw new MWException( "Call to undefined method $className::$fName" );
+               }
+       }
+
        /**#@+
          * Accessor
          *
@@ -758,6 +820,18 @@ class SpecialPage {
                return $this->mLocalName;
        }
 
+       /**
+        * Is this page expensive (for some definition of expensive)?
+        * Expensive pages are disabled or cached in miser mode.  Originally used
+        * (and still overridden) by QueryPage and subclasses, moved here so that
+        * Special:SpecialPages can safely call it for all special pages.
+        *
+        * @return Boolean
+        */
+       public function isExpensive() {
+               return false;
+       }
+
        /**
         * Can be overridden by subclasses with more complicated permissions
         * schemes.
@@ -841,8 +915,7 @@ class SpecialPage {
                } else {
                        $msg = $summaryMessageKey;
                }
-               $out = wfMsgNoTrans( $msg );
-               if ( ! wfEmptyMsg( $msg, $out ) and  $out !== '' and ! $this->including() ) {
+               if ( !wfMessage( $msg )->isBlank() and ! $this->including() ) {
                        $wgOut->wrapWikiMsg( "<div class='mw-specialpage-summary'>\n$1\n</div>", $msg );
                }
 
@@ -895,16 +968,41 @@ class SpecialPage {
        function getRedirectQuery() {
                global $wgRequest;
                $params = array();
+
                foreach( $this->mAllowedRedirectParams as $arg ) {
-                       if( ( $val = $wgRequest->getVal( $arg, null ) ) !== null )
-                               $params[] = $arg . '=' . $val;
+                       if( $wgRequest->getVal( $arg, null ) !== null ){
+                               $params[$arg] = $wgRequest->getVal( $arg );
+                       }
                }
-               
+
                foreach( $this->mAddedRedirectParams as $arg => $val ) {
-                       $params[] = $arg . '=' . $val;
+                       $params[$arg] = $val;
                }
-               
-               return count( $params ) ? implode( '&', $params ) : false;
+
+               return count( $params )
+                       ? $params
+                       : false;
+       }
+       
+       /**
+        * Sets the context this SpecialPage is executed in
+        * 
+        * @param $request WebRequest
+        * @param $output OutputPage
+        */
+       protected function setContext( $request, $output ) {
+               $this->mRequest = $request;
+               $this->mOutput = $output;
+               $this->mFullTitle = $output->getTitle();
+       }
+       /**
+        * Wrapper around wfMessage that sets the current context. Currently this
+        * is only the title.
+        * 
+        * @see wfMessage
+        */
+       public function msg( /* $args */ ) {
+               return call_user_func_array( 'wfMessage', func_get_args() )->title( $this->mFullTitle );
        }
 }
 
@@ -914,8 +1012,8 @@ class SpecialPage {
  */
 class UnlistedSpecialPage extends SpecialPage
 {
-       function UnlistedSpecialPage( $name, $restriction = '', $function = false, $file = 'default' ) {
-               parent::SpecialPage( $name, $restriction, false, $function, $file );
+       function __construct( $name, $restriction = '', $function = false, $file = 'default' ) {
+               parent::__construct( $name, $restriction, false, $function, $file );
        }
 }
 
@@ -925,8 +1023,8 @@ class UnlistedSpecialPage extends SpecialPage
  */
 class IncludableSpecialPage extends SpecialPage
 {
-       function IncludableSpecialPage( $name, $restriction = '', $listed = true, $function = false, $file = 'default' ) {
-               parent::SpecialPage( $name, $restriction, $listed, $function, $file, true );
+       function __construct( $name, $restriction = '', $listed = true, $function = false, $file = 'default' ) {
+               parent::__construct( $name, $restriction, $listed, $function, $file, true );
        }
 }
 
@@ -954,7 +1052,8 @@ class SpecialRedirectToSpecial extends UnlistedSpecialPage {
        }
 }
 
-/** SpecialMypage, SpecialMytalk and SpecialMycontributions special pages
+/**
+ * SpecialMypage, SpecialMytalk and SpecialMycontributions special pages
  * are used to get user independant links pointing to the user page, talk
  * page and list of contributions.
  * This can let us cache a single copy of any generated content for all
@@ -968,7 +1067,8 @@ class SpecialRedirectToSpecial extends UnlistedSpecialPage {
 class SpecialMypage extends UnlistedSpecialPage {
        function __construct() {
                parent::__construct( 'Mypage' );
-               $this->mAllowedRedirectParams = array( 'action' , 'preload' , 'editintro', 'section' );
+               $this->mAllowedRedirectParams = array( 'action' , 'preload' , 'editintro',
+                       'section', 'oldid', 'diff', 'dir' );
        }
 
        function getRedirect( $subpage ) {
@@ -988,7 +1088,8 @@ class SpecialMypage extends UnlistedSpecialPage {
 class SpecialMytalk extends UnlistedSpecialPage {
        function __construct() {
                parent::__construct( 'Mytalk' );
-               $this->mAllowedRedirectParams = array( 'action' , 'preload' , 'editintro', 'section' );
+               $this->mAllowedRedirectParams = array( 'action' , 'preload' , 'editintro',
+                       'section', 'oldid', 'diff', 'dir' );
        }
 
        function getRedirect( $subpage ) {
@@ -1017,3 +1118,34 @@ class SpecialMycontributions extends UnlistedSpecialPage {
                return SpecialPage::getTitleFor( 'Contributions', $wgUser->getName() );
        }
 }
+
+/**
+ * Redirect to Special:Listfiles?user=$wgUser
+ */
+class SpecialMyuploads extends UnlistedSpecialPage {
+       function __construct() {
+               parent::__construct( 'Myuploads' );
+               $this->mAllowedRedirectParams = array( 'limit' );
+       }
+
+       function getRedirect( $subpage ) {
+               global $wgUser;
+               return SpecialPage::getTitleFor( 'Listfiles', $wgUser->getName() );
+       }
+}
+
+/**
+ * Redirect from Special:PermanentLink/### to index.php?oldid=###
+ */
+class SpecialPermanentLink extends UnlistedSpecialPage {
+       function __construct() {
+               parent::__construct( 'PermanentLink' );
+               $this->mAllowedRedirectParams = array();
+       }
+
+       function getRedirect( $subpage ) {
+               $subpage = intval( $subpage );
+               $this->mAddedRedirectParams['oldid'] = $subpage;
+               return true;
+       }
+}