MediaWiki 1.42.0-rc.0
StatusValue.php
Go to the documentation of this file.
1<?php
23
48
53 protected $ok = true;
54
61 protected $errors = [];
62
64 public $value;
65
67 public $success = [];
68
70 public $successCount = 0;
71
73 public $failCount = 0;
74
77
85 public static function newFatal( $message, ...$parameters ) {
86 $result = new static();
87 $result->fatal( $message, ...$parameters );
88 return $result;
89 }
90
97 public static function newGood( $value = null ) {
98 $result = new static();
99 $result->value = $value;
100 return $result;
101 }
102
114 public function splitByErrorType() {
115 $errorsOnlyStatusValue = static::newGood();
116 $warningsOnlyStatusValue = static::newGood();
117 $warningsOnlyStatusValue->setResult( true, $this->getValue() );
118 $errorsOnlyStatusValue->setResult( $this->isOK(), $this->getValue() );
119
120 foreach ( $this->errors as $item ) {
121 if ( $item['type'] === 'warning' ) {
122 $warningsOnlyStatusValue->errors[] = $item;
123 } else {
124 $errorsOnlyStatusValue->errors[] = $item;
125 }
126 }
127
128 return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ];
129 }
130
137 public function isGood() {
138 return $this->ok && !$this->errors;
139 }
140
146 public function isOK() {
147 return $this->ok;
148 }
149
153 public function getValue() {
154 return $this->value;
155 }
156
165 public function getErrors() {
166 return $this->errors;
167 }
168
175 public function setOK( $ok ) {
176 $this->ok = $ok;
177 return $this;
178 }
179
187 public function setResult( $ok, $value = null ) {
188 $this->ok = (bool)$ok;
189 $this->value = $value;
190 return $this;
191 }
192
210 private function addError( array $newError ) {
211 if ( $newError[ 'message' ] instanceof MessageSpecifier ) {
212 $isEqual = static function ( $key, $params ) use ( $newError ) {
213 if ( $key instanceof MessageSpecifier ) {
214 // compare attributes of both MessageSpecifiers
215 return $newError['message'] == $key;
216 } else {
217 return $newError['message']->getKey() === $key &&
218 $newError['message']->getParams() === $params;
219 }
220 };
221 } else {
222 $isEqual = static function ( $key, $params ) use ( $newError ) {
223 if ( $key instanceof MessageSpecifier ) {
224 $params = $key->getParams();
225 $key = $key->getKey();
226 }
227 return $newError['message'] === $key && $newError['params'] === $params;
228 };
229 }
230 foreach ( $this->errors as [ 'type' => &$type, 'message' => $key, 'params' => $params ] ) {
231 if ( $isEqual( $key, $params ) ) {
232 if ( $type === 'warning' && $newError['type'] === 'error' ) {
233 $type = 'error';
234 }
235 return $this;
236 }
237 }
238 $this->errors[] = $newError;
239 return $this;
240 }
241
249 public function warning( $message, ...$parameters ) {
250 $message = $this->normalizeMessage( $message );
251
252 return $this->addError( [
253 'type' => 'warning',
254 'message' => $message,
255 'params' => $parameters
256 ] );
257 }
258
267 public function error( $message, ...$parameters ) {
268 $message = $this->normalizeMessage( $message );
269
270 return $this->addError( [
271 'type' => 'error',
272 'message' => $message,
273 'params' => $parameters
274 ] );
275 }
276
285 public function fatal( $message, ...$parameters ) {
286 $this->ok = false;
287 return $this->error( $message, ...$parameters );
288 }
289
297 public function merge( $other, $overwriteValue = false ) {
298 if ( $this->statusData !== null && $other->statusData !== null ) {
299 throw new RuntimeException( "Status cannot be merged, because they both have \$statusData" );
300 } else {
301 $this->statusData ??= $other->statusData;
302 }
303
304 foreach ( $other->errors as $error ) {
305 $this->addError( $error );
306 }
307 $this->ok = $this->ok && $other->ok;
308 if ( $overwriteValue ) {
309 $this->value = $other->value;
310 }
311 $this->successCount += $other->successCount;
312 $this->failCount += $other->failCount;
313
314 return $this;
315 }
316
328 public function getErrorsByType( $type ) {
329 $result = [];
330 foreach ( $this->errors as $error ) {
331 if ( $error['type'] === $type ) {
332 $result[] = $error;
333 }
334 }
335
336 return $result;
337 }
338
346 public function hasMessage( $message ) {
347 if ( $message instanceof MessageSpecifier || $message instanceof MessageValue ) {
348 $message = $message->getKey();
349 }
350
351 foreach ( $this->errors as [ 'message' => $key ] ) {
352 if ( ( $key instanceof MessageSpecifier && $key->getKey() === $message ) ||
353 $key === $message
354 ) {
355 return true;
356 }
357 }
358
359 return false;
360 }
361
369 public function hasMessagesExcept( ...$messages ) {
370 $exceptedKeys = [];
371 foreach ( $messages as $message ) {
372 if ( $message instanceof MessageSpecifier || $message instanceof MessageValue ) {
373 $message = $message->getKey();
374 }
375 $exceptedKeys[] = $message;
376 }
377
378 foreach ( $this->errors as [ 'message' => $key ] ) {
379 if ( $key instanceof MessageSpecifier ) {
380 $key = $key->getKey();
381 }
382 if ( !in_array( $key, $exceptedKeys, true ) ) {
383 return true;
384 }
385 }
386
387 return false;
388 }
389
401 public function replaceMessage( $source, $dest ) {
402 $replaced = false;
403
404 $source = $this->normalizeMessage( $source );
405 $dest = $this->normalizeMessage( $dest );
406
407 foreach ( $this->errors as [ 'message' => &$message ] ) {
408 if ( $message === $source ||
409 ( $message instanceof MessageSpecifier && $message->getKey() === $source )
410 ) {
411 $message = $dest;
412 $replaced = true;
413 }
414 }
415
416 return $replaced;
417 }
418
425 public function __toString() {
426 $status = $this->isOK() ? "OK" : "Error";
427 if ( count( $this->errors ) ) {
428 $errorcount = "collected " . ( count( $this->errors ) ) . " message(s) on the way";
429 } else {
430 $errorcount = "no errors detected";
431 }
432 if ( isset( $this->value ) ) {
433 $valstr = gettype( $this->value ) . " value set";
434 if ( is_object( $this->value ) ) {
435 $valstr .= "\"" . get_class( $this->value ) . "\" instance";
436 }
437 } else {
438 $valstr = "no value set";
439 }
440 $out = sprintf( "<%s, %s, %s>",
441 $status,
442 $errorcount,
443 $valstr
444 );
445 if ( count( $this->errors ) > 0 ) {
446 $hdr = sprintf( "+-%'-8s-+-%'-25s-+-%'-36s-+\n", "", "", "" );
447 $out .= "\n" . $hdr;
448 foreach ( $this->errors as [ 'type' => $type, 'message' => $key, 'params' => $params ] ) {
449 if ( $key instanceof MessageSpecifier ) {
450 $params = $key->getParams();
451 $key = $key->getKey();
452 }
453
454 $keyChunks = mb_str_split( $key, 25 );
455 $paramsChunks = mb_str_split( $this->flattenParams( $params, " | " ), 36 );
456
457 // array_map(null,...) is like Python's zip()
458 foreach ( array_map( null, [ $type ], $keyChunks, $paramsChunks )
459 as [ $typeChunk, $keyChunk, $paramsChunk ]
460 ) {
461 $out .= sprintf( "| %-8s | %-25s | %-36s |\n",
462 $typeChunk,
463 $keyChunk,
464 $paramsChunk
465 );
466 }
467 }
468 $out .= $hdr;
469 }
470
471 return $out;
472 }
473
480 private function flattenParams( array $params, string $joiner = ', ' ): string {
481 $ret = [];
482 foreach ( $params as $p ) {
483 if ( is_array( $p ) ) {
484 $r = '[ ' . self::flattenParams( $p ) . ' ]';
485 } elseif ( $p instanceof MessageSpecifier ) {
486 $r = '{ ' . $p->getKey() . ': ' . self::flattenParams( $p->getParams() ) . ' }';
487 } else {
488 $r = (string)$p;
489 }
490
491 $ret[] = mb_strlen( $r ) > 100 ? mb_substr( $r, 0, 99 ) . "..." : $r;
492 }
493 return implode( $joiner, $ret );
494 }
495
505 protected function getStatusArray( $type = false ) {
506 $result = [];
507
508 foreach ( $this->getErrors() as $error ) {
509 if ( !$type || $error['type'] === $type ) {
510 if ( $error['message'] instanceof MessageSpecifier ) {
511 $result[] = [ $error['message']->getKey(), ...$error['message']->getParams() ];
512 } else {
513 $result[] = [ $error['message'], ...$error['params'] ];
514 }
515 }
516 }
517
518 return $result;
519 }
520
526 private function normalizeMessage( $message ) {
527 if ( $message instanceof MessageValue ) {
528 $converter = new Converter();
529 return $converter->convertMessageValue( $message );
530 }
531
532 return $message;
533 }
534}
array $params
The job parameters.
Converter between Message and MessageValue.
Definition Converter.php:18
Generic operation result class Has warning/error list, boolean status and arbitrary value.
hasMessage( $message)
Returns true if the specified message is present as a warning or error.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
int $failCount
Counter for batch operations.
array[] $errors
getErrors()
Get the list of errors.
replaceMessage( $source, $dest)
If the specified source message exists, replace it with the specified destination message,...
splitByErrorType()
Splits this StatusValue object into two new StatusValue objects, one which contains only the error me...
setOK( $ok)
Change operation status.
hasMessagesExcept(... $messages)
Returns true if any other message than the specified ones is present as a warning or error.
getStatusArray( $type=false)
Returns a list of status messages of the given type (or all if false)
isOK()
Returns whether the operation completed.
fatal( $message,... $parameters)
Add an error and set OK to false, indicating that the operation as a whole was fatal.
setResult( $ok, $value=null)
Change operation result.
merge( $other, $overwriteValue=false)
Merge another status object into this one.
mixed $statusData
arbitrary extra data about the operation
__toString()
Returns a string representation of the status for debugging.
error( $message,... $parameters)
Add an error, do not set fatal flag This can be used for non-fatal errors.
getErrorsByType( $type)
Returns a list of status messages of the given type.
warning( $message,... $parameters)
Add a new warning.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
static newGood( $value=null)
Factory function for good results.
int $successCount
Counter for batch operations.
Value object representing a message for i18n.
getKey()
Returns the message key.
$source