MediaWiki REL1_39
MWException.php
Go to the documentation of this file.
1<?php
29class 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() {
111 if ( MWExceptionRenderer::shouldShowExceptionDetails() ) {
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,
127 MWExceptionHandler::getURL()
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() {
144 if ( MWExceptionRenderer::shouldShowExceptionDetails() ) {
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
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode $wgOut
Definition Setup.php:497
static header( $code)
Output an HTTP status code header.
MediaWiki exception.
isLoggable()
Whether to log this exception in the exception debug log.
useMessageCache()
Can the extension use the Message class/wfMessage to get i18n-ed messages?
msg( $key, $fallback,... $params)
Get a message from i18n.
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.
$header