MediaWiki  REL1_23
MWException.php
Go to the documentation of this file.
00001 <?php
00026 class MWException extends Exception {
00032     public function useOutputPage() {
00033         return $this->useMessageCache() &&
00034         !empty( $GLOBALS['wgFullyInitialised'] ) &&
00035         !empty( $GLOBALS['wgOut'] ) &&
00036         !defined( 'MEDIAWIKI_INSTALL' );
00037     }
00038 
00045     public function isLoggable() {
00046         return true;
00047     }
00048 
00054     public function useMessageCache() {
00055         global $wgLang;
00056 
00057         foreach ( $this->getTrace() as $frame ) {
00058             if ( isset( $frame['class'] ) && $frame['class'] === 'LocalisationCache' ) {
00059                 return false;
00060             }
00061         }
00062 
00063         return $wgLang instanceof Language;
00064     }
00065 
00073     public function runHooks( $name, $args = array() ) {
00074         global $wgExceptionHooks;
00075 
00076         if ( !isset( $wgExceptionHooks ) || !is_array( $wgExceptionHooks ) ) {
00077             return null; // Just silently ignore
00078         }
00079 
00080         if ( !array_key_exists( $name, $wgExceptionHooks ) ||
00081             !is_array( $wgExceptionHooks[$name] )
00082         ) {
00083             return null;
00084         }
00085 
00086         $hooks = $wgExceptionHooks[$name];
00087         $callargs = array_merge( array( $this ), $args );
00088 
00089         foreach ( $hooks as $hook ) {
00090             if (
00091                 is_string( $hook ) ||
00092                 ( is_array( $hook ) && count( $hook ) >= 2 && is_string( $hook[0] ) )
00093             ) {
00094                 // 'function' or array( 'class', hook' )
00095                 $result = call_user_func_array( $hook, $callargs );
00096             } else {
00097                 $result = null;
00098             }
00099 
00100             if ( is_string( $result ) ) {
00101                 return $result;
00102             }
00103         }
00104         return null;
00105     }
00106 
00116     public function msg( $key, $fallback /*[, params...] */ ) {
00117         $args = array_slice( func_get_args(), 2 );
00118 
00119         if ( $this->useMessageCache() ) {
00120             return wfMessage( $key, $args )->text();
00121         } else {
00122             return wfMsgReplaceArgs( $fallback, $args );
00123         }
00124     }
00125 
00133     public function getHTML() {
00134         global $wgShowExceptionDetails;
00135 
00136         if ( $wgShowExceptionDetails ) {
00137             return '<p>' . nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $this ) ) ) .
00138             '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $this ) ) ) .
00139             "</p>\n";
00140         } else {
00141             return "<div class=\"errorbox\">" .
00142             '[' . MWExceptionHandler::getLogId( $this ) . '] ' .
00143             gmdate( 'Y-m-d H:i:s' ) .
00144             ": Fatal exception of type " . get_class( $this ) . "</div>\n" .
00145             "<!-- Set \$wgShowExceptionDetails = true; " .
00146             "at the bottom of LocalSettings.php to show detailed " .
00147             "debugging information. -->";
00148         }
00149     }
00150 
00158     public function getText() {
00159         global $wgShowExceptionDetails;
00160 
00161         if ( $wgShowExceptionDetails ) {
00162             return MWExceptionHandler::getLogMessage( $this ) .
00163             "\nBacktrace:\n" . MWExceptionHandler::getRedactedTraceAsString( $this ) . "\n";
00164         } else {
00165             return "Set \$wgShowExceptionDetails = true; " .
00166             "in LocalSettings.php to show detailed debugging information.\n";
00167         }
00168     }
00169 
00175     public function getPageTitle() {
00176         return $this->msg( 'internalerror', 'Internal error' );
00177     }
00178 
00186     public function getLogId() {
00187         wfDeprecated( __METHOD__, '1.22' );
00188         return MWExceptionHandler::getLogId( $this );
00189     }
00190 
00199     public function getLogMessage() {
00200         wfDeprecated( __METHOD__, '1.22' );
00201         return MWExceptionHandler::getLogMessage( $this );
00202     }
00203 
00207     public function reportHTML() {
00208         global $wgOut, $wgSitename;
00209         if ( $this->useOutputPage() ) {
00210             $wgOut->prepareErrorPage( $this->getPageTitle() );
00211 
00212             $hookResult = $this->runHooks( get_class( $this ) );
00213             if ( $hookResult ) {
00214                 $wgOut->addHTML( $hookResult );
00215             } else {
00216                 $wgOut->addHTML( $this->getHTML() );
00217             }
00218 
00219             $wgOut->output();
00220         } else {
00221             header( 'Content-Type: text/html; charset=utf-8' );
00222             echo "<!DOCTYPE html>\n" .
00223                 '<html><head>' .
00224                 // Mimick OutputPage::setPageTitle behaviour
00225                 '<title>' . htmlspecialchars( $this->msg( 'pagetitle', "$1 - $wgSitename", $this->getPageTitle() ) ) . '</title>' .
00226                 '<style>body { font-family: sans-serif; margin: 0; padding: 0.5em 2em; }</style>' .
00227                 "</head><body>\n";
00228 
00229             $hookResult = $this->runHooks( get_class( $this ) . 'Raw' );
00230             if ( $hookResult ) {
00231                 echo $hookResult;
00232             } else {
00233                 echo $this->getHTML();
00234             }
00235 
00236             echo "</body></html>\n";
00237         }
00238     }
00239 
00244     public function report() {
00245         global $wgMimeType;
00246 
00247         MWExceptionHandler::logException( $this );
00248 
00249         if ( defined( 'MW_API' ) ) {
00250             // Unhandled API exception, we can't be sure that format printer is alive
00251             header( 'MediaWiki-API-Error: internal_api_error_' . get_class( $this ) );
00252             wfHttpError( 500, 'Internal Server Error', $this->getText() );
00253         } elseif ( self::isCommandLine() ) {
00254             MWExceptionHandler::printError( $this->getText() );
00255         } else {
00256             header( 'HTTP/1.1 500 MediaWiki exception' );
00257             header( 'Status: 500 MediaWiki exception', true );
00258             header( "Content-Type: $wgMimeType; charset=utf-8", true );
00259 
00260             $this->reportHTML();
00261         }
00262     }
00263 
00270     public static function isCommandLine() {
00271         return !empty( $GLOBALS['wgCommandLineMode'] );
00272     }
00273 }