MediaWiki 1.41.2
StatusValue.php
Go to the documentation of this file.
1<?php
23
47
49 protected $ok = true;
50
52 protected $errors = [];
53
55 public $value;
56
58 public $success = [];
59
61 public $successCount = 0;
62
64 public $failCount = 0;
65
68
76 public static function newFatal( $message, ...$parameters ) {
77 $result = new static();
78 $result->fatal( $message, ...$parameters );
79 return $result;
80 }
81
88 public static function newGood( $value = null ) {
89 $result = new static();
90 $result->value = $value;
91 return $result;
92 }
93
105 public function splitByErrorType() {
106 $errorsOnlyStatusValue = static::newGood();
107 $warningsOnlyStatusValue = static::newGood();
108 $warningsOnlyStatusValue->setResult( true, $this->getValue() );
109 $errorsOnlyStatusValue->setResult( $this->isOK(), $this->getValue() );
110
111 foreach ( $this->errors as $item ) {
112 if ( $item['type'] === 'warning' ) {
113 $warningsOnlyStatusValue->errors[] = $item;
114 } else {
115 $errorsOnlyStatusValue->errors[] = $item;
116 }
117 }
118
119 return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ];
120 }
121
128 public function isGood() {
129 return $this->ok && !$this->errors;
130 }
131
137 public function isOK() {
138 return $this->ok;
139 }
140
144 public function getValue() {
145 return $this->value;
146 }
147
156 public function getErrors() {
157 return $this->errors;
158 }
159
166 public function setOK( $ok ) {
167 $this->ok = $ok;
168 return $this;
169 }
170
178 public function setResult( $ok, $value = null ) {
179 $this->ok = (bool)$ok;
180 $this->value = $value;
181 return $this;
182 }
183
201 private function addError( array $newError ) {
202 if ( $newError[ 'message' ] instanceof MessageSpecifier ) {
203 $isEqual = static function ( $existingError ) use ( $newError ) {
204 if ( $existingError['message'] instanceof MessageSpecifier ) {
205 // compare attributes of both MessageSpecifiers
206 return $newError['message'] == $existingError['message'];
207 } else {
208 return $newError['message']->getKey() === $existingError['message'] &&
209 $newError['message']->getParams() === $existingError['params'];
210 }
211 };
212 } else {
213 $isEqual = static function ( $existingError ) use ( $newError ) {
214 if ( $existingError['message'] instanceof MessageSpecifier ) {
215 return $newError['message'] === $existingError['message']->getKey() &&
216 $newError['params'] === $existingError['message']->getParams();
217 } else {
218 return $newError['message'] === $existingError['message'] &&
219 $newError['params'] === $existingError['params'];
220 }
221 };
222 }
223 foreach ( $this->errors as $index => $existingError ) {
224 if ( $isEqual( $existingError ) ) {
225 if ( $newError[ 'type' ] === 'error' && $existingError[ 'type' ] === 'warning' ) {
226 $this->errors[ $index ][ 'type' ] = 'error';
227 }
228 return $this;
229 }
230 }
231 $this->errors[] = $newError;
232 return $this;
233 }
234
242 public function warning( $message, ...$parameters ) {
243 $message = $this->normalizeMessage( $message );
244
245 return $this->addError( [
246 'type' => 'warning',
247 'message' => $message,
248 'params' => $parameters
249 ] );
250 }
251
260 public function error( $message, ...$parameters ) {
261 $message = $this->normalizeMessage( $message );
262
263 return $this->addError( [
264 'type' => 'error',
265 'message' => $message,
266 'params' => $parameters
267 ] );
268 }
269
278 public function fatal( $message, ...$parameters ) {
279 $this->ok = false;
280 return $this->error( $message, ...$parameters );
281 }
282
290 public function merge( $other, $overwriteValue = false ) {
291 if ( $this->statusData !== null && $other->statusData !== null ) {
292 throw new RuntimeException( "Status cannot be merged, because they both have \$statusData" );
293 } else {
294 $this->statusData ??= $other->statusData;
295 }
296
297 foreach ( $other->errors as $error ) {
298 $this->addError( $error );
299 }
300 $this->ok = $this->ok && $other->ok;
301 if ( $overwriteValue ) {
302 $this->value = $other->value;
303 }
304 $this->successCount += $other->successCount;
305 $this->failCount += $other->failCount;
306
307 return $this;
308 }
309
321 public function getErrorsByType( $type ) {
322 $result = [];
323 foreach ( $this->errors as $error ) {
324 if ( $error['type'] === $type ) {
325 $result[] = $error;
326 }
327 }
328
329 return $result;
330 }
331
339 public function hasMessage( $message ) {
340 if ( $message instanceof MessageSpecifier || $message instanceof MessageValue ) {
341 $message = $message->getKey();
342 }
343
344 foreach ( $this->errors as $error ) {
345 if ( $error['message'] instanceof MessageSpecifier
346 && $error['message']->getKey() === $message
347 ) {
348 return true;
349 } elseif ( $error['message'] === $message ) {
350 return true;
351 }
352 }
353
354 return false;
355 }
356
364 public function hasMessagesExcept( ...$messages ) {
365 $exceptedKeys = [];
366 foreach ( $messages as $message ) {
367 if ( $message instanceof MessageSpecifier || $message instanceof MessageValue ) {
368 $message = $message->getKey();
369 }
370 $exceptedKeys[] = $message;
371 }
372
373 foreach ( $this->errors as $error ) {
374 if ( $error['message'] instanceof MessageSpecifier ) {
375 $actualKey = $error['message']->getKey();
376 } else {
377 $actualKey = $error['message'];
378 }
379 if ( !in_array( $actualKey, $exceptedKeys, true ) ) {
380 return true;
381 }
382 }
383
384 return false;
385 }
386
398 public function replaceMessage( $source, $dest ) {
399 $replaced = false;
400
401 $source = $this->normalizeMessage( $source );
402 $dest = $this->normalizeMessage( $dest );
403
404 foreach ( $this->errors as $index => $error ) {
405 if ( $error['message'] === $source ) {
406 $this->errors[$index]['message'] = $dest;
407 $replaced = true;
408 } elseif ( $error['message'] instanceof MessageSpecifier
409 && $error['message']->getKey() === $source ) {
410 $this->errors[$index]['message'] = $dest;
411 $replaced = true;
412 }
413 }
414
415 return $replaced;
416 }
417
424 public function __toString() {
425 $status = $this->isOK() ? "OK" : "Error";
426 if ( count( $this->errors ) ) {
427 $errorcount = "collected " . ( count( $this->errors ) ) . " message(s) on the way";
428 } else {
429 $errorcount = "no errors detected";
430 }
431 if ( isset( $this->value ) ) {
432 $valstr = gettype( $this->value ) . " value set";
433 if ( is_object( $this->value ) ) {
434 $valstr .= "\"" . get_class( $this->value ) . "\" instance";
435 }
436 } else {
437 $valstr = "no value set";
438 }
439 $out = sprintf( "<%s, %s, %s>",
440 $status,
441 $errorcount,
442 $valstr
443 );
444 if ( count( $this->errors ) > 0 ) {
445 $hdr = sprintf( "+-%'-8s-+-%'-25s-+-%'-36s-+\n", "", "", "" );
446 $out .= "\n";
447 $out .= $hdr;
448 foreach ( $this->errors as $error ) {
449 if ( $error['message'] instanceof MessageSpecifier ) {
450 $key = $error['message']->getKey();
451 $params = $error['message']->getParams();
452 } elseif ( $error['params'] ) {
453 $key = $error['message'];
454 $params = $error['params'];
455 } else {
456 $key = $error['message'];
457 $params = [];
458 }
459
460 $type = $error['type'];
461 $keyChunks = mb_str_split( $key, 25 );
462 $paramsChunks = mb_str_split( $this->flattenParams( $params, " | " ), 36 );
463
464 // array_map(null,...) is like Python's zip()
465 foreach ( array_map( null, [ $type ], $keyChunks, $paramsChunks )
466 as [ $typeChunk, $keyChunk, $paramsChunk ]
467 ) {
468 $out .= sprintf( "| %-8s | %-25s | %-36s |\n",
469 $typeChunk,
470 $keyChunk,
471 $paramsChunk
472 );
473 }
474 }
475 $out .= $hdr;
476 }
477
478 return $out;
479 }
480
487 private function flattenParams( array $params, string $joiner = ', ' ): string {
488 $ret = [];
489 foreach ( $params as $p ) {
490 if ( is_array( $p ) ) {
491 $r = '[ ' . self::flattenParams( $p ) . ' ]';
492 } elseif ( $p instanceof MessageSpecifier ) {
493 $r = '{ ' . $p->getKey() . ': ' . self::flattenParams( $p->getParams() ) . ' }';
494 } else {
495 $r = (string)$p;
496 }
497
498 $ret[] = mb_strlen( $r ) > 100 ? mb_substr( $r, 0, 99 ) . "..." : $r;
499 }
500 return implode( $joiner, $ret );
501 }
502
511 protected function getStatusArray( $type = false ) {
512 $result = [];
513
514 foreach ( $this->getErrors() as $error ) {
515 if ( $type === false || $error['type'] === $type ) {
516 if ( $error['message'] instanceof MessageSpecifier ) {
517 $result[] = array_merge(
518 [ $error['message']->getKey() ],
519 $error['message']->getParams()
520 );
521 } elseif ( $error['params'] ) {
522 $result[] = array_merge( [ $error['message'] ], $error['params'] );
523 } else {
524 $result[] = [ $error['message'] ];
525 }
526 }
527 }
528
529 return $result;
530 }
531
537 private function normalizeMessage( $message ) {
538 if ( $message instanceof MessageValue ) {
539 $converter = new Converter();
540 return $converter->convertMessageValue( $message );
541 }
542
543 return $message;
544 }
545}
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.
$source