resourceloader: Allow modules to be registered via a factory callback
authordaniel <daniel.kinzler@wikimedia.de>
Thu, 4 May 2017 16:10:28 +0000 (18:10 +0200)
committerKrinkle <krinklemail@gmail.com>
Sun, 21 May 2017 17:12:37 +0000 (17:12 +0000)
This should work the same way as registering API modules via a factory callback.
Point in case: Ifb8611473a971 could avoid global state using this mechanism.

Change-Id: Ifbf29006141ce2a2dff42efa352f406502a06bc6

RELEASE-NOTES-1.30
docs/extension.schema.v2.json
includes/resourceloader/ResourceLoader.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php

index fbe23ab..03ae7c2 100644 (file)
@@ -17,6 +17,9 @@ production.
   This is intended for extensions that want control
   over the instantiation of their jobs,
   to allow for proper dependency injection.
+* $wgResourceModules may now specify callback functions as an alternative
+  to plain class names, using the 'factory' key in the module description
+  array. This allows dependency injection to be used for ResourceLoader modules.
 
 === New features in 1.30 ===
 * (T37247) Output from Parser::parse() will now be wrapped in a div with
index d5a9b65..6345632 100644 (file)
                                                        }
                                                },
                                                {
-                                                       "description": "An arbitrary ResourceLoaderModule definition",
+                                                       "description": "An arbitrary ResourceLoaderModule definition by class",
                                                        "properties": {
                                                                "class": {
                                                                        "type": "string",
                                                                }
                                                        },
                                                        "required": ["class"]
+                                               },
+                                               {
+                                                       "description": "An arbitrary ResourceLoaderModule definition with instantiator",
+                                                       "properties": {
+                                                               "factory": {
+                                                                       "type": "string",
+                                                                       "description": "A static instantiator function for creating the ResourceLoaderModule object."
+                                                               }
+                                                       },
+                                                       "required": ["factory"]
                                                }
                                        ]
                                }
index 3cd7821..0d12840 100644 (file)
@@ -541,6 +541,10 @@ class ResourceLoader implements LoggerAwareInterface {
                        if ( isset( $info['object'] ) ) {
                                // Object given in info array
                                $object = $info['object'];
+                       } elseif ( isset( $info['factory'] ) ) {
+                               $object = call_user_func( $info['factory'], $info );
+                               $object->setConfig( $this->getConfig() );
+                               $object->setLogger( $this->logger );
                        } else {
                                if ( !isset( $info['class'] ) ) {
                                        $class = 'ResourceLoaderFileModule';
index af3212a..0833047 100644 (file)
@@ -143,6 +143,23 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                );
        }
 
+       /**
+        * @covers ResourceLoader::getModule
+        */
+       public function testGetModuleFactory() {
+               $factory = function( array $info ) {
+                       $this->assertArrayHasKey( 'kitten', $info );
+                       return new ResourceLoaderTestModule( $info );
+               };
+
+               $rl = new EmptyResourceLoader();
+               $rl->register( 'test', [ 'factory' => $factory, 'kitten' => 'little ball of fur' ] );
+               $this->assertInstanceOf(
+                       ResourceLoaderTestModule::class,
+                       $rl->getModule( 'test' )
+               );
+       }
+
        /**
         * @covers ResourceLoader::getModule
         */