MediaWiki  master
StatusValue.php
Go to the documentation of this file.
1 <?php
43 class StatusValue {
44 
46  protected $ok = true;
47 
49  protected $errors = [];
50 
52  public $value;
53 
55  public $success = [];
56 
58  public $successCount = 0;
59 
61  public $failCount = 0;
62 
70  public static function newFatal( $message, ...$parameters ) {
71  $result = new static();
72  $result->fatal( $message, ...$parameters );
73  return $result;
74  }
75 
82  public static function newGood( $value = null ) {
83  $result = new static();
84  $result->value = $value;
85  return $result;
86  }
87 
99  public function splitByErrorType() {
100  $errorsOnlyStatusValue = static::newGood();
101  $warningsOnlyStatusValue = static::newGood();
102  $warningsOnlyStatusValue->setResult( true, $this->getValue() );
103  $errorsOnlyStatusValue->setResult( $this->isOK(), $this->getValue() );
104 
105  foreach ( $this->errors as $item ) {
106  if ( $item['type'] === 'warning' ) {
107  $warningsOnlyStatusValue->errors[] = $item;
108  } else {
109  $errorsOnlyStatusValue->errors[] = $item;
110  }
111  }
112 
113  return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ];
114  }
115 
122  public function isGood() {
123  return $this->ok && !$this->errors;
124  }
125 
131  public function isOK() {
132  return $this->ok;
133  }
134 
138  public function getValue() {
139  return $this->value;
140  }
141 
149  public function getErrors() {
150  return $this->errors;
151  }
152 
159  public function setOK( $ok ) {
160  $this->ok = $ok;
161  return $this;
162  }
163 
171  public function setResult( $ok, $value = null ) {
172  $this->ok = (bool)$ok;
173  $this->value = $value;
174  return $this;
175  }
176 
193  private function addError( array $newError ) {
194  if ( $newError[ 'message' ] instanceof MessageSpecifier ) {
195  $isEqual = static function ( $existingError ) use ( $newError ) {
196  if ( $existingError['message'] instanceof MessageSpecifier ) {
197  // compare attributes of both MessageSpecifiers
198  return $newError['message'] == $existingError['message'];
199  } else {
200  return $newError['message']->getKey() === $existingError['message'] &&
201  $newError['message']->getParams() === $existingError['params'];
202  }
203  };
204  } else {
205  $isEqual = static function ( $existingError ) use ( $newError ) {
206  if ( $existingError['message'] instanceof MessageSpecifier ) {
207  return $newError['message'] === $existingError['message']->getKey() &&
208  $newError['params'] === $existingError['message']->getParams();
209  } else {
210  return $newError['message'] === $existingError['message'] &&
211  $newError['params'] === $existingError['params'];
212  }
213  };
214  }
215  foreach ( $this->errors as $index => $existingError ) {
216  if ( $isEqual( $existingError ) ) {
217  if ( $newError[ 'type' ] === 'error' && $existingError[ 'type' ] === 'warning' ) {
218  $this->errors[ $index ][ 'type' ] = 'error';
219  }
220  return $this;
221  }
222  }
223  $this->errors[] = $newError;
224  return $this;
225  }
226 
234  public function warning( $message, ...$parameters ) {
235  return $this->addError( [
236  'type' => 'warning',
237  'message' => $message,
238  'params' => $parameters
239  ] );
240  }
241 
250  public function error( $message, ...$parameters ) {
251  return $this->addError( [
252  'type' => 'error',
253  'message' => $message,
254  'params' => $parameters
255  ] );
256  }
257 
266  public function fatal( $message, ...$parameters ) {
267  $this->ok = false;
268  return $this->error( $message, ...$parameters );
269  }
270 
278  public function merge( $other, $overwriteValue = false ) {
279  foreach ( $other->errors as $error ) {
280  $this->addError( $error );
281  }
282  $this->ok = $this->ok && $other->ok;
283  if ( $overwriteValue ) {
284  $this->value = $other->value;
285  }
286  $this->successCount += $other->successCount;
287  $this->failCount += $other->failCount;
288  return $this;
289  }
290 
301  public function getErrorsByType( $type ) {
302  $result = [];
303  foreach ( $this->errors as $error ) {
304  if ( $error['type'] === $type ) {
305  $result[] = $error;
306  }
307  }
308 
309  return $result;
310  }
311 
319  public function hasMessage( $message ) {
320  if ( $message instanceof MessageSpecifier ) {
321  $message = $message->getKey();
322  }
323  foreach ( $this->errors as $error ) {
324  if ( $error['message'] instanceof MessageSpecifier
325  && $error['message']->getKey() === $message
326  ) {
327  return true;
328  } elseif ( $error['message'] === $message ) {
329  return true;
330  }
331  }
332 
333  return false;
334  }
335 
347  public function replaceMessage( $source, $dest ) {
348  $replaced = false;
349 
350  foreach ( $this->errors as $index => $error ) {
351  if ( $error['message'] === $source ) {
352  $this->errors[$index]['message'] = $dest;
353  $replaced = true;
354  } elseif ( $error['message'] instanceof MessageSpecifier
355  && $error['message']->getKey() === $source ) {
356  $this->errors[$index]['message'] = $dest;
357  $replaced = true;
358  }
359  }
360 
361  return $replaced;
362  }
363 
370  public function __toString() {
371  $status = $this->isOK() ? "OK" : "Error";
372  if ( count( $this->errors ) ) {
373  $errorcount = "collected " . ( count( $this->errors ) ) . " error(s) on the way";
374  } else {
375  $errorcount = "no errors detected";
376  }
377  if ( isset( $this->value ) ) {
378  $valstr = gettype( $this->value ) . " value set";
379  if ( is_object( $this->value ) ) {
380  $valstr .= "\"" . get_class( $this->value ) . "\" instance";
381  }
382  } else {
383  $valstr = "no value set";
384  }
385  $out = sprintf( "<%s, %s, %s>",
386  $status,
387  $errorcount,
388  $valstr
389  );
390  if ( count( $this->errors ) > 0 ) {
391  $hdr = sprintf( "+-%'-4s-+-%'-25s-+-%'-40s-+\n", "", "", "" );
392  $i = 1;
393  $out .= "\n";
394  $out .= $hdr;
395  foreach ( $this->errors as $error ) {
396  if ( $error['message'] instanceof MessageSpecifier ) {
397  $key = $error['message']->getKey();
398  $params = $error['message']->getParams();
399  } elseif ( $error['params'] ) {
400  $key = $error['message'];
401  $params = $error['params'];
402  } else {
403  $key = $error['message'];
404  $params = [];
405  }
406 
407  $keyChunks = str_split( $key, 25 );
408  $paramsChunks = str_split( $this->flattenParams( $params, " | " ), 40 );
409 
410  // array_map(null,...) is like Python's zip()
411  foreach ( array_map( null, [ $i ], $keyChunks, $paramsChunks )
412  as [ $iChunk, $keyChunk, $paramsChunk ]
413  ) {
414  $out .= sprintf( "| %4s | %-25.25s | %-40.40s |\n",
415  $iChunk,
416  $keyChunk,
417  $paramsChunk
418  );
419  }
420 
421  $i++;
422  }
423  $out .= $hdr;
424  }
425 
426  return $out;
427  }
428 
435  private function flattenParams( array $params, string $joiner = ', ' ): string {
436  $ret = [];
437  foreach ( $params as $p ) {
438  if ( is_array( $p ) ) {
439  $r = '[ ' . self::flattenParams( $p ) . ' ]';
440  } elseif ( $p instanceof MessageSpecifier ) {
441  $r = '{ ' . $p->getKey() . ': ' . self::flattenParams( $p->getParams() ) . ' }';
442  } else {
443  $r = (string)$p;
444  }
445 
446  $ret[] = strlen( $r ) > 100 ? substr( $r, 0, 99 ) . "..." : $r;
447  }
448  return implode( $joiner, $ret );
449  }
450 
459  protected function getStatusArray( $type = false ) {
460  $result = [];
461 
462  foreach ( $this->getErrors() as $error ) {
463  if ( $type === false || $error['type'] === $type ) {
464  if ( $error['message'] instanceof MessageSpecifier ) {
465  $result[] = array_merge(
466  [ $error['message']->getKey() ],
467  $error['message']->getParams()
468  );
469  } elseif ( $error['params'] ) {
470  $result[] = array_merge( [ $error['message'] ], $error['params'] );
471  } else {
472  $result[] = [ $error['message'] ];
473  }
474  }
475  }
476 
477  return $result;
478  }
479 }
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: StatusValue.php:43
hasMessage( $message)
Returns true if the specified message is present as a warning or error.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
int $failCount
Counter for batch operations.
Definition: StatusValue.php:61
array[] $errors
Definition: StatusValue.php:49
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...
Definition: StatusValue.php:99
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.
addError(array $newError)
Add a new error to the error array ($this->errors) if that error is not already in the error array.
merge( $other, $overwriteValue=false)
Merge another status object into this one.
__toString()
Returns a string representation of the status for debugging.
flattenParams(array $params, string $joiner=', ')
bool[] $success
Map of (key => bool) to indicate success of each part of batch operations.
Definition: StatusValue.php:55
mixed $value
Definition: StatusValue.php:52
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.
Definition: StatusValue.php:82
int $successCount
Counter for batch operations.
Definition: StatusValue.php:58
$source