MediaWiki REL1_37
ApiContinuationManager.php
Go to the documentation of this file.
1<?php
28 private $source;
29
31 private $allModules = [];
34
36 private $continuationData = [];
41
43 private $generatorParams = [];
45 private $generatorDone = false;
46
53 public function __construct(
54 ApiBase $module, array $allModules = [], array $generatedModules = []
55 ) {
56 $this->source = get_class( $module );
57 $request = $module->getRequest();
58
59 $this->generatedModules = $generatedModules
60 ? array_combine( $generatedModules, $generatedModules )
61 : [];
62
63 $skip = [];
64 $continue = $request->getVal( 'continue', '' );
65 if ( $continue !== '' ) {
66 $continue = explode( '||', $continue );
67 if ( count( $continue ) !== 2 ) {
68 throw ApiUsageException::newWithMessage( $module->getMain(), 'apierror-badcontinue' );
69 }
70 $this->generatorDone = ( $continue[0] === '-' );
71 $skip = explode( '|', $continue[1] );
72 if ( !$this->generatorDone ) {
73 $params = explode( '|', $continue[0] );
74 if ( $params ) {
75 $this->generatorParams = array_intersect_key(
76 $request->getValues(),
77 array_fill_keys( $params, true )
78 );
79 }
80 } else {
81 // When the generator is complete, don't run any modules that
82 // depend on it.
84 }
85 }
86
87 foreach ( $allModules as $module ) {
88 $name = $module->getModuleName();
89 if ( in_array( $name, $skip, true ) ) {
90 $this->allModules[$name] = false;
91 // Prevent spurious "unused parameter" warnings
92 $module->extractRequestParams();
93 } else {
94 $this->allModules[$name] = $module;
95 }
96 }
97 }
98
103 public function getSource() {
104 return $this->source;
105 }
106
110 public function isGeneratorDone() {
112 }
113
118 public function getRunModules() {
119 return array_values( array_filter( $this->allModules ) );
120 }
121
129 public function addContinueParam( ApiBase $module, $paramName, $paramValue ) {
130 $name = $module->getModuleName();
131 if ( !isset( $this->allModules[$name] ) ) {
132 throw new UnexpectedValueException(
133 "Module '$name' called " . __METHOD__ .
134 ' but was not passed to ' . __CLASS__ . '::__construct'
135 );
136 }
137 if ( !$this->allModules[$name] ) {
138 throw new UnexpectedValueException(
139 "Module '$name' was not supposed to have been executed, but " .
140 'it was executed anyway'
141 );
142 }
143 $paramName = $module->encodeParamName( $paramName );
144 if ( is_array( $paramValue ) ) {
145 $paramValue = implode( '|', $paramValue );
146 }
147 $this->continuationData[$name][$paramName] = $paramValue;
148 }
149
161 public function addGeneratorNonContinueParam( ApiBase $module, $paramName, $paramValue ) {
162 $name = $module->getModuleName();
163 $paramName = $module->encodeParamName( $paramName );
164 if ( is_array( $paramValue ) ) {
165 $paramValue = implode( '|', $paramValue );
166 }
167 $this->generatorNonContinuationData[$name][$paramName] = $paramValue;
168 }
169
176 public function addGeneratorContinueParam( ApiBase $module, $paramName, $paramValue ) {
177 $name = $module->getModuleName();
178 $paramName = $module->encodeParamName( $paramName );
179 if ( is_array( $paramValue ) ) {
180 $paramValue = implode( '|', $paramValue );
181 }
182 $this->generatorContinuationData[$name][$paramName] = $paramValue;
183 }
184
189 public function getRawContinuation() {
190 return array_merge_recursive( $this->continuationData, $this->generatorContinuationData );
191 }
192
198 public function getRawNonContinuation() {
200 }
201
206 public function getContinuation() {
207 $data = [];
208 $batchcomplete = false;
209
210 $finishedModules = array_diff(
211 array_keys( $this->allModules ),
212 array_keys( $this->continuationData )
213 );
214
215 // First, grab the non-generator-using continuation data
216 $continuationData = array_diff_key( $this->continuationData, $this->generatedModules );
217 foreach ( $continuationData as $module => $kvp ) {
218 $data += $kvp;
219 }
220
221 // Next, handle the generator-using continuation data
222 $continuationData = array_intersect_key( $this->continuationData, $this->generatedModules );
223 if ( $continuationData ) {
224 // Some modules are unfinished: include those params, and copy
225 // the generator params.
226 foreach ( $continuationData as $module => $kvp ) {
227 $data += $kvp;
228 }
229 $generatorParams = [];
230 foreach ( $this->generatorNonContinuationData as $kvp ) {
231 $generatorParams += $kvp;
232 }
234 // @phan-suppress-next-line PhanTypeInvalidLeftOperand False positive in phan
235 $data += $generatorParams;
236 $generatorKeys = implode( '|', array_keys( $generatorParams ) );
237 } elseif ( $this->generatorContinuationData ) {
238 // All the generator-using modules are complete, but the
239 // generator isn't. Continue the generator and restart the
240 // generator-using modules
241 $generatorParams = [];
242 foreach ( $this->generatorContinuationData as $kvp ) {
243 $generatorParams += $kvp;
244 }
245 $data += $generatorParams;
246 $finishedModules = array_diff( $finishedModules, $this->generatedModules );
247 $generatorKeys = implode( '|', array_keys( $generatorParams ) );
248 $batchcomplete = true;
249 } else {
250 // Generator and prop modules are all done. Mark it so.
251 $generatorKeys = '-';
252 $batchcomplete = true;
253 }
254
255 // Set 'continue' if any continuation data is set or if the generator
256 // still needs to run
257 if ( $data || $generatorKeys !== '-' ) {
258 $data['continue'] = $generatorKeys . '||' . implode( '|', $finishedModules );
259 }
260
261 return [ $data, $batchcomplete ];
262 }
263
268 public function setContinuationIntoResult( ApiResult $result ) {
269 list( $data, $batchcomplete ) = $this->getContinuation();
270 if ( $data ) {
271 $result->addValue( null, 'continue', $data,
272 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
273 }
274 if ( $batchcomplete ) {
275 $result->addValue( null, 'batchcomplete', true,
276 ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
277 }
278 }
279}
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:55
encodeParamName( $paramName)
This method mangles parameter name based on the prefix supplied to the constructor.
Definition ApiBase.php:742
getMain()
Get the main module.
Definition ApiBase.php:513
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:764
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:497
This manages continuation state.
addGeneratorNonContinueParam(ApiBase $module, $paramName, $paramValue)
Set the non-continuation parameter for the generator module.
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.