jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/351876 )

Change subject: Allow callback functions for creating jobs
......................................................................


Allow callback functions for creating jobs

$wgJobClasses can now specify a factory function for creating a job,
instead of a class to be instantiated directly. This makes it possible
to inject services in a job constructor, and register a factory function
that calls the constructor with default services.

This follows Ieb85493a7765 and Ia2107dc5af78, which introduced factory
functions for API modules and special pages.

Change-Id: I0461e59da2a8fa6681e3b1fcdfc38bfed7f3ac32
---
M RELEASE-NOTES-1.30
M docs/extension.schema.v1.json
M docs/extension.schema.v2.json
M includes/DefaultSettings.php
M includes/jobqueue/Job.php
M tests/phpunit/includes/jobqueue/JobTest.php
6 files changed, 62 insertions(+), 8 deletions(-)

Approvals:
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/RELEASE-NOTES-1.30 b/RELEASE-NOTES-1.30
index cdf8ba4..5370c6d 100644
--- a/RELEASE-NOTES-1.30
+++ b/RELEASE-NOTES-1.30
@@ -12,6 +12,11 @@
   case.
 * $wgShellLocale now affects LC_ALL rather than only LC_CTYPE. See
   documentation of $wgShellLocale for details.
+* $wgJobClasses may now specify callback functions
+  as an alternative to plain class names.
+  This is intended for extensions that want control
+  over the instantiation of their jobs,
+  to allow for proper dependency injection.
 
 === New features in 1.30 ===
 * …
diff --git a/docs/extension.schema.v1.json b/docs/extension.schema.v1.json
index 3d6eda9..f241cf5 100644
--- a/docs/extension.schema.v1.json
+++ b/docs/extension.schema.v1.json
@@ -576,7 +576,7 @@
                },
                "JobClasses": {
                        "type": "object",
-                       "description": "Job types this extension implements 
(mapping of job type to class name)"
+                       "description": "Job types this extension implements 
(mapping of job type to class name or factory function)"
                },
                "LogTypes": {
                        "type": "array",
diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json
index a2fdf65..137dd51 100644
--- a/docs/extension.schema.v2.json
+++ b/docs/extension.schema.v2.json
@@ -586,7 +586,7 @@
                },
                "JobClasses": {
                        "type": "object",
-                       "description": "Job types this extension implements 
(mapping of job type to class name)"
+                       "description": "Job types this extension implements 
(mapping of job type to class name or factory function)"
                },
                "LogTypes": {
                        "type": "array",
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 7c18fcc..a6bc7e5 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -7332,8 +7332,10 @@
 ];
 
 /**
- * Maps jobs to their handling classes; extensions
- * can add to this to provide custom jobs
+ * Maps jobs to their handlers; extensions
+ * can add to this to provide custom jobs.
+ * A job handler should either be a class name to be instantiated,
+ * or (since 1.30) a callback to use for creating the job object.
  */
 $wgJobClasses = [
        'refreshLinks' => 'RefreshLinksJob',
diff --git a/includes/jobqueue/Job.php b/includes/jobqueue/Job.php
index f814cee..703e485 100644
--- a/includes/jobqueue/Job.php
+++ b/includes/jobqueue/Job.php
@@ -69,12 +69,22 @@
                global $wgJobClasses;
 
                if ( isset( $wgJobClasses[$command] ) ) {
-                       $class = $wgJobClasses[$command];
+                       $handler = $wgJobClasses[$command];
 
-                       $job = new $class( $title, $params );
-                       $job->command = $command;
+                       if ( is_callable( $handler ) ) {
+                               $job = call_user_func( $handler, $title, 
$params );
+                       } elseif ( class_exists( $handler ) ) {
+                               $job = new $handler( $title, $params );
+                       } else {
+                               $job = null;
+                       }
 
-                       return $job;
+                       if ( $job instanceof Job ) {
+                               $job->command = $command;
+                               return $job;
+                       } else {
+                               throw new InvalidArgumentException( "Cannot 
instantiate job '$command': bad spec!" );
+                       }
                }
 
                throw new InvalidArgumentException( "Invalid job command 
'{$command}'" );
diff --git a/tests/phpunit/includes/jobqueue/JobTest.php 
b/tests/phpunit/includes/jobqueue/JobTest.php
index 1deb7aa..00c47c8 100644
--- a/tests/phpunit/includes/jobqueue/JobTest.php
+++ b/tests/phpunit/includes/jobqueue/JobTest.php
@@ -91,4 +91,41 @@
                return $mock;
        }
 
+       /**
+        * @dataProvider provideTestJobFactory
+        *
+        * @param mixed $handler
+        *
+        * @covers Job::factory
+        */
+       public function testJobFactory( $handler ) {
+               $this->mergeMWGlobalArrayValue( 'wgJobClasses', [ 'testdummy' 
=> $handler ] );
+
+               $job = Job::factory( 'testdummy', Title::newMainPage(), [] );
+               $this->assertInstanceOf( NullJob::class, $job );
+
+               $job2 = Job::factory( 'testdummy', Title::newMainPage(), [] );
+               $this->assertInstanceOf( NullJob::class, $job2 );
+               $this->assertNotSame( $job, $job2, 'should not reuse instance' 
);
+       }
+
+       public function provideTestJobFactory() {
+               return [
+                       'class name' => [ 'NullJob' ],
+                       'closure' => [ function( Title $title, array $params ) {
+                               return new NullJob( $title, $params );
+                       } ],
+                       'function' => [ [ $this, 'newNullJob' ] ],
+                       'static function' => [ self::class . '::staticNullJob' ]
+               ];
+       }
+
+       public function newNullJob( Title $title, array $params ) {
+               return new NullJob( $title, $params );
+       }
+
+       public static function staticNullJob( Title $title, array $params ) {
+               return new NullJob( $title, $params );
+       }
+
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/351876
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I0461e59da2a8fa6681e3b1fcdfc38bfed7f3ac32
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Lucas Werkmeister (WMDE) <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Lucas Werkmeister (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to