MediaWiki 1.44.0
SpecialRunJobs.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Specials;
22
31
40
41 private JobRunner $jobRunner;
42 private ReadOnlyMode $readOnlyMode;
43
44 public function __construct(
45 JobRunner $jobRunner,
46 ReadOnlyMode $readOnlyMode
47 ) {
48 parent::__construct( 'RunJobs' );
49 $this->jobRunner = $jobRunner;
50 $this->readOnlyMode = $readOnlyMode;
51 }
52
53 public function doesWrites() {
54 return true;
55 }
56
57 public function execute( $par ) {
58 $this->getOutput()->disable();
59
60 if ( $this->readOnlyMode->isReadOnly() ) {
61 wfHttpError( 423, 'Locked', 'Wiki is in read-only mode.' );
62 return;
63 }
64
65 // Validate request method
66 if ( !$this->getRequest()->wasPosted() ) {
67 wfHttpError( 400, 'Bad Request', 'Request must be POSTed.' );
68 return;
69 }
70
71 // Validate request parameters
72 $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false,
73 'async' => true, 'stats' => false ];
74 $required = array_fill_keys( [ 'title', 'tasks', 'signature', 'sigexpiry' ], true );
75 $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
76 $missing = array_diff_key( $required, $params );
77 if ( count( $missing ) ) {
78 wfHttpError( 400, 'Bad Request',
79 'Missing parameters: ' . implode( ', ', array_keys( $missing ) )
80 );
81 return;
82 }
83
84 // Validate request signature
85 $squery = $params;
86 unset( $squery['signature'] );
87 $correctSignature = self::getQuerySignature( $squery,
88 $this->getConfig()->get( MainConfigNames::SecretKey ) );
89 $providedSignature = $params['signature'];
90 $verified = is_string( $providedSignature )
91 && hash_equals( $correctSignature, $providedSignature );
92 if ( !$verified || $params['sigexpiry'] < time() ) {
93 wfHttpError( 400, 'Bad Request', 'Invalid or stale signature provided.' );
94 return;
95 }
96
97 // Apply any default parameter values
98 $params += $optional;
99
100 if ( $params['async'] ) {
101 // HTTP 202 Accepted
102 HttpStatus::header( 202 );
103 // Clients are meant to disconnect without waiting for the full response.
104 // Let the page output happen before the jobs start, so that clients know it's
105 // safe to disconnect. MediaWiki::preOutputCommit() calls ignore_user_abort()
106 // or similar to make sure we stay alive to run the deferred update.
107 DeferredUpdates::addUpdate(
109 function () use ( $params ) {
110 $this->doRun( $params );
111 },
112 __METHOD__
113 ),
114 DeferredUpdates::POSTSEND
115 );
116 } else {
117 $stats = $this->doRun( $params );
118
119 if ( $params['stats'] ) {
120 $this->getRequest()->response()->header( 'Content-Type: application/json' );
121 print FormatJson::encode( $stats );
122 } else {
123 print "Done\n";
124 }
125 }
126 }
127
128 protected function doRun( array $params ) {
129 return $this->jobRunner->run( [
130 'type' => $params['type'],
131 'maxJobs' => $params['maxjobs'] ?: 1,
132 'maxTime' => $params['maxtime'] ?: 30
133 ] );
134 }
135
141 public static function getQuerySignature( array $query, $secretKey ) {
142 ksort( $query ); // stable order
143 return hash_hmac( 'sha1', wfArrayToCgi( $query ), $secretKey );
144 }
145}
146
151class_alias( SpecialRunJobs::class, 'SpecialRunJobs' );
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Defer callable updates to run later in the PHP process.
Deferrable update that must run outside of any explicit LBFactory transaction round.
Job queue runner utility methods.
Definition JobRunner.php:48
JSON formatter wrapper class.
A class containing constants representing the names of configuration variables.
const SecretKey
Name constant for the SecretKey setting, for use with Config::get()
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getOutput()
Get the OutputPage being used for this instance.
Shortcut to construct a special page which is unlisted by default.
Special page designed for running background tasks (internal use only)
execute( $par)
Default execute method Checks user permissions.
static getQuerySignature(array $query, $secretKey)
doesWrites()
Indicates whether POST requests to this special page require write access to the wiki.
__construct(JobRunner $jobRunner, ReadOnlyMode $readOnlyMode)
Determine whether a site is currently in read-only mode.