From: mainframe98 Date: Fri, 6 Sep 2019 09:21:29 +0000 (+0200) Subject: Support the creation of special pages with services injected X-Git-Tag: 1.34.0-rc.0~321^2 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=b7b490e46db294b5ebae8e79a0fdc79cb3aace98 Support the creation of special pages with services injected Now that the ObjectFactory library supports object creation with services (T222409), the special page factory can use the object factory to create special pages based off a spec, allowing the creation of special pages that need services injected. The object factory now also handles constructing from class name and from callable. This also deprecates providing the special page list with an instance of SpecialPage, which hasn't been necessary since r15031. Bug: T222388 Change-Id: Iabb78ce5c98cfb3b586644be35d984871cb750cb --- diff --git a/RELEASE-NOTES-1.34 b/RELEASE-NOTES-1.34 index aaf4d78fea..eaabd2f352 100644 --- a/RELEASE-NOTES-1.34 +++ b/RELEASE-NOTES-1.34 @@ -117,6 +117,9 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false; GetBlockedStatus. * ObjectFactory is available as a service. When used as a service, the object specs can now specify needed DI services. +* (T222388) Special pages can now be specified as an ObjectFactory spec, + allowing the construction of special pages that require services to be + injected in their constructor. === External library changes in 1.34 === @@ -492,6 +495,9 @@ because of Phabricator reports. or extend RevisionSearchResult. * Skin::getSkinNameMessages() is deprecated and no longer used. * The mediawiki.RegExp module is deprecated; use mw.util.escapeRegExp() instead. +* Specifying a SpecialPage object for the list of special pages (either through + the SpecialPage_initList hook or by adding to $wgSpecialPages) is now + deprecated. === Other changes in 1.34 === * … diff --git a/docs/extension.schema.v1.json b/docs/extension.schema.v1.json index 9ce016f063..06701cdbd4 100644 --- a/docs/extension.schema.v1.json +++ b/docs/extension.schema.v1.json @@ -640,7 +640,7 @@ }, "SpecialPages": { "type": "object", - "description": "SpecialPages implemented in this extension (mapping of page name to class name)" + "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)" }, "AutoloadNamespaces": { "type": "object", diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json index 9d874f47f4..56d274bbc4 100644 --- a/docs/extension.schema.v2.json +++ b/docs/extension.schema.v2.json @@ -710,7 +710,7 @@ }, "SpecialPages": { "type": "object", - "description": "SpecialPages implemented in this extension (mapping of page name to class name)" + "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)" }, "AutoloadNamespaces": { "type": "object", diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 740377c027..f42ef31f05 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -734,7 +734,8 @@ return [ return new SpecialPageFactory( new ServiceOptions( SpecialPageFactory::$constructorOptions, $services->getMainConfig() ), - $services->getContentLanguage() + $services->getContentLanguage(), + $services->getObjectFactory() ); }, diff --git a/includes/specialpage/SpecialPageFactory.php b/includes/specialpage/SpecialPageFactory.php index 8134c9a829..2737e356a0 100644 --- a/includes/specialpage/SpecialPageFactory.php +++ b/includes/specialpage/SpecialPageFactory.php @@ -34,6 +34,7 @@ use RequestContext; use SpecialPage; use Title; use User; +use Wikimedia\ObjectFactory; /** * Factory for handling the special page list and generating SpecialPage objects. @@ -221,6 +222,9 @@ class SpecialPageFactory { /** @var Language */ private $contLang; + /** @var ObjectFactory */ + private $objectFactory; + /** * TODO Make this a const when HHVM support is dropped (T192166) * @@ -241,11 +245,17 @@ class SpecialPageFactory { /** * @param ServiceOptions $options * @param Language $contLang + * @param ObjectFactory $objectFactory */ - public function __construct( ServiceOptions $options, Language $contLang ) { + public function __construct( + ServiceOptions $options, + Language $contLang, + ObjectFactory $objectFactory + ) { $options->assertRequiredOptions( self::$constructorOptions ); $this->options = $options; $this->contLang = $contLang; + $this->objectFactory = $objectFactory; } /** @@ -412,14 +422,22 @@ class SpecialPageFactory { if ( isset( $specialPageList[$realName] ) ) { $rec = $specialPageList[$realName]; - if ( is_callable( $rec ) ) { - // Use callback to instantiate the special page - $page = $rec(); - } elseif ( is_string( $rec ) ) { - $className = $rec; - $page = new $className; - } elseif ( $rec instanceof SpecialPage ) { + if ( $rec instanceof SpecialPage ) { + wfDeprecated( + "a SpecialPage instance (for $realName) in " . + '$wgSpecialPages or from the SpecialPage_initList hook', + '1.34' + ); + $page = $rec; // XXX: we should deep clone here + } elseif ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) { + $page = $this->objectFactory->createObject( + $rec, + [ + 'allowClassName' => true, + 'allowCallable' => true + ] + ); } else { $page = null; } diff --git a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php index c0376ad05e..a5d5946b8f 100644 --- a/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php +++ b/tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php @@ -60,6 +60,10 @@ class SpecialPageFactoryTest extends MediaWikiTestCase { 'callback array' => [ [ 'SpecialPageTestHelper', 'newSpecialAllPages' ], false + ], + 'object factory spec' => [ + [ 'class' => SpecialAllPages::class ], + false ] ]; } @@ -264,4 +268,29 @@ class SpecialPageFactoryTest extends MediaWikiTestCase { $this->assertTrue( $called, 'Recursive call succeeded' ); } + /** + * @covers \MediaWiki\Special\SpecialPageFactory::getPage + */ + public function testSpecialPageCreationThatRequiresService() { + $type = null; + + $this->setMwGlobals( 'wgSpecialPages', + [ 'TestPage' => [ + 'factory' => function ( $spf ) use ( &$type ) { + $type = get_class( $spf ); + + return new class() extends SpecialPage { + + }; + }, + 'services' => [ + 'SpecialPageFactory' + ] + ] ] + ); + + SpecialPageFactory::getPage( 'TestPage' ); + + $this->assertEquals( \MediaWiki\Special\SpecialPageFactory::class, $type ); + } }