r86255 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86254‎ | r86255 | r86256 >
Date:11:31, 17 April 2011
Author:happy-melon
Status:resolved (Comments)
Tags:
Comment:
Refactor the factory/i18n/list/etc static methods from SpecialPage into their own class; there's no reason we need to be parsing them in every single SpecialPage subclass. Leave all the methods as stubs in SpecialPage.php; if we required PHP 5.3 they could be replaced by a a __callStatic() magic method, but that doesn't work on PHP 5.2.

Also make a few changes to the functions available. SpecialPageFactory::resolveAlias() now takes an optional subpage and returns array(<name>,<subpage>). Similarly merge getPage() and getPageByAlias(). There were many examples of (extensions particularly) making dubious assumptions about the presence or absence of subpages or canonical-ness.

I didn't deprecate SpecialPage::getTitleFor() as it's got over six hundred calls. I'm rather undecided on the best position of getPage()/executePath(). Although the latter needs cleanup anyway.
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/ChangesList.php (modified) (history)
  • /trunk/phase3/includes/Linker.php (modified) (history)
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/includes/PrefixSearch.php (modified) (history)
  • /trunk/phase3/includes/Skin.php (modified) (history)
  • /trunk/phase3/includes/SkinLegacy.php (modified) (history)
  • /trunk/phase3/includes/SkinTemplate.php (modified) (history)
  • /trunk/phase3/includes/SpecialPage.php (modified) (history)
  • /trunk/phase3/includes/SpecialPageFactory.php (added) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/Wiki.php (modified) (history)
  • /trunk/phase3/includes/api/ApiQuery.php (modified) (history)
  • /trunk/phase3/includes/parser/CoreParserFunctions.php (modified) (history)
  • /trunk/phase3/includes/parser/Parser.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialSpecialpages.php (modified) (history)
  • /trunk/phase3/maintenance/updateSpecialPages.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/updateSpecialPages.php
@@ -78,7 +78,7 @@
7979 continue;
8080 }
8181
82 - $specialObj = SpecialPage::getPage( $special );
 82+ $specialObj = SpecialPageFactory::getPage( $special );
8383 if ( !$specialObj ) {
8484 $this->output( "No such special page: $special\n" );
8585 exit;
Index: trunk/phase3/includes/SpecialPageFactory.php
@@ -0,0 +1,543 @@
 2+<?php
 3+/**
 4+ * SpecialPage: handling special pages and lists thereof.
 5+ *
 6+ * To add a special page in an extension, add to $wgSpecialPages either
 7+ * an object instance or an array containing the name and constructor
 8+ * parameters. The latter is preferred for performance reasons.
 9+ *
 10+ * The object instantiated must be either an instance of SpecialPage or a
 11+ * sub-class thereof. It must have an execute() method, which sends the HTML
 12+ * for the special page to $wgOut. The parent class has an execute() method
 13+ * which distributes the call to the historical global functions. Additionally,
 14+ * execute() also checks if the user has the necessary access privileges
 15+ * and bails out if not.
 16+ *
 17+ * To add a core special page, use the similar static list in
 18+ * SpecialPage::$mList. To remove a core static special page at runtime, use
 19+ * a SpecialPage_initList hook.
 20+ *
 21+ * @file
 22+ * @ingroup SpecialPage
 23+ * @defgroup SpecialPage SpecialPage
 24+ */
 25+
 26+/**
 27+ * Factory for handling the special page list and generating SpecialPage objects
 28+ * @ingroup SpecialPage
 29+ */
 30+class SpecialPageFactory {
 31+
 32+ /**
 33+ * List of special page names to the subclass of SpecialPage which handles them.
 34+ */
 35+ private static $mList = array(
 36+ // Maintenance Reports
 37+ 'BrokenRedirects' => 'BrokenRedirectsPage',
 38+ 'Deadendpages' => 'DeadendpagesPage',
 39+ 'DoubleRedirects' => 'DoubleRedirectsPage',
 40+ 'Longpages' => 'LongpagesPage',
 41+ 'Ancientpages' => 'AncientpagesPage',
 42+ 'Lonelypages' => 'LonelypagesPage',
 43+ 'Fewestrevisions' => 'FewestrevisionsPage',
 44+ 'Withoutinterwiki' => 'WithoutinterwikiPage',
 45+ 'Protectedpages' => 'SpecialProtectedpages',
 46+ 'Protectedtitles' => 'SpecialProtectedtitles',
 47+ 'Shortpages' => 'ShortpagesPage',
 48+ 'Uncategorizedcategories' => 'UncategorizedcategoriesPage',
 49+ 'Uncategorizedimages' => 'UncategorizedimagesPage',
 50+ 'Uncategorizedpages' => 'UncategorizedpagesPage',
 51+ 'Uncategorizedtemplates' => 'UncategorizedtemplatesPage',
 52+ 'Unusedcategories' => 'UnusedcategoriesPage',
 53+ 'Unusedimages' => 'UnusedimagesPage',
 54+ 'Unusedtemplates' => 'UnusedtemplatesPage',
 55+ 'Unwatchedpages' => 'UnwatchedpagesPage',
 56+ 'Wantedcategories' => 'WantedcategoriesPage',
 57+ 'Wantedfiles' => 'WantedfilesPage',
 58+ 'Wantedpages' => 'WantedpagesPage',
 59+ 'Wantedtemplates' => 'WantedtemplatesPage',
 60+
 61+ // List of pages
 62+ 'Allpages' => 'SpecialAllpages',
 63+ 'Prefixindex' => 'SpecialPrefixindex',
 64+ 'Categories' => 'SpecialCategories',
 65+ 'Disambiguations' => 'DisambiguationsPage',
 66+ 'Listredirects' => 'ListredirectsPage',
 67+
 68+ // Login/create account
 69+ 'Userlogin' => 'LoginForm',
 70+ 'CreateAccount' => 'SpecialCreateAccount',
 71+
 72+ // Users and rights
 73+ 'Block' => 'SpecialBlock',
 74+ 'Unblock' => 'SpecialUnblock',
 75+ 'BlockList' => 'SpecialBlockList',
 76+ 'Resetpass' => 'SpecialResetpass',
 77+ 'DeletedContributions' => 'DeletedContributionsPage',
 78+ 'Preferences' => 'SpecialPreferences',
 79+ 'Contributions' => 'SpecialContributions',
 80+ 'Listgrouprights' => 'SpecialListGroupRights',
 81+ 'Listusers' => 'SpecialListUsers' ,
 82+ 'Listadmins' => 'SpecialListAdmins',
 83+ 'Listbots' => 'SpecialListBots',
 84+ 'Activeusers' => 'SpecialActiveUsers',
 85+ 'Userrights' => 'UserrightsPage',
 86+ 'EditWatchlist' => 'SpecialEditWatchlist',
 87+
 88+ // Recent changes and logs
 89+ 'Newimages' => 'SpecialNewFiles',
 90+ 'Log' => 'SpecialLog',
 91+ 'Watchlist' => 'SpecialWatchlist',
 92+ 'Newpages' => 'SpecialNewpages',
 93+ 'Recentchanges' => 'SpecialRecentchanges',
 94+ 'Recentchangeslinked' => 'SpecialRecentchangeslinked',
 95+ 'Tags' => 'SpecialTags',
 96+
 97+ // Media reports and uploads
 98+ 'Listfiles' => 'SpecialListFiles',
 99+ 'Filepath' => 'SpecialFilepath',
 100+ 'MIMEsearch' => 'MIMEsearchPage',
 101+ 'FileDuplicateSearch' => 'FileDuplicateSearchPage',
 102+ 'Upload' => 'SpecialUpload',
 103+ 'UploadStash' => 'SpecialUploadStash',
 104+
 105+ // Wiki data and tools
 106+ 'Statistics' => 'SpecialStatistics',
 107+ 'Allmessages' => 'SpecialAllmessages',
 108+ 'Version' => 'SpecialVersion',
 109+ 'Lockdb' => 'SpecialLockdb',
 110+ 'Unlockdb' => 'SpecialUnlockdb',
 111+
 112+ // Redirecting special pages
 113+ 'LinkSearch' => 'LinkSearchPage',
 114+ 'Randompage' => 'Randompage',
 115+ 'Randomredirect' => 'SpecialRandomredirect',
 116+
 117+ // High use pages
 118+ 'Mostlinkedcategories' => 'MostlinkedCategoriesPage',
 119+ 'Mostimages' => 'MostimagesPage',
 120+ 'Mostlinked' => 'MostlinkedPage',
 121+ 'Mostlinkedtemplates' => 'MostlinkedTemplatesPage',
 122+ 'Mostcategories' => 'MostcategoriesPage',
 123+ 'Mostrevisions' => 'MostrevisionsPage',
 124+
 125+ // Page tools
 126+ 'ComparePages' => 'SpecialComparePages',
 127+ 'Export' => 'SpecialExport',
 128+ 'Import' => 'SpecialImport',
 129+ 'Undelete' => 'SpecialUndelete',
 130+ 'Whatlinkshere' => 'SpecialWhatlinkshere',
 131+ 'MergeHistory' => 'SpecialMergeHistory',
 132+
 133+ // Other
 134+ 'Booksources' => 'SpecialBookSources',
 135+
 136+ // Unlisted / redirects
 137+ 'Blankpage' => 'SpecialBlankpage',
 138+ 'Blockme' => 'SpecialBlockme',
 139+ 'Emailuser' => 'SpecialEmailUser',
 140+ 'Movepage' => 'MovePageForm',
 141+ 'Mycontributions' => 'SpecialMycontributions',
 142+ 'Mypage' => 'SpecialMypage',
 143+ 'Mytalk' => 'SpecialMytalk',
 144+ 'Myuploads' => 'SpecialMyuploads',
 145+ 'PermanentLink' => 'SpecialPermanentLink',
 146+ 'Revisiondelete' => 'SpecialRevisionDelete',
 147+ 'Specialpages' => 'SpecialSpecialpages',
 148+ 'Userlogout' => 'SpecialUserlogout',
 149+ );
 150+
 151+ private static $mAliases;
 152+
 153+ /**
 154+ * Initialise the special page list
 155+ * This must be called before accessing SpecialPage::$mList
 156+ */
 157+ static function getList() {
 158+ global $wgSpecialPages;
 159+ global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
 160+
 161+ if ( !is_object( self::$mList ) ) {
 162+ wfProfileIn( __METHOD__ );
 163+
 164+ if ( !$wgDisableCounters ) {
 165+ self::$mList['Popularpages'] = 'PopularpagesPage';
 166+ }
 167+
 168+ if ( !$wgDisableInternalSearch ) {
 169+ self::$mList['Search'] = 'SpecialSearch';
 170+ }
 171+
 172+ if ( $wgEmailAuthentication ) {
 173+ self::$mList['Confirmemail'] = 'EmailConfirmation';
 174+ self::$mList['Invalidateemail'] = 'EmailInvalidation';
 175+ }
 176+
 177+ // Add extension special pages
 178+ self::$mList = array_merge( self::$mList, $wgSpecialPages );
 179+
 180+ // Run hooks
 181+ // This hook can be used to remove undesired built-in special pages
 182+ wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) );
 183+
 184+ // Cast to object: func()[$key] doesn't work, but func()->$key does
 185+ settype( self::$mList, 'object' );
 186+
 187+ wfProfileOut( __METHOD__ );
 188+ }
 189+ return self::$mList;
 190+ }
 191+
 192+ static function getAliasList() {
 193+ if ( !is_object( self::$mAliases ) ) {
 194+ global $wgContLang;
 195+ $aliases = $wgContLang->getSpecialPageAliases();
 196+
 197+ // Objects are passed by reference by default, need to create a copy
 198+ $missingPages = clone self::getList();
 199+
 200+ self::$mAliases = array();
 201+ foreach ( $aliases as $realName => $aliasList ) {
 202+ foreach ( $aliasList as $alias ) {
 203+ self::$mAliases[$wgContLang->caseFold( $alias )] = $realName;
 204+ }
 205+ unset( $missingPages->$realName );
 206+ }
 207+ foreach ( $missingPages as $name => $stuff ) {
 208+ self::$mAliases[$wgContLang->caseFold( $name )] = $name;
 209+ }
 210+
 211+ // Cast to object: func()[$key] doesn't work, but func()->$key does
 212+ self::$mAliases = (object)self::$mAliases;
 213+ }
 214+ return self::$mAliases;
 215+ }
 216+
 217+ /**
 218+ * Given a special page name with a possible subpage, return an array
 219+ * where the first element is the special page name and the second is the
 220+ * subpage.
 221+ *
 222+ * @param $alias String
 223+ * @return Array( String, String|null ), or array( null, null ) if the page is invalid
 224+ */
 225+ public static function resolveAlias( $alias ) {
 226+ global $wgContLang;
 227+ $bits = explode( '/', $alias, 2 );
 228+
 229+ $caseFoldedAlias = $wgContLang->caseFold( $bits[0] );
 230+ $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
 231+ if ( isset( self::getAliasList()->$caseFoldedAlias ) ) {
 232+ $name = self::getAliasList()->$caseFoldedAlias;
 233+ } else {
 234+ return array( null, null );
 235+ }
 236+
 237+ if ( !isset( $bits[1] ) ) { // bug 2087
 238+ $par = null;
 239+ } else {
 240+ $par = $bits[1];
 241+ }
 242+
 243+ return array( $name, $par );
 244+ }
 245+
 246+ /**
 247+ * Add a page to a certain display group for Special:SpecialPages
 248+ *
 249+ * @param $page Mixed: SpecialPage or string
 250+ * @param $group String
 251+ */
 252+ public static function setGroup( $page, $group ) {
 253+ global $wgSpecialPageGroups;
 254+ $name = is_object( $page ) ? $page->mName : $page;
 255+ $wgSpecialPageGroups[$name] = $group;
 256+ }
 257+
 258+ /**
 259+ * Add a page to a certain display group for Special:SpecialPages
 260+ *
 261+ * @param $page SpecialPage
 262+ */
 263+ public static function getGroup( &$page ) {
 264+ global $wgSpecialPageGroups;
 265+ static $specialPageGroupsCache = array();
 266+ if ( isset( $specialPageGroupsCache[$page->mName] ) ) {
 267+ return $specialPageGroupsCache[$page->mName];
 268+ }
 269+ $msg = wfMessage( 'specialpages-specialpagegroup-' . strtolower( $page->mName ) );
 270+ if ( !$msg->isBlank() ) {
 271+ $group = $msg->text();
 272+ } else {
 273+ $group = isset( $wgSpecialPageGroups[$page->mName] )
 274+ ? $wgSpecialPageGroups[$page->mName]
 275+ : '-';
 276+ }
 277+ if ( $group == '-' ) {
 278+ $group = 'other';
 279+ }
 280+ $specialPageGroupsCache[$page->mName] = $group;
 281+ return $group;
 282+ }
 283+
 284+ /**
 285+ * Check if a given name exist as a special page or as a special page alias
 286+ *
 287+ * @param $name String: name of a special page
 288+ * @return Boolean: true if a special page exists with this name
 289+ */
 290+ public static function exists( $name ) {
 291+ list( $title, /*...*/ ) = self::resolveAlias( $name );
 292+ return property_exists( self::getList(), $title );
 293+ }
 294+
 295+ /**
 296+ * Find the object with a given name and return it (or NULL)
 297+ *
 298+ * @param $name String Special page name, may be localised and/or an alias
 299+ * @return SpecialPage object or null if the page doesn't exist
 300+ */
 301+ public static function getPage( $name ) {
 302+ list( $realName, /*...*/ ) = self::resolveAlias( $name );
 303+ if ( property_exists( self::getList(), $realName ) ) {
 304+ $rec = self::getList()->$realName;
 305+ if ( is_string( $rec ) ) {
 306+ $className = $rec;
 307+ self::getList()->$realName = new $className;
 308+ } elseif ( is_array( $rec ) ) {
 309+ // @deprecated, officially since 1.18, unofficially since forever
 310+ wfDebug( "Array syntax for \$wgSpecialPages is deprecated, define a subclass of SpecialPage instead." );
 311+ $className = array_shift( $rec );
 312+ self::getList()->$realName = MWFunction::newObj( $className, $rec );
 313+ }
 314+ return self::getList()->$realName;
 315+ } else {
 316+ return null;
 317+ }
 318+ }
 319+
 320+ /**
 321+ * Return categorised listable special pages which are available
 322+ * for the current user, and everyone.
 323+ *
 324+ * @return Array( String => Specialpage )
 325+ */
 326+ public static function getUsablePages() {
 327+ global $wgUser;
 328+ $pages = array();
 329+ foreach ( self::getList() as $name => $rec ) {
 330+ $page = self::getPage( $name );
 331+ if ( $page->isListed()
 332+ && (
 333+ !$page->isRestricted()
 334+ || $page->userCanExecute( $wgUser )
 335+ )
 336+ ) {
 337+ $pages[$name] = $page;
 338+ }
 339+ }
 340+ return $pages;
 341+ }
 342+
 343+ /**
 344+ * Return categorised listable special pages for all users
 345+ *
 346+ * @return Array( String => Specialpage )
 347+ */
 348+ public static function getRegularPages() {
 349+ $pages = array();
 350+ foreach ( self::getList() as $name => $rec ) {
 351+ $page = self::getPage( $name );
 352+ if ( $page->isListed() && !$page->isRestricted() ) {
 353+ $pages[$name] = $page;
 354+ }
 355+ }
 356+ return $pages;
 357+ }
 358+
 359+ /**
 360+ * Return categorised listable special pages which are available
 361+ * for the current user, but not for everyone
 362+ *
 363+ * @return Array( String => Specialpage )
 364+ */
 365+ public static function getRestrictedPages() {
 366+ global $wgUser;
 367+ $pages = array();
 368+ foreach ( self::getList() as $name => $rec ) {
 369+ $page = self::getPage( $name );
 370+ if (
 371+ $page->isListed()
 372+ && $page->isRestricted()
 373+ && $page->userCanExecute( $wgUser )
 374+ ) {
 375+ $pages[$name] = $page;
 376+ }
 377+ }
 378+ return $pages;
 379+ }
 380+
 381+ /**
 382+ * Execute a special page path.
 383+ * The path may contain parameters, e.g. Special:Name/Params
 384+ * Extracts the special page name and call the execute method, passing the parameters
 385+ *
 386+ * Returns a title object if the page is redirected, false if there was no such special
 387+ * page, and true if it was successful.
 388+ *
 389+ * @param $title Title object
 390+ * @param $context RequestContext
 391+ * @param $including Bool output is being captured for use in {{special:whatever}}
 392+ */
 393+ public static function executePath( Title &$title, RequestContext &$context, $including = false ) {
 394+ wfProfileIn( __METHOD__ );
 395+
 396+ // FIXME: redirects broken due to this call
 397+ $bits = explode( '/', $title->getDBkey(), 2 );
 398+ $name = $bits[0];
 399+ if ( !isset( $bits[1] ) ) { // bug 2087
 400+ $par = null;
 401+ } else {
 402+ $par = $bits[1];
 403+ }
 404+ $page = self::getPage( $name );
 405+ // Nonexistent?
 406+ if ( !$page ) {
 407+ $context->output->setArticleRelated( false );
 408+ $context->output->setRobotPolicy( 'noindex,nofollow' );
 409+ $context->output->setStatusCode( 404 );
 410+ $context->output->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
 411+ wfProfileOut( __METHOD__ );
 412+ return false;
 413+ }
 414+
 415+ // Page exists, set the context
 416+ $page->setContext( $context );
 417+
 418+ // Check for redirect
 419+ if ( !$including ) {
 420+ $redirect = $page->getRedirect( $par );
 421+ $query = $page->getRedirectQuery();
 422+ if ( $redirect instanceof Title ) {
 423+ $url = $redirect->getFullUrl( $query );
 424+ $context->output->redirect( $url );
 425+ wfProfileOut( __METHOD__ );
 426+ return $redirect;
 427+ } elseif ( $redirect === true ) {
 428+ global $wgScript;
 429+ $url = $wgScript . '?' . wfArrayToCGI( $query );
 430+ $context->output->redirect( $url );
 431+ wfProfileOut( __METHOD__ );
 432+ return $redirect;
 433+ }
 434+
 435+ // Redirect to canonical alias for GET commands
 436+ // Not for POST, we'd lose the post data, so it's best to just distribute
 437+ // the request. Such POST requests are possible for old extensions that
 438+ // generate self-links without being aware that their default name has
 439+ // changed.
 440+ if ( $name != $page->getLocalName() && !$context->request->wasPosted() ) {
 441+ $query = $_GET;
 442+ unset( $query['title'] );
 443+ $query = wfArrayToCGI( $query );
 444+ $title = $page->getTitle( $par );
 445+ $url = $title->getFullUrl( $query );
 446+ $context->output->redirect( $url );
 447+ wfProfileOut( __METHOD__ );
 448+ return $redirect;
 449+ } else {
 450+ $context->title = $page->getTitle();
 451+ }
 452+
 453+ } elseif ( !$page->includable() ) {
 454+ wfProfileOut( __METHOD__ );
 455+ return false;
 456+ }
 457+
 458+ $page->including( $including );
 459+
 460+ // Execute special page
 461+ $profName = 'Special:' . $page->name();
 462+ wfProfileIn( $profName );
 463+ $page->execute( $par );
 464+ wfProfileOut( $profName );
 465+ wfProfileOut( __METHOD__ );
 466+ return true;
 467+ }
 468+
 469+ /**
 470+ * Just like executePath() except it returns the HTML instead of outputting it
 471+ * Returns false if there was no such special page, or a title object if it was
 472+ * a redirect.
 473+ *
 474+ * @return String: HTML fragment
 475+ */
 476+ static function capturePath( &$title ) {
 477+ global $wgOut, $wgTitle;
 478+
 479+ $oldTitle = $wgTitle;
 480+ $oldOut = $wgOut;
 481+
 482+ $context = new RequestContext;
 483+ $context->setTitle( $title );
 484+ $wgOut = $context->getOutput();
 485+
 486+ $ret = self::executePath( $title, $context, true );
 487+ if ( $ret === true ) {
 488+ $ret = $wgOut->getHTML();
 489+ }
 490+ $wgTitle = $oldTitle;
 491+ $wgOut = $oldOut;
 492+ return $ret;
 493+ }
 494+
 495+ /**
 496+ * Get the local name for a specified canonical name
 497+ *
 498+ * @param $name String
 499+ * @param $subpage String|Bool
 500+ *
 501+ * @return String
 502+ */
 503+ static function getLocalNameFor( $name, $subpage = false ) {
 504+ global $wgContLang;
 505+ $aliases = $wgContLang->getSpecialPageAliases();
 506+ if ( isset( $aliases[$name][0] ) ) {
 507+ $name = $aliases[$name][0];
 508+ } else {
 509+ // Try harder in case someone misspelled the correct casing
 510+ $found = false;
 511+ foreach ( $aliases as $n => $values ) {
 512+ if ( strcasecmp( $name, $n ) === 0 ) {
 513+ wfWarn( "Found alias defined for $n when searching for " .
 514+ "special page aliases for $name. Case mismatch?" );
 515+ $name = $values[0];
 516+ $found = true;
 517+ break;
 518+ }
 519+ }
 520+ if ( !$found ) {
 521+ wfWarn( "Did not find alias for special page '$name'. " .
 522+ "Perhaps no aliases are defined for it?" );
 523+ }
 524+ }
 525+ if ( $subpage !== false && !is_null( $subpage ) ) {
 526+ $name = "$name/$subpage";
 527+ }
 528+ return $wgContLang->ucfirst( $name );
 529+ }
 530+
 531+ /**
 532+ * Get a title for a given alias
 533+ *
 534+ * @return Title or null if there is no such alias
 535+ */
 536+ static function getTitleForAlias( $alias ) {
 537+ $name = self::resolveAlias( $alias );
 538+ if ( $name ) {
 539+ return self::getTitleFor( $name );
 540+ } else {
 541+ return null;
 542+ }
 543+ }
 544+}
\ No newline at end of file
Property changes on: trunk/phase3/includes/SpecialPageFactory.php
___________________________________________________________________
Added: svn:mergeinfo
1545 Merged /branches/new-installer/phase3/includes/SpecialPage.php:r43664-66004
2546 Merged /branches/wmf-deployment/includes/SpecialPage.php:r53381
3547 Merged /branches/uploadwizard/phase3/includes/SpecialPage.php:r73550-75905
4548 Merged /branches/REL1_15/phase3/includes/SpecialPage.php:r51646
5549 Merged /branches/sqlite/includes/SpecialPage.php:r58211-58321
Added: svn:eol-style
6550 + native
Added: svn:keywords
7551 + Author Date Id Revision
Index: trunk/phase3/includes/PrefixSearch.php
@@ -85,15 +85,13 @@
8686
8787 // Unlike SpecialPage itself, we want the canonical forms of both
8888 // canonical and alias title forms...
89 - SpecialPage::initList();
90 - SpecialPage::initAliasList();
9189 $keys = array();
92 - foreach( array_keys( SpecialPage::$mList ) as $page ) {
 90+ foreach( SpecialPageFactory::getList() as $page => $class ) {
9391 $keys[$wgContLang->caseFold( $page )] = $page;
9492 }
9593
9694 foreach( $wgContLang->getSpecialPageAliases() as $page => $aliases ) {
97 - if( !array_key_exists( $page, SpecialPage::$mList ) ) {# bug 20885
 95+ if( !array_key_exists( $page, SpecialPageFactory::getList() ) ) {# bug 20885
9896 continue;
9997 }
10098
Index: trunk/phase3/includes/parser/Parser.php
@@ -3252,7 +3252,7 @@
32533253 && $this->mOptions->getAllowSpecialInclusion()
32543254 && $this->ot['html'] )
32553255 {
3256 - $text = SpecialPage::capturePath( $title );
 3256+ $text = SpecialPageFactory::capturePath( $title );
32573257 if ( is_string( $text ) ) {
32583258 $found = true;
32593259 $isHTML = true;
Index: trunk/phase3/includes/parser/CoreParserFunctions.php
@@ -653,7 +653,7 @@
654654 }
655655
656656 static function special( $parser, $text ) {
657 - list( $page, $subpage ) = SpecialPage::resolveAliasWithSubpage( $text );
 657+ list( $page, $subpage ) = SpecialPageFactory::resolveAlias( $text );
658658 if ( $page ) {
659659 $title = SpecialPage::getTitleFor( $page, $subpage );
660660 return $title;
Index: trunk/phase3/includes/Linker.php
@@ -376,7 +376,7 @@
377377
378378 static function normaliseSpecialPage( Title $title ) {
379379 if ( $title->getNamespace() == NS_SPECIAL ) {
380 - list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $title->getDBkey() );
 380+ list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
381381 if ( !$name ) {
382382 return $title;
383383 }
Index: trunk/phase3/includes/OutputPage.php
@@ -2652,8 +2652,7 @@
26532653 $ns = $title->getNamespace();
26542654 $nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $title->getNsText();
26552655 if ( $ns == NS_SPECIAL ) {
2656 - $parts = SpecialPage::resolveAliasWithSubpage( $title->getDBkey() );
2657 - $canonicalName = $parts[0];
 2656+ list( $canonicalName, /*...*/ ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
26582657 } else {
26592658 $canonicalName = false; # bug 21115
26602659 }
Index: trunk/phase3/includes/api/ApiQuery.php
@@ -430,7 +430,7 @@
431431 ApiQueryBase::addTitleInfo( $vals, $title );
432432 $vals['special'] = '';
433433 if ( $title->getNamespace() == NS_SPECIAL &&
434 - !SpecialPage::exists( $title->getDbKey() ) ) {
 434+ !SpecialPageFactory::exists( $title->getDbKey() ) ) {
435435 $vals['missing'] = '';
436436 } elseif ( $title->getNamespace() == NS_MEDIA &&
437437 !wfFindFile( $title ) ) {
Index: trunk/phase3/includes/AutoLoader.php
@@ -226,6 +226,7 @@
227227 'SpecialMypage' => 'includes/SpecialPage.php',
228228 'SpecialMytalk' => 'includes/SpecialPage.php',
229229 'SpecialPage' => 'includes/SpecialPage.php',
 230+ 'SpecialPageFactory' => 'includes/SpecialPageFactory.php',
230231 'SpecialRedirectToSpecial' => 'includes/SpecialPage.php',
231232 'SquidUpdate' => 'includes/SquidUpdate.php',
232233 'SquidPurgeClient' => 'includes/SquidPurgeClient.php',
Index: trunk/phase3/includes/Wiki.php
@@ -212,7 +212,7 @@
213213 && !count( array_diff( array_keys( $this->context->request->getValues() ), array( 'action', 'title' ) ) ) )
214214 {
215215 if ( $this->context->title->getNamespace() == NS_SPECIAL ) {
216 - list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $this->context->title->getDBkey() );
 216+ list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $this->context->title->getDBkey() );
217217 if ( $name ) {
218218 $this->context->title = SpecialPage::getTitleFor( $name, $subpage );
219219 }
@@ -249,7 +249,7 @@
250250 // Special pages
251251 } else if ( NS_SPECIAL == $this->context->title->getNamespace() ) {
252252 // actions that need to be made when we have a special pages
253 - SpecialPage::executePath( $this->context->title, $this->context );
 253+ SpecialPageFactory::executePath( $this->context->title, $this->context );
254254 } else {
255255 // No match to special cases
256256 wfProfileOut( __METHOD__ );
@@ -553,7 +553,7 @@
554554 break;
555555 case 'revisiondelete':
556556 // For show/hide submission from history page
557 - $special = SpecialPage::getPage( 'Revisiondelete' );
 557+ $special = SpecialPageFactory::getPage( 'Revisiondelete' );
558558 $special->execute( '' );
559559 break;
560560 default:
Index: trunk/phase3/includes/ChangesList.php
@@ -558,7 +558,7 @@
559559 $this->insertLog( $s, $logtitle, $rc->mAttribs['rc_log_type'] );
560560 // Log entries (old format) or log targets, and special pages
561561 } elseif( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
562 - list( $name, $subpage ) = SpecialPage::resolveAliasWithSubpage( $rc->mAttribs['rc_title'] );
 562+ list( $name, $subpage ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
563563 if( $name == 'Log' ) {
564564 $this->insertLog( $s, $rc->getTitle(), $subpage );
565565 }
@@ -694,7 +694,7 @@
695695 $watched = false;
696696 // Log entries (old format) and special pages
697697 } elseif( $rc->mAttribs['rc_namespace'] == NS_SPECIAL ) {
698 - list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $rc->mAttribs['rc_title'] );
 698+ list( $specialName, $logtype ) = SpecialPageFactory::resolveAlias( $rc->mAttribs['rc_title'] );
699699 if ( $specialName == 'Log' ) {
700700 # Log updates, etc
701701 $logname = LogPage::logName( $logtype );
Index: trunk/phase3/includes/Title.php
@@ -1812,7 +1812,7 @@
18131813 # If it's a special page, ditch the subpage bit and check again
18141814 if ( $this->getNamespace() == NS_SPECIAL ) {
18151815 $name = $this->getDBkey();
1816 - list( $name, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $name );
 1816+ list( $name, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $name );
18171817 if ( $name === false ) {
18181818 # Invalid special page, but we show standard login required message
18191819 return false;
@@ -3811,7 +3811,7 @@
38123812 return (bool)wfFindFile( $this );
38133813 case NS_SPECIAL:
38143814 // valid special page
3815 - return SpecialPage::exists( $this->getDBkey() );
 3815+ return SpecialPageFactory::exists( $this->getDBkey() );
38163816 case NS_MAIN:
38173817 // selflink, possibly with fragment
38183818 return $this->mDbkeyform == '';
@@ -4038,7 +4038,7 @@
40394039 */
40404040 public function isSpecial( $name ) {
40414041 if ( $this->getNamespace() == NS_SPECIAL ) {
4042 - list( $thisName, /* $subpage */ ) = SpecialPage::resolveAliasWithSubpage( $this->getDBkey() );
 4042+ list( $thisName, /* $subpage */ ) = SpecialPageFactory::resolveAlias( $this->getDBkey() );
40434043 if ( $name == $thisName ) {
40444044 return true;
40454045 }
@@ -4054,9 +4054,9 @@
40554055 */
40564056 public function fixSpecialName() {
40574057 if ( $this->getNamespace() == NS_SPECIAL ) {
4058 - $canonicalName = SpecialPage::resolveAlias( $this->mDbkeyform );
 4058+ list( $canonicalName, /*...*/ ) = SpecialPageFactory::resolveAlias( $this->mDbkeyform );
40594059 if ( $canonicalName ) {
4060 - $localName = SpecialPage::getLocalNameFor( $canonicalName );
 4060+ $localName = SpecialPageFactory::getLocalNameFor( $canonicalName );
40614061 if ( $localName != $this->mDbkeyform ) {
40624062 return Title::makeTitle( NS_SPECIAL, $localName );
40634063 }
Index: trunk/phase3/includes/SkinLegacy.php
@@ -432,7 +432,7 @@
433433 function specialPagesList() {
434434 global $wgContLang, $wgServer, $wgRedirectScript;
435435
436 - $pages = SpecialPage::getUsablePages();
 436+ $pages = SpecialPageFactory::getUsablePages();
437437
438438 foreach ( $pages as $name => $page ) {
439439 $pages[$name] = $page->getDescription();
Index: trunk/phase3/includes/SkinTemplate.php
@@ -608,8 +608,7 @@
609609 # contain the original alias-with-subpage.
610610 $origTitle = Title::newFromText( $wgRequest->getText( 'title' ) );
611611 if( $origTitle instanceof Title && $origTitle->getNamespace() == NS_SPECIAL ) {
612 - list( $spName, $spPar ) =
613 - SpecialPage::resolveAliasWithSubpage( $origTitle->getText() );
 612+ list( $spName, $spPar ) = SpecialPageFactory::resolveAlias( $origTitle->getText() );
614613 $active = $spName == 'Contributions'
615614 && ( ( $spPar && $spPar == $this->username )
616615 || $wgRequest->getText( 'target' ) == $this->username );
Index: trunk/phase3/includes/specials/SpecialSpecialpages.php
@@ -51,7 +51,7 @@
5252 private function getPageGroups() {
5353 global $wgSortSpecialPages;
5454
55 - $pages = SpecialPage::getUsablePages();
 55+ $pages = SpecialPageFactory::getUsablePages();
5656
5757 if( !count( $pages ) ) {
5858 # Yeah, that was pointless. Thanks for coming.
@@ -62,7 +62,7 @@
6363 $groups = array();
6464 foreach ( $pages as $page ) {
6565 if ( $page->isListed() ) {
66 - $group = SpecialPage::getGroup( $page );
 66+ $group = SpecialPageFactory::getGroup( $page );
6767 if( !isset( $groups[$group] ) ) {
6868 $groups[$group] = array();
6969 }
Index: trunk/phase3/includes/Skin.php
@@ -303,6 +303,7 @@
304304 * Special:Contributions mark the user which they are relevant to so that
305305 * things like the toolbox can display the information they usually are only
306306 * able to display on a user's userpage and talkpage.
 307+ * @return User
307308 */
308309 public function getRelevantUser() {
309310 if ( isset($this->mRelevantUser) ) {
@@ -485,7 +486,7 @@
486487 if ( $title->getNamespace() == NS_SPECIAL ) {
487488 $type = 'ns-special';
488489 // bug 23315: provide a class based on the canonical special page name without subpages
489 - list( $canonicalName ) = SpecialPage::resolveAliasWithSubpage( $title->getDBkey() );
 490+ list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
490491 if ( $canonicalName ) {
491492 $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
492493 } else {
@@ -1128,7 +1129,7 @@
11291130 }
11301131
11311132 static function makeSpecialUrl( $name, $urlaction = '' ) {
1132 - $title = SpecialPage::getTitleFor( $name );
 1133+ $title = SpecialPage::getSafeTitleFor( $name );
11331134 return $title->getLocalURL( $urlaction );
11341135 }
11351136
Index: trunk/phase3/includes/SpecialPage.php
@@ -201,64 +201,20 @@
202202 static public $mAliases;
203203 static public $mListInitialised = false;
204204
205 - /**#@-*/
206 -
207205 /**
208206 * Initialise the special page list
209207 * This must be called before accessing SpecialPage::$mList
 208+ * @deprecated since 1.18
210209 */
211210 static function initList() {
212 - global $wgSpecialPages;
213 - global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
214 -
215 - if ( self::$mListInitialised ) {
216 - return;
217 - }
218 - wfProfileIn( __METHOD__ );
219 -
220 - # Better to set this now, to avoid infinite recursion in carelessly written hooks
221 - self::$mListInitialised = true;
222 -
223 - if( !$wgDisableCounters ) {
224 - self::$mList['Popularpages'] = 'PopularpagesPage';
225 - }
226 -
227 - if( !$wgDisableInternalSearch ) {
228 - self::$mList['Search'] = 'SpecialSearch';
229 - }
230 -
231 - if( $wgEmailAuthentication ) {
232 - self::$mList['Confirmemail'] = 'EmailConfirmation';
233 - self::$mList['Invalidateemail'] = 'EmailInvalidation';
234 - }
235 -
236 - # Add extension special pages
237 - self::$mList = array_merge( self::$mList, $wgSpecialPages );
238 -
239 - # Run hooks
240 - # This hook can be used to remove undesired built-in special pages
241 - wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) );
242 - wfProfileOut( __METHOD__ );
 211+ // Noop
243212 }
244213
 214+ /**
 215+ * @deprecated since 1.18
 216+ */
245217 static function initAliasList() {
246 - if ( !is_null( self::$mAliases ) ) {
247 - return;
248 - }
249 -
250 - global $wgContLang;
251 - $aliases = $wgContLang->getSpecialPageAliases();
252 - $missingPages = self::$mList;
253 - self::$mAliases = array();
254 - foreach ( $aliases as $realName => $aliasList ) {
255 - foreach ( $aliasList as $alias ) {
256 - self::$mAliases[$wgContLang->caseFold( $alias )] = $realName;
257 - }
258 - unset( $missingPages[$realName] );
259 - }
260 - foreach ( $missingPages as $name => $stuff ) {
261 - self::$mAliases[$wgContLang->caseFold( $name )] = $name;
262 - }
 218+ // Noop
263219 }
264220
265221 /**
@@ -267,19 +223,11 @@
268224 *
269225 * @param $alias String
270226 * @return String or false
 227+ * @deprecated since 1.18 call SpecialPageFactory method directly
271228 */
272229 static function resolveAlias( $alias ) {
273 - global $wgContLang;
274 -
275 - if ( !self::$mListInitialised ) self::initList();
276 - if ( is_null( self::$mAliases ) ) self::initAliasList();
277 - $caseFoldedAlias = $wgContLang->caseFold( $alias );
278 - $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
279 - if ( isset( self::$mAliases[$caseFoldedAlias] ) ) {
280 - return self::$mAliases[$caseFoldedAlias];
281 - } else {
282 - return false;
283 - }
 230+ list( $name, /*...*/ ) = SpecialPageFactory::resolveAlias( $alias );
 231+ return $name;
284232 }
285233
286234 /**
@@ -289,16 +237,10 @@
290238 *
291239 * @param $alias String
292240 * @return Array
 241+ * @deprecated since 1.18 call SpecialPageFactory method directly
293242 */
294243 static function resolveAliasWithSubpage( $alias ) {
295 - $bits = explode( '/', $alias, 2 );
296 - $name = self::resolveAlias( $bits[0] );
297 - if( !isset( $bits[1] ) ) { // bug 2087
298 - $par = null;
299 - } else {
300 - $par = $bits[1];
301 - }
302 - return array( $name, $par );
 244+ return SpecialPageFactory::resolveAlias( $alias );
303245 }
304246
305247 /**
@@ -307,14 +249,11 @@
308250 * an associative record to $wgSpecialPages. This avoids autoloading SpecialPage.
309251 *
310252 * @param $page SpecialPage
311 - * Deprecated in 1.7, warnings in 1.17, might be removed in 1.20
 253+ * @deprecated in 1.7, warnings in 1.17, might be removed in 1.20
312254 */
313255 static function addPage( &$page ) {
314256 wfDeprecated( __METHOD__ );
315 - if ( !self::$mListInitialised ) {
316 - self::initList();
317 - }
318 - self::$mList[$page->mName] = $page;
 257+ SpecialPageFactory::getList()->{$page->mName} = $page;
319258 }
320259
321260 /**
@@ -322,47 +261,30 @@
323262 *
324263 * @param $page Mixed: SpecialPage or string
325264 * @param $group String
 265+ * @deprecated since 1.18 call SpecialPageFactory method directly
326266 */
327267 static function setGroup( $page, $group ) {
328 - global $wgSpecialPageGroups;
329 - $name = is_object($page) ? $page->mName : $page;
330 - $wgSpecialPageGroups[$name] = $group;
 268+ return SpecialPageFactory::setGroup( $page, $group );
331269 }
332270
333271 /**
334272 * Add a page to a certain display group for Special:SpecialPages
335273 *
336274 * @param $page SpecialPage
 275+ * @deprecated since 1.18 call SpecialPageFactory method directly
337276 */
338277 static function getGroup( &$page ) {
339 - global $wgSpecialPageGroups;
340 - static $specialPageGroupsCache = array();
341 - if( isset($specialPageGroupsCache[$page->mName]) ) {
342 - return $specialPageGroupsCache[$page->mName];
343 - }
344 - $msg = wfMessage('specialpages-specialpagegroup-'.strtolower($page->mName));
345 - if ( !$msg->isBlank() ) {
346 - $group = $msg->text();
347 - } else {
348 - $group = isset($wgSpecialPageGroups[$page->mName])
349 - ? $wgSpecialPageGroups[$page->mName]
350 - : '-';
351 - }
352 - if( $group == '-' ) $group = 'other';
353 - $specialPageGroupsCache[$page->mName] = $group;
354 - return $group;
 278+ return SpecialPageFactory::getGroup( $page );
355279 }
356280
357281 /**
358282 * Remove a special page from the list
359283 * Formerly used to disable expensive or dangerous special pages. The
360284 * preferred method is now to add a SpecialPage_initList hook.
 285+ * @deprecated since 1.18
361286 */
362287 static function removePage( $name ) {
363 - if ( !self::$mListInitialised ) {
364 - self::initList();
365 - }
366 - unset( self::$mList[$name] );
 288+ unset( SpecialPageFactory::getList()->$name );
367289 }
368290
369291 /**
@@ -370,24 +292,10 @@
371293 *
372294 * @param $name String: name of a special page
373295 * @return Boolean: true if a special page exists with this name
 296+ * @deprecated since 1.18 call SpecialPageFactory method directly
374297 */
375298 static function exists( $name ) {
376 - global $wgContLang;
377 - if ( !self::$mListInitialised ) {
378 - self::initList();
379 - }
380 - if( !self::$mAliases ) {
381 - self::initAliasList();
382 - }
383 -
384 - # Remove special pages inline parameters:
385 - $bits = explode( '/', $name );
386 - $name = $wgContLang->caseFold($bits[0]);
387 -
388 - return
389 - array_key_exists( $name, self::$mList )
390 - or array_key_exists( $name, self::$mAliases )
391 - ;
 299+ return SpecialPageFactory::exists( $name );
392300 }
393301
394302 /**
@@ -395,26 +303,10 @@
396304 *
397305 * @param $name String
398306 * @return SpecialPage object or null if the page doesn't exist
 307+ * @deprecated since 1.18 call SpecialPageFactory method directly
399308 */
400309 static function getPage( $name ) {
401 - if ( !self::$mListInitialised ) {
402 - self::initList();
403 - }
404 - if ( array_key_exists( $name, self::$mList ) ) {
405 - $rec = self::$mList[$name];
406 - if ( is_string( $rec ) ) {
407 - $className = $rec;
408 - self::$mList[$name] = new $className;
409 - } elseif ( is_array( $rec ) ) {
410 - // @deprecated officially since 1.18, unofficially since forever
411 - wfDebug( "Array syntax for \$wgSpecialPages is deprecated, define a subclass of SpecialPage instead." );
412 - $className = array_shift( $rec );
413 - self::$mList[$name] = MWFunction::newObj( $className, $rec );
414 - }
415 - return self::$mList[$name];
416 - } else {
417 - return null;
418 - }
 310+ return SpecialPageFactory::getPage( $name );
419311 }
420312
421313 /**
@@ -422,14 +314,10 @@
423315 * is no such special page.
424316 *
425317 * @return SpecialPage object or null if the page doesn't exist
 318+ * @deprecated since 1.18 call SpecialPageFactory method directly
426319 */
427320 static function getPageByAlias( $alias ) {
428 - $realName = self::resolveAlias( $alias );
429 - if ( $realName ) {
430 - return self::getPage( $realName );
431 - } else {
432 - return null;
433 - }
 321+ return SpecialPageFactory::getPage( $alias );
434322 }
435323
436324 /**
@@ -437,46 +325,20 @@
438326 * for the current user, and everyone.
439327 *
440328 * @return Associative array mapping page's name to its SpecialPage object
 329+ * @deprecated since 1.18 call SpecialPageFactory method directly
441330 */
442331 static function getUsablePages() {
443 - global $wgUser;
444 - if ( !self::$mListInitialised ) {
445 - self::initList();
446 - }
447 - $pages = array();
448 -
449 - foreach ( self::$mList as $name => $rec ) {
450 - $page = self::getPage( $name );
451 - if ( $page->isListed()
452 - && (
453 - !$page->isRestricted()
454 - || $page->userCanExecute( $wgUser )
455 - )
456 - ) {
457 - $pages[$name] = $page;
458 - }
459 - }
460 - return $pages;
 332+ return SpecialPageFactory::getUsablePages();
461333 }
462334
463335 /**
464336 * Return categorised listable special pages for all users
465337 *
466338 * @return Associative array mapping page's name to its SpecialPage object
 339+ * @deprecated since 1.18 call SpecialPageFactory method directly
467340 */
468341 static function getRegularPages() {
469 - if ( !self::$mListInitialised ) {
470 - self::initList();
471 - }
472 - $pages = array();
473 -
474 - foreach ( self::$mList as $name => $rec ) {
475 - $page = self::getPage( $name );
476 - if ( $page->isListed() && !$page->isRestricted() ) {
477 - $pages[$name] = $page;
478 - }
479 - }
480 - return $pages;
 342+ return SpecialPageFactory::getRegularPages();
481343 }
482344
483345 /**
@@ -484,25 +346,10 @@
485347 * for the current user, but not for everyone
486348 *
487349 * @return Associative array mapping page's name to its SpecialPage object
 350+ * @deprecated since 1.18 call SpecialPageFactory method directly
488351 */
489352 static function getRestrictedPages() {
490 - global $wgUser;
491 - if( !self::$mListInitialised ) {
492 - self::initList();
493 - }
494 - $pages = array();
495 -
496 - foreach( self::$mList as $name => $rec ) {
497 - $page = self::getPage( $name );
498 - if(
499 - $page->isListed()
500 - && $page->isRestricted()
501 - && $page->userCanExecute( $wgUser )
502 - ) {
503 - $pages[$name] = $page;
504 - }
505 - }
506 - return $pages;
 353+ return SpecialPageFactory::getRestrictedPages();
507354 }
508355
509356 /**
@@ -516,81 +363,10 @@
517364 * @param $title Title object
518365 * @param $context RequestContext
519366 * @param $including Bool output is being captured for use in {{special:whatever}}
 367+ * @deprecated since 1.18 call SpecialPageFactory method directly
520368 */
521369 public static function executePath( &$title, RequestContext &$context, $including = false ) {
522 - wfProfileIn( __METHOD__ );
523 -
524 - # FIXME: redirects broken due to this call
525 - $bits = explode( '/', $title->getDBkey(), 2 );
526 - $name = $bits[0];
527 - if( !isset( $bits[1] ) ) { // bug 2087
528 - $par = null;
529 - } else {
530 - $par = $bits[1];
531 - }
532 - $page = SpecialPage::getPageByAlias( $name );
533 - # Nonexistent?
534 - if ( !$page ) {
535 - $context->output->setArticleRelated( false );
536 - $context->output->setRobotPolicy( 'noindex,nofollow' );
537 - $context->output->setStatusCode( 404 );
538 - $context->output->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
539 - wfProfileOut( __METHOD__ );
540 - return false;
541 - }
542 -
543 - # Page exists, set the context
544 - $page->setContext( $context );
545 -
546 - # Check for redirect
547 - if ( !$including ) {
548 - $redirect = $page->getRedirect( $par );
549 - $query = $page->getRedirectQuery();
550 - if ( $redirect instanceof Title ) {
551 - $url = $redirect->getFullUrl( $query );
552 - $context->output->redirect( $url );
553 - wfProfileOut( __METHOD__ );
554 - return $redirect;
555 - } elseif( $redirect === true ) {
556 - global $wgScript;
557 - $url = $wgScript . '?' . wfArrayToCGI( $query );
558 - $context->output->redirect( $url );
559 - wfProfileOut( __METHOD__ );
560 - return $redirect;
561 - }
562 - }
563 -
564 - # Redirect to canonical alias for GET commands
565 - # Not for POST, we'd lose the post data, so it's best to just distribute
566 - # the request. Such POST requests are possible for old extensions that
567 - # generate self-links without being aware that their default name has
568 - # changed.
569 - if ( !$including && $name != $page->getLocalName() && !$context->request->wasPosted() ) {
570 - $query = $_GET;
571 - unset( $query['title'] );
572 - $query = wfArrayToCGI( $query );
573 - $title = $page->getTitle( $par );
574 - $url = $title->getFullUrl( $query );
575 - $context->output->redirect( $url );
576 - wfProfileOut( __METHOD__ );
577 - return $redirect;
578 - }
579 -
580 - if ( $including && !$page->includable() ) {
581 - wfProfileOut( __METHOD__ );
582 - return false;
583 - } elseif ( !$including ) {
584 - $context->title = $page->getTitle();
585 - }
586 - $page->including( $including );
587 -
588 - // Execute special page
589 - $profName = 'Special:' . $page->name();
590 - wfProfileIn( $profName );
591 - $page->execute( $par );
592 - wfProfileOut( $profName );
593 - wfProfileOut( __METHOD__ );
594 - return true;
 370+ return SpecialPageFactory::executePath( $title, $context, $including );
595371 }
596372
597373 /**
@@ -599,24 +375,10 @@
600376 * a redirect.
601377 *
602378 * @return String: HTML fragment
 379+ * @deprecated since 1.18 call SpecialPageFactory method directly
603380 */
604381 static function capturePath( &$title ) {
605 - global $wgOut, $wgTitle;
606 -
607 - $oldTitle = $wgTitle;
608 - $oldOut = $wgOut;
609 -
610 - $context = new RequestContext;
611 - $context->setTitle( $title );
612 - $wgOut = $context->getOutput();
613 -
614 - $ret = SpecialPage::executePath( $title, $context, true );
615 - if ( $ret === true ) {
616 - $ret = $wgOut->getHTML();
617 - }
618 - $wgTitle = $oldTitle;
619 - $wgOut = $oldOut;
620 - return $ret;
 382+ return SpecialPageFactory::capturePath( $title );
621383 }
622384
623385 /**
@@ -626,33 +388,10 @@
627389 * @param $subpage Mixed: boolean false, or string
628390 *
629391 * @return String
 392+ * @deprecated since 1.18 call SpecialPageFactory method directly
630393 */
631394 static function getLocalNameFor( $name, $subpage = false ) {
632 - global $wgContLang;
633 - $aliases = $wgContLang->getSpecialPageAliases();
634 - if ( isset( $aliases[$name][0] ) ) {
635 - $name = $aliases[$name][0];
636 - } else {
637 - // Try harder in case someone misspelled the correct casing
638 - $found = false;
639 - foreach ( $aliases as $n => $values ) {
640 - if ( strcasecmp( $name, $n ) === 0 ) {
641 - wfWarn( "Found alias defined for $n when searching for " .
642 - "special page aliases for $name. Case mismatch?" );
643 - $name = $values[0];
644 - $found = true;
645 - break;
646 - }
647 - }
648 - if ( !$found ) {
649 - wfWarn( "Did not find alias for special page '$name'. " .
650 - "Perhaps no aliases are defined for it?" );
651 - }
652 - }
653 - if ( $subpage !== false && !is_null( $subpage ) ) {
654 - $name = "$name/$subpage";
655 - }
656 - return $wgContLang->ucfirst( $name );
 395+ return SpecialPageFactory::getLocalNameFor( $name, $subpage );
657396 }
658397
659398 /**
@@ -660,8 +399,8 @@
661400 *
662401 * @return Title object
663402 */
664 - static function getTitleFor( $name, $subpage = false ) {
665 - $name = self::getLocalNameFor( $name, $subpage );
 403+ public static function getTitleFor( $name, $subpage = false ) {
 404+ $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
666405 if ( $name ) {
667406 return Title::makeTitle( NS_SPECIAL, $name );
668407 } else {
@@ -674,8 +413,8 @@
675414 *
676415 * @return Title object or null if the page doesn't exist
677416 */
678 - static function getSafeTitleFor( $name, $subpage = false ) {
679 - $name = self::getLocalNameFor( $name, $subpage );
 417+ public static function getSafeTitleFor( $name, $subpage = false ) {
 418+ $name = SpecialPageFactory::getLocalNameFor( $name, $subpage );
680419 if ( $name ) {
681420 return Title::makeTitleSafe( NS_SPECIAL, $name );
682421 } else {
@@ -687,14 +426,10 @@
688427 * Get a title for a given alias
689428 *
690429 * @return Title or null if there is no such alias
 430+ * @deprecated since 1.18 call SpecialPageFactory method directly
691431 */
692432 static function getTitleForAlias( $alias ) {
693 - $name = self::resolveAlias( $alias );
694 - if ( $name ) {
695 - return self::getTitleFor( $name );
696 - } else {
697 - return null;
698 - }
 433+ return SpecialPageFactory::getTitleForAlias( $alias );
699434 }
700435
701436 /**
@@ -800,7 +535,7 @@
801536 */
802537 function getLocalName() {
803538 if ( !isset( $this->mLocalName ) ) {
804 - $this->mLocalName = self::getLocalNameFor( $this->mName );
 539+ $this->mLocalName = SpecialPageFactory::getLocalNameFor( $this->mName );
805540 }
806541 return $this->mLocalName;
807542 }
@@ -846,7 +581,7 @@
847582 * Output an error message telling the user what access level they have to have
848583 */
849584 function displayRestrictionError() {
850 - $this->getOutput()->permissionRequired( $this->mRestriction );
 585+ throw new PermissionsError( $this->mRestriction );
851586 }
852587
853588 /**
@@ -928,6 +663,8 @@
929664
930665 /**
931666 * Set whether this page is listed in Special:Specialpages, at run-time
 667+ *
 668+ * @return Bool
932669 */
933670 function setListed( $listed ) {
934671 return wfSetVar( $this->mListed, $listed );
@@ -936,6 +673,8 @@
937674 /**
938675 * If the special page is a redirect, then get the Title object it redirects to.
939676 * False otherwise.
 677+ *
 678+ * @return Title|false
940679 */
941680 function getRedirect( $subpage ) {
942681 return false;
@@ -971,7 +710,7 @@
972711 * @param $context RequestContext
973712 * @since 1.18
974713 */
975 - protected function setContext( $context ) {
 714+ public function setContext( $context ) {
976715 $this->mContext = $context;
977716 }
978717
@@ -1090,9 +829,9 @@
1091830
1092831 function getRedirect( $subpage ) {
1093832 if ( $this->redirSubpage === false ) {
1094 - return SpecialPage::getTitleFor( $this->redirName, $subpage );
 833+ return SpecialPageFactory::getTitleFor( $this->redirName, $subpage );
1095834 } else {
1096 - return SpecialPage::getTitleFor( $this->redirName, $this->redirSubpage );
 835+ return SpecialPageFactory::getTitleFor( $this->redirName, $this->redirSubpage );
1097836 }
1098837 }
1099838 }
@@ -1187,7 +926,7 @@
1188927
1189928 function getRedirect( $subpage ) {
1190929 global $wgUser;
1191 - return SpecialPage::getTitleFor( 'Contributions', $wgUser->getName() );
 930+ return SpecialPageFactory::getTitleFor( 'Contributions', $wgUser->getName() );
1192931 }
1193932 }
1194933
@@ -1202,7 +941,7 @@
1203942
1204943 function getRedirect( $subpage ) {
1205944 global $wgUser;
1206 - return SpecialPage::getTitleFor( 'Listfiles', $wgUser->getName() );
 945+ return SpecialPageFactory::getTitleFor( 'Listfiles', $wgUser->getName() );
1207946 }
1208947 }
1209948

Follow-up revisions

RevisionCommit summaryAuthorDate
r86282Follow-up r86255: rm duplicated config listhappy-melon20:34, 17 April 2011
r86339Follow-up r86255: getTitleFor() was not migrated.happy-melon19:44, 18 April 2011
r86407Follow-up r86255: don't special-case redirecting special pages in executePath...happy-melon15:45, 19 April 2011
r86416Fix r86255...reedy17:45, 19 April 2011
r86449make SpecialUpload::userCanExecute signature compatible with SpecialPage, whi...neilk00:25, 20 April 2011
r97857* (bug 31100) Fix regression in sidebar (special: page links lost parameters)...brion21:35, 22 September 2011
r97858MFT r97857 to 1.18 -- regression from r86255 (bug 31100)brion21:38, 22 September 2011
r97859MFT r97857 to 1.18wmf1 -- regression from r86255 (bug 31100)brion21:39, 22 September 2011

Comments

#Comment by Raymond (talk | contribs)   17:26, 19 April 2011

Whatever revision:

PHP Strict Standards: Declaration of UserrightsPage::userCanExecute() should be compatible with that of SpecialPage::userCanExecute() in /www/w/includes/AutoLoader.php on line 871
#Comment by Raymond (talk | contribs)   19:35, 19 April 2011

The next one:

PHP Strict Standards: Declaration of SpecialUpload::userCanExecute() should be compatible with that of SpecialPage::userCanExecute() in /www/w/includes/AutoLoader.php on line 871
#Comment by Reedy (talk | contribs)   05:12, 20 April 2011

Fixed by Neil in r86449

#Comment by 😂 (talk | contribs)   04:51, 20 April 2011

I'm not sure I like casting $mList to an object, since it's always been an array. Other than wanting to be lazy and type getList()->$var, is there a compelling reason for the change?

#Comment by Happy-melon (talk | contribs)   11:22, 20 April 2011

It's not so much laziness as code clarity; it would need a dozen temporary variables to make it parse properly as an array. Plus an object has the advantage that it's intrinsically pass-by-reference. I could implement some sort of Iterator which can be accessed with either method, but that might well make it more opaque, not less.

#Comment by Happy-melon (talk | contribs)   11:23, 20 April 2011

The E_STRICT warnings are actually caused by r86407, not this rev.

#Comment by Aaron Schulz (talk | contribs)   19:11, 21 June 2011

throw new PermissionsError( $this->mRestriction );

I'm not really sold on permission errors as MW exceptions. What's the use for it?

#Comment by Bawolff (talk | contribs)   14:18, 22 September 2011

This causes a very minor regression in 1.18 (noticed by Jack Phoenix on irc). If you have a link a line in mediawiki:sidebar like:

Special:Code/MediaWiki|Look at MediaWiki codebase

before it would link to Special:Code/MediaWiki where now it links to Special:Code. (Same for all special pages, however subpages are preserved for normal links)

#Comment by Brion VIBBER (talk | contribs)   21:23, 22 September 2011

Not minor -- that's just plain wrong. :)

Bug 31100.

#Comment by Brion VIBBER (talk | contribs)   21:36, 22 September 2011

Fixed in r97857.

#Comment by Happy-melon (talk | contribs)   21:04, 23 September 2011

Thanks Brion. :)

Status & tagging log