Browse Source

Added a handler for fatal errors, showing internal server error page when debug is disabled or a custom fatal error page when enabled.

Juan Basso 14 years ago
parent
commit
440f0c38eb

+ 4 - 1
app/Config/core.php

@@ -45,13 +45,16 @@
  *    including anonymous functions.
  * - `level` - int - The level of errors you are interested in capturing.
  * - `trace` - boolean - Include stack traces for errors in log files.
+ * - `handleFatalError` - boolean - Enable the CakePHP fatal error handler, generating custom
+ *    pages for fatal errors instead of show broke pages.
  *
  * @see ErrorHandler for more information on error handling and configuration.
  */
 	Configure::write('Error', array(
 		'handler' => 'ErrorHandler::handleError',
 		'level' => E_ALL & ~E_DEPRECATED,
-		'trace' => true
+		'trace' => true,
+		'handleFatalError' => true
 	));
 
 /**

+ 1 - 0
lib/Cake/Core/Configure.php

@@ -345,5 +345,6 @@ class Configure {
 		if (!empty($exception['handler'])) {
 			set_exception_handler($exception['handler']);
 		}
+		register_shutdown_function('ErrorHandler::handleFatalError');
 	}
 }

+ 38 - 0
lib/Cake/Error/ErrorHandler.php

@@ -184,6 +184,44 @@ class ErrorHandler {
 	}
 
 /**
+ * Generate an error page when some fatal error happens.
+ *
+ * Use Configure::write('Error.handleFatalError', false) to disable this feature
+ *
+ * @return void
+ */
+	public static function handleFatalError() {
+		if (Configure::read('Error.handleFatalError') !== true) {
+			return;
+		}
+
+		$lastError = error_get_last();
+		if (!is_array($lastError)) {
+			return;
+		}
+
+		list($error, $log) = self::mapErrorCode($lastError['type']);
+		if ($log !== LOG_ERROR) {
+			return;
+		}
+
+		$logMessage = $error . ' (' . $lastError['type'] . '): ' . $lastError['message'] . ' in [' . $lastError['file'] . ', line ' . $lastError['line'] . ']';
+		CakeLog::write($log, $logMessage);
+
+		$exceptionHandler = Configure::read('Exception.handler');
+		if (!is_callable($exceptionHandler)) {
+			return;
+		}
+
+		ob_clean();
+		if (Configure::read('debug')) {
+			call_user_func($exceptionHandler, new FatalErrorException($lastError['message'], 500, $lastError['file'], $lastError['line']));
+		} else {
+			call_user_func($exceptionHandler, new InternalErrorException());
+		}
+	}
+
+/**
  * Map an error code into an Error word, and log location.
  *
  * @param integer $code Error code to map

+ 27 - 0
lib/Cake/Error/exceptions.php

@@ -517,3 +517,30 @@ class XmlException extends CakeException {
  */
 class ConsoleException extends CakeException {
 }
+
+/**
+ * Represents a fatal error
+ *
+ * @package       Cake.Error
+ */
+class FatalErrorException extends CakeException {
+
+/**
+ * Constructor
+ *
+ * @param string $message
+ * @param integer $code
+ * @param string $file
+ * @param integer $line
+ */
+	public function __construct($message, $code = 500, $file = null, $line = null) {
+		parent::__construct($message, $code);
+		if ($file) {
+			$this->file = $file;
+		}
+		if ($line) {
+			$this->line = $line;
+		}
+	}
+
+}

+ 35 - 0
lib/Cake/View/Errors/fatal_error.ctp

@@ -0,0 +1,35 @@
+<?php
+/**
+ *
+ * PHP 5
+ *
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @package       Cake.View.Errors
+ * @since         CakePHP(tm) v 2.2.0
+ * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+?>
+<h2><?php echo __d('cake_dev', 'Fatal Error'); ?></h2>
+<p class="error">
+	<strong><?php echo __d('cake_dev', 'Error'); ?>: </strong>
+	<?php echo h($error->getMessage()); ?>
+	<br>
+
+	<strong><?php echo __d('cake_dev', 'File'); ?>: </strong>
+	<?php echo h($error->getFile()); ?>
+	<br>
+
+	<strong><?php echo __d('cake_dev', 'Line'); ?>: </strong>
+	<?php echo h($error->getLine()); ?>
+</p>
+<p class="notice">
+	<strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong>
+	<?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'fatal_error.ctp'); ?>
+</p>