MediaWiki  master
MWException.php
Go to the documentation of this file.
1 <?php
26 class MWException extends Exception {
32  public function useOutputPage() {
33  return $this->useMessageCache() &&
34  !empty( $GLOBALS['wgFullyInitialised'] ) &&
35  !empty( $GLOBALS['wgOut'] ) &&
36  !defined( 'MEDIAWIKI_INSTALL' );
37  }
38 
45  public function isLoggable() {
46  return true;
47  }
48 
54  public function useMessageCache() {
55  global $wgLang;
56 
57  foreach ( $this->getTrace() as $frame ) {
58  if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
59  return false;
60  }
61  }
62 
63  return $wgLang instanceof Language;
64  }
65 
75  public function msg( $key, $fallback, ...$params ) {
76  global $wgSitename;
77 
78  // FIXME: Keep logic in sync with MWExceptionRenderer::msg.
79  $res = false;
80  if ( $this->useMessageCache() ) {
81  try {
82  $res = wfMessage( $key, ...$params )->text();
83  } catch ( Exception $e ) {
84  }
85  }
86  if ( $res === false ) {
87  $res = wfMsgReplaceArgs( $fallback, $params );
88  // If an exception happens inside message rendering,
89  // {{SITENAME}} sometimes won't be replaced.
90  $res = strtr( $res, [
91  '{{SITENAME}}' => $wgSitename,
92  ] );
93  }
94  return $res;
95  }
96 
104  public function getHTML() {
106 
107  if ( $wgShowExceptionDetails ) {
108  return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
109  '</p><p>Backtrace:</p><p>' .
110  nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
111  "</p>\n";
112  } else {
113  $logId = WebRequest::getRequestId();
114  $type = static::class;
115  return Html::errorBox(
116  htmlspecialchars(
117  '[' . $logId . '] ' .
118  gmdate( 'Y-m-d H:i:s' ) . ": " .
119  $this->msg( "internalerror-fatal-exception",
120  "Fatal exception of type $1",
121  $type,
122  $logId,
124  )
125  ) ) .
126  "<!-- Set \$wgShowExceptionDetails = true; " .
127  "at the bottom of LocalSettings.php to show detailed " .
128  "debugging information. -->";
129  }
130  }
131 
139  public function getText() {
141 
142  if ( $wgShowExceptionDetails ) {
143  return MWExceptionHandler::getLogMessage( $this ) .
144  "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
145  } else {
146  return "Set \$wgShowExceptionDetails = true; " .
147  "in LocalSettings.php to show detailed debugging information.\n";
148  }
149  }
150 
156  public function getPageTitle() {
157  return $this->msg( 'internalerror', 'Internal error' );
158  }
159 
163  public function reportHTML() {
164  global $wgOut, $wgSitename;
165  if ( $this->useOutputPage() ) {
166  $wgOut->prepareErrorPage( $this->getPageTitle() );
167  // Manually set the html title, since sometimes
168  // {{SITENAME}} does not get replaced for exceptions
169  // happening inside message rendering.
170  $wgOut->setHTMLTitle(
171  $this->msg(
172  'pagetitle',
173  "$1 - $wgSitename",
174  $this->getPageTitle()
175  )
176  );
177 
178  $wgOut->addHTML( $this->getHTML() );
179 
180  $wgOut->output();
181  } else {
182  self::header( 'Content-Type: text/html; charset=utf-8' );
183  echo "<!DOCTYPE html>\n" .
184  '<html><head>' .
185  // Mimick OutputPage::setPageTitle behaviour
186  '<title>' .
187  htmlspecialchars( $this->msg( 'pagetitle', "$1 - $wgSitename", $this->getPageTitle() ) ) .
188  '</title>' .
189  '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
190  "</head><body>\n";
191 
192  echo $this->getHTML();
193 
194  echo "</body></html>\n";
195  }
196  }
197 
202  public function report() {
203  global $wgMimeType;
204 
205  if ( defined( 'MW_API' ) ) {
206  // Unhandled API exception, we can't be sure that format printer is alive
207  self::header( 'MediaWiki-API-Error: internal_api_error_' . static::class );
208  wfHttpError( 500, 'Internal Server Error', $this->getText() );
209  } elseif ( self::isCommandLine() ) {
210  $message = $this->getText();
211  $this->writeToCommandLine( $message );
212  } else {
213  self::statusHeader( 500 );
214  self::header( "Content-Type: $wgMimeType; charset=utf-8" );
215 
216  $this->reportHTML();
217  }
218  }
219 
226  private function writeToCommandLine( $message ) {
227  // T17602: STDERR may not be available
228  if ( !defined( 'MW_PHPUNIT_TEST' ) && defined( 'STDERR' ) ) {
229  fwrite( STDERR, $message );
230  } else {
231  echo $message;
232  }
233  }
234 
241  public static function isCommandLine() {
242  return !empty( $GLOBALS['wgCommandLineMode'] );
243  }
244 
250  private static function header( $header ) {
251  if ( !headers_sent() ) {
252  header( $header );
253  }
254  }
255 
256  private static function statusHeader( $code ) {
257  if ( !headers_sent() ) {
258  HttpStatus::header( $code );
259  }
260  }
261 }
$wgMimeType
$wgMimeType
The default Content-Type header.
Definition: DefaultSettings.php:3261
$fallback
$fallback
Definition: MessagesAb.php:11
wfMsgReplaceArgs
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
Definition: GlobalFunctions.php:1298
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1263
$res
$res
Definition: testCompression.php:54
MWException\isLoggable
isLoggable()
Whether to log this exception in the exception debug log.
Definition: MWException.php:45
MWException\useMessageCache
useMessageCache()
Can the extension use the Message class/wfMessage to get i18n-ed messages?
Definition: MWException.php:54
MWException\isCommandLine
static isCommandLine()
Check whether we are in command line mode or not to report the exception in the correct format.
Definition: MWException.php:241
MWException
MediaWiki exception.
Definition: MWException.php:26
MWException\getText
getText()
Get the text to display when reporting the error on the command line.
Definition: MWException.php:139
MWExceptionHandler\getURL
static getURL()
If the exception occurred in the course of responding to a request, returns the requested URL.
Definition: MWExceptionHandler.php:433
MWExceptionHandler\getLogMessage
static getLogMessage( $e)
Get a message formatting the exception message and its origin.
Definition: MWExceptionHandler.php:448
MWException\getPageTitle
getPageTitle()
Return the title of the page when reporting this error in a HTTP response.
Definition: MWException.php:156
MWException\getHTML
getHTML()
If $wgShowExceptionDetails is true, return a HTML message with a backtrace to the error,...
Definition: MWException.php:104
$wgLang
$wgLang
Definition: Setup.php:858
MWException\report
report()
Output a report about the exception and takes care of formatting.
Definition: MWException.php:202
$header
$header
Definition: updateCredits.php:41
MWException\reportHTML
reportHTML()
Output the exception report using HTML.
Definition: MWException.php:163
$wgSitename
$wgSitename
Name of the site.
Definition: DefaultSettings.php:80
MWException\msg
msg( $key, $fallback,... $params)
Get a message from i18n.
Definition: MWException.php:75
MWException\header
static header( $header)
Send a header, if we haven't already sent them.
Definition: MWException.php:250
wfHttpError
wfHttpError( $code, $label, $desc)
Provide a simple HTTP error.
Definition: GlobalFunctions.php:1658
HttpStatus\header
static header( $code)
Output an HTTP status code header.
Definition: HttpStatus.php:96
WebRequest\getRequestId
static getRequestId()
Get the unique request ID.
Definition: WebRequest.php:309
$wgShowExceptionDetails
$wgShowExceptionDetails
If set to true, uncaught exceptions will print the exception message and a complete stack trace to ou...
Definition: DefaultSettings.php:6308
MWException\writeToCommandLine
writeToCommandLine( $message)
Write a message to stderr falling back to stdout if stderr unavailable.
Definition: MWException.php:226
$wgOut
$wgOut
Definition: Setup.php:863
MWExceptionHandler\getRedactedTraceAsString
static getRedactedTraceAsString( $e)
Generate a string representation of an exception's stack trace.
Definition: MWExceptionHandler.php:342
MWException\statusHeader
static statusHeader( $code)
Definition: MWException.php:256
Language
Internationalisation code.
Definition: Language.php:39
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6
MWException\useOutputPage
useOutputPage()
Should the exception use $wgOut to output the error?
Definition: MWException.php:32
$type
$type
Definition: testCompression.php:50