MediaWiki
REL1_23
|
00001 <?php 00046 class SpecialPageFactory { 00050 private static $list = array( 00051 // Maintenance Reports 00052 'BrokenRedirects' => 'BrokenRedirectsPage', 00053 'Deadendpages' => 'DeadendPagesPage', 00054 'DoubleRedirects' => 'DoubleRedirectsPage', 00055 'Longpages' => 'LongPagesPage', 00056 'Ancientpages' => 'AncientPagesPage', 00057 'Lonelypages' => 'LonelyPagesPage', 00058 'Fewestrevisions' => 'FewestrevisionsPage', 00059 'Withoutinterwiki' => 'WithoutInterwikiPage', 00060 'Protectedpages' => 'SpecialProtectedpages', 00061 'Protectedtitles' => 'SpecialProtectedtitles', 00062 'Shortpages' => 'ShortpagesPage', 00063 'Uncategorizedcategories' => 'UncategorizedCategoriesPage', 00064 'Uncategorizedimages' => 'UncategorizedImagesPage', 00065 'Uncategorizedpages' => 'UncategorizedPagesPage', 00066 'Uncategorizedtemplates' => 'UncategorizedTemplatesPage', 00067 'Unusedcategories' => 'UnusedCategoriesPage', 00068 'Unusedimages' => 'UnusedimagesPage', 00069 'Unusedtemplates' => 'UnusedtemplatesPage', 00070 'Unwatchedpages' => 'UnwatchedpagesPage', 00071 'Wantedcategories' => 'WantedCategoriesPage', 00072 'Wantedfiles' => 'WantedFilesPage', 00073 'Wantedpages' => 'WantedPagesPage', 00074 'Wantedtemplates' => 'WantedTemplatesPage', 00075 00076 // List of pages 00077 'Allpages' => 'SpecialAllpages', 00078 'Prefixindex' => 'SpecialPrefixindex', 00079 'Categories' => 'SpecialCategories', 00080 'Listredirects' => 'ListredirectsPage', 00081 'PagesWithProp' => 'SpecialPagesWithProp', 00082 'TrackingCategories' => 'SpecialTrackingCategories', 00083 00084 // Login/create account 00085 'Userlogin' => 'LoginForm', 00086 'CreateAccount' => 'SpecialCreateAccount', 00087 00088 // Users and rights 00089 'Block' => 'SpecialBlock', 00090 'Unblock' => 'SpecialUnblock', 00091 'BlockList' => 'SpecialBlockList', 00092 'ChangePassword' => 'SpecialChangePassword', 00093 'PasswordReset' => 'SpecialPasswordReset', 00094 'DeletedContributions' => 'DeletedContributionsPage', 00095 'Preferences' => 'SpecialPreferences', 00096 'ResetTokens' => 'SpecialResetTokens', 00097 'Contributions' => 'SpecialContributions', 00098 'Listgrouprights' => 'SpecialListGroupRights', 00099 'Listusers' => 'SpecialListUsers', 00100 'Listadmins' => 'SpecialListAdmins', 00101 'Listbots' => 'SpecialListBots', 00102 'Userrights' => 'UserrightsPage', 00103 'EditWatchlist' => 'SpecialEditWatchlist', 00104 00105 // Recent changes and logs 00106 'Newimages' => 'SpecialNewFiles', 00107 'Log' => 'SpecialLog', 00108 'Watchlist' => 'SpecialWatchlist', 00109 'Newpages' => 'SpecialNewpages', 00110 'Recentchanges' => 'SpecialRecentChanges', 00111 'Recentchangeslinked' => 'SpecialRecentChangesLinked', 00112 'Tags' => 'SpecialTags', 00113 00114 // Media reports and uploads 00115 'Listfiles' => 'SpecialListFiles', 00116 'Filepath' => 'SpecialFilepath', 00117 'MIMEsearch' => 'MIMEsearchPage', 00118 'FileDuplicateSearch' => 'FileDuplicateSearchPage', 00119 'Upload' => 'SpecialUpload', 00120 'UploadStash' => 'SpecialUploadStash', 00121 'ListDuplicatedFiles' => 'ListDuplicatedFilesPage', 00122 00123 // Data and tools 00124 'Statistics' => 'SpecialStatistics', 00125 'Allmessages' => 'SpecialAllmessages', 00126 'Version' => 'SpecialVersion', 00127 'Lockdb' => 'SpecialLockdb', 00128 'Unlockdb' => 'SpecialUnlockdb', 00129 00130 // Redirecting special pages 00131 'LinkSearch' => 'LinkSearchPage', 00132 'Randompage' => 'RandomPage', 00133 'RandomInCategory' => 'SpecialRandomInCategory', 00134 'Randomredirect' => 'SpecialRandomredirect', 00135 00136 // High use pages 00137 'Mostlinkedcategories' => 'MostlinkedCategoriesPage', 00138 'Mostimages' => 'MostimagesPage', 00139 'Mostinterwikis' => 'MostinterwikisPage', 00140 'Mostlinked' => 'MostlinkedPage', 00141 'Mostlinkedtemplates' => 'MostlinkedTemplatesPage', 00142 'Mostcategories' => 'MostcategoriesPage', 00143 'Mostrevisions' => 'MostrevisionsPage', 00144 00145 // Page tools 00146 'ComparePages' => 'SpecialComparePages', 00147 'Export' => 'SpecialExport', 00148 'Import' => 'SpecialImport', 00149 'Undelete' => 'SpecialUndelete', 00150 'Whatlinkshere' => 'SpecialWhatLinksHere', 00151 'MergeHistory' => 'SpecialMergeHistory', 00152 'ExpandTemplates' => 'SpecialExpandTemplates', 00153 00154 // Other 00155 'Booksources' => 'SpecialBookSources', 00156 00157 // Unlisted / redirects 00158 'Blankpage' => 'SpecialBlankpage', 00159 'Diff' => 'SpecialDiff', 00160 'Emailuser' => 'SpecialEmailUser', 00161 'Movepage' => 'MovePageForm', 00162 'Mycontributions' => 'SpecialMycontributions', 00163 'Mypage' => 'SpecialMypage', 00164 'Mytalk' => 'SpecialMytalk', 00165 'Myuploads' => 'SpecialMyuploads', 00166 'AllMyUploads' => 'SpecialAllMyUploads', 00167 'PermanentLink' => 'SpecialPermanentLink', 00168 'Redirect' => 'SpecialRedirect', 00169 'Revisiondelete' => 'SpecialRevisionDelete', 00170 'RunJobs' => 'SpecialRunJobs', 00171 'Specialpages' => 'SpecialSpecialpages', 00172 'Userlogout' => 'SpecialUserlogout', 00173 ); 00174 00175 private static $aliases; 00176 00182 static function getList() { 00183 global $wgSpecialPages; 00184 global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication; 00185 global $wgEnableEmail, $wgEnableJavaScriptTest; 00186 00187 if ( !is_object( self::$list ) ) { 00188 wfProfileIn( __METHOD__ ); 00189 00190 if ( !$wgDisableCounters ) { 00191 self::$list['Popularpages'] = 'PopularPagesPage'; 00192 } 00193 00194 if ( !$wgDisableInternalSearch ) { 00195 self::$list['Search'] = 'SpecialSearch'; 00196 } 00197 00198 if ( $wgEmailAuthentication ) { 00199 self::$list['Confirmemail'] = 'EmailConfirmation'; 00200 self::$list['Invalidateemail'] = 'EmailInvalidation'; 00201 } 00202 00203 if ( $wgEnableEmail ) { 00204 self::$list['ChangeEmail'] = 'SpecialChangeEmail'; 00205 } 00206 00207 if ( $wgEnableJavaScriptTest ) { 00208 self::$list['JavaScriptTest'] = 'SpecialJavaScriptTest'; 00209 } 00210 00211 self::$list['Activeusers'] = 'SpecialActiveUsers'; 00212 00213 // Add extension special pages 00214 self::$list = array_merge( self::$list, $wgSpecialPages ); 00215 00216 // Run hooks 00217 // This hook can be used to remove undesired built-in special pages 00218 wfRunHooks( 'SpecialPage_initList', array( &self::$list ) ); 00219 00220 // Cast to object: func()[$key] doesn't work, but func()->$key does 00221 settype( self::$list, 'object' ); 00222 00223 wfProfileOut( __METHOD__ ); 00224 } 00225 00226 return self::$list; 00227 } 00228 00237 static function getAliasList() { 00238 if ( !is_object( self::$aliases ) ) { 00239 global $wgContLang; 00240 $aliases = $wgContLang->getSpecialPageAliases(); 00241 00242 // Objects are passed by reference by default, need to create a copy 00243 $missingPages = clone self::getList(); 00244 00245 self::$aliases = array(); 00246 foreach ( $aliases as $realName => $aliasList ) { 00247 foreach ( $aliasList as $alias ) { 00248 self::$aliases[$wgContLang->caseFold( $alias )] = $realName; 00249 } 00250 unset( $missingPages->$realName ); 00251 } 00252 foreach ( $missingPages as $name => $stuff ) { 00253 self::$aliases[$wgContLang->caseFold( $name )] = $name; 00254 } 00255 00256 // Cast to object: func()[$key] doesn't work, but func()->$key does 00257 self::$aliases = (object)self::$aliases; 00258 } 00259 00260 return self::$aliases; 00261 } 00262 00271 public static function resolveAlias( $alias ) { 00272 global $wgContLang; 00273 $bits = explode( '/', $alias, 2 ); 00274 00275 $caseFoldedAlias = $wgContLang->caseFold( $bits[0] ); 00276 $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias ); 00277 if ( isset( self::getAliasList()->$caseFoldedAlias ) ) { 00278 $name = self::getAliasList()->$caseFoldedAlias; 00279 } else { 00280 return array( null, null ); 00281 } 00282 00283 if ( !isset( $bits[1] ) ) { // bug 2087 00284 $par = null; 00285 } else { 00286 $par = $bits[1]; 00287 } 00288 00289 return array( $name, $par ); 00290 } 00291 00299 public static function setGroup( $page, $group ) { 00300 wfDeprecated( __METHOD__, '1.21' ); 00301 00302 global $wgSpecialPageGroups; 00303 $name = is_object( $page ) ? $page->getName() : $page; 00304 $wgSpecialPageGroups[$name] = $group; 00305 } 00306 00314 public static function getGroup( &$page ) { 00315 wfDeprecated( __METHOD__, '1.21' ); 00316 00317 return $page->getFinalGroupName(); 00318 } 00319 00326 public static function exists( $name ) { 00327 list( $title, /*...*/ ) = self::resolveAlias( $name ); 00328 00329 return property_exists( self::getList(), $title ); 00330 } 00331 00338 public static function getPage( $name ) { 00339 list( $realName, /*...*/ ) = self::resolveAlias( $name ); 00340 if ( property_exists( self::getList(), $realName ) ) { 00341 $rec = self::getList()->$realName; 00342 if ( is_string( $rec ) ) { 00343 $className = $rec; 00344 00345 return new $className; 00346 } elseif ( is_array( $rec ) ) { 00347 // @deprecated, officially since 1.18, unofficially since forever 00348 wfDebug( "Array syntax for \$wgSpecialPages is deprecated, " . 00349 "define a subclass of SpecialPage instead." ); 00350 $className = array_shift( $rec ); 00351 self::getList()->$realName = MWFunction::newObj( $className, $rec ); 00352 } 00353 00354 return self::getList()->$realName; 00355 } else { 00356 return null; 00357 } 00358 } 00359 00368 public static function getUsablePages( User $user = null ) { 00369 $pages = array(); 00370 if ( $user === null ) { 00371 global $wgUser; 00372 $user = $wgUser; 00373 } 00374 foreach ( self::getList() as $name => $rec ) { 00375 $page = self::getPage( $name ); 00376 if ( $page ) { // not null 00377 $page->setContext( RequestContext::getMain() ); 00378 if ( $page->isListed() 00379 && ( !$page->isRestricted() || $page->userCanExecute( $user ) ) 00380 ) { 00381 $pages[$name] = $page; 00382 } 00383 } 00384 } 00385 00386 return $pages; 00387 } 00388 00394 public static function getRegularPages() { 00395 $pages = array(); 00396 foreach ( self::getList() as $name => $rec ) { 00397 $page = self::getPage( $name ); 00398 if ( $page->isListed() && !$page->isRestricted() ) { 00399 $pages[$name] = $page; 00400 } 00401 } 00402 00403 return $pages; 00404 } 00405 00412 public static function getRestrictedPages() { 00413 global $wgUser; 00414 $pages = array(); 00415 foreach ( self::getList() as $name => $rec ) { 00416 $page = self::getPage( $name ); 00417 if ( 00418 $page->isListed() 00419 && $page->isRestricted() 00420 && $page->userCanExecute( $wgUser ) 00421 ) { 00422 $pages[$name] = $page; 00423 } 00424 } 00425 00426 return $pages; 00427 } 00428 00443 public static function executePath( Title &$title, IContextSource &$context, $including = false ) { 00444 wfProfileIn( __METHOD__ ); 00445 00446 // @todo FIXME: Redirects broken due to this call 00447 $bits = explode( '/', $title->getDBkey(), 2 ); 00448 $name = $bits[0]; 00449 if ( !isset( $bits[1] ) ) { // bug 2087 00450 $par = null; 00451 } else { 00452 $par = $bits[1]; 00453 } 00454 $page = self::getPage( $name ); 00455 // Nonexistent? 00456 if ( !$page ) { 00457 $context->getOutput()->setArticleRelated( false ); 00458 $context->getOutput()->setRobotPolicy( 'noindex,nofollow' ); 00459 00460 global $wgSend404Code; 00461 if ( $wgSend404Code ) { 00462 $context->getOutput()->setStatusCode( 404 ); 00463 } 00464 00465 $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); 00466 wfProfileOut( __METHOD__ ); 00467 00468 return false; 00469 } 00470 00471 // Page exists, set the context 00472 $page->setContext( $context ); 00473 00474 if ( !$including ) { 00475 // Redirect to canonical alias for GET commands 00476 // Not for POST, we'd lose the post data, so it's best to just distribute 00477 // the request. Such POST requests are possible for old extensions that 00478 // generate self-links without being aware that their default name has 00479 // changed. 00480 if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) { 00481 $query = $context->getRequest()->getQueryValues(); 00482 unset( $query['title'] ); 00483 $title = $page->getPageTitle( $par ); 00484 $url = $title->getFullURL( $query ); 00485 $context->getOutput()->redirect( $url ); 00486 wfProfileOut( __METHOD__ ); 00487 00488 return $title; 00489 } else { 00490 $context->setTitle( $page->getPageTitle( $par ) ); 00491 } 00492 } elseif ( !$page->isIncludable() ) { 00493 wfProfileOut( __METHOD__ ); 00494 00495 return false; 00496 } 00497 00498 $page->including( $including ); 00499 00500 // Execute special page 00501 $profName = 'Special:' . $page->getName(); 00502 wfProfileIn( $profName ); 00503 $page->run( $par ); 00504 wfProfileOut( $profName ); 00505 wfProfileOut( __METHOD__ ); 00506 00507 return true; 00508 } 00509 00524 static function capturePath( Title $title, IContextSource $context ) { 00525 global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang; 00526 00527 // Save current globals 00528 $oldTitle = $wgTitle; 00529 $oldOut = $wgOut; 00530 $oldRequest = $wgRequest; 00531 $oldUser = $wgUser; 00532 $oldLang = $wgLang; 00533 00534 // Set the globals to the current context 00535 $wgTitle = $title; 00536 $wgOut = $context->getOutput(); 00537 $wgRequest = $context->getRequest(); 00538 $wgUser = $context->getUser(); 00539 $wgLang = $context->getLanguage(); 00540 00541 // The useful part 00542 $ret = self::executePath( $title, $context, true ); 00543 00544 // And restore the old globals 00545 $wgTitle = $oldTitle; 00546 $wgOut = $oldOut; 00547 $wgRequest = $oldRequest; 00548 $wgUser = $oldUser; 00549 $wgLang = $oldLang; 00550 00551 return $ret; 00552 } 00553 00561 static function getLocalNameFor( $name, $subpage = false ) { 00562 global $wgContLang; 00563 $aliases = $wgContLang->getSpecialPageAliases(); 00564 00565 if ( isset( $aliases[$name][0] ) ) { 00566 $name = $aliases[$name][0]; 00567 } else { 00568 // Try harder in case someone misspelled the correct casing 00569 $found = false; 00570 foreach ( $aliases as $n => $values ) { 00571 if ( strcasecmp( $name, $n ) === 0 ) { 00572 wfWarn( "Found alias defined for $n when searching for " . 00573 "special page aliases for $name. Case mismatch?" ); 00574 $name = $values[0]; 00575 $found = true; 00576 break; 00577 } 00578 } 00579 if ( !$found ) { 00580 wfWarn( "Did not find alias for special page '$name'. " . 00581 "Perhaps no aliases are defined for it?" ); 00582 } 00583 } 00584 if ( $subpage !== false && !is_null( $subpage ) ) { 00585 $name = "$name/$subpage"; 00586 } 00587 00588 return $wgContLang->ucfirst( $name ); 00589 } 00590 00597 static function getTitleForAlias( $alias ) { 00598 $name = self::resolveAlias( $alias ); 00599 if ( $name ) { 00600 return SpecialPage::getTitleFor( $name ); 00601 } else { 00602 return null; 00603 } 00604 } 00605 }