MediaWiki  master
ApiContinuationManager.php
Go to the documentation of this file.
1 <?php
27  private $source;
28 
29  private $allModules = [];
30  private $generatedModules = [];
31 
33  private $continuationData = [];
36 
37  private $generatorParams = [];
38  private $generatorDone = false;
39 
46  public function __construct(
47  ApiBase $module, array $allModules = [], array $generatedModules = []
48  ) {
49  $this->source = get_class( $module );
50  $request = $module->getRequest();
51 
52  $this->generatedModules = $generatedModules
53  ? array_combine( $generatedModules, $generatedModules )
54  : [];
55 
56  $skip = [];
57  $continue = $request->getVal( 'continue', '' );
58  if ( $continue !== '' ) {
59  $continue = explode( '||', $continue );
60  if ( count( $continue ) !== 2 ) {
61  throw ApiUsageException::newWithMessage( $module->getMain(), 'apierror-badcontinue' );
62  }
63  $this->generatorDone = ( $continue[0] === '-' );
64  $skip = explode( '|', $continue[1] );
65  if ( !$this->generatorDone ) {
66  $params = explode( '|', $continue[0] );
67  if ( $params ) {
68  $this->generatorParams = array_intersect_key(
69  $request->getValues(),
70  array_flip( $params )
71  );
72  }
73  } else {
74  // When the generator is complete, don't run any modules that
75  // depend on it.
76  $skip += $this->generatedModules;
77  }
78  }
79 
80  foreach ( $allModules as $module ) {
81  $name = $module->getModuleName();
82  if ( in_array( $name, $skip, true ) ) {
83  $this->allModules[$name] = false;
84  // Prevent spurious "unused parameter" warnings
85  $module->extractRequestParams();
86  } else {
87  $this->allModules[$name] = $module;
88  }
89  }
90  }
91 
96  public function getSource() {
97  return $this->source;
98  }
99 
104  public function isGeneratorDone() {
105  return $this->generatorDone;
106  }
107 
112  public function getRunModules() {
113  return array_values( array_filter( $this->allModules ) );
114  }
115 
123  public function addContinueParam( ApiBase $module, $paramName, $paramValue ) {
124  $name = $module->getModuleName();
125  if ( !isset( $this->allModules[$name] ) ) {
126  throw new UnexpectedValueException(
127  "Module '$name' called " . __METHOD__ .
128  ' but was not passed to ' . __CLASS__ . '::__construct'
129  );
130  }
131  if ( !$this->allModules[$name] ) {
132  throw new UnexpectedValueException(
133  "Module '$name' was not supposed to have been executed, but " .
134  'it was executed anyway'
135  );
136  }
137  $paramName = $module->encodeParamName( $paramName );
138  if ( is_array( $paramValue ) ) {
139  $paramValue = implode( '|', $paramValue );
140  }
141  $this->continuationData[$name][$paramName] = $paramValue;
142  }
143 
155  public function addGeneratorNonContinueParam( ApiBase $module, $paramName, $paramValue ) {
156  $name = $module->getModuleName();
157  $paramName = $module->encodeParamName( $paramName );
158  if ( is_array( $paramValue ) ) {
159  $paramValue = implode( '|', $paramValue );
160  }
161  $this->generatorNonContinuationData[$name][$paramName] = $paramValue;
162  }
163 
170  public function addGeneratorContinueParam( ApiBase $module, $paramName, $paramValue ) {
171  $name = $module->getModuleName();
172  $paramName = $module->encodeParamName( $paramName );
173  if ( is_array( $paramValue ) ) {
174  $paramValue = implode( '|', $paramValue );
175  }
176  $this->generatorContinuationData[$name][$paramName] = $paramValue;
177  }
178 
183  public function getRawContinuation() {
184  return array_merge_recursive( $this->continuationData, $this->generatorContinuationData );
185  }
186 
192  public function getRawNonContinuation() {
194  }
195 
200  public function getContinuation() {
201  $data = [];
202  $batchcomplete = false;
203 
204  $finishedModules = array_diff(
205  array_keys( $this->allModules ),
206  array_keys( $this->continuationData )
207  );
208 
209  // First, grab the non-generator-using continuation data
210  $continuationData = array_diff_key( $this->continuationData, $this->generatedModules );
211  foreach ( $continuationData as $module => $kvp ) {
212  $data += $kvp;
213  }
214 
215  // Next, handle the generator-using continuation data
216  $continuationData = array_intersect_key( $this->continuationData, $this->generatedModules );
217  if ( $continuationData ) {
218  // Some modules are unfinished: include those params, and copy
219  // the generator params.
220  foreach ( $continuationData as $module => $kvp ) {
221  $data += $kvp;
222  }
223  $generatorParams = [];
224  foreach ( $this->generatorNonContinuationData as $kvp ) {
225  $generatorParams += $kvp;
226  }
228  $data += $generatorParams;
229  $generatorKeys = implode( '|', array_keys( $generatorParams ) );
230  } elseif ( $this->generatorContinuationData ) {
231  // All the generator-using modules are complete, but the
232  // generator isn't. Continue the generator and restart the
233  // generator-using modules
234  $generatorParams = [];
235  foreach ( $this->generatorContinuationData as $kvp ) {
236  $generatorParams += $kvp;
237  }
238  $data += $generatorParams;
239  $finishedModules = array_diff( $finishedModules, $this->generatedModules );
240  $generatorKeys = implode( '|', array_keys( $generatorParams ) );
241  $batchcomplete = true;
242  } else {
243  // Generator and prop modules are all done. Mark it so.
244  $generatorKeys = '-';
245  $batchcomplete = true;
246  }
247 
248  // Set 'continue' if any continuation data is set or if the generator
249  // still needs to run
250  if ( $data || $generatorKeys !== '-' ) {
251  $data['continue'] = $generatorKeys . '||' . implode( '|', $finishedModules );
252  }
253 
254  return [ $data, $batchcomplete ];
255  }
256 
261  public function setContinuationIntoResult( ApiResult $result ) {
262  list( $data, $batchcomplete ) = $this->getContinuation();
263  if ( $data ) {
264  $result->addValue( null, 'continue', $data,
266  }
267  if ( $batchcomplete ) {
268  $result->addValue( null, 'batchcomplete', true,
270  }
271  }
272 }
ApiContinuationManager\setContinuationIntoResult
setContinuationIntoResult(ApiResult $result)
Store the continuation data into the result.
Definition: ApiContinuationManager.php:261
ApiUsageException\newWithMessage
static newWithMessage(?ApiBase $module, $msg, $code=null, $data=null, $httpCode=0, Throwable $previous=null)
Definition: ApiUsageException.php:68
ApiContinuationManager
This manages continuation state.
Definition: ApiContinuationManager.php:26
ApiContinuationManager\addContinueParam
addContinueParam(ApiBase $module, $paramName, $paramValue)
Set the continuation parameter for a module.
Definition: ApiContinuationManager.php:123
ApiContinuationManager\getRunModules
getRunModules()
Get the list of modules that should actually be run.
Definition: ApiContinuationManager.php:112
ApiContinuationManager\$generatorContinuationData
$generatorContinuationData
Definition: ApiContinuationManager.php:34
ApiResult\NO_SIZE_CHECK
const NO_SIZE_CHECK
For addValue() and similar functions, do not check size while adding a value Don't use this unless yo...
Definition: ApiResult.php:58
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:76
ApiContinuationManager\$generatorDone
$generatorDone
Definition: ApiContinuationManager.php:38
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:52
ApiContinuationManager\getContinuation
getContinuation()
Fetch continuation result data.
Definition: ApiContinuationManager.php:200
ApiContinuationManager\$generatorNonContinuationData
$generatorNonContinuationData
Definition: ApiContinuationManager.php:35
ApiResult
This class represents the result of the API operations.
Definition: ApiResult.php:35
ApiContinuationManager\$continuationData
array[] $continuationData
Definition: ApiContinuationManager.php:33
ApiResult\addValue
addValue( $path, $name, $value, $flags=0)
Add value to the output data at the given path.
Definition: ApiResult.php:393
ApiContinuationManager\$generatedModules
$generatedModules
Definition: ApiContinuationManager.php:30
ApiContinuationManager\addGeneratorNonContinueParam
addGeneratorNonContinueParam(ApiBase $module, $paramName, $paramValue)
Set the non-continuation parameter for the generator module.
Definition: ApiContinuationManager.php:155
ApiBase\encodeParamName
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition: ApiBase.php:695
ApiContinuationManager\getRawNonContinuation
getRawNonContinuation()
Fetch raw non-continuation data.
Definition: ApiContinuationManager.php:192
ApiResult\ADD_ON_TOP
const ADD_ON_TOP
For addValue(), setValue() and similar functions, if the value does not exist, add it as the first el...
Definition: ApiResult.php:49
ApiContinuationManager\isGeneratorDone
isGeneratorDone()
Is the generator done?
Definition: ApiContinuationManager.php:104
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:444
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:460
ApiContinuationManager\__construct
__construct(ApiBase $module, array $allModules=[], array $generatedModules=[])
Definition: ApiContinuationManager.php:46
ApiContinuationManager\getRawContinuation
getRawContinuation()
Fetch raw continuation data.
Definition: ApiContinuationManager.php:183
ApiContinuationManager\addGeneratorContinueParam
addGeneratorContinueParam(ApiBase $module, $paramName, $paramValue)
Set the continuation parameter for the generator module.
Definition: ApiContinuationManager.php:170
ApiContinuationManager\$generatorParams
$generatorParams
Definition: ApiContinuationManager.php:37
ApiContinuationManager\$source
$source
Definition: ApiContinuationManager.php:27
ApiContinuationManager\getSource
getSource()
Get the class that created this manager.
Definition: ApiContinuationManager.php:96
ApiContinuationManager\$allModules
$allModules
Definition: ApiContinuationManager.php:29