Merge "Copy translations of Special:MyLanguage alias from Translate"
[lhc/web/wiklou.git] / includes / specialpage / SpecialPageFactory.php
index 07b6b4e..48bcb77 100644 (file)
@@ -114,6 +114,7 @@ class SpecialPageFactory {
                // Media reports and uploads
                'Listfiles' => 'SpecialListFiles',
                'Filepath' => 'SpecialFilepath',
+               'MediaStatistics' => 'MediaStatisticsPage',
                'MIMEsearch' => 'MIMEsearchPage',
                'FileDuplicateSearch' => 'FileDuplicateSearchPage',
                'Upload' => 'SpecialUpload',
@@ -176,11 +177,41 @@ class SpecialPageFactory {
        private static $aliases;
 
        /**
-        * Get the special page list
+        * Reset the internal list of special pages. Useful when changing $wgSpecialPages after
+        * the internal list has already been initialized, e.g. during testing.
+        */
+       public static function resetList() {
+               self::$list = null;
+               self::$aliases = null;
+       }
+
+       /**
+        * Returns a list of canonical special page names.
+        * May be used to iterate over all registered special pages.
         *
+        * @return string[]
+        */
+       public static function getNames() {
+               return array_keys( self::getPageList() );
+       }
+
+       /**
+        * Get the special page list as an array
+        *
+        * @deprecated since 1.24, use getNames() instead.
         * @return array
         */
-       static function getList() {
+       public static function getList() {
+               wfDeprecated( __FUNCTION__, '1.24' );
+               return self::getPageList();
+       }
+
+       /**
+        * Get the special page list as an array
+        *
+        * @return array
+        */
+       private static function getPageList() {
                global $wgSpecialPages;
                global $wgDisableCounters, $wgDisableInternalSearch, $wgEmailAuthentication;
                global $wgEnableEmail, $wgEnableJavaScriptTest;
@@ -223,9 +254,6 @@ class SpecialPageFactory {
                        // This hook can be used to remove undesired built-in special pages
                        wfRunHooks( 'SpecialPage_initList', array( &self::$list ) );
 
-                       // Cast to object: func()[$key] doesn't work, but func()->$key does
-                       settype( self::$list, 'object' );
-
                        wfProfileOut( __METHOD__ );
                }
 
@@ -240,13 +268,12 @@ class SpecialPageFactory {
         * contain at least one entry (English fallbacks will be added if necessary).
         * @return object
         */
-       static function getAliasList() {
+       private static function getAliasListObject() {
                if ( !is_object( self::$aliases ) ) {
                        global $wgContLang;
                        $aliases = $wgContLang->getSpecialPageAliases();
 
-                       // Objects are passed by reference by default, need to create a copy
-                       $missingPages = clone self::getList();
+                       $missingPages = self::getPageList();
 
                        self::$aliases = array();
                        // Check for $aliases being an array since Language::getSpecialPageAliases can return null
@@ -283,8 +310,8 @@ class SpecialPageFactory {
 
                $caseFoldedAlias = $wgContLang->caseFold( $bits[0] );
                $caseFoldedAlias = str_replace( ' ', '_', $caseFoldedAlias );
-               if ( isset( self::getAliasList()->$caseFoldedAlias ) ) {
-                       $name = self::getAliasList()->$caseFoldedAlias;
+               if ( isset( self::getAliasListObject()->$caseFoldedAlias ) ) {
+                       $name = self::getAliasListObject()->$caseFoldedAlias;
                } else {
                        return array( null, null );
                }
@@ -335,7 +362,8 @@ class SpecialPageFactory {
        public static function exists( $name ) {
                list( $title, /*...*/ ) = self::resolveAlias( $name );
 
-               return property_exists( self::getList(), $title );
+               $specialPageList = self::getPageList();
+               return isset( $specialPageList[$title] );
        }
 
        /**
@@ -346,21 +374,39 @@ class SpecialPageFactory {
         */
        public static function getPage( $name ) {
                list( $realName, /*...*/ ) = self::resolveAlias( $name );
-               if ( property_exists( self::getList(), $realName ) ) {
-                       $rec = self::getList()->$realName;
+
+               $specialPageList = self::getPageList();
+
+               if ( isset( $specialPageList[$realName] ) ) {
+                       $rec = $specialPageList[$realName];
+
                        if ( is_string( $rec ) ) {
                                $className = $rec;
-
-                               return new $className;
+                               $page = new $className;
+                       } elseif ( is_callable( $rec ) ) {
+                               // Use callback to instantiate the special page
+                               $page = call_user_func( $rec );
                        } 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' );
-                               self::getList()->$realName = MWFunction::newObj( $className, $rec );
+                               $page = MWFunction::newObj( $className, $rec );
+                       } elseif ( $rec instanceof SpecialPage ) {
+                               $page = $rec; //XXX: we should deep clone here
+                       } else {
+                               $page = null;
+                       }
+
+                       if ( $page instanceof SpecialPage ) {
+                               return $page;
+                       } else {
+                               // It's not a classname, nor a callback, nor a legacy constructor array,
+                               // nor a special page object. Give up.
+                               wfLogWarning( "Cannot instantiate special page $realName: bad spec!" );
+                               return null;
                        }
 
-                       return self::getList()->$realName;
                } else {
                        return null;
                }
@@ -380,7 +426,7 @@ class SpecialPageFactory {
                        global $wgUser;
                        $user = $wgUser;
                }
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getPageList() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if ( $page ) { // not null
                                $page->setContext( RequestContext::getMain() );
@@ -402,7 +448,7 @@ class SpecialPageFactory {
         */
        public static function getRegularPages() {
                $pages = array();
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getPageList() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if ( $page->isListed() && !$page->isRestricted() ) {
                                $pages[$name] = $page;
@@ -425,7 +471,7 @@ class SpecialPageFactory {
                        global $wgUser;
                        $user = $wgUser;
                }
-               foreach ( self::getList() as $name => $rec ) {
+               foreach ( self::getPageList() as $name => $rec ) {
                        $page = self::getPage( $name );
                        if (
                                $page->isListed()
@@ -534,7 +580,7 @@ class SpecialPageFactory {
         * @param IContextSource $context
         * @return string HTML fragment
         */
-       static function capturePath( Title $title, IContextSource $context ) {
+       public static function capturePath( Title $title, IContextSource $context ) {
                global $wgOut, $wgTitle, $wgRequest, $wgUser, $wgLang;
 
                // Save current globals
@@ -571,7 +617,7 @@ class SpecialPageFactory {
         * @param string|bool $subpage
         * @return string
         */
-       static function getLocalNameFor( $name, $subpage = false ) {
+       public static function getLocalNameFor( $name, $subpage = false ) {
                global $wgContLang;
                $aliases = $wgContLang->getSpecialPageAliases();
 
@@ -610,10 +656,10 @@ class SpecialPageFactory {
         * @param string $alias
         * @return Title|null Title or null if there is no such alias
         */
-       static function getTitleForAlias( $alias ) {
-               $name = self::resolveAlias( $alias );
-               if ( $name ) {
-                       return SpecialPage::getTitleFor( $name );
+       public static function getTitleForAlias( $alias ) {
+               list( $name, $subpage ) = self::resolveAlias( $alias );
+               if ( $name != null ) {
+                       return SpecialPage::getTitleFor( $name, $subpage );
                } else {
                        return null;
                }