MediaWiki REL1_35
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.
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() {
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,
265 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
266 }
267 if ( $batchcomplete ) {
268 $result->addValue( null, 'batchcomplete', true,
269 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
270 }
271 }
272}
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:52
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition ApiBase.php:750
getMain()
Get the main module.
Definition ApiBase.php:515
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:772
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:499
This manages continuation state.
addGeneratorNonContinueParam(ApiBase $module, $paramName, $paramValue)
Set the non-continuation parameter for the generator module.
isGeneratorDone()
Is the generator done?
addGeneratorContinueParam(ApiBase $module, $paramName, $paramValue)
Set the continuation parameter for the generator module.
setContinuationIntoResult(ApiResult $result)
Store the continuation data into the result.
getRunModules()
Get the list of modules that should actually be run.
addContinueParam(ApiBase $module, $paramName, $paramValue)
Set the continuation parameter for a module.
getSource()
Get the class that created this manager.
getRawNonContinuation()
Fetch raw non-continuation data.
__construct(ApiBase $module, array $allModules=[], array $generatedModules=[])
getContinuation()
Fetch continuation result data.
getRawContinuation()
Fetch raw continuation data.
This class represents the result of the API operations.
Definition ApiResult.php:35
addValue( $path, $name, $value, $flags=0)
Add value to the output data at the given path.