MediaWiki REL1_39
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
73 public static function newFatal( $message, ...$parameters ) {
74 $result = new static();
75 $result->fatal( $message, ...$parameters );
76 return $result;
77 }
78
85 public static function newGood( $value = null ) {
86 $result = new static();
87 $result->value = $value;
88 return $result;
89 }
90
102 public function splitByErrorType() {
103 $errorsOnlyStatusValue = static::newGood();
104 $warningsOnlyStatusValue = static::newGood();
105 $warningsOnlyStatusValue->setResult( true, $this->getValue() );
106 $errorsOnlyStatusValue->setResult( $this->isOK(), $this->getValue() );
107
108 foreach ( $this->errors as $item ) {
109 if ( $item['type'] === 'warning' ) {
110 $warningsOnlyStatusValue->errors[] = $item;
111 } else {
112 $errorsOnlyStatusValue->errors[] = $item;
113 }
114 }
115
116 return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ];
117 }
118
125 public function isGood() {
126 return $this->ok && !$this->errors;
127 }
128
134 public function isOK() {
135 return $this->ok;
136 }
137
141 public function getValue() {
142 return $this->value;
143 }
144
152 public function getErrors() {
153 return $this->errors;
154 }
155
162 public function setOK( $ok ) {
163 $this->ok = $ok;
164 return $this;
165 }
166
174 public function setResult( $ok, $value = null ) {
175 $this->ok = (bool)$ok;
176 $this->value = $value;
177 return $this;
178 }
179
196 private function addError( array $newError ) {
197 if ( $newError[ 'message' ] instanceof MessageSpecifier ) {
198 $isEqual = static function ( $existingError ) use ( $newError ) {
199 if ( $existingError['message'] instanceof MessageSpecifier ) {
200 // compare attributes of both MessageSpecifiers
201 return $newError['message'] == $existingError['message'];
202 } else {
203 return $newError['message']->getKey() === $existingError['message'] &&
204 $newError['message']->getParams() === $existingError['params'];
205 }
206 };
207 } else {
208 $isEqual = static function ( $existingError ) use ( $newError ) {
209 if ( $existingError['message'] instanceof MessageSpecifier ) {
210 return $newError['message'] === $existingError['message']->getKey() &&
211 $newError['params'] === $existingError['message']->getParams();
212 } else {
213 return $newError['message'] === $existingError['message'] &&
214 $newError['params'] === $existingError['params'];
215 }
216 };
217 }
218 foreach ( $this->errors as $index => $existingError ) {
219 if ( $isEqual( $existingError ) ) {
220 if ( $newError[ 'type' ] === 'error' && $existingError[ 'type' ] === 'warning' ) {
221 $this->errors[ $index ][ 'type' ] = 'error';
222 }
223 return $this;
224 }
225 }
226 $this->errors[] = $newError;
227 return $this;
228 }
229
237 public function warning( $message, ...$parameters ) {
238 $message = $this->normalizeMessage( $message, $parameters );
239
240 return $this->addError( [
241 'type' => 'warning',
242 'message' => $message,
243 'params' => $parameters
244 ] );
245 }
246
255 public function error( $message, ...$parameters ) {
256 $message = $this->normalizeMessage( $message, $parameters );
257
258 return $this->addError( [
259 'type' => 'error',
260 'message' => $message,
261 'params' => $parameters
262 ] );
263 }
264
273 public function fatal( $message, ...$parameters ) {
274 $this->ok = false;
275 return $this->error( $message, ...$parameters );
276 }
277
285 public function merge( $other, $overwriteValue = false ) {
286 foreach ( $other->errors as $error ) {
287 $this->addError( $error );
288 }
289 $this->ok = $this->ok && $other->ok;
290 if ( $overwriteValue ) {
291 $this->value = $other->value;
292 }
293 $this->successCount += $other->successCount;
294 $this->failCount += $other->failCount;
295 return $this;
296 }
297
308 public function getErrorsByType( $type ) {
309 $result = [];
310 foreach ( $this->errors as $error ) {
311 if ( $error['type'] === $type ) {
312 $result[] = $error;
313 }
314 }
315
316 return $result;
317 }
318
326 public function hasMessage( $message ) {
327 if ( $message instanceof MessageSpecifier ) {
328 $message = $message->getKey();
329 } elseif ( $message instanceof MessageValue ) {
330 $message = $message->getKey();
331 }
332
333 foreach ( $this->errors as $error ) {
334 if ( $error['message'] instanceof MessageSpecifier
335 && $error['message']->getKey() === $message
336 ) {
337 return true;
338 } elseif ( $error['message'] === $message ) {
339 return true;
340 }
341 }
342
343 return false;
344 }
345
357 public function replaceMessage( $source, $dest ) {
358 $replaced = false;
359
360 $source = $this->normalizeMessage( $source );
361 $dest = $this->normalizeMessage( $dest );
362
363 foreach ( $this->errors as $index => $error ) {
364 if ( $error['message'] === $source ) {
365 $this->errors[$index]['message'] = $dest;
366 $replaced = true;
367 } elseif ( $error['message'] instanceof MessageSpecifier
368 && $error['message']->getKey() === $source ) {
369 $this->errors[$index]['message'] = $dest;
370 $replaced = true;
371 }
372 }
373
374 return $replaced;
375 }
376
383 public function __toString() {
384 $status = $this->isOK() ? "OK" : "Error";
385 if ( count( $this->errors ) ) {
386 $errorcount = "collected " . ( count( $this->errors ) ) . " message(s) on the way";
387 } else {
388 $errorcount = "no errors detected";
389 }
390 if ( isset( $this->value ) ) {
391 $valstr = gettype( $this->value ) . " value set";
392 if ( is_object( $this->value ) ) {
393 $valstr .= "\"" . get_class( $this->value ) . "\" instance";
394 }
395 } else {
396 $valstr = "no value set";
397 }
398 $out = sprintf( "<%s, %s, %s>",
399 $status,
400 $errorcount,
401 $valstr
402 );
403 if ( count( $this->errors ) > 0 ) {
404 $hdr = sprintf( "+-%'-8s-+-%'-25s-+-%'-36s-+\n", "", "", "" );
405 $i = 1;
406 $out .= "\n";
407 $out .= $hdr;
408 foreach ( $this->errors as $error ) {
409 if ( $error['message'] instanceof MessageSpecifier ) {
410 $key = $error['message']->getKey();
411 $params = $error['message']->getParams();
412 } elseif ( $error['params'] ) {
413 $key = $error['message'];
414 $params = $error['params'];
415 } else {
416 $key = $error['message'];
417 $params = [];
418 }
419
420 $type = $error['type'];
421 $keyChunks = mb_str_split( $key, 25 );
422 $paramsChunks = mb_str_split( $this->flattenParams( $params, " | " ), 36 );
423
424 // array_map(null,...) is like Python's zip()
425 foreach ( array_map( null, [ $type ], $keyChunks, $paramsChunks )
426 as [ $typeChunk, $keyChunk, $paramsChunk ]
427 ) {
428 $out .= sprintf( "| %-8s | %-25s | %-36s |\n",
429 $typeChunk,
430 $keyChunk,
431 $paramsChunk
432 );
433 }
434
435 $i++;
436 }
437 $out .= $hdr;
438 }
439
440 return $out;
441 }
442
449 private function flattenParams( array $params, string $joiner = ', ' ): string {
450 $ret = [];
451 foreach ( $params as $p ) {
452 if ( is_array( $p ) ) {
453 $r = '[ ' . self::flattenParams( $p ) . ' ]';
454 } elseif ( $p instanceof MessageSpecifier ) {
455 $r = '{ ' . $p->getKey() . ': ' . self::flattenParams( $p->getParams() ) . ' }';
456 } else {
457 $r = (string)$p;
458 }
459
460 $ret[] = mb_strlen( $r ) > 100 ? mb_substr( $r, 0, 99 ) . "..." : $r;
461 }
462 return implode( $joiner, $ret );
463 }
464
473 protected function getStatusArray( $type = false ) {
474 $result = [];
475
476 foreach ( $this->getErrors() as $error ) {
477 if ( $type === false || $error['type'] === $type ) {
478 if ( $error['message'] instanceof MessageSpecifier ) {
479 $result[] = array_merge(
480 [ $error['message']->getKey() ],
481 $error['message']->getParams()
482 );
483 } elseif ( $error['params'] ) {
484 $result[] = array_merge( [ $error['message'] ], $error['params'] );
485 } else {
486 $result[] = [ $error['message'] ];
487 }
488 }
489 }
490
491 return $result;
492 }
493
500 private function normalizeMessage( $message, array $parameters = [] ) {
501 if ( $message instanceof MessageValue ) {
502 $converter = new Converter();
503 return $converter->convertMessageValue( $message );
504 }
505
506 return $message;
507 }
508}
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.
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.
__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