[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * http://www.gnu.org/copyleft/gpl.html 17 * 18 * @file 19 */ 20 21 /** 22 * MediaWiki exception 23 * 24 * @ingroup Exception 25 */ 26 class MWException extends Exception { 27 /** 28 * Should the exception use $wgOut to output the error? 29 * 30 * @return bool 31 */ 32 public function useOutputPage() { 33 return $this->useMessageCache() && 34 !empty( $GLOBALS['wgFullyInitialised'] ) && 35 !empty( $GLOBALS['wgOut'] ) && 36 !defined( 'MEDIAWIKI_INSTALL' ); 37 } 38 39 /** 40 * Whether to log this exception in the exception debug log. 41 * 42 * @since 1.23 43 * @return bool 44 */ 45 public function isLoggable() { 46 return true; 47 } 48 49 /** 50 * Can the extension use the Message class/wfMessage to get i18n-ed messages? 51 * 52 * @return bool 53 */ 54 public function useMessageCache() { 55 global $wgLang; 56 57 foreach ( $this->getTrace() as $frame ) { 58 if ( isset( $frame['class'] ) && $frame['class'] === 'LocalisationCache' ) { 59 return false; 60 } 61 } 62 63 return $wgLang instanceof Language; 64 } 65 66 /** 67 * Run hook to allow extensions to modify the text of the exception 68 * 69 * @param string $name Class name of the exception 70 * @param array $args Arguments to pass to the callback functions 71 * @return string|null String to output or null if any hook has been called 72 */ 73 public function runHooks( $name, $args = array() ) { 74 global $wgExceptionHooks; 75 76 if ( !isset( $wgExceptionHooks ) || !is_array( $wgExceptionHooks ) ) { 77 return null; // Just silently ignore 78 } 79 80 if ( !array_key_exists( $name, $wgExceptionHooks ) || 81 !is_array( $wgExceptionHooks[$name] ) 82 ) { 83 return null; 84 } 85 86 $hooks = $wgExceptionHooks[$name]; 87 $callargs = array_merge( array( $this ), $args ); 88 89 foreach ( $hooks as $hook ) { 90 if ( 91 is_string( $hook ) || 92 ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) ) 93 ) { 94 // 'function' or array( 'class', hook' ) 95 $result = call_user_func_array( $hook, $callargs ); 96 } else { 97 $result = null; 98 } 99 100 if ( is_string( $result ) ) { 101 return $result; 102 } 103 } 104 return null; 105 } 106 107 /** 108 * Get a message from i18n 109 * 110 * @param string $key Message name 111 * @param string $fallback Default message if the message cache can't be 112 * called by the exception 113 * The function also has other parameters that are arguments for the message 114 * @return string Message with arguments replaced 115 */ 116 public function msg( $key, $fallback /*[, params...] */ ) { 117 $args = array_slice( func_get_args(), 2 ); 118 119 if ( $this->useMessageCache() ) { 120 return wfMessage( $key, $args )->text(); 121 } else { 122 return wfMsgReplaceArgs( $fallback, $args ); 123 } 124 } 125 126 /** 127 * If $wgShowExceptionDetails is true, return a HTML message with a 128 * backtrace to the error, otherwise show a message to ask to set it to true 129 * to show that information. 130 * 131 * @return string Html to output 132 */ 133 public function getHTML() { 134 global $wgShowExceptionDetails; 135 136 if ( $wgShowExceptionDetails ) { 137 return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) . 138 '</p><p>Backtrace:</p><p>' . 139 nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) . 140 "</p>\n"; 141 } else { 142 return "<div class=\"errorbox\">" . 143 '[' . MWExceptionHandler::getLogId( $this ) . '] ' . 144 gmdate( 'Y-m-d H:i:s' ) . 145 ": Fatal exception of type " . get_class( $this ) . "</div>\n" . 146 "<!-- Set \$wgShowExceptionDetails = true; " . 147 "at the bottom of LocalSettings.php to show detailed " . 148 "debugging information. -->"; 149 } 150 } 151 152 /** 153 * Get the text to display when reporting the error on the command line. 154 * If $wgShowExceptionDetails is true, return a text message with a 155 * backtrace to the error. 156 * 157 * @return string 158 */ 159 public function getText() { 160 global $wgShowExceptionDetails; 161 162 if ( $wgShowExceptionDetails ) { 163 return MWExceptionHandler::getLogMessage( $this ) . 164 "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n"; 165 } else { 166 return "Set \$wgShowExceptionDetails = true; " . 167 "in LocalSettings.php to show detailed debugging information.\n"; 168 } 169 } 170 171 /** 172 * Return the title of the page when reporting this error in a HTTP response. 173 * 174 * @return string 175 */ 176 public function getPageTitle() { 177 return $this->msg( 'internalerror', 'Internal error' ); 178 } 179 180 /** 181 * Output the exception report using HTML. 182 */ 183 public function reportHTML() { 184 global $wgOut, $wgSitename; 185 if ( $this->useOutputPage() ) { 186 $wgOut->prepareErrorPage( $this->getPageTitle() ); 187 188 $hookResult = $this->runHooks( get_class( $this ) ); 189 if ( $hookResult ) { 190 $wgOut->addHTML( $hookResult ); 191 } else { 192 $wgOut->addHTML( $this->getHTML() ); 193 } 194 195 $wgOut->output(); 196 } else { 197 self::header( 'Content-Type: text/html; charset=utf-8' ); 198 echo "<!DOCTYPE html>\n" . 199 '<html><head>' . 200 // Mimick OutputPage::setPageTitle behaviour 201 '<title>' . 202 htmlspecialchars( $this->msg( 'pagetitle', "$1 - $wgSitename", $this->getPageTitle() ) ) . 203 '</title>' . 204 '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' . 205 "</head><body>\n"; 206 207 $hookResult = $this->runHooks( get_class( $this ) . 'Raw' ); 208 if ( $hookResult ) { 209 echo $hookResult; 210 } else { 211 echo $this->getHTML(); 212 } 213 214 echo "</body></html>\n"; 215 } 216 } 217 218 /** 219 * Output a report about the exception and takes care of formatting. 220 * It will be either HTML or plain text based on isCommandLine(). 221 */ 222 public function report() { 223 global $wgMimeType; 224 225 MWExceptionHandler::logException( $this ); 226 227 if ( defined( 'MW_API' ) ) { 228 // Unhandled API exception, we can't be sure that format printer is alive 229 self::header( 'MediaWiki-API-Error: internal_api_error_' . get_class( $this ) ); 230 wfHttpError( 500, 'Internal Server Error', $this->getText() ); 231 } elseif ( self::isCommandLine() ) { 232 MWExceptionHandler::printError( $this->getText() ); 233 } else { 234 self::header( 'HTTP/1.1 500 MediaWiki exception' ); 235 self::header( 'Status: 500 MediaWiki exception' ); 236 self::header( "Content-Type: $wgMimeType; charset=utf-8" ); 237 238 $this->reportHTML(); 239 } 240 } 241 242 /** 243 * Check whether we are in command line mode or not to report the exception 244 * in the correct format. 245 * 246 * @return bool 247 */ 248 public static function isCommandLine() { 249 return !empty( $GLOBALS['wgCommandLineMode'] ); 250 } 251 252 /** 253 * Send a header, if we haven't already sent them. We shouldn't, 254 * but sometimes we might in a weird case like Export 255 * @param string $header 256 */ 257 private static function header( $header ) { 258 if ( !headers_sent() ) { 259 header( $header ); 260 } 261 } 262 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |