MediaWiki  master
MWException.php
Go to the documentation of this file.
1 <?php
29 class MWException extends Exception {
35  private function useOutputPage() {
36  // NOTE: keep in sync with MWExceptionRenderer::useOutputPage
37  return $this->useMessageCache() &&
38  !empty( $GLOBALS['wgFullyInitialised'] ) &&
39  !empty( $GLOBALS['wgOut'] ) &&
40  !defined( 'MEDIAWIKI_INSTALL' ) &&
41  // Don't send a skinned HTTP 500 page to API clients.
42  !defined( 'MW_API' );
43  }
44 
53  public function isLoggable() {
54  return true;
55  }
56 
64  public function useMessageCache() {
65  foreach ( $this->getTrace() as $frame ) {
66  if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
67  return false;
68  }
69  }
70  return true;
71  }
72 
82  public function msg( $key, $fallback, ...$params ) {
83  // NOTE: Keep logic in sync with MWExceptionRenderer::msg.
84  $res = false;
85  if ( $this->useMessageCache() ) {
86  try {
87  $res = wfMessage( $key, ...$params )->text();
88  } catch ( Exception $e ) {
89  }
90  }
91  if ( $res === false ) {
92  // Fallback to static message text and generic sitename.
93  // Avoid live config as this must work before Setup/MediaWikiServices finish.
94  $res = wfMsgReplaceArgs( $fallback, $params );
95  $res = strtr( $res, [
96  '{{SITENAME}}' => 'MediaWiki',
97  ] );
98  }
99  return $res;
100  }
101 
110  public function getHTML() {
112  return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
113  '</p><p>Backtrace:</p><p>' .
114  nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
115  "</p>\n";
116  } else {
117  $logId = WebRequest::getRequestId();
118  $type = static::class;
119  return Html::errorBox(
120  htmlspecialchars(
121  '[' . $logId . '] ' .
122  gmdate( 'Y-m-d H:i:s' ) . ": " .
123  $this->msg( "internalerror-fatal-exception",
124  "Fatal exception of type $1",
125  $type,
126  $logId,
128  )
129  ) ) .
130  "<!-- Set \$wgShowExceptionDetails = true; " .
131  "at the bottom of LocalSettings.php to show detailed " .
132  "debugging information. -->";
133  }
134  }
135 
143  public function getText() {
145  return MWExceptionHandler::getLogMessage( $this ) .
146  "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
147  } else {
148  return "Set \$wgShowExceptionDetails = true; " .
149  "in LocalSettings.php to show detailed debugging information.\n";
150  }
151  }
152 
160  public function getPageTitle() {
161  return $this->msg( 'internalerror', 'Internal error' );
162  }
163 
168  public function reportHTML() {
169  global $wgOut;
170  if ( $this->useOutputPage() ) {
171  $wgOut->prepareErrorPage( $this->getPageTitle() );
172  // Manually set the html title, since sometimes
173  // {{SITENAME}} does not get replaced for exceptions
174  // happening inside message rendering.
175  $wgOut->setHTMLTitle(
176  $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() )
177  );
178 
179  $wgOut->addHTML( $this->getHTML() );
180  // Content-Type is set by OutputPage::output
181  $wgOut->output();
182  } else {
183  self::header( 'Content-Type: text/html; charset=UTF-8' );
184  echo "<!DOCTYPE html>\n" .
185  '<html><head>' .
186  // Mimic OutputPage::setPageTitle behaviour
187  '<title>' .
188  htmlspecialchars( $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() ) ) .
189  '</title>' .
190  '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
191  "</head><body>\n";
192 
193  echo $this->getHTML();
194 
195  echo "</body></html>\n";
196  }
197  }
198 
205  public function report() {
206  if ( defined( 'MW_API' ) ) {
207  self::header( 'MediaWiki-API-Error: internal_api_error_' . static::class );
208  }
209 
210  if ( self::isCommandLine() ) {
211  $message = $this->getText();
212  $this->writeToCommandLine( $message );
213  } else {
214  self::statusHeader( 500 );
215  $this->reportHTML();
216  }
217  }
218 
225  private function writeToCommandLine( $message ) {
226  // T17602: STDERR may not be available
227  if ( !defined( 'MW_PHPUNIT_TEST' ) && defined( 'STDERR' ) ) {
228  fwrite( STDERR, $message );
229  } else {
230  echo $message;
231  }
232  }
233 
240  public static function isCommandLine() {
241  return !empty( $GLOBALS['wgCommandLineMode'] );
242  }
243 
249  private static function header( $header ) {
250  if ( !headers_sent() ) {
251  header( $header );
252  }
253  }
254 
255  private static function statusHeader( $code ) {
256  if ( !headers_sent() ) {
257  HttpStatus::header( $code );
258  }
259  }
260 }
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:10
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgOut
Definition: Setup.php:497
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:29
isLoggable()
Whether to log this exception in the exception debug log.
Definition: MWException.php:53
useMessageCache()
Can the extension use the Message class/wfMessage to get i18n-ed messages?
Definition: MWException.php:64
msg( $key, $fallback,... $params)
Get a message from i18n.
Definition: MWException.php:82
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:343
$header