MediaWiki
REL1_19
|
00001 <?php 00030 class SpecialPageFactory { 00031 00035 private static $mList = array( 00036 // Maintenance Reports 00037 'BrokenRedirects' => 'BrokenRedirectsPage', 00038 'Deadendpages' => 'DeadendpagesPage', 00039 'DoubleRedirects' => 'DoubleRedirectsPage', 00040 'Longpages' => 'LongpagesPage', 00041 'Ancientpages' => 'AncientpagesPage', 00042 'Lonelypages' => 'LonelypagesPage', 00043 'Fewestrevisions' => 'FewestrevisionsPage', 00044 'Withoutinterwiki' => 'WithoutinterwikiPage', 00045 'Protectedpages' => 'SpecialProtectedpages', 00046 'Protectedtitles' => 'SpecialProtectedtitles', 00047 'Shortpages' => 'ShortpagesPage', 00048 'Uncategorizedcategories' => 'UncategorizedcategoriesPage', 00049 'Uncategorizedimages' => 'UncategorizedimagesPage', 00050 'Uncategorizedpages' => 'UncategorizedpagesPage', 00051 'Uncategorizedtemplates' => 'UncategorizedtemplatesPage', 00052 'Unusedcategories' => 'UnusedcategoriesPage', 00053 'Unusedimages' => 'UnusedimagesPage', 00054 'Unusedtemplates' => 'UnusedtemplatesPage', 00055 'Unwatchedpages' => 'UnwatchedpagesPage', 00056 'Wantedcategories' => 'WantedcategoriesPage', 00057 'Wantedfiles' => 'WantedfilesPage', 00058 'Wantedpages' => 'WantedpagesPage', 00059 'Wantedtemplates' => 'WantedtemplatesPage', 00060 00061 // List of pages 00062 'Allpages' => 'SpecialAllpages', 00063 'Prefixindex' => 'SpecialPrefixindex', 00064 'Categories' => 'SpecialCategories', 00065 'Disambiguations' => 'DisambiguationsPage', 00066 'Listredirects' => 'ListredirectsPage', 00067 00068 // Login/create account 00069 'Userlogin' => 'LoginForm', 00070 'CreateAccount' => 'SpecialCreateAccount', 00071 00072 // Users and rights 00073 'Block' => 'SpecialBlock', 00074 'Unblock' => 'SpecialUnblock', 00075 'BlockList' => 'SpecialBlockList', 00076 'ChangePassword' => 'SpecialChangePassword', 00077 'PasswordReset' => 'SpecialPasswordReset', 00078 'DeletedContributions' => 'DeletedContributionsPage', 00079 'Preferences' => 'SpecialPreferences', 00080 'Contributions' => 'SpecialContributions', 00081 'Listgrouprights' => 'SpecialListGroupRights', 00082 'Listusers' => 'SpecialListUsers' , 00083 'Listadmins' => 'SpecialListAdmins', 00084 'Listbots' => 'SpecialListBots', 00085 'Activeusers' => 'SpecialActiveUsers', 00086 'Userrights' => 'UserrightsPage', 00087 'EditWatchlist' => 'SpecialEditWatchlist', 00088 00089 // Recent changes and logs 00090 'Newimages' => 'SpecialNewFiles', 00091 'Log' => 'SpecialLog', 00092 'Watchlist' => 'SpecialWatchlist', 00093 'Newpages' => 'SpecialNewpages', 00094 'Recentchanges' => 'SpecialRecentchanges', 00095 'Recentchangeslinked' => 'SpecialRecentchangeslinked', 00096 'Tags' => 'SpecialTags', 00097 00098 // Media reports and uploads 00099 'Listfiles' => 'SpecialListFiles', 00100 'Filepath' => 'SpecialFilepath', 00101 'MIMEsearch' => 'MIMEsearchPage', 00102 'FileDuplicateSearch' => 'FileDuplicateSearchPage', 00103 'Upload' => 'SpecialUpload', 00104 'UploadStash' => 'SpecialUploadStash', 00105 00106 // Wiki data and tools 00107 'Statistics' => 'SpecialStatistics', 00108 'Allmessages' => 'SpecialAllmessages', 00109 'Version' => 'SpecialVersion', 00110 'Lockdb' => 'SpecialLockdb', 00111 'Unlockdb' => 'SpecialUnlockdb', 00112 00113 // Redirecting special pages 00114 'LinkSearch' => 'LinkSearchPage', 00115 'Randompage' => 'Randompage', 00116 'Randomredirect' => 'SpecialRandomredirect', 00117 00118 // High use pages 00119 'Mostlinkedcategories' => 'MostlinkedCategoriesPage', 00120 'Mostimages' => 'MostimagesPage', 00121 'Mostlinked' => 'MostlinkedPage', 00122 'Mostlinkedtemplates' => 'MostlinkedTemplatesPage', 00123 'Mostcategories' => 'MostcategoriesPage', 00124 'Mostrevisions' => 'MostrevisionsPage', 00125 00126 // Page tools 00127 'ComparePages' => 'SpecialComparePages', 00128 'Export' => 'SpecialExport', 00129 'Import' => 'SpecialImport', 00130 'Undelete' => 'SpecialUndelete', 00131 'Whatlinkshere' => 'SpecialWhatlinkshere', 00132 'MergeHistory' => 'SpecialMergeHistory', 00133 00134 // Other 00135 'Booksources' => 'SpecialBookSources', 00136 00137 // Unlisted / redirects 00138 'Blankpage' => 'SpecialBlankpage', 00139 'Blockme' => 'SpecialBlockme', 00140 'Emailuser' => 'SpecialEmailUser', 00141 'JavaScriptTest' => 'SpecialJavaScriptTest', 00142 'Movepage' => 'MovePageForm', 00143 'Mycontributions' => 'SpecialMycontributions', 00144 'Mypage' => 'SpecialMypage', 00145 'Mytalk' => 'SpecialMytalk', 00146 'Myuploads' => 'SpecialMyuploads', 00147 'PermanentLink' => 'SpecialPermanentLink', 00148 'Revisiondelete' => 'SpecialRevisionDelete', 00149 'Specialpages' => 'SpecialSpecialpages', 00150 'Userlogout' => 'SpecialUserlogout', 00151 ); 00152 00153 private static $mAliases; 00154 00161 static function getList() { 00162 global $wgSpecialPages; 00163 global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication; 00164 global $wgEnableEmail; 00165 00166 if ( !is_object( self::$mList ) ) { 00167 wfProfileIn( __METHOD__ ); 00168 00169 if ( !$wgDisableCounters ) { 00170 self::$mList['Popularpages'] = 'PopularpagesPage'; 00171 } 00172 00173 if ( !$wgDisableInternalSearch ) { 00174 self::$mList['Search'] = 'SpecialSearch'; 00175 } 00176 00177 if ( $wgEmailAuthentication ) { 00178 self::$mList['Confirmemail'] = 'EmailConfirmation'; 00179 self::$mList['Invalidateemail'] = 'EmailInvalidation'; 00180 } 00181 00182 if ( $wgEnableEmail ) { 00183 self::$mList['ChangeEmail'] = 'SpecialChangeEmail'; 00184 } 00185 00186 // Add extension special pages 00187 self::$mList = array_merge( self::$mList, $wgSpecialPages ); 00188 00189 // Run hooks 00190 // This hook can be used to remove undesired built-in special pages 00191 wfRunHooks( 'SpecialPage_initList', array( &self::$mList ) ); 00192 00193 // Cast to object: func()[$key] doesn't work, but func()->$key does 00194 settype( self::$mList, 'object' ); 00195 00196 wfProfileOut( __METHOD__ ); 00197 } 00198 return self::$mList; 00199 } 00200 00209 static function getAliasList() { 00210 if ( !is_object( self::$mAliases ) ) { 00211 global $wgContLang; 00212 $aliases = $wgContLang->getSpecialPageAliases(); 00213 00214 // Objects are passed by reference by default, need to create a copy 00215 $missingPages = clone self::getList(); 00216 00217 self::$mAliases = array(); 00218 foreach ( $aliases as $realName => $aliasList ) { 00219 foreach ( $aliasList as $alias ) { 00220 self::$mAliases[$wgContLang->caseFold( $alias )] = $realName; 00221 } 00222 unset( $missingPages->$realName ); 00223 } 00224 foreach ( $missingPages as $name => $stuff ) { 00225 self::$mAliases[$wgContLang->caseFold( $name )] = $name; 00226 } 00227 00228 // Cast to object: func()[$key] doesn't work, but func()->$key does 00229 self::$mAliases = (object)self::$mAliases; 00230 } 00231 return self::$mAliases; 00232 } 00233 00242 public static function resolveAlias( $alias ) { 00243 global $wgContLang; 00244 $bits = explode( '/', $alias, 2 ); 00245 00246 $caseFoldedAlias = $wgContLang->caseFold( $bits[0] ); 00247 $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias ); 00248 if ( isset( self::getAliasList()->$caseFoldedAlias ) ) { 00249 $name = self::getAliasList()->$caseFoldedAlias; 00250 } else { 00251 return array( null, null ); 00252 } 00253 00254 if ( !isset( $bits[1] ) ) { // bug 2087 00255 $par = null; 00256 } else { 00257 $par = $bits[1]; 00258 } 00259 00260 return array( $name, $par ); 00261 } 00262 00269 public static function setGroup( $page, $group ) { 00270 global $wgSpecialPageGroups; 00271 $name = is_object( $page ) ? $page->getName() : $page; 00272 $wgSpecialPageGroups[$name] = $group; 00273 } 00274 00280 public static function getGroup( &$page ) { 00281 $name = $page->getName(); 00282 00283 global $wgSpecialPageGroups; 00284 static $specialPageGroupsCache = array(); 00285 if ( isset( $specialPageGroupsCache[$name] ) ) { 00286 return $specialPageGroupsCache[$name]; 00287 } 00288 $msg = wfMessage( 'specialpages-specialpagegroup-' . strtolower( $name ) ); 00289 if ( !$msg->isBlank() ) { 00290 $group = $msg->text(); 00291 } else { 00292 $group = isset( $wgSpecialPageGroups[$name] ) 00293 ? $wgSpecialPageGroups[$name] 00294 : '-'; 00295 } 00296 if ( $group == '-' ) { 00297 $group = 'other'; 00298 } 00299 $specialPageGroupsCache[$name] = $group; 00300 return $group; 00301 } 00302 00309 public static function exists( $name ) { 00310 list( $title, /*...*/ ) = self::resolveAlias( $name ); 00311 return property_exists( self::getList(), $title ); 00312 } 00313 00320 public static function getPage( $name ) { 00321 list( $realName, /*...*/ ) = self::resolveAlias( $name ); 00322 if ( property_exists( self::getList(), $realName ) ) { 00323 $rec = self::getList()->$realName; 00324 if ( is_string( $rec ) ) { 00325 $className = $rec; 00326 return new $className; 00327 } elseif ( is_array( $rec ) ) { 00328 // @deprecated, officially since 1.18, unofficially since forever 00329 wfDebug( "Array syntax for \$wgSpecialPages is deprecated, define a subclass of SpecialPage instead." ); 00330 $className = array_shift( $rec ); 00331 self::getList()->$realName = MWFunction::newObj( $className, $rec ); 00332 } 00333 return self::getList()->$realName; 00334 } else { 00335 return null; 00336 } 00337 } 00338 00347 public static function getUsablePages( User $user = null ) { 00348 $pages = array(); 00349 if ( $user === null ) { 00350 global $wgUser; 00351 $user = $wgUser; 00352 } 00353 foreach ( self::getList() as $name => $rec ) { 00354 $page = self::getPage( $name ); 00355 if ( $page // not null 00356 && $page->isListed() 00357 && ( !$page->isRestricted() || $page->userCanExecute( $user ) ) 00358 ) { 00359 $pages[$name] = $page; 00360 } 00361 } 00362 return $pages; 00363 } 00364 00370 public static function getRegularPages() { 00371 $pages = array(); 00372 foreach ( self::getList() as $name => $rec ) { 00373 $page = self::getPage( $name ); 00374 if ( $page->isListed() && !$page->isRestricted() ) { 00375 $pages[$name] = $page; 00376 } 00377 } 00378 return $pages; 00379 } 00380 00387 public static function getRestrictedPages() { 00388 global $wgUser; 00389 $pages = array(); 00390 foreach ( self::getList() as $name => $rec ) { 00391 $page = self::getPage( $name ); 00392 if ( 00393 $page->isListed() 00394 && $page->isRestricted() 00395 && $page->userCanExecute( $wgUser ) 00396 ) { 00397 $pages[$name] = $page; 00398 } 00399 } 00400 return $pages; 00401 } 00402 00417 public static function executePath( Title &$title, IContextSource &$context, $including = false ) { 00418 wfProfileIn( __METHOD__ ); 00419 00420 // @todo FIXME: Redirects broken due to this call 00421 $bits = explode( '/', $title->getDBkey(), 2 ); 00422 $name = $bits[0]; 00423 if ( !isset( $bits[1] ) ) { // bug 2087 00424 $par = null; 00425 } else { 00426 $par = $bits[1]; 00427 } 00428 $page = self::getPage( $name ); 00429 // Nonexistent? 00430 if ( !$page ) { 00431 $context->getOutput()->setArticleRelated( false ); 00432 $context->getOutput()->setRobotPolicy( 'noindex,nofollow' ); 00433 00434 global $wgSend404Code; 00435 if ( $wgSend404Code ) { 00436 $context->getOutput()->setStatusCode( 404 ); 00437 } 00438 00439 $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); 00440 wfProfileOut( __METHOD__ ); 00441 return false; 00442 } 00443 00444 // Page exists, set the context 00445 $page->setContext( $context ); 00446 00447 if ( !$including ) { 00448 // Redirect to canonical alias for GET commands 00449 // Not for POST, we'd lose the post data, so it's best to just distribute 00450 // the request. Such POST requests are possible for old extensions that 00451 // generate self-links without being aware that their default name has 00452 // changed. 00453 if ( $name != $page->getLocalName() && !$context->getRequest()->wasPosted() ) { 00454 $query = $context->getRequest()->getQueryValues(); 00455 unset( $query['title'] ); 00456 $query = wfArrayToCGI( $query ); 00457 $title = $page->getTitle( $par ); 00458 $url = $title->getFullUrl( $query ); 00459 $context->getOutput()->redirect( $url ); 00460 wfProfileOut( __METHOD__ ); 00461 return $title; 00462 } else { 00463 $context->setTitle( $page->getTitle( $par ) ); 00464 } 00465 00466 } elseif ( !$page->isIncludable() ) { 00467 wfProfileOut( __METHOD__ ); 00468 return false; 00469 } 00470 00471 $page->including( $including ); 00472 00473 // Execute special page 00474 $profName = 'Special:' . $page->getName(); 00475 wfProfileIn( $profName ); 00476 $page->execute( $par ); 00477 wfProfileOut( $profName ); 00478 wfProfileOut( __METHOD__ ); 00479 return true; 00480 } 00481 00497 static function capturePath( Title $title, IContextSource $context ) { 00498 global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang; 00499 00500 // Save current globals 00501 $oldTitle = $wgTitle; 00502 $oldOut = $wgOut; 00503 $oldRequest = $wgRequest; 00504 $oldUser = $wgUser; 00505 $oldLang = $wgLang; 00506 00507 // Set the globals to the current context 00508 $wgTitle = $title; 00509 $wgOut = $context->getOutput(); 00510 $wgRequest = $context->getRequest(); 00511 $wgUser = $context->getUser(); 00512 $wgLang = $context->getLanguage(); 00513 00514 // The useful part 00515 $ret = self::executePath( $title, $context, true ); 00516 00517 // And restore the old globals 00518 $wgTitle = $oldTitle; 00519 $wgOut = $oldOut; 00520 $wgRequest = $oldRequest; 00521 $wgUser = $oldUser; 00522 $wgLang = $oldLang; 00523 00524 return $ret; 00525 } 00526 00535 static function getLocalNameFor( $name, $subpage = false ) { 00536 global $wgContLang; 00537 $aliases = $wgContLang->getSpecialPageAliases(); 00538 00539 if ( isset( $aliases[$name][0] ) ) { 00540 $name = $aliases[$name][0]; 00541 } else { 00542 // Try harder in case someone misspelled the correct casing 00543 $found = false; 00544 foreach ( $aliases as $n => $values ) { 00545 if ( strcasecmp( $name, $n ) === 0 ) { 00546 wfWarn( "Found alias defined for $n when searching for " . 00547 "special page aliases for $name. Case mismatch?" ); 00548 $name = $values[0]; 00549 $found = true; 00550 break; 00551 } 00552 } 00553 if ( !$found ) { 00554 wfWarn( "Did not find alias for special page '$name'. " . 00555 "Perhaps no aliases are defined for it?" ); 00556 } 00557 } 00558 if ( $subpage !== false && !is_null( $subpage ) ) { 00559 $name = "$name/$subpage"; 00560 } 00561 return $wgContLang->ucfirst( $name ); 00562 } 00563 00571 static function getTitleForAlias( $alias ) { 00572 $name = self::resolveAlias( $alias ); 00573 if ( $name ) { 00574 return SpecialPage::getTitleFor( $name ); 00575 } else { 00576 return null; 00577 } 00578 } 00579 }