MediaWiki REL1_41
Status.php
Go to the documentation of this file.
1<?php
24
25use ApiMessage;
27use Language;
31use Message;
34use ParserOutput;
35use RuntimeException;
36use StatusValue;
37use UnexpectedValueException;
38
58class Status extends StatusValue {
60 public $cleanCallback = false;
61
64
76 public static function wrap( $sv ) {
77 if ( $sv instanceof static ) {
78 return $sv;
79 }
80
81 $result = new static();
82 $result->ok =& $sv->ok;
83 $result->errors =& $sv->errors;
84 $result->value =& $sv->value;
85 $result->successCount =& $sv->successCount;
86 $result->failCount =& $sv->failCount;
87 $result->success =& $sv->success;
88 $result->statusData =& $sv->statusData;
89
90 return $result;
91 }
92
100 public function __get( $name ) {
101 if ( $name === 'ok' ) {
102 return $this->isOK();
103 }
104 if ( $name === 'errors' ) {
105 return $this->getErrors();
106 }
107
108 throw new RuntimeException( "Cannot get '$name' property." );
109 }
110
119 public function __set( $name, $value ) {
120 if ( $name === 'ok' ) {
121 $this->setOK( $value );
122 } elseif ( !property_exists( $this, $name ) ) {
123 // Caller is using undeclared ad-hoc properties
124 $this->$name = $value;
125 } else {
126 throw new RuntimeException( "Cannot set '$name' property." );
127 }
128 }
129
141 $this->messageLocalizer = $messageLocalizer;
142 }
143
155 public function splitByErrorType() {
156 [ $errorsOnlyStatus, $warningsOnlyStatus ] = parent::splitByErrorType();
157 // phan/phan#2133?
158 '@phan-var Status $errorsOnlyStatus';
159 '@phan-var Status $warningsOnlyStatus';
160
161 if ( $this->messageLocalizer ) {
162 $errorsOnlyStatus->setMessageLocalizer( $this->messageLocalizer );
163 $warningsOnlyStatus->setMessageLocalizer( $this->messageLocalizer );
164 }
165 $errorsOnlyStatus->cleanCallback = $warningsOnlyStatus->cleanCallback = $this->cleanCallback;
166
167 return [ $errorsOnlyStatus, $warningsOnlyStatus ];
168 }
169
175 public function getStatusValue() {
176 return $this;
177 }
178
183 protected function cleanParams( array $params ) {
184 if ( !$this->cleanCallback ) {
185 return $params;
186 }
187 $cleanParams = [];
188 foreach ( $params as $i => $param ) {
189 $cleanParams[$i] = call_user_func( $this->cleanCallback, $param );
190 }
191 return $cleanParams;
192 }
193
203 public function getWikiText( $shortContext = false, $longContext = false, $lang = null ) {
204 $rawErrors = $this->getErrors();
205 if ( count( $rawErrors ) === 0 ) {
206 if ( $this->isOK() ) {
207 $this->fatal(
208 'internalerror_info',
209 __METHOD__ . " called for a good result, this is incorrect\n"
210 );
211 } else {
212 $this->fatal(
213 'internalerror_info',
214 __METHOD__ . ": Invalid result object: no error text but not OK\n"
215 );
216 }
217 $rawErrors = $this->getErrors(); // just added a fatal
218 }
219 if ( count( $rawErrors ) === 1 ) {
220 $s = $this->getErrorMessage( $rawErrors[0], $lang )->plain();
221 if ( $shortContext ) {
222 $s = $this->msgInLang( $shortContext, $lang, $s )->plain();
223 } elseif ( $longContext ) {
224 $s = $this->msgInLang( $longContext, $lang, "* $s\n" )->plain();
225 }
226 } else {
227 $errors = $this->getErrorMessageArray( $rawErrors, $lang );
228 foreach ( $errors as &$error ) {
229 $error = $error->plain();
230 }
231 $s = '* ' . implode( "\n* ", $errors ) . "\n";
232 if ( $longContext ) {
233 $s = $this->msgInLang( $longContext, $lang, $s )->plain();
234 } elseif ( $shortContext ) {
235 $s = $this->msgInLang( $shortContext, $lang, "\n$s\n" )->plain();
236 }
237 }
238 return $s;
239 }
240
261 public function getMessage( $shortContext = false, $longContext = false, $lang = null ) {
262 $rawErrors = $this->getErrors();
263 if ( count( $rawErrors ) === 0 ) {
264 if ( $this->isOK() ) {
265 $this->fatal(
266 'internalerror_info',
267 __METHOD__ . " called for a good result, this is incorrect\n"
268 );
269 } else {
270 $this->fatal(
271 'internalerror_info',
272 __METHOD__ . ": Invalid result object: no error text but not OK\n"
273 );
274 }
275 $rawErrors = $this->getErrors(); // just added a fatal
276 }
277 if ( count( $rawErrors ) === 1 ) {
278 $s = $this->getErrorMessage( $rawErrors[0], $lang );
279 if ( $shortContext ) {
280 $s = $this->msgInLang( $shortContext, $lang, $s );
281 } elseif ( $longContext ) {
282 $wrapper = new RawMessage( "* \$1\n" );
283 $wrapper->params( $s )->parse();
284 $s = $this->msgInLang( $longContext, $lang, $wrapper );
285 }
286 } else {
287 $msgs = $this->getErrorMessageArray( $rawErrors, $lang );
288 $msgCount = count( $msgs );
289
290 $s = new RawMessage( '* $' . implode( "\n* \$", range( 1, $msgCount ) ) );
291 $s->params( $msgs )->parse();
292
293 if ( $longContext ) {
294 $s = $this->msgInLang( $longContext, $lang, $s );
295 } elseif ( $shortContext ) {
296 $wrapper = new RawMessage( "\n\$1\n", [ $s ] );
297 $wrapper->parse();
298 $s = $this->msgInLang( $shortContext, $lang, $wrapper );
299 }
300 }
301
302 return $s;
303 }
304
313 public function getPsr3MessageAndContext(): array {
314 if ( count( $this->errors ) === 1 ) {
315 // identical to getMessage( false, false, 'en' ) when there's just one error
316 $message = $this->getErrorMessage( $this->errors[0], 'en' );
317
318 $text = null;
319 if ( in_array( get_class( $message ), [ Message::class, ApiMessage::class ], true ) ) {
320 // Fall back to getWikiText for rawmessage, which is just a placeholder for non-translated text.
321 // Turning the entire message into a context parameter wouldn't be useful.
322 if ( $message->getKey() === 'rawmessage' ) {
323 return [ $this->getWikiText( false, false, 'en' ), [] ];
324 }
325 // $1,$2... will be left as-is when no parameters are provided.
326 $text = $this->msgInLang( $message->getKey(), 'en' )->plain();
327 } elseif ( in_array( get_class( $message ), [ RawMessage::class, ApiRawMessage::class ], true ) ) {
328 $text = $message->getKey();
329 } else {
330 // Unknown Message subclass, we can't be sure how it marks parameters. Fall back to getWikiText.
331 return [ $this->getWikiText( false, false, 'en' ), [] ];
332 }
333
334 $context = [];
335 $i = 1;
336 foreach ( $message->getParams() as $param ) {
337 if ( is_array( $param ) && count( $param ) === 1 ) {
338 // probably Message::numParam() or similar
339 $param = reset( $param );
340 }
341 if ( is_int( $param ) || is_float( $param ) || is_string( $param ) ) {
342 $context["parameter$i"] = $param;
343 } else {
344 // Parameter is not of a safe type, fall back to getWikiText.
345 return [ $this->getWikiText( false, false, 'en' ), [] ];
346 }
347
348 $text = str_replace( "\$$i", "{parameter$i}", $text );
349
350 $i++;
351 }
352
353 return [ $text, $context ];
354 }
355 // Parameters cannot be easily extracted, fall back to getWikiText,
356 return [ $this->getWikiText( false, false, 'en' ), [] ];
357 }
358
369 protected function getErrorMessage( $error, $lang = null ) {
370 if ( is_array( $error ) ) {
371 if ( isset( $error['message'] ) && $error['message'] instanceof Message ) {
372 // Apply context from MessageLocalizer even if we have a Message object already
373 $msg = $this->msg( $error['message'] );
374 } elseif ( isset( $error['message'] ) && isset( $error['params'] ) ) {
375 $msg = $this->msg(
376 $error['message'],
377 array_map( static function ( $param ) {
378 return is_string( $param ) ? wfEscapeWikiText( $param ) : $param;
379 }, $this->cleanParams( $error['params'] ) )
380 );
381 } else {
382 $msgName = array_shift( $error );
383 $msg = $this->msg(
384 $msgName,
385 array_map( static function ( $param ) {
386 return is_string( $param ) ? wfEscapeWikiText( $param ) : $param;
387 }, $this->cleanParams( $error ) )
388 );
389 }
390 } elseif ( is_string( $error ) ) {
391 $msg = $this->msg( $error );
392 } else {
393 throw new UnexpectedValueException( 'Got ' . get_class( $error ) . ' for key.' );
394 }
395
396 if ( $lang ) {
397 $msg->inLanguage( $lang );
398 }
399 return $msg;
400 }
401
410 public function getHTML( $shortContext = false, $longContext = false, $lang = null ) {
411 $text = $this->getWikiText( $shortContext, $longContext, $lang );
412 $out = MediaWikiServices::getInstance()->getMessageCache()
413 ->parse( $text, null, true, true, $lang );
414 return $out instanceof ParserOutput
415 ? $out->getText( [ 'enableSectionEditLinks' => false ] )
416 : $out;
417 }
418
425 protected function getErrorMessageArray( $errors, $lang = null ) {
426 return array_map( function ( $e ) use ( $lang ) {
427 return $this->getErrorMessage( $e, $lang );
428 }, $errors );
429 }
430
438 public function getErrorsArray() {
439 return $this->getStatusArray( 'error' );
440 }
441
449 public function getWarningsArray() {
450 return $this->getStatusArray( 'warning' );
451 }
452
460 public function __sleep() {
461 $keys = array_keys( get_object_vars( $this ) );
462 return array_diff( $keys, [ 'cleanCallback', 'messageLocalizer' ] );
463 }
464
468 public function __wakeup() {
469 $this->cleanCallback = false;
470 $this->messageLocalizer = null;
471 }
472
478 private function msg( $key, ...$params ): Message {
479 if ( $this->messageLocalizer ) {
480 return $this->messageLocalizer->msg( $key, ...$params );
481 } else {
482 return wfMessage( $key, ...$params );
483 }
484 }
485
492 private function msgInLang( $key, $lang, ...$params ): Message {
493 $msg = $this->msg( $key, ...$params );
494 if ( $lang ) {
495 $msg->inLanguage( $lang );
496 }
497 return $msg;
498 }
499}
500
504class_alias( Status::class, 'Status' );
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:88
Extension of Message implementing IApiMessage.
Extension of RawMessage implementing IApiMessage.
Base class for language-specific code.
Definition Language.php:63
Variant of the Message class.
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:58
getWikiText( $shortContext=false, $longContext=false, $lang=null)
Get the error list as a wikitext formatted list.
Definition Status.php:203
splitByErrorType()
Splits this Status object into two new Status objects, one which contains only the error messages,...
Definition Status.php:155
cleanParams(array $params)
Definition Status.php:183
getWarningsArray()
Get the list of warnings (but not errors)
Definition Status.php:449
__set( $name, $value)
Change operation result Backwards compatibility logic.
Definition Status.php:119
getMessage( $shortContext=false, $longContext=false, $lang=null)
Get a bullet list of the errors as a Message object.
Definition Status.php:261
__sleep()
Don't save the callback when serializing, because Closures can't be serialized and we're going to cle...
Definition Status.php:460
getErrorMessageArray( $errors, $lang=null)
Return an array with a Message object for each error.
Definition Status.php:425
static wrap( $sv)
Succinct helper method to wrap a StatusValue.
Definition Status.php:76
getErrorMessage( $error, $lang=null)
Return the message for a single error.
Definition Status.php:369
callable false $cleanCallback
Definition Status.php:60
__wakeup()
Sanitize the callback parameter on wakeup, to avoid arbitrary execution.
Definition Status.php:468
getHTML( $shortContext=false, $longContext=false, $lang=null)
Get the error message as HTML.
Definition Status.php:410
getErrorsArray()
Get the list of errors (but not warnings)
Definition Status.php:438
getStatusValue()
Returns the wrapped StatusValue object.
Definition Status.php:175
__get( $name)
Backwards compatibility logic.
Definition Status.php:100
getPsr3MessageAndContext()
Try to convert the status to a PSR-3 friendly format.
Definition Status.php:313
setMessageLocalizer(MessageLocalizer $messageLocalizer)
Makes this Status object use the given localizer instead of the global one.
Definition Status.php:140
MessageLocalizer null $messageLocalizer
Definition Status.php:63
Stub object for the user language.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
inLanguage( $lang)
Request the message in any language that is supported.
Definition Message.php:837
Rendered output of a wiki page, as parsed from wikitext.
getText( $options=[])
Get the output HTML.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
array[] $errors
getErrors()
Get the list of errors.
setOK( $ok)
Change operation status.
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.
Interface for localizing messages in MediaWiki.