Lucas Werkmeister (WMDE) has uploaded a new change for review. ( 
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 Ieb85493a7765, which introduced factory
functions for API modules and special pages.

Change-Id: I0461e59da2a8fa6681e3b1fcdfc38bfed7f3ac32
---
M RELEASE-NOTES-1.30
M includes/DefaultSettings.php
M includes/jobqueue/Job.php
M tests/phpunit/includes/jobqueue/JobTest.php
4 files changed, 60 insertions(+), 6 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/76/351876/1

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/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 7c18fcc..8563fa1 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 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..79128be 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 );
+                       } else if ( is_string( $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..5b59fa9 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: newchange
Gerrit-Change-Id: I0461e59da2a8fa6681e3b1fcdfc38bfed7f3ac32
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Lucas Werkmeister (WMDE) <[email protected]>

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

Reply via email to