Merge remote branch 'origin/2.0' into feature/2.0/pdo

This commit is contained in:
José Lorenzo Rodríguez 2010-12-03 14:08:03 -04:30
commit 7c4ab886e6
39 changed files with 1082 additions and 559 deletions

View file

@ -36,19 +36,46 @@
Configure::write('debug', 2);
/**
* CakePHP Log Level:
* Configure the Error handler used to handle errors for your application. By default
* ErrorHandler::handleError() is used. It will display errors using Debugger, when debug > 0
* and log errors with CakeLog when debug = 0.
*
* In case of Production Mode CakePHP gives you the possibility to continue logging errors.
* Options:
*
* The following parameters can be used:
* Boolean: Set true/false to activate/deactivate logging
* Configure::write('log', true);
* - `handler` - callback - The callback to handle errors. You can set this to any callback type,
* including anonymous functions.
* - `level` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Include stack traces for errors in log files.
*
* Integer: Use built-in PHP constants to set the error level (see error_reporting)
* Configure::write('log', E_ERROR | E_WARNING);
* Configure::write('log', E_ALL ^ E_NOTICE);
* @see ErrorHandler for more information on error handling and configuration.
*/
Configure::write('log', true);
Configure::write('Error', array(
'handler' => 'ErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED,
'trace' => true
));
/**
* Configure the Exception handler used for uncaught exceptions. By default,
* ErrorHandler::handleException() is used. It will display a HTML page for the exception, and
* while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0,
* framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `handler` - callback - The callback to handle exceptions. You can set this to any callback type,
* including anonymous functions.
* - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you
* should place the file for that class in app/libs. This class needs to implement a render method.
* - `log` - boolean - Should Exceptions be logged?
*
* @see ErrorHandler for more information on exception handling and configuration.
*/
Configure::write('Exception', array(
'handler' => 'ErrorHandler::handleException',
'renderer' => 'ExceptionRenderer',
'log' => true
));
/**
* Application wide charset encoding

View file

@ -186,11 +186,7 @@ if (!function_exists('sortByKey')) {
if (is_string($double)) {
$charset = $double;
}
if ($charset) {
return htmlspecialchars($text, ENT_QUOTES, $charset, $double);
} else {
return htmlspecialchars($text, ENT_QUOTES, $defaultCharset, $double);
}
return htmlspecialchars($text, ENT_QUOTES, ($charset) ? $charset : $defaultCharset, $double);
}
/**

View file

@ -26,15 +26,14 @@ error_reporting(E_ALL & ~E_DEPRECATED);
require CORE_PATH . 'cake' . DS . 'basics.php';
require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php';
require LIBS . 'exceptions.php';
require LIBS . 'error' . DS . 'exceptions.php';
require LIBS . 'object.php';
require LIBS . 'inflector.php';
require LIBS . 'app.php';
require LIBS . 'configure.php';
require LIBS . 'set.php';
require LIBS . 'cache.php';
require LIBS . 'error_handler.php';
set_exception_handler(array('ErrorHandler', 'handleException'));
require LIBS . 'error' . DS . 'error_handler.php';
Configure::bootstrap(isset($boot) ? $boot : true);

View file

@ -35,17 +35,19 @@ class ConsoleErrorHandler extends ErrorHandler {
* @var filehandle
* @access public
*/
public $stderr;
public static $stderr;
/**
* Class constructor.
* Get the stderr object for the console error handling.
*
* @param Exception $error Exception to handle.
* @param array $messages Error messages
*/
function __construct($error) {
$this->stderr = new ConsoleOutput('php://stderr');
parent::__construct($error);
public static function getStderr() {
if (empty(self::$stderr)) {
self::$stderr = new ConsoleOutput('php://stderr');
}
return self::$stderr;
}
/**
@ -54,57 +56,40 @@ class ConsoleErrorHandler extends ErrorHandler {
* @return void
*/
public static function handleException($exception) {
$error = new ConsoleErrorHandler($exception);
$error->render();
$stderr = self::getStderr();
$stderr->write(sprintf(
__("<error>Error:</error> %s\n%s"),
$exception->getMessage(),
$exception->getTraceAsString()
));
}
/**
* Do nothing, no controllers are needed in the console.
* Handle errors in the console environment.
*
* @return void
*/
protected function _getController($exception) {
return null;
public static function handleError($code, $description, $file = null, $line = null, $context = null) {
if (error_reporting() === 0) {
return;
}
$stderr = self::getStderr();
list($name, $log) = self::_mapErrorCode($code);
$message = sprintf(__('%s in [%s, line %s]'), $description, $file, $line);
$stderr->write(sprintf(__("<error>%s Error:</error> %s\n"), $name, $message));
if (Configure::read('debug') == 0) {
App::import('Core', 'CakeLog');
CakeLog::write($log, $message);
}
}
/**
* Overwrite how _cakeError behaves for console. There is no reason
* to prepare urls as they are not relevant for this.
* undocumented function
*
* @param $error Exception Exception being handled.
* @return void
*/
protected function _cakeError($error) {
$this->_outputMessage();
}
/**
* Override error404 method
*
* @param Exception $error Exception
* @return void
*/
public function error400($error) {
$this->_outputMessage();
}
/**
* Override error500 method
*
* @param Exception $error Exception
* @return void
*/
public function error500($error) {
$this->_outputMessage();
}
/**
* Outputs the exception to STDERR.
*
* @param string $template The name of the template to render.
* @return void
*/
public function _outputMessage($template = null) {
public function render() {
$this->stderr->write(sprintf(
__("<error>Error:</error> %s\n%s"),
$this->error->getMessage(),

View file

@ -80,8 +80,6 @@ class ShellDispatcher {
*/
function __initConstants() {
if (function_exists('ini_set')) {
ini_set('display_errors', '1');
ini_set('error_reporting', E_ALL & ~E_DEPRECATED);
ini_set('html_errors', false);
ini_set('implicit_flush', true);
ini_set('max_execution_time', 0);
@ -90,7 +88,6 @@ class ShellDispatcher {
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('DS', DIRECTORY_SEPARATOR);
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__))));
define('DISABLE_DEFAULT_ERROR_HANDLING', false);
define('CAKEPHP_SHELL', true);
if (!defined('CORE_PATH')) {
if (function_exists('ini_set') && ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ini_get('include_path'))) {
@ -141,13 +138,15 @@ class ShellDispatcher {
$boot = file_exists(ROOT . DS . APP_DIR . DS . 'config' . DS . 'bootstrap.php');
require CORE_PATH . 'cake' . DS . 'bootstrap.php';
require_once CONSOLE_LIBS . 'console_error_handler.php';
set_exception_handler(array('ConsoleErrorHandler', 'handleException'));
if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) {
include_once CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php';
App::build();
}
require_once CONSOLE_LIBS . 'console_error_handler.php';
set_exception_handler(array('ConsoleErrorHandler', 'handleException'));
set_error_handler(array('ConsoleErrorHandler', 'handleError'), Configure::read('Error.level'));
if (!defined('FULL_BASE_URL')) {
define('FULL_BASE_URL', '/');
}

View file

@ -253,6 +253,10 @@ class TestSuiteShell extends Shell {
*/
protected function run($runnerArgs, $options = array()) {
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_runner.php';
restore_error_handler();
restore_error_handler();
$testCli = new TestRunner($runnerArgs);
$testCli->run($options);
}

View file

@ -36,19 +36,46 @@
Configure::write('debug', 2);
/**
* CakePHP Log Level:
* Configure the Error handler used to handle errors for your application. By default
* ErrorHandler::handleError() is used. It will display errors using Debugger, when debug > 0
* and log errors with CakeLog when debug = 0.
*
* In case of Production Mode CakePHP gives you the possibility to continue logging errors.
* Options:
*
* The following parameters can be used:
* Boolean: Set true/false to activate/deactivate logging
* Configure::write('log', true);
* - `handler` - callback - The callback to handle errors. You can set this to any callback type,
* including anonymous functions.
* - `level` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Include stack traces for errors in log files.
*
* Integer: Use built-in PHP constants to set the error level (see error_reporting)
* Configure::write('log', E_ERROR | E_WARNING);
* Configure::write('log', E_ALL ^ E_NOTICE);
* @see ErrorHandler for more information on error handling and configuration.
*/
Configure::write('log', true);
Configure::write('Error', array(
'handler' => 'ErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED,
'trace' => true
));
/**
* Configure the Exception handler used for uncaught exceptions. By default,
* ErrorHandler::handleException() is used. It will display a HTML page for the exception, and
* while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0,
* framework errors will be coerced into generic HTTP errors.
*
* Options:
*
* - `handler` - callback - The callback to handle exceptions. You can set this to any callback type,
* including anonymous functions.
* - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you
* should place the file for that class in app/libs. This class needs to implement a render method.
* - `log` - boolean - Should Exceptions be logged?
*
* @see ErrorHandler for more information on exception handling and configuration.
*/
Configure::write('Exception', array(
'handler' => 'ErrorHandler::handleException',
'renderer' => 'ExceptionRenderer',
'log' => true
));
/**
* Application wide charset encoding
@ -128,7 +155,7 @@
* - `Session.handler` - Can be used to enable a custom session handler. Expects an array of of callables,
* that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler`
* to the ini array.
* - `Session.autoRegenerate` - Enabling this setting, turns on automatic regeneration of sessions, and
* - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and
* sessionids that change frequently. See CakeSession::$requestCountdown.
* - `Session.ini` - An associative array of additional ini values to set.
*

View file

@ -505,7 +505,11 @@ class App {
$file = Inflector::underscore($name) . ".{$ext}";
}
$ext = self::__settings($type, $plugin, $parent);
if ($name != null && !class_exists($name . $ext['class'])) {
$className = $name;
if (strpos($className, '/') !== false) {
$className = substr($className, strrpos($className, '/') + 1);
}
if ($name != null && !class_exists($className . $ext['class'])) {
if ($load = self::__mapped($name . $ext['class'], $type, $plugin)) {
if (self::__load($load)) {
if (self::$return) {

View file

@ -99,7 +99,7 @@ class CakeLog {
* @return boolean success of configuration.
* @throws Exception
*/
static function config($key, $config) {
public static function config($key, $config) {
if (empty($config['engine'])) {
throw new Exception(__('Missing logger classname'));
}
@ -222,54 +222,4 @@ class CakeLog {
}
return true;
}
/**
* An error_handler that will log errors to file using CakeLog::write();
* You can control how verbose and what type of errors this error_handler will
* catch using `Configure::write('log', $value)`. See core.php for more information.
*
*
* @param integer $code Code of error
* @param string $description Error description
* @param string $file File on which error occurred
* @param integer $line Line that triggered the error
* @param array $context Context
* @return void
*/
public static function handleError($code, $description, $file = null, $line = null, $context = null) {
if ($code === 2048 || $code === 8192) {
return;
}
switch ($code) {
case E_PARSE:
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$error = 'Fatal Error';
$level = LOG_ERROR;
break;
case E_WARNING:
case E_USER_WARNING:
case E_COMPILE_WARNING:
case E_RECOVERABLE_ERROR:
$error = 'Warning';
$level = LOG_WARNING;
break;
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
$level = LOG_NOTICE;
break;
default:
return;
break;
}
$message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
CakeLog::write($level, $message);
}
}
if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {
set_error_handler(array('CakeLog', 'handleError'));
}

View file

@ -141,7 +141,7 @@ class CakeSession {
* @param boolean $start Should session be started right now
*/
public static function init($base = null, $start = true) {
App::import('Core', array('Set', 'Security'));
App::import('Core', 'Security');
self::$time = time();
$checkAgent = Configure::read('Session.checkAgent');

View file

@ -0,0 +1,101 @@
<?php
/**
* IniFile
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs.controller.components
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Ini file configuration parser. Since IniFile uses parse_ini_file underneath,
* you should be aware that this class shares the same behavior, especially with
* regards to boolean and null values.
*
* @package cake.config
* @see http://php.net/parse_ini_file
*/
class IniFile implements ArrayAccess {
/**
* Values inside the ini file.
*
* @var array
*/
protected $_values = array();
/**
* Build and construct a new ini file parser, the parser will be a representation of the ini
* file as an object.
*
* @param string $filename Full path to the file to parse.
* @param string $section Only get one section.
*/
public function __construct($filename, $section = null) {
$contents = parse_ini_file($filename, true);
if (!empty($section) && isset($contents[$section])) {
$this->_values = $contents[$section];
} else {
$this->_values = $contents;
}
}
/**
* Get the contents of the ini file as a plain array.
*
* @return array
*/
public function asArray() {
return $this->_values;
}
/**
* Part of ArrayAccess implementation.
*
* @param string $name
*/
public function offsetExists($name) {
return isset($this->_values[$name]);
}
/**
* Part of ArrayAccess implementation.
*
* @param string $name
*/
public function offsetGet($name) {
if (!isset($this->_values[$name])) {
return null;
}
return $this->_values[$name];
}
/**
* Part of ArrayAccess implementation.
*
* @param string $name
*/
public function offsetSet($name, $value) {
throw new LogicException('You cannot modify an IniFile parse result.');
}
/**
* Part of ArrayAccess implementation.
*
* @param string $name
*/
public function offsetUnset($name) {
unset($this->_values[$name]);
}
}

View file

@ -42,11 +42,78 @@ class Configure {
/**
* Initializes configure and runs the bootstrap process.
* Bootstrapping includes the following steps:
*
* - Setup App array in Configure.
* - Include app/config/core.php.
* - Configure core cache configurations.
* - Load App cache files.
* - Include app/config/bootstrap.php.
* - Setup error/exception handlers.
*
* @return void
*/
public static function bootstrap($boot = true) {
self::__loadBootstrap($boot);
if ($boot) {
self::write('App', array('base' => false, 'baseUrl' => false, 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'www_root' => WWW_ROOT));
if (!include(CONFIGS . 'core.php')) {
trigger_error(sprintf(__("Can't find application core file. Please create %score.php, and make sure it is readable by PHP."), CONFIGS), E_USER_ERROR);
}
if (Configure::read('Cache.disable') !== true) {
$cache = Cache::config('default');
if (empty($cache['settings'])) {
trigger_error(__('Cache not configured properly. Please check Cache::config(); in APP/config/core.php'), E_USER_WARNING);
$cache = Cache::config('default', array('engine' => 'File'));
}
$path = $prefix = $duration = null;
if (!empty($cache['settings']['path'])) {
$path = realpath($cache['settings']['path']);
} else {
$prefix = $cache['settings']['prefix'];
}
if (Configure::read('debug') >= 1) {
$duration = '+10 seconds';
} else {
$duration = '+999 days';
}
if (Cache::config('_cake_core_') === false) {
Cache::config('_cake_core_', array_merge((array)$cache['settings'], array(
'prefix' => $prefix . 'cake_core_', 'path' => $path . DS . 'persistent' . DS,
'serialize' => true, 'duration' => $duration
)));
}
if (Cache::config('_cake_model_') === false) {
Cache::config('_cake_model_', array_merge((array)$cache['settings'], array(
'prefix' => $prefix . 'cake_model_', 'path' => $path . DS . 'models' . DS,
'serialize' => true, 'duration' => $duration
)));
}
}
App::init();
App::build();
if (!include(CONFIGS . 'bootstrap.php')) {
trigger_error(sprintf(__("Can't find application bootstrap file. Please create %sbootstrap.php, and make sure it is readable by PHP."), CONFIGS), E_USER_ERROR);
}
$level = -1;
if (isset(self::$_values['Error']['level'])) {
error_reporting(self::$_values['Error']['level']);
$level = self::$_values['Error']['level'];
}
if (!empty(self::$_values['Error']['handler'])) {
set_error_handler(self::$_values['Error']['handler'], $level);
}
if (!empty(self::$_values['Exception']['handler'])) {
set_exception_handler(self::$_values['Exception']['handler']);
}
}
}
/**
@ -101,30 +168,13 @@ class Configure {
}
if (isset($config['debug']) || isset($config['log'])) {
$reporting = 0;
if (self::$_values['debug']) {
if (!class_exists('Debugger')) {
require LIBS . 'debugger.php';
}
$reporting = E_ALL & ~E_DEPRECATED;
if (function_exists('ini_set')) {
if (self::$_values['debug']) {
ini_set('display_errors', 1);
}
} elseif (function_exists('ini_set')) {
} else {
ini_set('display_errors', 0);
}
if (isset(self::$_values['log']) && self::$_values['log']) {
if (!class_exists('CakeLog')) {
require LIBS . 'cake_log.php';
}
if (is_integer(self::$_values['log']) && !self::$_values['debug']) {
$reporting = self::$_values['log'];
} else {
$reporting = E_ALL & ~E_DEPRECATED;
}
}
error_reporting($reporting);
}
return true;
}
@ -330,62 +380,4 @@ class Configure {
}
}
/**
* Loads app/config/bootstrap.php.
* If the alternative paths are set in this file
* they will be added to the paths vars.
*
* @param boolean $boot Load application bootstrap (if true)
* @return void
*/
private static function __loadBootstrap($boot) {
if ($boot) {
Configure::write('App', array('base' => false, 'baseUrl' => false, 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'www_root' => WWW_ROOT));
if (!include(CONFIGS . 'core.php')) {
trigger_error(sprintf(__("Can't find application core file. Please create %score.php, and make sure it is readable by PHP."), CONFIGS), E_USER_ERROR);
}
if (Configure::read('Cache.disable') !== true) {
$cache = Cache::config('default');
if (empty($cache['settings'])) {
trigger_error(__('Cache not configured properly. Please check Cache::config(); in APP/config/core.php'), E_USER_WARNING);
$cache = Cache::config('default', array('engine' => 'File'));
}
$path = $prefix = $duration = null;
if (!empty($cache['settings']['path'])) {
$path = realpath($cache['settings']['path']);
} else {
$prefix = $cache['settings']['prefix'];
}
if (Configure::read('debug') >= 1) {
$duration = '+10 seconds';
} else {
$duration = '+999 days';
}
if (Cache::config('_cake_core_') === false) {
Cache::config('_cake_core_', array_merge((array)$cache['settings'], array(
'prefix' => $prefix . 'cake_core_', 'path' => $path . DS . 'persistent' . DS,
'serialize' => true, 'duration' => $duration
)));
}
if (Cache::config('_cake_model_') === false) {
Cache::config('_cake_model_', array_merge((array)$cache['settings'], array(
'prefix' => $prefix . 'cake_model_', 'path' => $path . DS . 'models' . DS,
'serialize' => true, 'duration' => $duration
)));
}
}
App::init();
App::build();
if (!include(CONFIGS . 'bootstrap.php')) {
trigger_error(sprintf(__("Can't find application bootstrap file. Please create %sbootstrap.php, and make sure it is readable by PHP."), CONFIGS), E_USER_ERROR);
}
}
}
}

View file

@ -538,6 +538,15 @@ class IniAcl extends Object implements AclInterface {
*/
public $config = null;
/**
* The Set::classicExtract() path to the user/aro identifier in the
* acl.ini file. This path will be used to extract the string
* representation of a user used in the ini file.
*
* @var string
*/
public $userPath = 'User.username';
/**
* Initialize method
*
@ -600,6 +609,10 @@ class IniAcl extends Object implements AclInterface {
}
$aclConfig = $this->config;
if (is_array($aro)) {
$aro = Set::classicExtract($aro, $this->userPath);
}
if (isset($aclConfig[$aro]['deny'])) {
$userDenies = $this->arrayTrim(explode(",", $aclConfig[$aro]['deny']));
@ -645,43 +658,13 @@ class IniAcl extends Object implements AclInterface {
/**
* Parses an INI file and returns an array that reflects the INI file's section structure. Double-quote friendly.
*
* @param string $fileName File
* @param string $filename File
* @return array INI section structure
*/
public function readConfigFile($fileName) {
$fileLineArray = file($fileName);
foreach ($fileLineArray as $fileLine) {
$dataLine = trim($fileLine);
$firstChar = substr($dataLine, 0, 1);
if ($firstChar != ';' && $dataLine != '') {
if ($firstChar == '[' && substr($dataLine, -1, 1) == ']') {
$sectionName = preg_replace('/[\[\]]/', '', $dataLine);
} else {
$delimiter = strpos($dataLine, '=');
if ($delimiter > 0) {
$key = strtolower(trim(substr($dataLine, 0, $delimiter)));
$value = trim(substr($dataLine, $delimiter + 1));
if (substr($value, 0, 1) == '"' && substr($value, -1) == '"') {
$value = substr($value, 1, -1);
}
$iniSetting[$sectionName][$key]=stripcslashes($value);
} else {
if (!isset($sectionName)) {
$sectionName = '';
}
$iniSetting[$sectionName][strtolower(trim($dataLine))]='';
}
}
}
}
return $iniSetting;
public function readConfigFile($filename) {
App::import('Core', 'config/IniFile');
$iniFile = new IniFile($filename);
return $iniFile->asArray();
}
/**

View file

@ -20,7 +20,8 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('Router', 'Security'), false);
App::import('Core', 'Router', false);
App::import('Core', 'Security', false);
/**
* Authentication control component class

View file

@ -810,7 +810,7 @@ class EmailComponent extends Component {
* @access private
*/
function _smtp() {
App::import('Core', array('CakeSocket'));
App::import('Core', 'CakeSocket');
$defaults = array(
'host' => 'localhost',

View file

@ -17,7 +17,8 @@
* @since CakePHP(tm) v 0.10.8.2156
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('String', 'Security'));
App::import('Core', 'String', false);
App::import('Core', 'Security', false);
/**
* SecurityComponent

View file

@ -236,11 +236,7 @@ class Debugger {
* @param array $context Context
* @return boolean true if error was handled
*/
public function handleError($code, $description, $file = null, $line = null, $context = null) {
if (error_reporting() == 0 || $code === 2048 || $code === 8192) {
return;
}
public function showError($code, $description, $file = null, $line = null, $context = null) {
$_this = Debugger::getInstance();
if (empty($file)) {
@ -295,13 +291,7 @@ class Debugger {
$data = compact(
'level', 'error', 'code', 'helpID', 'description', 'file', 'path', 'line', 'context'
);
echo self::_output($data);
if (Configure::read('log')) {
$tpl = $_this->_templates['log']['error'];
$options = array('before' => '{:', 'after' => '}');
CakeLog::write($level, String::insert($tpl, $data, $options));
}
echo $_this->outputError($data);
if ($error == 'Fatal Error') {
exit();
@ -585,11 +575,12 @@ class Debugger {
}
/**
* Renders error messages
* Takes a processed array of data from an error and displays it in the chosen format.
*
* @param array $data Data about the current error
* @param string $data
* @return void
*/
protected function _output($data = array()) {
public function outputError($data) {
$defaults = array(
'level' => 0,
'error' => 0,
@ -598,13 +589,14 @@ class Debugger {
'description' => '',
'file' => '',
'line' => 0,
'context' => array()
'context' => array(),
'start' => 2
);
$data += $defaults;
$files = $this->trace(array('start' => 2, 'format' => 'points'));
$files = $this->trace(array('start' => $data['start'], 'format' => 'points'));
$code = $this->excerpt($files[0]['file'], $files[0]['line'] - 1, 1);
$trace = $this->trace(array('start' => 2, 'depth' => '20'));
$trace = $this->trace(array('start' => $data['start'], 'depth' => '20'));
$insertOpts = array('before' => '{:', 'after' => '}');
$context = array();
$links = array();
@ -672,20 +664,4 @@ class Debugger {
}
}
/**
* Invokes the given debugger object as the current error handler, taking over control from the
* previous handler in a stack-like hierarchy.
*
* @param object $debugger A reference to the Debugger object
* @access public
* @static
* @link http://book.cakephp.org/view/1191/Using-the-Debugger-Class
*/
function invoke(&$debugger) {
set_error_handler(array(&$debugger, 'handleError'));
}
}
if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) {
Debugger::invoke(Debugger::getInstance());
}

View file

@ -24,7 +24,9 @@
/**
* List of helpers to include
*/
App::import('Core', array('Router', 'CakeRequest', 'CakeResponse'), false);
App::import('Core', 'Router', false);
App::import('Core', 'CakeRequest', false);
App::import('Core', 'CakeResponse', false);
App::import('Controller', 'Controller', false);
/**

View file

@ -0,0 +1,216 @@
<?php
/**
* Error handler
*
* Provides Error Capturing for Framework errors.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs
* @since CakePHP(tm) v 0.10.5.1732
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
*
* Error Handler provides basic error and exception handling for your application. It captures and
* handles all unhandled exceptions and errors. Displays helpful framework errors when debug > 1.
*
* ### Uncaught exceptions
*
* When debug < 1 a CakeException will render 404 or 500 errors. If an uncaught exception is thrown
* and it is a type that ErrorHandler does not know about it will be treated as a 500 error.
*
* ### Implementing application specific exception handling
*
* You can implement application specific exception handling in one of a few ways. Each approach
* gives you different amounts of control over the exception handling process.
*
* - Set Configure::write('Exception.handler', 'YourClass::yourMethod');
* - Create AppController::appError();
* - Set Configure::write('Exception.renderer', 'YourClass');
*
* #### Create your own Exception handler with `Exception.handler`
*
* This gives you full control over the exception handling process. The class you choose should be
* loaded in your app/config/bootstrap.php, so its available to handle any exceptions. You can
* define the handler as any callback type. Using Exception.handler overrides all other exception
* handling settings and logic.
*
* #### Using `AppController::appError();`
*
* This controller method is called instead of the default exception rendering. It receives the
* thrown exception as its only argument. You should implement your error handling in that method.
* Using AppController::appError(), will superseed any configuration for Exception.renderer.
*
* #### Using a custom renderer with `Exception.renderer`
*
* If you don't want to take control of the exception handling, but want to change how exceptions are
* rendered you can use `Exception.renderer` to choose a class to render exception pages. By default
* `ExceptionRenderer` is used. Your custom exception renderer class should be placed in app/libs.
*
* Your custom renderer should expect an exception in its constructor, and implement a render method.
* Failing to do so will cause additional errors.
*
* #### Logging exceptions
*
* Using the built-in exception handling, you can log all the exceptions
* that are dealt with by ErrorHandler by setting `Exception.log` to true in your core.php.
* Enabling this will log every exception to CakeLog and the configured loggers.
*
* ### PHP errors
*
* Error handler also provides the built in features for handling php errors (trigger_error).
* While in debug mode, errors will be output to the screen using debugger. While in production mode,
* errors will be logged to CakeLog. You can control which errors are logged by setting
* `Error.level` in your core.php.
*
* #### Logging errors
*
* When ErrorHandler is used for handling errors, you can enable error logging by setting `Error.log` to true.
* This will log all errors to the configured log handlers.
*
* #### Controlling what errors are logged/displayed
*
* You can control which errors are logged / displayed by ErrorHandler by setting `Error.level`. Setting this
* to one or a combination of a few of the E_* constants will only enable the specified errors.
*
* e.g. `Configure::write('Error.level', E_ALL & ~E_NOTICE);`
*
* Would enable handling for all non Notice errors.
*
* @package cake
* @subpackage cake.cake.libs
* @see ExceptionRenderer for more information on how to customize exception rendering.
*/
class ErrorHandler {
/**
* Set as the default exception handler by the CakePHP bootstrap process.
*
* This will either use an AppError class if your application has one,
* or use the default ExceptionRenderer.
*
* @return void
* @see http://php.net/manual/en/function.set-exception-handler.php
*/
public static function handleException(Exception $exception) {
App::import('Core', 'error/ExceptionRenderer');
$config = Configure::read('Exception');
if (!empty($config['log'])) {
if (!class_exists('CakeLog')) {
require LIBS . 'cake_log.php';
}
CakeLog::write(LOG_ERR, '[' . get_class($exception) . '] ' . $exception->getMessage());
}
if ($config['renderer'] !== 'ExceptionRenderer') {
App::import('Lib', $config['renderer']);
}
$error = new $config['renderer']($exception);
$error->render();
}
/**
* Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own
* error handling methods. This function will use Debugger to display errors when debug > 0. And
* will log errors to CakeLog, when debug == 0.
*
* You can use Configure::write('Error.level', $value); to set what type of errors will be handled here.
* Stack traces for errors can be enabled with Configure::write('Error.trace', true);
*
* @param integer $code Code of error
* @param string $description Error description
* @param string $file File on which error occurred
* @param integer $line Line that triggered the error
* @param array $context Context
* @return boolean true if error was handled
*/
public static function handleError($code, $description, $file = null, $line = null, $context = null) {
if (error_reporting() === 0) {
return false;
}
$errorConfig = Configure::read('Error');
list($error, $log) = self::_mapErrorCode($code);
$debug = Configure::read('debug');
if ($debug) {
if (!class_exists('Debugger')) {
require LIBS . 'debugger.php';
}
$data = array(
'level' => $log,
'code' => $code,
'error' => $error,
'description' => $description,
'file' => $file,
'line' => $line,
'context' => $context,
'start' => 2,
'path' => Debugger::trimPath($file)
);
return Debugger::getInstance()->outputError($data);
} else {
if (!class_exists('CakeLog')) {
require LIBS . 'cake_log.php';
}
$message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']';
if (!empty($errorConfig['trace'])) {
if (!class_exists('Debugger')) {
require LIBS . 'debugger.php';
}
$trace = Debugger::trace(array('start' => 1, 'format' => 'log'));
$message .= "\nTrace:\n" . $trace . "\n";
}
return CakeLog::write($log, $message);
}
}
/**
* Map an error code into an Error word, and log location.
*
* @param int $code Error code to map
* @return array Array of error word, and log location.
*/
protected static function _mapErrorCode($code) {
switch ($code) {
case E_PARSE:
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$error = 'Fatal Error';
$log = LOG_ERROR;
break;
case E_WARNING:
case E_USER_WARNING:
case E_COMPILE_WARNING:
case E_RECOVERABLE_ERROR:
$error = 'Warning';
$log = LOG_WARNING;
break;
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
$log = LOG_NOTICE;
break;
case E_STRICT:
$error = 'Strict';
$log = LOG_NOTICE;
break;
case E_DEPRECATED:
$error = 'Deprecated';
$log = LOG_NOTICE;
break;
}
return array($error, $log);
}
}

View file

@ -1,8 +1,9 @@
<?php
/**
* Error handler
* Exception Renderer
*
* Provides Error Capturing for Framework errors.
* Provides Exception rendering features. Which allow exceptions to be rendered
* as HTML pages.
*
* PHP 5
*
@ -16,43 +17,38 @@
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs
* @since CakePHP(tm) v 0.10.5.1732
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Error Handler.
* Exception Renderer.
*
* Captures and handles all unhandled exceptions. Displays helpful framework errors when debug > 1.
* When debug < 1 a CakeException will render 404 or 500 errors. If an uncaught exception is thrown
* and it is a type that ErrorHandler does not know about it will be treated as a 500 error.
* and it is a type that ExceptionHandler does not know about it will be treated as a 500 error.
*
* ### Implementing application specific exception handling
* ### Implementing application specific exception rendering
*
* You can implement application specific exception handling in one of a few ways:
*
* - Create a AppController::appError();
* - Create an AppError class.
* - Create a subclass of ExceptionRenderer and configure it to be the `Exception.renderer`
*
* #### Using AppController::appError();
*
* This controller method is called instead of the default exception handling. It receives the
* thrown exception as its only argument. You should implement your error handling in that method.
*
* #### Using an AppError class
* #### Using a subclass of ExceptionRenderer
*
* This approach gives more flexibility and power in how you handle exceptions. You can create
* `app/libs/app_error.php` and create a class called `AppError`. The core ErrorHandler class
* will attempt to construct this class and let it handle the exception. This provides a more
* flexible way to handle exceptions in your application.
*
* Finally, in your `app/config/bootstrap.php` you can configure use `set_exception_handler()`
* to take total control over application exception handling.
* Using a subclass of ExceptionRenderer gives you full control over how Exceptions are rendered, you
* can configure your class in your core.php, with `Configure::write('Exception.renderer', 'MyClass');`
* You should place any custom exception renderers in `app/libs`.
*
* @package cake
* @subpackage cake.cake.libs
*/
class ErrorHandler {
class ExceptionRenderer {
/**
* Controller instance.
@ -118,7 +114,7 @@ class ErrorHandler {
if (Configure::read('debug') == 0) {
$parentClass = get_parent_class($this);
if ($parentClass != 'ErrorHandler') {
if ($parentClass != __CLASS__) {
$method = 'error400';
}
$parentMethods = (array)get_class_methods($parentClass);
@ -157,35 +153,16 @@ class ErrorHandler {
return $controller;
}
/**
* Set as the default exception handler by the CakePHP bootstrap process.
*
* This will either use an AppError class if your application has one,
* or use the default ErrorHandler.
*
* @return void
* @see http://php.net/manual/en/function.set-exception-handler.php
*/
public static function handleException(Exception $exception) {
if (file_exists(APP . 'app_error.php') || class_exists('AppError')) {
if (!class_exists('AppError')) {
require(APP . 'app_error.php');
}
$AppError = new AppError($exception);
return $AppError->render();
}
$error = new ErrorHandler($exception);
$error->render();
}
/**
* Renders the response for the exception.
*
* @return void
*/
public function render() {
if ($this->method) {
call_user_func_array(array($this, $this->method), array($this->error));
}
}
/**
* Generic handler for the internal framework errors CakePHP can generate.

View file

@ -17,7 +17,8 @@
* @since CakePHP(tm) v 1.2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('CakeSocket', 'Set', 'Router'));
App::import('Core', 'CakeSocket');
App::import('Core', 'Router');
/**
* Cake network socket connection class.

View file

@ -21,7 +21,8 @@
/**
* Included libraries.
*/
App::import('Core', array('l10n', 'Multibyte'));
App::import('Core', 'L10n');
App::import('Core', 'Multibyte');
/**
* I18n handles translation of Text and time format strings.

View file

@ -17,7 +17,8 @@
* @since CakePHP(tm) v 1.2.0.5550
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('Model', 'ConnectionManager'));
App::import('Core', 'Model');
App::import('Core', 'ConnectionManager');
/**
* Base Class for Schema management

View file

@ -17,7 +17,7 @@
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('Set', 'String'));
App::import('Core', 'String');
/**
* DboSource

View file

@ -23,7 +23,9 @@
/**
* Included libs
*/
App::import('Core', array('ClassRegistry', 'Validation', 'Set', 'String'));
App::import('Core', 'ClassRegistry', false);
App::import('Core', 'Validation', false);
App::import('Core', 'String', false);
App::import('Model', 'BehaviorCollection', false);
App::import('Model', 'ModelBehavior', false);
App::import('Model', 'ConnectionManager', false);

View file

@ -243,12 +243,12 @@ class FormHelper extends AppHelper {
if (empty($options['url']['controller'])) {
if (!empty($model) && $model != $this->defaultModel) {
$options['url']['controller'] = Inflector::underscore(Inflector::pluralize($model));
} elseif (!empty($this->request['controller'])) {
$options['url']['controller'] = Inflector::underscore($this->request['controller']);
} elseif (!empty($this->request->params['controller'])) {
$options['url']['controller'] = Inflector::underscore($this->request->params['controller']);
}
}
if (empty($options['action'])) {
$options['action'] = $this->request['action'];
$options['action'] = $this->request->params['action'];
}
$actionDefaults = array(
@ -307,9 +307,9 @@ class FormHelper extends AppHelper {
$htmlAttributes = array_merge($options, $htmlAttributes);
$this->fields = array();
if (isset($this->request['_Token']) && !empty($this->request['_Token'])) {
if (isset($this->request->params['_Token']) && !empty($this->request->params['_Token'])) {
$append .= $this->hidden('_Token.key', array(
'value' => $this->request['_Token']['key'], 'id' => 'Token' . mt_rand())
'value' => $this->request->params['_Token']['key'], 'id' => 'Token' . mt_rand())
);
}

View file

@ -27,14 +27,36 @@ require_once CONSOLE_LIBS . 'console_error_handler.php';
class ConsoleErrorHandlerTest extends CakeTestCase {
/**
* Factory method for error handlers with stderr() mocked out.
* setup, create mocks
*
* @return Mock object
*/
function getErrorHandler($exception) {
$error = new ConsoleErrorHandler($exception);
$error->stderr = $this->getMock('ConsoleOutput', array(), array(), '', false);
return $error;
function setUp() {
parent::setUp();
ConsoleErrorHandler::$stderr = $this->getMock('ConsoleOutput', array(), array(), '', false);
}
/**
* teardown
*
* @return void
*/
function tearDown() {
parent::tearDown();
ConsoleErrorHandler::$stderr = null;
}
/**
* test that the console error handler can deal with CakeExceptions.
*
* @return void
*/
function testHandleError() {
$content = '<error>Notice Error:</error> This is a notice error in [/some/file, line 275]';
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($content);
ConsoleErrorHandler::handleError(E_NOTICE, 'This is a notice error', '/some/file', 275);
}
/**
@ -44,12 +66,10 @@ class ConsoleErrorHandlerTest extends CakeTestCase {
*/
function testCakeErrors() {
$exception = new MissingActionException('Missing action');
$error = $this->getErrorHandler($exception);
$error->stderr->expects($this->once())->method('write')
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($this->stringContains('Missing action'));
$error->render();
ConsoleErrorHandler::handleException($exception);
}
/**
@ -59,12 +79,11 @@ class ConsoleErrorHandlerTest extends CakeTestCase {
*/
function testNonCakeExceptions() {
$exception = new InvalidArgumentException('Too many parameters.');
$error = $this->getErrorHandler($exception);
$error->stderr->expects($this->once())->method('write')
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($this->stringContains('Too many parameters.'));
$error->render();
ConsoleErrorHandler::handleException($exception);
}
/**
@ -74,12 +93,11 @@ class ConsoleErrorHandlerTest extends CakeTestCase {
*/
function testError404Exception() {
$exception = new NotFoundException('dont use me in cli.');
$error = $this->getErrorHandler($exception);
$error->stderr->expects($this->once())->method('write')
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($this->stringContains('dont use me in cli.'));
$error->render();
ConsoleErrorHandler::handleException($exception);
}
/**
@ -89,23 +107,11 @@ class ConsoleErrorHandlerTest extends CakeTestCase {
*/
function testError500Exception() {
$exception = new InternalErrorException('dont use me in cli.');
$error = $this->getErrorHandler($exception);
$error->stderr->expects($this->once())->method('write')
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($this->stringContains('dont use me in cli.'));
$error->render();
ConsoleErrorHandler::handleException($exception);
}
/**
* test that ConsoleErrorHandler has a stderr file handle.
*
* @return void
*/
function testStdErrFilehandle() {
$exception = new InternalErrorException('dont use me in cli.');
$error = new ConsoleErrorHandler($exception);
$this->assertType('ConsoleOutput', $error->stderr, 'No handle.');
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* AllErrorTest file
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.tests.cases
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* AllErrorTest class
*
* This test group will run error handling related tests.
*
* @package cake
* @subpackage cake.tests.groups
*/
class AllErrorTest extends PHPUnit_Framework_TestSuite {
/**
* suite method, defines tests for this suite.
*
* @return void
*/
public static function suite() {
$suite = new PHPUnit_Framework_TestSuite('All Error handling tests');
$libs = CORE_TEST_CASES . DS . 'libs' . DS;
$suite->addTestFile($libs . 'error' . DS . 'error_handler.test.php');
$suite->addTestFile($libs . 'error' . DS . 'exception_renderer.test.php');
return $suite;
}
}

View file

@ -39,7 +39,6 @@ class AllLibsTest extends PHPUnit_Framework_TestSuite {
$suite->addTestFile(CORE_TEST_CASES . DS . 'basics.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'cake_session.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'debugger.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'error_handler.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'file.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'folder.test.php');
$suite->addTestFile(CORE_TEST_CASES . DS . 'libs' . DS . 'inflector.test.php');

View file

@ -48,6 +48,7 @@ class AllTests extends PHPUnit_Framework_TestSuite {
$suite->addTestFile($path . 'all_configure.test.php');
$suite->addTestFile($path . 'all_controllers.test.php');
$suite->addTestFile($path . 'all_database.test.php');
$suite->addTestFile($path . 'all_error.test.php');
$suite->addTestFile($path . 'all_helpers.test.php');
$suite->addTestFile($path . 'all_libs.test.php');
$suite->addTestFile($path . 'all_localization.test.php');

View file

@ -211,6 +211,10 @@ class AppImportTest extends CakeTestCase {
$this->assertTrue($file);
$this->assertTrue(class_exists('Shell'));
$file = App::import('Lib', 'cache/Apc');
$this->assertTrue($file);
$this->assertTrue(class_exists('ApcEngine'));
$file = App::import('Model', 'SomeRandomModelThatDoesNotExist', false);
$this->assertFalse($file);

View file

@ -116,7 +116,9 @@ class CakeLogTest extends CakeTestCase {
$result = CakeLog::configured();
$this->assertEqual($result, array('file'));
if (file_exists(LOGS . 'error.log')) {
@unlink(LOGS . 'error.log');
}
CakeLog::write(LOG_WARNING, 'Test warning');
$this->assertTrue(file_exists(LOGS . 'error.log'));
@ -164,25 +166,4 @@ class CakeLogTest extends CakeTestCase {
unlink(LOGS . 'error.log');
}
/**
* Test logging with the error handler.
*
* @return void
*/
function testLoggingWithErrorHandling() {
@unlink(LOGS . 'debug.log');
Configure::write('log', E_ALL & ~E_DEPRECATED);
Configure::write('debug', 0);
set_error_handler(array('CakeLog', 'handleError'));
$out .= '';
$result = file(LOGS . 'debug.log');
$this->assertEqual(count($result), 1);
$this->assertPattern(
'/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} Notice: Notice \(8\): Undefined variable:\s+out in \[.+ line \d+\]$/',
$result[0]
);
@unlink(LOGS . 'debug.log');
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
* IniFileTest
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.cases
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', 'config/IniFile');
class IniFileTest extends CakeTestCase {
/**
* The test file that will be read.
*
* @var string
*/
var $file;
/**
* setup
*
* @return void
*/
function setup() {
parent::setup();
$this->file = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS . 'acl.ini.php';
}
/**
* test constrction
*
* @return void
*/
function testConstruct() {
$config = new IniFile($this->file);
$this->assertTrue(isset($config['admin']));
$this->assertTrue(isset($config['paul']['groups']));
$this->assertEquals('ads', $config['admin']['deny']);
}
/**
* no other sections should exist.
*
* @return void
*/
function testReadingOnlyOneSection() {
$config = new IniFile($this->file, 'admin');
$this->assertTrue(isset($config['groups']));
$this->assertEquals('administrators', $config['groups']);
}
/**
* test getting all the values as an array
*
* @return void
*/
function testAsArray() {
$config = new IniFile($this->file);
$content = $config->asArray();
$this->assertTrue(isset($content['admin']['groups']));
$this->assertTrue(isset($content['paul']['groups']));
}
/**
* test that values cannot be modified
*
* @expectedException LogicException
*/
function testNoModification() {
$config = new IniFile($this->file);
$config['admin'] = 'something';
}
}

View file

@ -135,54 +135,18 @@ class ConfigureTest extends CakeTestCase {
}
/**
* testSetErrorReporting Level
* test setting display_errors with debug.
*
* @return void
*/
function testSetErrorReportingLevel() {
Configure::write('log', false);
function testDebugSettingDisplayErrors() {
Configure::write('debug', 0);
$result = ini_get('error_reporting');
$result = ini_get('display_errors');
$this->assertEqual($result, 0);
Configure::write('debug', 2);
$result = ini_get('error_reporting');
$this->assertEqual($result, E_ALL & ~E_DEPRECATED);
$result = ini_get('display_errors');
$this->assertEqual($result, 1);
Configure::write('debug', 0);
$result = ini_get('error_reporting');
$this->assertEqual($result, 0);
}
/**
* test that log and debug configure values interact well.
*
* @return void
*/
function testInteractionOfDebugAndLog() {
Configure::write('log', false);
Configure::write('debug', 0);
$this->assertEqual(ini_get('error_reporting'), 0);
$this->assertEqual(ini_get('display_errors'), 0);
Configure::write('log', E_WARNING);
Configure::write('debug', 0);
$this->assertEqual(ini_get('error_reporting'), E_WARNING);
$this->assertEqual(ini_get('display_errors'), 0);
Configure::write('debug', 2);
$this->assertEqual(ini_get('error_reporting'), E_ALL & ~E_DEPRECATED);
$this->assertEqual(ini_get('display_errors'), 1);
Configure::write('debug', 0);
Configure::write('log', false);
$this->assertEqual(ini_get('error_reporting'), 0);
$this->assertEqual(ini_get('display_errors'), 0);
}
/**

View file

@ -17,7 +17,8 @@
* @since CakePHP(tm) v 1.2.0.5435
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import(array('controller' .DS . 'components' . DS . 'acl', 'model' . DS . 'db_acl'));
App::import('Component', 'Acl');
App::import('model' . DS . 'db_acl');
/**
* AclNodeTwoTestBase class
@ -259,53 +260,6 @@ class AclComponentTest extends CakeTestCase {
*/
class IniAclTest extends CakeTestCase {
/**
* testIniReadConfigFile
*
* @access public
* @return void
*/
function testReadConfigFile() {
$Ini = new IniAcl();
$iniFile = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS . 'acl.ini.php';
$result = $Ini->readConfigFile($iniFile);
$expected = array(
'admin' => array(
'groups' => 'administrators',
'allow' => '',
'deny' => 'ads',
),
'paul' => array(
'groups' => 'users',
'allow' =>'',
'deny' => '',
),
'jenny' => array(
'groups' => 'users',
'allow' => 'ads',
'deny' => 'images, files',
),
'nobody' => array(
'groups' => 'anonymous',
'allow' => '',
'deny' => '',
),
'administrators' => array(
'deny' => '',
'allow' => 'posts, comments, images, files, stats, ads',
),
'users' => array(
'allow' => 'posts, comments, images, files',
'deny' => 'stats, ads',
),
'anonymous' => array(
'allow' => '',
'deny' => 'posts, comments, images, files, stats, ads',
),
);
$this->assertEqual($result, $expected);
}
/**
* testIniCheck method
*
@ -329,6 +283,24 @@ class IniAclTest extends CakeTestCase {
$this->assertFalse($Ini->check('nobody', 'comments'));
}
/**
* check should accept a user array.
*
* @return void
*/
function testCheckArray() {
$iniFile = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS . 'acl.ini.php';
$Ini = new IniAcl();
$Ini->config = $Ini->readConfigFile($iniFile);
$Ini->userPath = 'User.username';
$user = array(
'User' => array('username' => 'admin')
);
$this->assertTrue($Ini->check($user, 'posts'));
}
}

View file

@ -39,6 +39,8 @@ class DebuggerTest extends CakeTestCase {
// !!! Be careful with changing code below as it may
// !!! change line numbers which are used in the tests
// !!!
protected $_restoreError = false;
/**
* setUp method
*
@ -60,6 +62,9 @@ class DebuggerTest extends CakeTestCase {
function tearDown() {
parent::teardown();
Configure::write('log', true);
if ($this->_restoreError) {
restore_error_handler();
}
}
/**
@ -106,7 +111,9 @@ class DebuggerTest extends CakeTestCase {
* @return void
*/
function testOutput() {
Debugger::invoke(Debugger::getInstance());
set_error_handler('Debugger::showError');
$this->_restoreError = true;
$result = Debugger::output(false);
$this->assertEqual($result, '');
$out .= '';
@ -141,8 +148,8 @@ class DebuggerTest extends CakeTestCase {
'pre' => array('class' => 'cake-debug'),
'a' => array(
'href' => "javascript:void(0);",
'onclick' => "document.getElementById('cakeErr4-trace').style.display = " .
"(document.getElementById('cakeErr4-trace').style.display == 'none'" .
'onclick' => "document.getElementById('cakeErr9-trace').style.display = " .
"(document.getElementById('cakeErr9-trace').style.display == 'none'" .
" ? '' : 'none');"
),
'b' => array(), 'Notice', '/b', ' (8)',
@ -151,8 +158,6 @@ class DebuggerTest extends CakeTestCase {
$this->assertPattern('/Undefined variable:\s+buzz/', $result[1]);
$this->assertPattern('/<a[^>]+>Code/', $result[1]);
$this->assertPattern('/<a[^>]+>Context/', $result[2]);
restore_error_handler();
}
/**
@ -161,7 +166,9 @@ class DebuggerTest extends CakeTestCase {
* @return void
*/
function testChangeOutputFormats() {
Debugger::invoke(Debugger::getInstance());
set_error_handler('Debugger::showError');
$this->_restoreError = true;
Debugger::output('js', array(
'traceLine' => '{:reference} - <a href="txmt://open?url=file://{:file}' .
'&line={:line}">{:path}</a>, line {:line}'
@ -190,8 +197,6 @@ class DebuggerTest extends CakeTestCase {
'/error'
);
$this->assertTags($result, $data, true);
restore_error_handler();
}
/**

View file

@ -0,0 +1,225 @@
<?php
/**
* ErrorHandlerTest file
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.cases.libs
* @since CakePHP(tm) v 1.2.0.5432
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('ErrorHandler', 'Controller', 'Router'));
/**
* ErrorHandlerTest class
*
* @package cake
* @subpackage cake.tests.cases.libs
*/
class ErrorHandlerTest extends CakeTestCase {
var $_restoreError = false;
/**
* setup create a request object to get out of router later.
*
* @return void
*/
function setUp() {
App::build(array(
'views' => array(
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS
)
), true);
Router::reload();
$request = new CakeRequest(null, false);
$request->base = '';
Router::setRequestInfo($request);
$this->_debug = Configure::read('debug');
$this->_error = Configure::read('Error');
Configure::write('debug', 2);
}
/**
* teardown
*
* @return void
*/
function teardown() {
Configure::write('debug', $this->_debug);
Configure::write('Error', $this->_error);
App::build();
if ($this->_restoreError) {
restore_error_handler();
}
}
/**
* test error handling when debug is on, an error should be printed from Debugger.
*
* @return void
*/
function testHandleErrorDebugOn() {
set_error_handler('ErrorHandler::handleError');
$this->_restoreError = true;
ob_start();
$wrong .= '';
$result = ob_get_clean();
$this->assertPattern('/<pre class="cake-debug">/', $result);
$this->assertPattern('/<b>Notice<\/b>/', $result);
$this->assertPattern('/variable:\s+wrong/', $result);
}
/**
* provides errors for mapping tests.
*
* @return void
*/
public static function errorProvider() {
return array(
array(E_USER_NOTICE, 'Notice'),
array(E_USER_WARNING, 'Warning'),
array(E_USER_ERROR, 'Fatal Error'),
);
}
/**
* test error mappings
*
* @dataProvider errorProvider
* @return void
*/
function testErrorMapping($error, $expected) {
set_error_handler('ErrorHandler::handleError');
$this->_restoreError = true;
ob_start();
trigger_error('Test error', $error);
$result = ob_get_clean();
$this->assertPattern('/<b>' . $expected . '<\/b>/', $result);
}
/**
* test error prepended by @
*
* @return void
*/
function testErrorSuppressed() {
set_error_handler('ErrorHandler::handleError');
$this->_restoreError = true;
ob_start();
@include 'invalid.file';
$result = ob_get_clean();
$this->assertTrue(empty($result));
}
/**
* Test that errors go into CakeLog when debug = 0.
*
* @return void
*/
function testHandleErrorDebugOff() {
Configure::write('debug', 0);
Configure::write('Error.trace', false);
if (file_exists(LOGS . 'debug.log')) {
@unlink(LOGS . 'debug.log');
}
set_error_handler('ErrorHandler::handleError');
$this->_restoreError = true;
$out .= '';
$result = file(LOGS . 'debug.log');
$this->assertEqual(count($result), 1);
$this->assertPattern(
'/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} Notice: Notice \(8\): Undefined variable:\s+out in \[.+ line \d+\]$/',
$result[0]
);
@unlink(LOGS . 'debug.log');
}
/**
* Test that errors going into CakeLog include traces.
*
* @return void
*/
function testHandleErrorLoggingTrace() {
Configure::write('debug', 0);
Configure::write('Error.trace', true);
if (file_exists(LOGS . 'debug.log')) {
@unlink(LOGS . 'debug.log');
}
set_error_handler('ErrorHandler::handleError');
$this->_restoreError = true;
$out .= '';
$result = file(LOGS . 'debug.log');
$this->assertPattern(
'/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} Notice: Notice \(8\): Undefined variable:\s+out in \[.+ line \d+\]$/',
$result[0]
);
$this->assertPattern('/^Trace:/', $result[1]);
$this->assertPattern('/^ErrorHandlerTest\:\:testHandleErrorLoggingTrace\(\)/', $result[2]);
@unlink(LOGS . 'debug.log');
}
/**
* test handleException generating a page.
*
* @return void
*/
function testHandleException() {
if ($this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.')) {
return;
}
$error = new NotFoundException('Kaboom!');
ob_start();
ErrorHandler::handleException($error);
$result = ob_get_clean();
$this->assertPattern('/Kaboom!/', $result, 'message missing.');
}
/**
* test handleException generating a page.
*
* @return void
*/
function testHandleExceptionLog() {
if ($this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.')) {
return;
}
if (file_exists(LOGS . 'error.log')) {
unlink(LOGS . 'error.log');
}
Configure::write('Exception.log', true);
$error = new NotFoundException('Kaboom!');
ob_start();
ErrorHandler::handleException($error);
$result = ob_get_clean();
$this->assertPattern('/Kaboom!/', $result, 'message missing.');
$log = file(LOGS . 'error.log');
$this->assertPattern('/\[NotFoundException\] Kaboom!/', $log[0], 'message missing.');
}
}

View file

@ -1,6 +1,6 @@
<?php
/**
* ErrorHandlerTest file
* ExceptionRendererTest file
*
* PHP 5
*
@ -14,11 +14,11 @@
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.cases.libs
* @since CakePHP(tm) v 1.2.0.5432
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Core', array('ErrorHandler', 'Controller', 'Component'));
App::import('Core', array('ExceptionRenderer', 'Controller', 'Component'));
/**
* Short description for class.
@ -119,12 +119,12 @@ class TestErrorController extends Controller {
}
/**
* MyCustomErrorHandler class
* MyCustomExceptionRenderer class
*
* @package cake
* @subpackage cake.tests.cases.libs
*/
class MyCustomErrorHandler extends ErrorHandler {
class MyCustomExceptionRenderer extends ExceptionRenderer {
/**
* custom error message type.
@ -144,13 +144,14 @@ class MissingWidgetThingException extends NotFoundException { }
/**
* ErrorHandlerTest class
* ExceptionRendererTest class
*
* @package cake
* @subpackage cake.tests.cases.libs
*/
class ErrorHandlerTest extends CakeTestCase {
class ExceptionRendererTest extends CakeTestCase {
var $_restoreError = false;
/**
* setup create a request object to get out of router later.
*
@ -169,6 +170,8 @@ class ErrorHandlerTest extends CakeTestCase {
$request->base = '';
Router::setRequestInfo($request);
$this->_debug = Configure::read('debug');
$this->_error = Configure::read('Error');
Configure::write('debug', 2);
}
/**
@ -178,11 +181,15 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function teardown() {
Configure::write('debug', $this->_debug);
Configure::write('Error', $this->_error);
App::build();
if ($this->_restoreError) {
restore_error_handler();
}
}
/**
* Mocks out the response on the errorhandler object so headers aren't modified.
* Mocks out the response on the ExceptionRenderer object so headers aren't modified.
*
* @return void
*/
@ -192,26 +199,7 @@ class ErrorHandlerTest extends CakeTestCase {
}
/**
* test handleException generating a page.
*
* @return void
*/
function testHandleException() {
if ($this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.')) {
return;
}
if ($this->skipIf(PHP_SAPI == 'cli', 'This integration test can not be run in cli.')) {
return;
}
$error = new NotFoundException('Kaboom!');
ob_start();
ErrorHandler::handleException($error);
$result = ob_get_clean();
$this->assertPattern('/Kaboom!/', $result, 'message missing.');
}
/**
* test that methods declared in an ErrorHandler subclass are not converted
* test that methods declared in an ExceptionRenderer subclass are not converted
* into error400 when debug > 0
*
* @return void
@ -220,10 +208,10 @@ class ErrorHandlerTest extends CakeTestCase {
Configure::write('debug', 2);
$exception = new MissingWidgetThingException('Widget not found');
$ErrorHandler = $this->_mockResponse(new MyCustomErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertEqual($result, 'widget thing is missing');
@ -237,19 +225,19 @@ class ErrorHandlerTest extends CakeTestCase {
function testSubclassMethodsNotBeingConvertedDebug0() {
Configure::write('debug', 0);
$exception = new MissingWidgetThingException('Widget not found');
$ErrorHandler = $this->_mockResponse(new MyCustomErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
$this->assertEqual('missingWidgetThing', $ErrorHandler->method);
$this->assertEqual('missingWidgetThing', $ExceptionRenderer->method);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error400');
}
/**
* test that ErrorHandler subclasses properly convert framework errors.
* test that ExceptionRenderer subclasses properly convert framework errors.
*
* @return void
*/
@ -257,12 +245,12 @@ class ErrorHandlerTest extends CakeTestCase {
Configure::write('debug', 0);
$exception = new MissingControllerException('PostsController');
$ErrorHandler = $this->_mockResponse(new MyCustomErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));
$this->assertEqual('error400', $ErrorHandler->method);
$this->assertEqual('error400', $ExceptionRenderer->method);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error400. %s');
@ -275,11 +263,11 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function testConstruction() {
$exception = new NotFoundException('Page not found');
$ErrorHandler = new ErrorHandler($exception);
$ExceptionRenderer = new ExceptionRenderer($exception);
$this->assertType('CakeErrorController', $ErrorHandler->controller);
$this->assertEquals('error400', $ErrorHandler->method);
$this->assertEquals($exception, $ErrorHandler->error);
$this->assertType('CakeErrorController', $ExceptionRenderer->controller);
$this->assertEquals('error400', $ExceptionRenderer->method);
$this->assertEquals($exception, $ExceptionRenderer->error);
}
/**
@ -290,11 +278,11 @@ class ErrorHandlerTest extends CakeTestCase {
function testErrorMethodCoercion() {
Configure::write('debug', 0);
$exception = new MissingActionException('Page not found');
$ErrorHandler = new ErrorHandler($exception);
$ExceptionRenderer = new ExceptionRenderer($exception);
$this->assertType('CakeErrorController', $ErrorHandler->controller);
$this->assertEquals('error400', $ErrorHandler->method);
$this->assertEquals($exception, $ErrorHandler->error);
$this->assertType('CakeErrorController', $ExceptionRenderer->controller);
$this->assertEquals('error400', $ExceptionRenderer->method);
$this->assertEquals($exception, $ExceptionRenderer->error);
}
/**
@ -304,16 +292,16 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function testUnknownExceptionTypeWithExceptionThatHasA400Code() {
$exception = new MissingWidgetThingException('coding fail.');
$ErrorHandler = new ErrorHandler($exception);
$ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404);
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$results = ob_get_clean();
$this->assertFalse(method_exists($ErrorHandler, 'missingWidgetThing'), 'no method should exist.');
$this->assertEquals('error400', $ErrorHandler->method, 'incorrect method coercion.');
$this->assertFalse(method_exists($ExceptionRenderer, 'missingWidgetThing'), 'no method should exist.');
$this->assertEquals('error400', $ExceptionRenderer->method, 'incorrect method coercion.');
}
/**
@ -323,15 +311,15 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function testUnknownExceptionTypeWithNoCodeIsA500() {
$exception = new OutOfBoundsException('foul ball.');
$ErrorHandler = new ErrorHandler($exception);
$ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500);
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$results = ob_get_clean();
$this->assertEquals('error500', $ErrorHandler->method, 'incorrect method coercion.');
$this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
}
/**
@ -347,12 +335,12 @@ class ErrorHandlerTest extends CakeTestCase {
Router::setRequestInfo($request);
$exception = new NotFoundException('Custom message');
$ErrorHandler = new ErrorHandler($exception);
$ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404);
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertPattern('/<h2>Custom message<\/h2>/', $result);
@ -368,18 +356,18 @@ class ErrorHandlerTest extends CakeTestCase {
Configure::write('debug', 0);
$exception = new NotFoundException('Custom message');
$ErrorHandler = $this->_mockResponse(new ErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertContains('Custom message', $result);
$exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index'));
$ErrorHandler = $this->_mockResponse(new ErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertContains('Not Found', $result);
}
@ -395,10 +383,10 @@ class ErrorHandlerTest extends CakeTestCase {
Router::setRequestInfo($request);
$exception = new NotFoundException('Custom message');
$ErrorHandler = $this->_mockResponse(new ErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertNoPattern('#<script>document#', $result);
@ -413,12 +401,12 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function testError500Message() {
$exception = new InternalErrorException('An Internal Error Has Occurred');
$ErrorHandler = new ErrorHandler($exception);
$ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500);
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertPattern('/<h2>An Internal Error Has Occurred<\/h2>/', $result);
@ -432,10 +420,10 @@ class ErrorHandlerTest extends CakeTestCase {
*/
function testMissingController() {
$exception = new MissingControllerException(array('controller' => 'PostsController'));
$ErrorHandler = $this->_mockResponse(new ErrorHandler($exception));
$ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception));
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
$this->assertPattern('/<h2>Missing Controller<\/h2>/', $result);
@ -568,14 +556,14 @@ class ErrorHandlerTest extends CakeTestCase {
* @return void
*/
function testCakeExceptionHandling($exception, $patterns, $code) {
$ErrorHandler = new ErrorHandler($exception);
$ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ErrorHandler->controller->response->expects($this->once())
$ExceptionRenderer = new ExceptionRenderer($exception);
$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
$ExceptionRenderer->controller->response->expects($this->once())
->method('statusCode')
->with($code);
ob_start();
$ErrorHandler->render();
$ExceptionRenderer->render();
$result = ob_get_clean();
foreach ($patterns as $pattern) {