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