MediaWiki  master
SpecialRunJobs.php
Go to the documentation of this file.
1 <?php
24 namespace MediaWiki\Specials;
25 
26 use DeferredUpdates;
27 use FormatJson;
28 use HttpStatus;
29 use JobRunner;
34 
41 
42  private JobRunner $jobRunner;
43  private ReadOnlyMode $readOnlyMode;
44 
49  public function __construct(
50  JobRunner $jobRunner,
51  ReadOnlyMode $readOnlyMode
52  ) {
53  parent::__construct( 'RunJobs' );
54  $this->jobRunner = $jobRunner;
55  $this->readOnlyMode = $readOnlyMode;
56  }
57 
58  public function doesWrites() {
59  return true;
60  }
61 
62  public function execute( $par ) {
63  $this->getOutput()->disable();
64 
65  if ( $this->readOnlyMode->isReadOnly() ) {
66  wfHttpError( 423, 'Locked', 'Wiki is in read-only mode.' );
67  return;
68  }
69 
70  // Validate request method
71  if ( !$this->getRequest()->wasPosted() ) {
72  wfHttpError( 400, 'Bad Request', 'Request must be POSTed.' );
73  return;
74  }
75 
76  // Validate request parameters
77  $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false,
78  'async' => true, 'stats' => false ];
79  $required = array_fill_keys( [ 'title', 'tasks', 'signature', 'sigexpiry' ], true );
80  $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
81  $missing = array_diff_key( $required, $params );
82  if ( count( $missing ) ) {
83  wfHttpError( 400, 'Bad Request',
84  'Missing parameters: ' . implode( ', ', array_keys( $missing ) )
85  );
86  return;
87  }
88 
89  // Validate request signature
90  $squery = $params;
91  unset( $squery['signature'] );
92  $correctSignature = self::getQuerySignature( $squery,
93  $this->getConfig()->get( MainConfigNames::SecretKey ) );
94  $providedSignature = $params['signature'];
95  $verified = is_string( $providedSignature )
96  && hash_equals( $correctSignature, $providedSignature );
97  if ( !$verified || $params['sigexpiry'] < time() ) {
98  wfHttpError( 400, 'Bad Request', 'Invalid or stale signature provided.' );
99  return;
100  }
101 
102  // Apply any default parameter values
103  $params += $optional;
104 
105  if ( $params['async'] ) {
106  // HTTP 202 Accepted
107  HttpStatus::header( 202 );
108  // Clients are meant to disconnect without waiting for the full response.
109  // Let the page output happen before the jobs start, so that clients know it's
110  // safe to disconnect. MediaWiki::preOutputCommit() calls ignore_user_abort()
111  // or similar to make sure we stay alive to run the deferred update.
114  function () use ( $params ) {
115  $this->doRun( $params );
116  },
117  __METHOD__
118  ),
119  DeferredUpdates::POSTSEND
120  );
121  } else {
122  $stats = $this->doRun( $params );
123 
124  if ( $params['stats'] ) {
125  $this->getRequest()->response()->header( 'Content-Type: application/json' );
126  print FormatJson::encode( $stats );
127  } else {
128  print "Done\n";
129  }
130  }
131  }
132 
133  protected function doRun( array $params ) {
134  return $this->jobRunner->run( [
135  'type' => $params['type'],
136  'maxJobs' => $params['maxjobs'] ?: 1,
137  'maxTime' => $params['maxtime'] ?: 30
138  ] );
139  }
140 
146  public static function getQuerySignature( array $query, $secretKey ) {
147  ksort( $query ); // stable order
148  return hash_hmac( 'sha1', wfArrayToCgi( $query ), $secretKey );
149  }
150 }
151 
156 class_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.
static addUpdate(DeferrableUpdate $update, $stage=self::POSTSEND)
Add an update to the pending update queue for execution at the appropriate time.
JSON formatter wrapper class.
Definition: FormatJson.php:28
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:98
static header( $code)
Output an HTTP status code header.
Definition: HttpStatus.php:96
Job queue runner utility methods.
Definition: JobRunner.php:42
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 this special page may perform database writes.
__construct(JobRunner $jobRunner, ReadOnlyMode $readOnlyMode)
Deferrable update that must run outside of any explicit LBFactory transaction round.
Determine whether a site is currently in read-only mode.