MediaWiki master
MWException.php
Go to the documentation of this file.
1<?php
23
33class MWException extends Exception {
39 private function useOutputPage() {
40 // NOTE: keep in sync with MWExceptionRenderer::useOutputPage
41 return $this->useMessageCache() &&
42 !empty( $GLOBALS['wgFullyInitialised'] ) &&
43 !empty( $GLOBALS['wgOut'] ) &&
44 !defined( 'MEDIAWIKI_INSTALL' ) &&
45 // Don't send a skinned HTTP 500 page to API clients.
46 !defined( 'MW_API' );
47 }
48
57 public function isLoggable() {
58 return true;
59 }
60
68 public function useMessageCache() {
69 foreach ( $this->getTrace() as $frame ) {
70 if ( isset( $frame['class'] ) && $frame['class'] === LocalisationCache::class ) {
71 return false;
72 }
73 }
74 return true;
75 }
76
86 public function msg( $key, $fallback, ...$params ) {
87 // NOTE: Keep logic in sync with MWExceptionRenderer::msg.
88 $res = false;
89 if ( $this->useMessageCache() ) {
90 try {
91 $res = wfMessage( $key, ...$params )->text();
92 } catch ( Exception $e ) {
93 }
94 }
95 if ( $res === false ) {
96 // Fallback to static message text and generic sitename.
97 // Avoid live config as this must work before Setup/MediaWikiServices finish.
99 $res = strtr( $res, [
100 '{{SITENAME}}' => 'MediaWiki',
101 ] );
102 }
103 return $res;
104 }
105
113 public function getHTML() {
114 wfDeprecated( __METHOD__, '1.42' );
115 if ( MWExceptionRenderer::shouldShowExceptionDetails() ) {
116 return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
117 '</p><p>Backtrace:</p><p>' .
118 nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
119 "</p>\n";
120 } else {
121 $logId = WebRequest::getRequestId();
122 $type = static::class;
123 return Html::errorBox(
124 htmlspecialchars(
125 '[' . $logId . '] ' .
126 gmdate( 'Y-m-d H:i:s' ) . ": " .
127 $this->msg( "internalerror-fatal-exception",
128 "Fatal exception of type $1",
129 $type,
130 $logId,
131 MWExceptionHandler::getURL()
132 )
133 ) ) .
134 "<!-- Set \$wgShowExceptionDetails = true; " .
135 "at the bottom of LocalSettings.php to show detailed " .
136 "debugging information. -->";
137 }
138 }
139
147 public function getText() {
148 wfDeprecated( __METHOD__, '1.42' );
149 if ( MWExceptionRenderer::shouldShowExceptionDetails() ) {
150 return MWExceptionHandler::getLogMessage( $this ) .
151 "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
152 } else {
153 return "Set \$wgShowExceptionDetails = true; " .
154 "in LocalSettings.php to show detailed debugging information.\n";
155 }
156 }
157
165 public function getPageTitle() {
166 wfDeprecated( __METHOD__, '1.42' );
167 return $this->msg( 'internalerror', 'Internal error' );
168 }
169
175 public function reportHTML() {
176 wfDeprecated( __METHOD__, '1.42' );
177 global $wgOut;
178
179 if ( $this->useOutputPage() ) {
180 $wgOut->prepareErrorPage();
181 $wgOut->setPageTitle( $this->getPageTitle() );
182 // Manually set the html title, since sometimes
183 // {{SITENAME}} does not get replaced for exceptions
184 // happening inside message rendering.
185 $wgOut->setHTMLTitle(
186 $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() )
187 );
188
189 $wgOut->addHTML( $this->getHTML() );
190 // Content-Type is set by OutputPage::output
191 $wgOut->output();
192 } else {
193 self::header( 'Content-Type: text/html; charset=UTF-8' );
194 echo "<!DOCTYPE html>\n" .
195 '<html><head>' .
196 // Mimic OutputPage::setPageTitle behaviour
197 '<title>' .
198 htmlspecialchars( $this->msg( 'pagetitle', '$1 - MediaWiki', $this->getPageTitle() ) ) .
199 '</title>' .
200 '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
201 "</head><body>\n";
202
203 echo $this->getHTML();
204
205 echo "</body></html>\n";
206 }
207 }
208
215 public function report() {
216 if ( defined( 'MW_API' ) ) {
217 self::header( 'MediaWiki-API-Error: internal_api_error_' . static::class );
218 }
219
220 if ( self::isCommandLine() ) {
221 $message = $this->getText();
222 $this->writeToCommandLine( $message );
223 } else {
224 self::statusHeader( 500 );
225 $this->reportHTML();
226 }
227 }
228
232 final public function hasOverriddenHandler(): bool {
233 // No deprecation warning - report() is not deprecated, only the other methods
234 if ( MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'report' ) ) {
235 return true;
236 }
237
238 // Check them all here to avoid short-circuiting and report all deprecations,
239 // even if the function is not called in this request
240 $detectedOverrides = [
241 'getHTML' => MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'getHTML', '1.42' ),
242 'getText' => MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'getText', '1.42' ),
243 'getPageTitle' => MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'getPageTitle', '1.42' ),
244 'reportHTML' => MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'reportHTML', '1.42' ),
245 ];
246
247 return (bool)array_filter( $detectedOverrides );
248 }
249
256 private function writeToCommandLine( $message ) {
257 // T17602: STDERR may not be available
258 if ( !defined( 'MW_PHPUNIT_TEST' ) && defined( 'STDERR' ) ) {
259 fwrite( STDERR, $message );
260 } else {
261 echo $message;
262 }
263 }
264
271 public static function isCommandLine() {
272 return MW_ENTRY_POINT === 'cli';
273 }
274
280 private static function header( $header ) {
281 if ( !headers_sent() ) {
282 header( $header );
283 }
284 }
285
286 private static function statusHeader( $code ) {
287 if ( !headers_sent() ) {
288 HttpStatus::header( $code );
289 }
290 }
291}
wfMsgReplaceArgs( $message, $args)
Replace message parameter keys on the given formatted output.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
$fallback
if(!defined( 'MW_NO_SESSION') &&MW_ENTRY_POINT !=='cli') $wgOut
Definition Setup.php:536
array $params
The job parameters.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
const MW_ENTRY_POINT
Definition api.php:35
static header( $code)
Output an HTTP status code header.
Debug toolbar.
Definition MWDebug.php:42
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.
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
$header