MediaWiki
master
|
00001 <?php 00046 class SpecialPageFactory { 00047 00051 private static $mList = array( 00052 // Maintenance Reports 00053 'BrokenRedirects' => 'BrokenRedirectsPage', 00054 'Deadendpages' => 'DeadendpagesPage', 00055 'DoubleRedirects' => 'DoubleRedirectsPage', 00056 'Longpages' => 'LongpagesPage', 00057 'Ancientpages' => 'AncientpagesPage', 00058 'Lonelypages' => 'LonelypagesPage', 00059 'Fewestrevisions' => 'FewestrevisionsPage', 00060 'Withoutinterwiki' => 'WithoutinterwikiPage', 00061 'Protectedpages' => 'SpecialProtectedpages', 00062 'Protectedtitles' => 'SpecialProtectedtitles', 00063 'Shortpages' => 'ShortpagesPage', 00064 'Uncategorizedcategories' => 'UncategorizedcategoriesPage', 00065 'Uncategorizedimages' => 'UncategorizedimagesPage', 00066 'Uncategorizedpages' => 'UncategorizedpagesPage', 00067 'Uncategorizedtemplates' => 'UncategorizedtemplatesPage', 00068 'Unusedcategories' => 'UnusedcategoriesPage', 00069 'Unusedimages' => 'UnusedimagesPage', 00070 'Unusedtemplates' => 'UnusedtemplatesPage', 00071 'Unwatchedpages' => 'UnwatchedpagesPage', 00072 'Wantedcategories' => 'WantedcategoriesPage', 00073 'Wantedfiles' => 'WantedfilesPage', 00074 'Wantedpages' => 'WantedpagesPage', 00075 'Wantedtemplates' => 'WantedtemplatesPage', 00076 00077 // List of pages 00078 'Allpages' => 'SpecialAllpages', 00079 'Prefixindex' => 'SpecialPrefixindex', 00080 'Categories' => 'SpecialCategories', 00081 'Disambiguations' => 'DisambiguationsPage', 00082 'Listredirects' => 'ListredirectsPage', 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 'Contributions' => 'SpecialContributions', 00097 'Listgrouprights' => 'SpecialListGroupRights', 00098 'Listusers' => 'SpecialListUsers' , 00099 'Listadmins' => 'SpecialListAdmins', 00100 'Listbots' => 'SpecialListBots', 00101 'Activeusers' => 'SpecialActiveUsers', 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 00122 // Wiki data and tools 00123 'Statistics' => 'SpecialStatistics', 00124 'Allmessages' => 'SpecialAllmessages', 00125 'Version' => 'SpecialVersion', 00126 'Lockdb' => 'SpecialLockdb', 00127 'Unlockdb' => 'SpecialUnlockdb', 00128 00129 // Redirecting special pages 00130 'LinkSearch' => 'LinkSearchPage', 00131 'Randompage' => 'Randompage', 00132 'Randomredirect' => 'SpecialRandomredirect', 00133 00134 // High use pages 00135 'Mostlinkedcategories' => 'MostlinkedCategoriesPage', 00136 'Mostimages' => 'MostimagesPage', 00137 'Mostinterwikis' => 'MostinterwikisPage', 00138 'Mostlinked' => 'MostlinkedPage', 00139 'Mostlinkedtemplates' => 'MostlinkedTemplatesPage', 00140 'Mostcategories' => 'MostcategoriesPage', 00141 'Mostrevisions' => 'MostrevisionsPage', 00142 00143 // Page tools 00144 'ComparePages' => 'SpecialComparePages', 00145 'Export' => 'SpecialExport', 00146 'Import' => 'SpecialImport', 00147 'Undelete' => 'SpecialUndelete', 00148 'Whatlinkshere' => 'SpecialWhatlinkshere', 00149 'MergeHistory' => 'SpecialMergeHistory', 00150 00151 // Other 00152 'Booksources' => 'SpecialBookSources', 00153 00154 // Unlisted / redirects 00155 'Blankpage' => 'SpecialBlankpage', 00156 'Blockme' => 'SpecialBlockme', 00157 'Emailuser' => 'SpecialEmailUser', 00158 'Movepage' => 'MovePageForm', 00159 'Mycontributions' => 'SpecialMycontributions', 00160 'Mypage' => 'SpecialMypage', 00161 'Mytalk' => 'SpecialMytalk', 00162 'Myuploads' => 'SpecialMyuploads', 00163 'PermanentLink' => 'SpecialPermanentLink', 00164 'Revisiondelete' => 'SpecialRevisionDelete', 00165 'Specialpages' => 'SpecialSpecialpages', 00166 'Userlogout' => 'SpecialUserlogout', 00167 ); 00168 00169 private static $mAliases; 00170 00177 static function getList() { 00178 global $wgSpecialPages; 00179 global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication; 00180 global $wgEnableEmail, $wgEnableJavaScriptTest; 00181 00182 if ( !is_object( self::$mList ) ) { 00183 wfProfileIn( __METHOD__ ); 00184 00185 if ( !$wgDisableCounters ) { 00186 self::$mList['Popularpages'] = 'PopularpagesPage'; 00187 } 00188 00189 if ( !$wgDisableInternalSearch ) { 00190 self::$mList['Search'] = 'SpecialSearch'; 00191 } 00192 00193 if ( $wgEmailAuthentication ) { 00194 self::$mList['Confirmemail'] = 'EmailConfirmation'; 00195 self::$mList['Invalidateemail'] = 'EmailInvalidation'; 00196 } 00197 00198 if ( $wgEnableEmail ) { 00199 self::$mList['ChangeEmail'] = 'SpecialChangeEmail'; 00200 } 00201 00202 if( $wgEnableJavaScriptTest ) { 00203 self::$mList['JavaScriptTest'] = 'SpecialJavaScriptTest'; 00204 } 00205 00206 // Add extension special pages 00207 self::$mList = array_merge( self::$mList, $wgSpecialPages ); 00208 00209 // Run hooks 00210 // This hook can be used to remove undesired built-in special pages 00211 wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) ); 00212 00213 // Cast to object: func()[$key] doesn't work, but func()->$key does 00214 settype( self::$mList, 'object' ); 00215 00216 wfProfileOut( __METHOD__ ); 00217 } 00218 return self::$mList; 00219 } 00220 00229 static function getAliasList() { 00230 if ( !is_object( self::$mAliases ) ) { 00231 global $wgContLang; 00232 $aliases = $wgContLang->getSpecialPageAliases(); 00233 00234 // Objects are passed by reference by default, need to create a copy 00235 $missingPages = clone self::getList(); 00236 00237 self::$mAliases = array(); 00238 foreach ( $aliases as $realName => $aliasList ) { 00239 foreach ( $aliasList as $alias ) { 00240 self::$mAliases[$wgContLang->caseFold( $alias )] = $realName; 00241 } 00242 unset( $missingPages->$realName ); 00243 } 00244 foreach ( $missingPages as $name => $stuff ) { 00245 self::$mAliases[$wgContLang->caseFold( $name )] = $name; 00246 } 00247 00248 // Cast to object: func()[$key] doesn't work, but func()->$key does 00249 self::$mAliases = (object)self::$mAliases; 00250 } 00251 return self::$mAliases; 00252 } 00253 00262 public static function resolveAlias( $alias ) { 00263 global $wgContLang; 00264 $bits = explode( '/', $alias, 2 ); 00265 00266 $caseFoldedAlias = $wgContLang->caseFold( $bits[0] ); 00267 $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias ); 00268 if ( isset( self::getAliasList()->$caseFoldedAlias ) ) { 00269 $name = self::getAliasList()->$caseFoldedAlias; 00270 } else { 00271 return array( null, null ); 00272 } 00273 00274 if ( !isset( $bits[1] ) ) { // bug 2087 00275 $par = null; 00276 } else { 00277 $par = $bits[1]; 00278 } 00279 00280 return array( $name, $par ); 00281 } 00282 00289 public static function setGroup( $page, $group ) { 00290 global $wgSpecialPageGroups; 00291 $name = is_object( $page ) ? $page->getName() : $page; 00292 $wgSpecialPageGroups[$name] = $group; 00293 } 00294 00301 public static function getGroup( &$page ) { 00302 $name = $page->getName(); 00303 00304 global $wgSpecialPageGroups; 00305 static $specialPageGroupsCache = array(); 00306 if ( isset( $specialPageGroupsCache[$name] ) ) { 00307 return $specialPageGroupsCache[$name]; 00308 } 00309 $msg = wfMessage( 'specialpages-specialpagegroup-' . strtolower( $name ) ); 00310 if ( !$msg->isBlank() ) { 00311 $group = $msg->text(); 00312 } else { 00313 $group = isset( $wgSpecialPageGroups[$name] ) 00314 ? $wgSpecialPageGroups[$name] 00315 : '-'; 00316 } 00317 if ( $group == '-' ) { 00318 $group = 'other'; 00319 } 00320 $specialPageGroupsCache[$name] = $group; 00321 return $group; 00322 } 00323 00330 public static function exists( $name ) { 00331 list( $title, /*...*/ ) = self::resolveAlias( $name ); 00332 return property_exists( self::getList(), $title ); 00333 } 00334 00341 public static function getPage( $name ) { 00342 list( $realName, /*...*/ ) = self::resolveAlias( $name ); 00343 if ( property_exists( self::getList(), $realName ) ) { 00344 $rec = self::getList()->$realName; 00345 if ( is_string( $rec ) ) { 00346 $className = $rec; 00347 return new $className; 00348 } elseif ( is_array( $rec ) ) { 00349 // @deprecated, officially since 1.18, unofficially since forever 00350 wfDebug( "Array syntax for \$wgSpecialPages is deprecated, define a subclass of SpecialPage instead." ); 00351 $className = array_shift( $rec ); 00352 self::getList()->$realName = MWFunction::newObj( $className, $rec ); 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->isListed() 00378 && ( !$page->isRestricted() || $page->userCanExecute( $user ) ) 00379 ) { 00380 $pages[$name] = $page; 00381 } 00382 } 00383 return $pages; 00384 } 00385 00391 public static function getRegularPages() { 00392 $pages = array(); 00393 foreach ( self::getList() as $name => $rec ) { 00394 $page = self::getPage( $name ); 00395 if ( $page->isListed() && !$page->isRestricted() ) { 00396 $pages[$name] = $page; 00397 } 00398 } 00399 return $pages; 00400 } 00401 00408 public static function getRestrictedPages() { 00409 global $wgUser; 00410 $pages = array(); 00411 foreach ( self::getList() as $name => $rec ) { 00412 $page = self::getPage( $name ); 00413 if ( 00414 $page->isListed() 00415 && $page->isRestricted() 00416 && $page->userCanExecute( $wgUser ) 00417 ) { 00418 $pages[$name] = $page; 00419 } 00420 } 00421 return $pages; 00422 } 00423 00438 public static function executePath( Title &$title, IContextSource &$context, $including = false ) { 00439 wfProfileIn( __METHOD__ ); 00440 00441 // @todo FIXME: Redirects broken due to this call 00442 $bits = explode( '/', $title->getDBkey(), 2 ); 00443 $name = $bits[0]; 00444 if ( !isset( $bits[1] ) ) { // bug 2087 00445 $par = null; 00446 } else { 00447 $par = $bits[1]; 00448 } 00449 $page = self::getPage( $name ); 00450 // Nonexistent? 00451 if ( !$page ) { 00452 $context->getOutput()->setArticleRelated( false ); 00453 $context->getOutput()->setRobotPolicy( 'noindex,nofollow' ); 00454 00455 global $wgSend404Code; 00456 if ( $wgSend404Code ) { 00457 $context->getOutput()->setStatusCode( 404 ); 00458 } 00459 00460 $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); 00461 wfProfileOut( __METHOD__ ); 00462 return false; 00463 } 00464 00465 // Page exists, set the context 00466 $page->setContext( $context ); 00467 00468 if ( !$including ) { 00469 // Redirect to canonical alias for GET commands 00470 // Not for POST, we'd lose the post data, so it's best to just distribute 00471 // the request. Such POST requests are possible for old extensions that 00472 // generate self-links without being aware that their default name has 00473 // changed. 00474 if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) { 00475 $query = $context->getRequest()->getQueryValues(); 00476 unset( $query['title'] ); 00477 $query = wfArrayToCGI( $query ); 00478 $title = $page->getTitle( $par ); 00479 $url = $title->getFullUrl( $query ); 00480 $context->getOutput()->redirect( $url ); 00481 wfProfileOut( __METHOD__ ); 00482 return $title; 00483 } else { 00484 $context->setTitle( $page->getTitle( $par ) ); 00485 } 00486 00487 } elseif ( !$page->isIncludable() ) { 00488 wfProfileOut( __METHOD__ ); 00489 return false; 00490 } 00491 00492 $page->including( $including ); 00493 00494 // Execute special page 00495 $profName = 'Special:' . $page->getName(); 00496 wfProfileIn( $profName ); 00497 $page->run( $par ); 00498 wfProfileOut( $profName ); 00499 wfProfileOut( __METHOD__ ); 00500 return true; 00501 } 00502 00518 static function capturePath( Title $title, IContextSource $context ) { 00519 global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang; 00520 00521 // Save current globals 00522 $oldTitle = $wgTitle; 00523 $oldOut = $wgOut; 00524 $oldRequest = $wgRequest; 00525 $oldUser = $wgUser; 00526 $oldLang = $wgLang; 00527 00528 // Set the globals to the current context 00529 $wgTitle = $title; 00530 $wgOut = $context->getOutput(); 00531 $wgRequest = $context->getRequest(); 00532 $wgUser = $context->getUser(); 00533 $wgLang = $context->getLanguage(); 00534 00535 // The useful part 00536 $ret = self::executePath( $title, $context, true ); 00537 00538 // And restore the old globals 00539 $wgTitle = $oldTitle; 00540 $wgOut = $oldOut; 00541 $wgRequest = $oldRequest; 00542 $wgUser = $oldUser; 00543 $wgLang = $oldLang; 00544 00545 return $ret; 00546 } 00547 00556 static function getLocalNameFor( $name, $subpage = false ) { 00557 global $wgContLang; 00558 $aliases = $wgContLang->getSpecialPageAliases(); 00559 00560 if ( isset( $aliases[$name][0] ) ) { 00561 $name = $aliases[$name][0]; 00562 } else { 00563 // Try harder in case someone misspelled the correct casing 00564 $found = false; 00565 foreach ( $aliases as $n => $values ) { 00566 if ( strcasecmp( $name, $n ) === 0 ) { 00567 wfWarn( "Found alias defined for $n when searching for " . 00568 "special page aliases for $name. Case mismatch?" ); 00569 $name = $values[0]; 00570 $found = true; 00571 break; 00572 } 00573 } 00574 if ( !$found ) { 00575 wfWarn( "Did not find alias for special page '$name'. " . 00576 "Perhaps no aliases are defined for it?" ); 00577 } 00578 } 00579 if ( $subpage !== false && !is_null( $subpage ) ) { 00580 $name = "$name/$subpage"; 00581 } 00582 return $wgContLang->ucfirst( $name ); 00583 } 00584 00592 static function getTitleForAlias( $alias ) { 00593 $name = self::resolveAlias( $alias ); 00594 if ( $name ) { 00595 return SpecialPage::getTitleFor( $name ); 00596 } else { 00597 return null; 00598 } 00599 } 00600 }