[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/exception/ -> MWException.php (source)

   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  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1