Merge "Allow callback functions for creating jobs"

This commit is contained in:
jenkins-bot 2017-05-09 18:38:57 +00:00 committed by Gerrit Code Review
commit 58e1e472ba
6 changed files with 62 additions and 8 deletions

View file

@ -12,6 +12,11 @@ production.
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 ===
* (T37247) Output from Parser::parse() will now be wrapped in a div with

View file

@ -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",

View file

@ -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",

View file

@ -7323,8 +7323,10 @@ $wgServiceWiringFiles = [
];
/**
* 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',

View file

@ -69,12 +69,22 @@ abstract class Job implements IJobSpecification {
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}'" );

View file

@ -91,4 +91,41 @@ class JobTest extends MediaWikiTestCase {
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 );
}
}