/**
* List of special page names to the subclass of SpecialPage which handles them.
*/
- private static $list = array(
+ private static $coreList = array(
// Maintenance Reports
'BrokenRedirects' => 'BrokenRedirectsPage',
'Deadendpages' => 'DeadendPagesPage',
'Withoutinterwiki' => 'WithoutInterwikiPage',
'Protectedpages' => 'SpecialProtectedpages',
'Protectedtitles' => 'SpecialProtectedtitles',
- 'Shortpages' => 'ShortpagesPage',
+ 'Shortpages' => 'ShortPagesPage',
'Uncategorizedcategories' => 'UncategorizedCategoriesPage',
'Uncategorizedimages' => 'UncategorizedImagesPage',
'Uncategorizedpages' => 'UncategorizedPagesPage',
'Wantedtemplates' => 'WantedTemplatesPage',
// List of pages
- 'Allpages' => 'SpecialAllpages',
+ 'Allpages' => 'SpecialAllPages',
'Prefixindex' => 'SpecialPrefixindex',
'Categories' => 'SpecialCategories',
'Listredirects' => 'ListredirectsPage',
// Data and tools
'Statistics' => 'SpecialStatistics',
- 'Allmessages' => 'SpecialAllmessages',
+ 'Allmessages' => 'SpecialAllMessages',
'Version' => 'SpecialVersion',
'Lockdb' => 'SpecialLockdb',
'Unlockdb' => 'SpecialUnlockdb',
'Userlogout' => 'SpecialUserlogout',
);
+ private static $list;
private static $aliases;
/**
*/
private static function getPageList() {
global $wgSpecialPages;
- global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
+ global $wgDisableInternalSearch, $wgEmailAuthentication;
global $wgEnableEmail, $wgEnableJavaScriptTest;
global $wgPageLanguageUseDB;
- if ( !is_object( self::$list ) ) {
- wfProfileIn( __METHOD__ );
+ if ( !is_array( self::$list ) ) {
- if ( !$wgDisableCounters ) {
- self::$list['Popularpages'] = 'PopularPagesPage';
- }
+ self::$list = self::$coreList;
if ( !$wgDisableInternalSearch ) {
self::$list['Search'] = 'SpecialSearch';
// Run hooks
// This hook can be used to remove undesired built-in special pages
- wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
+ Hooks::run( 'SpecialPage_initList', array( &self::$list ) );
- wfProfileOut( __METHOD__ );
}
return self::$list;
/**
* Initialise and return the list of special page aliases. Returns an object with
- * properties which can be accessed $obj->pagename - each property is an array of
- * aliases; the first in the array is the canonical alias. All registered special
- * pages are guaranteed to have a property entry, and for that property array to
- * contain at least one entry (English fallbacks will be added if necessary).
+ * properties which can be accessed $obj->pagename - each property name is an
+ * alias, with the value being the canonical name of the special page. All
+ * registered special pages are guaranteed to map to themselves.
* @return object
*/
private static function getAliasListObject() {
if ( !is_object( self::$aliases ) ) {
global $wgContLang;
$aliases = $wgContLang->getSpecialPageAliases();
-
- $missingPages = self::getPageList();
+ $pageList = self::getPageList();
self::$aliases = array();
+ $keepAlias = array();
+
+ // Force every canonical name to be an alias for itself.
+ foreach ( $pageList as $name => $stuff ) {
+ $caseFoldedAlias = $wgContLang->caseFold( $name );
+ self::$aliases[$caseFoldedAlias] = $name;
+ $keepAlias[$caseFoldedAlias] = 'canonical';
+ }
+
// Check for $aliases being an array since Language::getSpecialPageAliases can return null
if ( is_array( $aliases ) ) {
foreach ( $aliases as $realName => $aliasList ) {
- foreach ( $aliasList as $alias ) {
- self::$aliases[$wgContLang->caseFold( $alias )] = $realName;
+ $aliasList = array_values( $aliasList );
+ foreach ( $aliasList as $i => $alias ) {
+ $caseFoldedAlias = $wgContLang->caseFold( $alias );
+
+ if ( isset( self::$aliases[$caseFoldedAlias] ) &&
+ $realName === self::$aliases[$caseFoldedAlias]
+ ) {
+ // Ignore same-realName conflicts
+ continue;
+ }
+
+ if ( !isset( $keepAlias[$caseFoldedAlias] ) ) {
+ self::$aliases[$caseFoldedAlias] = $realName;
+ if ( !$i ) {
+ $keepAlias[$caseFoldedAlias] = 'first';
+ }
+ } elseif ( !$i ) {
+ wfWarn( "First alias '$alias' for $realName conflicts with " .
+ "{$keepAlias[$caseFoldedAlias]} alias for " .
+ self::$aliases[$caseFoldedAlias]
+ );
+ }
}
- unset( $missingPages->$realName );
}
}
- foreach ( $missingPages as $name => $stuff ) {
- self::$aliases[$wgContLang->caseFold( $name )] = $name;
- }
// Cast to object: func()[$key] doesn't work, but func()->$key does
self::$aliases = (object)self::$aliases;
if ( isset( $specialPageList[$realName] ) ) {
$rec = $specialPageList[$realName];
- if ( is_string( $rec ) ) {
- $className = $rec;
- $page = new $className;
- } elseif ( is_callable( $rec ) ) {
+ if ( is_callable( $rec ) ) {
// Use callback to instantiate the special page
$page = call_user_func( $rec );
+ } elseif ( is_string( $rec ) ) {
+ $className = $rec;
+ $page = new $className;
} elseif ( is_array( $rec ) ) {
$className = array_shift( $rec );
// @deprecated, officially since 1.18, unofficially since forever
wfDeprecated( "Array syntax for \$wgSpecialPages is deprecated ($className), " .
"define a subclass of SpecialPage instead.", '1.18' );
- $page = MWFunction::newObj( $className, $rec );
+ $page = ObjectFactory::getObjectFromSpec( array(
+ 'class' => $className,
+ 'args' => $rec,
+ 'closure_expansion' => false,
+ ) );
} elseif ( $rec instanceof SpecialPage ) {
$page = $rec; //XXX: we should deep clone here
} else {
* @return bool
*/
public static function executePath( Title &$title, IContextSource &$context, $including = false ) {
- wfProfileIn( __METHOD__ );
// @todo FIXME: Redirects broken due to this call
$bits = explode( '/', $title->getDBkey(), 2 );
}
$context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
- wfProfileOut( __METHOD__ );
return false;
}
$title = $page->getPageTitle( $par );
$url = $title->getFullURL( $query );
$context->getOutput()->redirect( $url );
- wfProfileOut( __METHOD__ );
return $title;
} else {
$context->setTitle( $page->getPageTitle( $par ) );
}
} elseif ( !$page->isIncludable() ) {
- wfProfileOut( __METHOD__ );
return false;
}
$page->including( $including );
// Execute special page
- $profName = 'Special:' . $page->getName();
- wfProfileIn( $profName );
$page->run( $par );
- wfProfileOut( $profName );
- wfProfileOut( __METHOD__ );
return true;
}
public static function getLocalNameFor( $name, $subpage = false ) {
global $wgContLang;
$aliases = $wgContLang->getSpecialPageAliases();
+ $aliasList = self::getAliasListObject();
- if ( isset( $aliases[$name][0] ) ) {
- $name = $aliases[$name][0];
- } else {
- // Try harder in case someone misspelled the correct casing
+ // Find the first alias that maps back to $name
+ if ( isset( $aliases[$name] ) ) {
$found = false;
- // Check for $aliases being an array since Language::getSpecialPageAliases can return null
+ foreach ( $aliases[$name] as $alias ) {
+ $caseFoldedAlias = $wgContLang->caseFold( $alias );
+ $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
+ if ( isset( $aliasList->$caseFoldedAlias ) &&
+ $aliasList->$caseFoldedAlias === $name
+ ) {
+ $name = $alias;
+ $found = true;
+ break;
+ }
+ }
+ if ( !$found ) {
+ wfWarn( "Did not find a usable alias for special page '$name'. " .
+ "It seems all defined aliases conflict?" );
+ }
+ } else {
+ // Check if someone misspelled the correct casing
if ( is_array( $aliases ) ) {
foreach ( $aliases as $n => $values ) {
if ( strcasecmp( $name, $n ) === 0 ) {
wfWarn( "Found alias defined for $n when searching for " .
"special page aliases for $name. Case mismatch?" );
- $name = $values[0];
- $found = true;
- break;
+ return self::getLocalNameFor( $n, $subpage );
}
}
}
- if ( !$found ) {
- wfWarn( "Did not find alias for special page '$name'. " .
- "Perhaps no aliases are defined for it?" );
- }
+
+ wfWarn( "Did not find alias for special page '$name'. " .
+ "Perhaps no aliases are defined for it?" );
}
+
if ( $subpage !== false && !is_null( $subpage ) ) {
$name = "$name/$subpage";
}