From a11ad5f0b644760172ebbd7dbc110303929eff0e Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Wed, 21 Aug 2019 12:10:30 -0400 Subject: [PATCH] Add ObjectFactory as a service ObjectFactory exists to handle lazy instantiation of objects based on declarative specifications. One drawback to the current use of static ObjectFactory::getObjectFromSpec() is that it doesn't have a good way to handle dependency injection. The best you could do is refer to a static 'factory' function in your specification, and that function would access the global service container. But DI would prefer not to have that "global service container" being accessed. The solution is to have a non-static ObjectFactory that can supply the needed services based on the object definition. For example, [ 'class' => MyObject::class, 'services' => [ 'FooFactory', 'BarFactory' ], ] would get the FooFactory and BarFactory from a service container to pass into MyObject's constructor. But in order for that to be possible, you need to have an instance of ObjectFactory that has reference to the service container from which to fetch the services. And the most DI-correct way to get that is to have it dependency-injected into your constructor, at which point the ObjectFactory instance should itself be a service in the DI service container. Bug: T222409 Change-Id: I2a56059a9209abce0b22fb93c9f9c6a09a825c56 --- RELEASE-NOTES-1.34 | 2 ++ includes/MediaWikiServices.php | 12 ++++++++++++ includes/ServiceWiring.php | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/RELEASE-NOTES-1.34 b/RELEASE-NOTES-1.34 index 3f4287bc1d..d60b35eca6 100644 --- a/RELEASE-NOTES-1.34 +++ b/RELEASE-NOTES-1.34 @@ -100,6 +100,8 @@ For notes on 1.33.x and older releases, see HISTORY. See for details. * (T229035) The GetUserBlock hook was added. Use this instead of GetBlockedStatus. +* ObjectFactory is available as a service. When used as a service, the object + specs can now specify needed DI services. === External library changes in 1.34 === diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php index 8445842b9e..1ffbf1d185 100644 --- a/includes/MediaWikiServices.php +++ b/includes/MediaWikiServices.php @@ -65,6 +65,7 @@ use SkinFactory; use TitleFormatter; use TitleParser; use VirtualRESTServiceClient; +use Wikimedia\ObjectFactory; use Wikimedia\Rdbms\LBFactory; use Wikimedia\Services\SalvageableService; use Wikimedia\Services\ServiceContainer; @@ -749,6 +750,17 @@ class MediaWikiServices extends ServiceContainer { return $this->getService( 'NameTableStoreFactory' ); } + /** + * ObjectFactory is intended for instantiating "handlers" from declarative definitions, + * such as Action API modules, special pages, or REST API handlers. + * + * @since 1.34 + * @return ObjectFactory + */ + public function getObjectFactory() { + return $this->getService( 'ObjectFactory' ); + } + /** * @since 1.32 * @return OldRevisionImporter diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 7bdd7c8af1..f9d5ca1285 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -70,6 +70,7 @@ use MediaWiki\Storage\BlobStoreFactory; use MediaWiki\Storage\NameTableStoreFactory; use MediaWiki\Storage\SqlBlobStore; use MediaWiki\Storage\PageEditStash; +use Wikimedia\ObjectFactory; return [ 'ActorMigration' => function ( MediaWikiServices $services ) : ActorMigration { @@ -480,6 +481,10 @@ return [ ); }, + 'ObjectFactory' => function ( MediaWikiServices $services ) : ObjectFactory { + return new ObjectFactory( $services ); + }, + 'OldRevisionImporter' => function ( MediaWikiServices $services ) : OldRevisionImporter { return new ImportableOldRevisionImporter( true, -- 2.20.1