From e8419973ef0c8cd6ff8969060abe2d4985d81770 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Tue, 30 Sep 2014 23:20:04 -0400 Subject: [PATCH] Fix SpecialPageFactory list handling * Since Ic917c7d8/I7420b9ec, SpecialPageFactory doesn't properly cache SpecialPageFactory::$list. * SpecialPageFactory::resetList() has never really worked right, it loses all the core special pages. * SpecialPageFactory::getAliasListObject() could be called recursively from a SpecialPage_initList hook. There's no particular reason to fail it, just allow the original call to override the result of the recursive one and hope it works. Change-Id: I7adb346eab00d5849d087ddff75230a35be3ee8f --- includes/specialpage/SpecialPageFactory.php | 10 ++++-- .../specialpage/SpecialPageFactoryTest.php | 34 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/includes/specialpage/SpecialPageFactory.php b/includes/specialpage/SpecialPageFactory.php index e0a0f46410..9a6b787d2f 100644 --- a/includes/specialpage/SpecialPageFactory.php +++ b/includes/specialpage/SpecialPageFactory.php @@ -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', @@ -174,6 +174,7 @@ class SpecialPageFactory { 'Userlogout' => 'SpecialUserlogout', ); + private static $list; private static $aliases; /** @@ -217,9 +218,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'; } @@ -271,12 +274,13 @@ class SpecialPageFactory { if ( !is_object( self::$aliases ) ) { global $wgContLang; $aliases = $wgContLang->getSpecialPageAliases(); + $pageList = self::getPageList(); self::$aliases = array(); $keepAlias = array(); // Force every canonical name to be an alias for itself. - foreach ( self::getPageList() as $name => $stuff ) { + foreach ( $pageList as $name => $stuff ) { $caseFoldedAlias = $wgContLang->caseFold( $name ); self::$aliases[$caseFoldedAlias] = $name; $keepAlias[$caseFoldedAlias] = 'canonical'; diff --git a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php index 42602dcbef..cb122732de 100644 --- a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php +++ b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php @@ -28,6 +28,25 @@ class SpecialPageFactoryTest extends MediaWikiTestCase { SpecialPageFactory::resetList(); } + public function testResetList() { + SpecialPageFactory::resetList(); + $this->assertContains( 'Specialpages', SpecialPageFactory::getNames() ); + } + + public function testHookNotCalledTwice() { + $count = 0; + $this->mergeMwGlobalArrayValue( 'wgHooks', array( + 'SpecialPage_initList' => array( + function () use ( &$count ) { + $count++; + } + ) ) ); + SpecialPageFactory::resetList(); + SpecialPageFactory::getNames(); + SpecialPageFactory::getNames(); + $this->assertEquals( 1, $count ); + } + public function newSpecialAllPages() { return new SpecialAllPages(); } @@ -235,4 +254,19 @@ class SpecialPageFactoryTest extends MediaWikiTestCase { ); } + public function testGetAliasListRecursion() { + $called = false; + $this->mergeMwGlobalArrayValue( 'wgHooks', array( + 'SpecialPage_initList' => array( + function () use ( &$called ) { + SpecialPageFactory::getLocalNameFor( 'Specialpages' ); + $called = true; + } + ), + ) ); + SpecialPageFactory::resetList(); + SpecialPageFactory::getLocalNameFor( 'Specialpages' ); + $this->assertTrue( $called, 'Recursive call succeeded' ); + } + } -- 2.20.1