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