Merge "API: HTMLize and internationalize the help, add Special:ApiHelp"
[lhc/web/wiklou.git] / includes / specialpage / SpecialPageFactory.php
index 3b20161..febd119 100644 (file)
@@ -47,7 +47,7 @@ class SpecialPageFactory {
        /**
         * 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',
@@ -59,7 +59,7 @@ class SpecialPageFactory {
                'Withoutinterwiki' => 'WithoutInterwikiPage',
                'Protectedpages' => 'SpecialProtectedpages',
                'Protectedtitles' => 'SpecialProtectedtitles',
-               'Shortpages' => 'ShortpagesPage',
+               'Shortpages' => 'ShortPagesPage',
                'Uncategorizedcategories' => 'UncategorizedCategoriesPage',
                'Uncategorizedimages' => 'UncategorizedImagesPage',
                'Uncategorizedpages' => 'UncategorizedPagesPage',
@@ -74,7 +74,7 @@ class SpecialPageFactory {
                'Wantedtemplates' => 'WantedTemplatesPage',
 
                // List of pages
-               'Allpages' => 'SpecialAllpages',
+               'Allpages' => 'SpecialAllPages',
                'Prefixindex' => 'SpecialPrefixindex',
                'Categories' => 'SpecialCategories',
                'Listredirects' => 'ListredirectsPage',
@@ -123,7 +123,7 @@ class SpecialPageFactory {
 
                // Data and tools
                'Statistics' => 'SpecialStatistics',
-               'Allmessages' => 'SpecialAllmessages',
+               'Allmessages' => 'SpecialAllMessages',
                'Version' => 'SpecialVersion',
                'Lockdb' => 'SpecialLockdb',
                'Unlockdb' => 'SpecialUnlockdb',
@@ -175,6 +175,7 @@ class SpecialPageFactory {
                'Userlogout' => 'SpecialUserlogout',
        );
 
+       private static $list;
        private static $aliases;
 
        /**
@@ -218,9 +219,11 @@ class SpecialPageFactory {
                global $wgEnableEmail, $wgEnableJavaScriptTest;
                global $wgPageLanguageUseDB;
 
-               if ( !is_object( self::$list ) ) {
+               if ( !is_array( self::$list ) ) {
                        wfProfileIn( __METHOD__ );
 
+                       self::$list = self::$coreList;
+
                        if ( !$wgDisableCounters ) {
                                self::$list['Popularpages'] = 'PopularPagesPage';
                        }
@@ -263,32 +266,55 @@ class SpecialPageFactory {
 
        /**
         * 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;
@@ -381,12 +407,12 @@ class SpecialPageFactory {
                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
@@ -621,29 +647,42 @@ class SpecialPageFactory {
        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";
                }