MediaWiki  master
MWException.php
Go to the documentation of this file.
1 <?php
30 class MWException extends Exception {
36  private function useOutputPage() {
37  // NOTE: keep in sync with MWExceptionRenderer::useOutputPage
38  return $this->useMessageCache() &&
39  !empty( $GLOBALS['wgFullyInitialised'] ) &&
40  !empty( $GLOBALS['wgOut'] ) &&
41  !defined( 'MEDIAWIKI_INSTALL' ) &&
42  // Don't send a skinned HTTP 500 page to API clients.
43  !defined( 'MW_API' );
44  }
45 
54  public function isLoggable() {
55  return true;
56  }
57 
65  public function useMessageCache() {
66  foreach ( $this->getTrace() as $frame ) {
67  if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
68  return false;
69  }
70  }
71  return true;
72  }
73 
83  public function msg( $key, $fallback, ...$params ) {
84  // NOTE: Keep logic in sync with MWExceptionRenderer::msg.
85  $res = false;
86  if ( $this->useMessageCache() ) {
87  try {
88  $res = wfMessage( $key, ...$params )->text();
89  } catch ( Exception $e ) {
90  }
91  }
92  if ( $res === false ) {
93  // Fallback to static message text and generic sitename.
94  // Avoid live config as this must work before Setup/MediaWikiServices finish.
95  $res = wfMsgReplaceArgs( $fallback, $params );
96  $res = strtr( $res, [
97  '{{SITENAME}}' => 'MediaWiki',
98  ] );
99  }
100  return $res;
101  }
102 
111  public function getHTML() {
113  return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
114  '</p><p>Backtrace:</p><p>' .
115  nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
116  "</p>\n";
117  } else {
118  $logId = WebRequest::getRequestId();
119  $type = static::class;
120  return Html::errorBox(
121  htmlspecialchars(
122  '[' . $logId . '] ' .
123  gmdate( 'Y-m-d H:i:s' ) . ": " .
124  $this->msg( "internalerror-fatal-exception",
125  "Fatal exception of type $1",
126  $type,
127  $logId,
129  )
130  ) ) .
131  "<!-- Set \$wgShowExceptionDetails = true; " .
132  "at the bottom of LocalSettings.php to show detailed " .
133  "debugging information. -->";
134  }
135  }
136 
144  public function getText() {
146  return MWExceptionHandler::getLogMessage( $this ) .
147  "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
148  } else {
149  return "Set \$wgShowExceptionDetails = true; " .
150  "in LocalSettings.php to show detailed debugging information.\n";
151  }
152  }
153 
161  public function getPageTitle() {
162  return $this->msg( 'internalerror', 'Internal error' );
163  }
164 
169  public function reportHTML() {
170  global $wgOut;
171  if ( $this->useOutputPage() ) {
172  $wgOut->prepareErrorPage( $this->getPageTitle() );
173  // Manually set the html title, since sometimes
174  // {{SITENAME}} does not get replaced for exceptions
175  // happening inside message rendering.
176  $wgOut->setHTMLTitle(
177  $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() )
178  );
179 
180  $wgOut->addHTML( $this->getHTML() );
181  // Content-Type is set by OutputPage::output
182  $wgOut->output();
183  } else {
184  self::header( 'Content-Type: text/html; charset=UTF-8' );
185  echo "<!DOCTYPE html>\n" .
186  '<html><head>' .
187  // Mimic OutputPage::setPageTitle behaviour
188  '<title>' .
189  htmlspecialchars( $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() ) ) .
190  '</title>' .
191  '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
192  "</head><body>\n";
193 
194  echo $this->getHTML();
195 
196  echo "</body></html>\n";
197  }
198  }
199 
206  public function report() {
207  if ( defined( 'MW_API' ) ) {
208  self::header( 'MediaWiki-API-Error: internal_api_error_' . static::class );
209  }
210 
211  if ( self::isCommandLine() ) {
212  $message = $this->getText();
213  $this->writeToCommandLine( $message );
214  } else {
215  self::statusHeader( 500 );
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 }
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
$fallback
Definition: MessagesAb.php:8
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgOut
Definition: Setup.php:508
static errorBox( $html, $heading='', $className='')
Return an error box.
Definition: Html.php:788
static header( $code)
Output an HTTP status code header.
Definition: HttpStatus.php:96
static getRedactedTraceAsString(Throwable $e)
Generate a string representation of a throwable's stack trace.
static getLogMessage(Throwable $e)
Get a message formatting the throwable message and its origin.
static getURL()
If the exception occurred in the course of responding to a request, returns the requested URL.
MediaWiki exception.
Definition: MWException.php:30
isLoggable()
Whether to log this exception in the exception debug log.
Definition: MWException.php:54
useMessageCache()
Can the extension use the Message class/wfMessage to get i18n-ed messages?
Definition: MWException.php:65
msg( $key, $fallback,... $params)
Get a message from i18n.
Definition: MWException.php:83
getHTML()
Format an HTML message for the current exception object.
static isCommandLine()
Check whether we are in command line mode or not to report the exception in the correct format.
report()
Output a report about the exception and takes care of formatting.
getPageTitle()
Return the title of the page when reporting this error in a HTTP response.
reportHTML()
Output the exception report using HTML.
getText()
Format plain text message for the current exception object.
static getRequestId()
Get the current request ID.
Definition: WebRequest.php:342
$header