diff --git a/app/webroot/index.php b/app/webroot/index.php index 396775b73..f6984a448 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -79,6 +79,7 @@ if (isset($_GET['url']) && $_GET['url'] === 'favicon.ico') { return; } else { + require CAKE . 'dispatcher.php'; $Dispatcher = new Dispatcher(); $Dispatcher->dispatch(); } diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 7a05b8b01..413ef9931 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -25,7 +25,6 @@ if (!defined('E_DEPRECATED')) { error_reporting(E_ALL & ~E_DEPRECATED); require CORE_PATH . 'cake' . DS . 'basics.php'; -$TIME_START = microtime(true); require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; require LIBS . 'exceptions.php'; require LIBS . 'object.php'; @@ -33,5 +32,8 @@ require LIBS . 'inflector.php'; require LIBS . 'configure.php'; require LIBS . 'set.php'; require LIBS . 'cache.php'; -Configure::bootstrap(); -require CAKE . 'dispatcher.php'; +require LIBS . 'error_handler.php'; +set_exception_handler(array('ErrorHandler', 'handleException')); + +Configure::bootstrap(isset($boot) ? $boot : true); + diff --git a/cake/console/cake.php b/cake/console/cake.php index 4e4673cfc..472987c46 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -20,9 +20,7 @@ * @since CakePHP(tm) v 1.2.0.5012 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -if (!defined('E_DEPRECATED')) { - define('E_DEPRECATED', 8192); -} + /** * Shell dispatcher * @@ -172,7 +170,6 @@ class ShellDispatcher { } } } - require_once(CORE_PATH . 'cake' . DS . 'basics.php'); } /** @@ -258,26 +255,10 @@ class ShellDispatcher { define('TMP', CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'tmp' . DS); } - $includes = array( - CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'object.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'inflector.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'configure.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'file.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'cache.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'string.php', - CORE_PATH . 'cake' . DS . 'libs' . DS . 'class_registry.php', - CORE_PATH . 'cake' . DS . 'console' . DS . 'error.php' - ); - - foreach ($includes as $inc) { - if (!require($inc)) { - $this->stderr("Failed to load Cake core file {$inc}"); - return false; - } - } - - Configure::bootstrap(file_exists(CONFIGS . 'bootstrap.php')); + $boot = file_exists(ROOT . DS . APP_DIR . DS . 'config' . DS . 'bootstrap.php'); + require CORE_PATH . 'cake' . DS . 'bootstrap.php'; + require_once CORE_PATH . 'cake' . DS . 'console' . DS . 'console_error_handler.php'; + set_exception_handler(array('ConsoleErrorHandler', 'handleException')); if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) { include_once CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php'; diff --git a/cake/console/console_error_handler.php b/cake/console/console_error_handler.php new file mode 100644 index 000000000..91469b89e --- /dev/null +++ b/cake/console/console_error_handler.php @@ -0,0 +1,119 @@ +stderr = fopen('php://stderr', 'w'); + parent::__construct($error); + } + +/** + * Handle a exception in the console environment. + * + * @return void + */ + public static function handleException($exception) { + $error = new ConsoleErrorHandler($exception); + $error->render(); + } + +/** + * Do nothing, no controllers are needed in the console. + * + * @return void + */ + protected function _getController($exception) { + return null; + } + +/** + * Overwrite how _cakeError behaves for console. There is no reason + * to prepare urls as they are not relevant for this. + * + * @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) { + $this->stderr($this->error->getMessage() . "\n" . $this->error->getTraceAsString()); + } + +/** + * Outputs to the stderr filehandle. + * + * @param string $string Error text to output. + */ + public function stderr($string) { + fwrite($this->stderr, "Error: ". $string . "\n"); + } +} diff --git a/cake/console/error.php b/cake/console/error.php deleted file mode 100644 index 21860ef0d..000000000 --- a/cake/console/error.php +++ /dev/null @@ -1,248 +0,0 @@ -stdout = fopen('php://stdout', 'w'); - $this->stderr = fopen('php://stderr', 'w'); - call_user_func_array(array(&$this, $method), $messages); - } - -/** - * Displays an error page (e.g. 404 Not found). - * - * @param array $params Parameters (code, name, and message) - */ - public function error($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr($code . $name . $message."\n"); - $this->_stop(); - } - -/** - * Convenience method to display a 404 page. - * - * @param array $params Parameters (url, message) - */ - public function error404($params) { - extract($params, EXTR_OVERWRITE); - $this->error(array( - 'code' => '404', - 'name' => 'Not found', - 'message' => sprintf(__('The requested address %s was not found on this server.'), $url, $message) - )); - $this->_stop(); - } - -/** - * Renders the Missing Controller web page. - * - * @param array $params Parameters (className) - */ - public function missingController($params) { - extract($params, EXTR_OVERWRITE); - $controllerName = str_replace('Controller', '', $className); - $this->stderr(sprintf(__("Missing Controller '%s'"), $controllerName)); - $this->_stop(); - } - -/** - * Renders the Missing Action web page. - * - * @param array $params Parameters (action, className) - */ - public function missingAction($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Method '%s' in '%s'"), $action, $className)); - $this->_stop(); - } - -/** - * Renders the Private Action web page. - * - * @param array $params Parameters (action, className) - */ - public function privateAction($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Trying to access private method '%s' in '%s'"), $action, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Table web page. - * - * @param array $params Parameters (table, className) - */ - public function missingTable($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing database table '%s' for model '%s'"), $table, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Database web page. - * - * @param array $params Parameters - */ - public function missingDatabase($params = array()) { - $this->stderr(__('Missing Database')); - $this->_stop(); - } - -/** - * Renders the Missing View web page. - * - * @param array $params Parameters (file, action, className) - */ - public function missingView($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing View '%s' for '%s' in '%s'"), $file, $action, $className)); - $this->_stop(); - } - -/** - * Renders the Missing Layout web page. - * - * @param array $params Parameters (file) - */ - public function missingLayout($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Layout '%s'"), $file)); - $this->_stop(); - } - -/** - * Renders the Database Connection web page. - * - * @param array $params Parameters - */ - public function missingConnection($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(__("Missing Database Connection. Try 'cake bake'")); - $this->_stop(); - } - -/** - * Renders the Missing Helper file web page. - * - * @param array $params Parameters (file, helper) - */ - public function missingHelperFile($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Helper file '%s' for '%s'"), $file, Inflector::camelize($helper))); - $this->_stop(); - } - -/** - * Renders the Missing Helper class web page. - * - * @param array $params Parameters (file, helper) - */ - public function missingHelperClass($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Helper class '%s' in '%s'"), Inflector::camelize($helper), $file)); - $this->_stop(); - } - -/** - * Renders the Missing Component file web page. - * - * @param array $params Parameters (file, component) - */ - public function missingComponentFile($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Component file '%s' for '%s'"), $file, Inflector::camelize($component))); - $this->_stop(); - } - -/** - * Renders the Missing Component class web page. - * - * @param array $params Parameters (file, component) - */ - public function missingComponentClass($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing Component class '%s' in '%s'"), Inflector::camelize($component), $file)); - $this->_stop(); - } - -/** - * Renders the Missing Model class web page. - * - * @param array $params Parameters (className) - */ - public function missingModel($params) { - extract($params, EXTR_OVERWRITE); - $this->stderr(sprintf(__("Missing model '%s'"), $className)); - $this->_stop(); - } - -/** - * Outputs to the stdout filehandle. - * - * @param string $string String to output. - * @param boolean $newline If true, the outputs gets an added newline. - */ - public function stdout($string, $newline = true) { - if ($newline) { - fwrite($this->stdout, $string . "\n"); - } else { - fwrite($this->stdout, $string); - } - } - -/** - * Outputs to the stderr filehandle. - * - * @param string $string Error text to output. - */ - public function stderr($string) { - fwrite($this->stderr, "Error: ". $string . "\n"); - } -} diff --git a/cake/console/libs/acl.php b/cake/console/libs/acl.php index 6627d1850..fde573223 100644 --- a/cake/console/libs/acl.php +++ b/cake/console/libs/acl.php @@ -91,7 +91,8 @@ class AclShell extends Shell { require_once (CONFIGS.'database.php'); if (!in_array($this->command, array('initdb'))) { - $this->Acl =& new AclComponent(); + $collection = new ComponentCollection(); + $this->Acl =& new AclComponent($collection); $controller = null; $this->Acl->startup($controller); } diff --git a/cake/dispatcher.php b/cake/dispatcher.php index 54cf20dc7..cd5ae451a 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -134,7 +134,9 @@ class Dispatcher { if (!is_object($controller)) { Router::setRequestInfo($request); - throw new MissingControllerException(Inflector::camelize($request->params['controller']) . 'Controller'); + throw new MissingControllerException(array( + 'controller' => Inflector::camelize($request->params['controller']) . 'Controller' + )); } $privateAction = $request->params['action'][0] === '_'; $prefixes = Router::prefixes(); @@ -151,12 +153,10 @@ class Dispatcher { Router::setRequestInfo($request); if ($privateAction) { - $message = sprintf( - '%s::%s()', - Inflector::camelize($request->params['controller']) . "Controller", - $request->params['action'] - ); - throw new PrivateActionException($message); + throw new PrivateActionException(array( + 'controller' => Inflector::camelize($request->params['controller']) . "Controller", + 'action' => $request->params['action'] + )); } return $this->_invoke($controller, $request); @@ -184,12 +184,10 @@ class Dispatcher { App::import('Controller', 'Scaffold', false); return new Scaffold($controller, $request); } - $message = sprintf( - '%s::%s()', - Inflector::camelize($request->params['controller']) . "Controller", - $request->params['action'] - ); - throw new MissingActionException($message); + throw new MissingActionException(array( + 'controller' => Inflector::camelize($request->params['controller']) . "Controller", + 'action' => $request->params['action'] + )); } $result =& call_user_func_array(array(&$controller, $request->params['action']), $request->params['pass']); $response = $controller->getResponse(); diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 182ab0c14..ad38f2f69 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -1108,6 +1108,7 @@ class App { return array('class' => $type, 'suffix' => $type, 'path' => $path); break; case 'component': + App::import('Core', 'Component', false); if ($plugin) { $path = $pluginPath . DS . 'controllers' . DS . 'components' . DS; } @@ -1120,6 +1121,7 @@ class App { return array('class' => null, 'suffix' => null, 'path' => $path); break; case 'view': + App::import('View', 'View', false); if ($plugin) { $path = $pluginPath . DS . 'views' . DS; } diff --git a/cake/libs/controller/cake_error_controller.php b/cake/libs/controller/cake_error_controller.php new file mode 100644 index 000000000..765e79f30 --- /dev/null +++ b/cake/libs/controller/cake_error_controller.php @@ -0,0 +1,48 @@ +_set(Router::getPaths()); + $this->request = $this->params = Router::getRequest(false); + $this->constructClasses(); + $this->Components->trigger('initialize', array(&$this)); + $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); + } + +/** + * Escapes the viewVars. + * + * @return void + */ + function beforeRender() { + parent::beforeRender(); + foreach ($this->viewVars as $key => $value) { + if (!is_object($value)){ + $this->viewVars[$key] = h($value); + } + } + } +} \ No newline at end of file diff --git a/cake/libs/controller/component_collection.php b/cake/libs/controller/component_collection.php index f0fc314e8..a4aea463b 100644 --- a/cake/libs/controller/component_collection.php +++ b/cake/libs/controller/component_collection.php @@ -54,10 +54,16 @@ class ComponentCollection extends ObjectCollection { $componentClass = $name . 'Component'; if (!class_exists($componentClass)) { if (!App::import('Component', $component)) { - throw new MissingComponentFileException(Inflector::underscore($component) . '.php'); + throw new MissingComponentFileException(array( + 'file' => Inflector::underscore($component) . '.php', + 'class' => $componentClass + )); } if (!class_exists($componentClass)) { - throw new MissingComponentFileException($component); + throw new MissingComponentFileException(array( + 'file' => Inflector::underscore($component) . '.php', + 'class' => $componentClass + )); } } $this->_loaded[$name] = new $componentClass($this, $settings); diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 688b422a9..e866c6655 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -23,6 +23,7 @@ */ App::import('Core', 'CakeResponse', false); App::import('Controller', 'Component', false); +App::import('Core', 'CakeResponse', false); App::import('View', 'View', false); /** @@ -491,9 +492,10 @@ class Controller extends Object { * see Controller::loadModel(); for more info. * Loads Components and prepares them for initialization. * - * @return mixed true if models found and instance created, or cakeError if models not found. + * @return mixed true if models found and instance created. * @see Controller::loadModel() * @link http://book.cakephp.org/view/977/Controller-Methods#constructClasses-986 + * @throws MissingModelException */ public function constructClasses() { $this->__mergeVars(); diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index 9d5779746..a281083db 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -414,11 +414,13 @@ class Scaffold { break; } } else { - $message = sprintf('%s::%s()', $this->controller->name . "Controller", $request->action); - throw new MissingActionException($message); + throw new MissingActionException(array( + 'controller' => $this->controller->name, + 'action' => $request->action + )); } } else { - throw new MissingDatabaseException($this->ScaffoldModel->useDbConfig); + throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig)); } } @@ -460,9 +462,7 @@ class Scaffold { * @package cake * @subpackage cake.cake.libs.controller */ -if (!class_exists('ThemeView')) { - App::import('View', 'Theme'); -} +App::import('View', 'Theme'); /** * ScaffoldView provides specific view file loading features for scaffolded views. diff --git a/cake/libs/error.php b/cake/libs/error.php deleted file mode 100644 index dcfecddaf..000000000 --- a/cake/libs/error.php +++ /dev/null @@ -1,443 +0,0 @@ -_set(Router::getPaths()); - $this->request = $this->params = Router::getRequest(); - $this->constructClasses(); - $this->Component->initialize($this); - $this->_set(array('cacheAction' => false, 'viewPath' => 'errors')); - } -} - -/** - * Error Handler. - * - * Captures and handles all cakeError() calls. - * Displays helpful framework errors when debug > 1. - * When debug < 1 cakeError() will render 404 or 500 errors. - * - * @package cake - * @subpackage cake.cake.libs - */ -class ErrorHandler extends Object { - -/** - * Controller instance. - * - * @var Controller - * @access public - */ - public $controller = null; - -/** - * Class constructor. - * - * @param string $method Method producing the error - * @param array $messages Error messages - */ - function __construct($method, $messages) { - App::import('Core', 'Sanitize'); - static $__previousError = null; - - if ($__previousError != array($method, $messages)) { - $__previousError = array($method, $messages); - $this->controller = new CakeErrorController(); - } else { - $this->controller = new Controller(); - $this->controller->viewPath = 'errors'; - } - $options = array('escape' => false); - $messages = Sanitize::clean($messages, $options); - - if (!isset($messages[0])) { - $messages = array($messages); - } - - if (method_exists($this->controller, 'apperror')) { - return $this->controller->appError($method, $messages); - } - - if (!in_array(strtolower($method), array_map('strtolower', get_class_methods($this)))) { - $method = 'error'; - } - - if ($method !== 'error') { - if (Configure::read('debug') == 0) { - $parentClass = get_parent_class($this); - if (strtolower($parentClass) != 'errorhandler') { - $method = 'error404'; - } - $parentMethods = array_map('strtolower', get_class_methods($parentClass)); - if (in_array(strtolower($method), $parentMethods)) { - $method = 'error404'; - } - if (isset($messages[0]['code']) && $messages[0]['code'] == 500) { - $method = 'error500'; - } - } - } - $this->dispatchMethod($method, $messages); - $this->_stop(); - } - -/** - * Displays an error page (e.g. 404 Not found). - * - * @param array $params Parameters for controller - */ - public function error($params) { - extract($params, EXTR_OVERWRITE); - $this->controller->set(array( - 'code' => $code, - 'name' => $name, - 'message' => $message, - 'title' => $code . ' ' . $name - )); - $this->_outputMessage('error404'); - } - -/** - * Convenience method to display a 404 page. - * - * @param array $params Parameters for controller - */ - public function error404($params) { - extract($params, EXTR_OVERWRITE); - - if (!isset($url)) { - $url = $this->controller->here; - } - $url = Router::normalize($url); - $this->controller->header("HTTP/1.0 404 Not Found"); - $this->controller->set(array( - 'code' => '404', - 'name' => __('Not Found'), - 'message' => h($url), - 'base' => $this->controller->request->base - )); - $this->_outputMessage('error404'); - } - -/** - * Convenience method to display a 500 page. - * - * @param array $params Parameters for controller - */ - public function error500($params) { - extract($params, EXTR_OVERWRITE); - - if (!isset($url)) { - $url = $this->controller->request->here; - } - $url = Router::normalize($url); - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'name' => __('An Internal Error Has Occurred'), - 'message' => h($url), - 'base' => $this->controller->request->base - )); - $this->_outputMessage('error500'); - } -/** - * Renders the Missing Controller web page. - * - * @param array $params Parameters for controller - */ - public function missingController($params) { - extract($params, EXTR_OVERWRITE); - - $controllerName = str_replace('Controller', '', $className); - $this->controller->set(array( - 'controller' => $className, - 'controllerName' => $controllerName, - 'title' => __('Missing Controller') - )); - $this->_outputMessage('missingController'); - } - -/** - * Renders the Missing Action web page. - * - * @param array $params Parameters for controller - */ - public function missingAction($params) { - extract($params, EXTR_OVERWRITE); - - $controllerName = str_replace('Controller', '', $className); - $this->controller->set(array( - 'controller' => $className, - 'controllerName' => $controllerName, - 'action' => $action, - 'title' => __('Missing Method in Controller') - )); - $this->_outputMessage('missingAction'); - } - -/** - * Renders the Private Action web page. - * - * @param array $params Parameters for controller - */ - public function privateAction($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'controller' => $className, - 'action' => $action, - 'title' => __('Trying to access private method in class') - )); - $this->_outputMessage('privateAction'); - } - -/** - * Renders the Missing Table web page. - * - * @param array $params Parameters for controller - */ - public function missingTable($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'model' => $className, - 'table' => $table, - 'title' => __('Missing Database Table') - )); - $this->_outputMessage('missingTable'); - } - -/** - * Renders the Missing Database web page. - * - * @param array $params Parameters for controller - */ - public function missingDatabase($params = array()) { - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'title' => __('Scaffold Missing Database Connection') - )); - $this->_outputMessage('missingScaffolddb'); - } - -/** - * Renders the Missing View web page. - * - * @param array $params Parameters for controller - */ - public function missingView($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'controller' => $className, - 'action' => $action, - 'file' => $file, - 'title' => __('Missing View') - )); - $this->_outputMessage('missingView'); - } - -/** - * Renders the Missing Layout web page. - * - * @param array $params Parameters for controller - */ - public function missingLayout($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->layout = 'default'; - $this->controller->set(array( - 'file' => $file, - 'title' => __('Missing Layout') - )); - $this->_outputMessage('missingLayout'); - } - -/** - * Renders the Database Connection web page. - * - * @param array $params Parameters for controller - */ - public function missingConnection($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->header("HTTP/1.0 500 Internal Server Error"); - $this->controller->set(array( - 'code' => '500', - 'model' => $className, - 'title' => __('Missing Database Connection') - )); - $this->_outputMessage('missingConnection'); - } - -/** - * Renders the Missing Helper file web page. - * - * @param array $params Parameters for controller - */ - public function missingHelperFile($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'helperClass' => Inflector::camelize($helper) . "Helper", - 'file' => $file, - 'title' => __('Missing Helper File') - )); - $this->_outputMessage('missingHelperFile'); - } - -/** - * Renders the Missing Helper class web page. - * - * @param array $params Parameters for controller - */ - public function missingHelperClass($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'helperClass' => Inflector::camelize($helper) . "Helper", - 'file' => $file, - 'title' => __('Missing Helper Class') - )); - $this->_outputMessage('missingHelperClass'); - } - -/** - * Renders the Missing Behavior file web page. - * - * @param array $params Parameters for controller - */ - public function missingBehaviorFile($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'behaviorClass' => Inflector::camelize($behavior) . "Behavior", - 'file' => $file, - 'title' => __('Missing Behavior File') - )); - $this->_outputMessage('missingBehaviorFile'); - } - -/** - * Renders the Missing Behavior class web page. - * - * @param array $params Parameters for controller - */ - public function missingBehaviorClass($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'behaviorClass' => Inflector::camelize($behavior) . "Behavior", - 'file' => $file, - 'title' => __('Missing Behavior Class') - )); - $this->_outputMessage('missingBehaviorClass'); - } - -/** - * Renders the Missing Component file web page. - * - * @param array $params Parameters for controller - */ - public function missingComponentFile($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'controller' => $className, - 'component' => $component, - 'file' => $file, - 'title' => __('Missing Component File') - )); - $this->_outputMessage('missingComponentFile'); - } - -/** - * Renders the Missing Component class web page. - * - * @param array $params Parameters for controller - */ - public function missingComponentClass($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'controller' => $className, - 'component' => $component, - 'file' => $file, - 'title' => __('Missing Component Class') - )); - $this->_outputMessage('missingComponentClass'); - } - -/** - * Renders the Missing Model class web page. - * - * @param unknown_type $params Parameters for controller - */ - public function missingModel($params) { - extract($params, EXTR_OVERWRITE); - - $this->controller->set(array( - 'model' => $className, - 'title' => __('Missing Model') - )); - $this->_outputMessage('missingModel'); - } - -/** - * Output message - * - */ - protected function _outputMessage($template) { - $this->controller->render($template); - $this->controller->afterFilter(); - echo $this->controller->output; - } -} diff --git a/cake/libs/error_handler.php b/cake/libs/error_handler.php new file mode 100644 index 000000000..53e1dfbaf --- /dev/null +++ b/cake/libs/error_handler.php @@ -0,0 +1,257 @@ + 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. + * + * ### Implementing application specific exception handling + * + * You can implement application specific exception handling in one of a few ways: + * + * - Create a AppController::appError(); + * - Create an AppError class. + * + * #### 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 + * + * 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. + * + * @package cake + * @subpackage cake.cake.libs + */ +class ErrorHandler { + +/** + * Controller instance. + * + * @var Controller + * @access public + */ + public $controller = null; + +/** + * template to render for CakeException + * + * @var string + */ + public $template = ''; + +/** + * The method corresponding to the Exception this object is for. + * + * @var string + */ + public $method = ''; + +/** + * The exception being handled. + * + * @var Exception + */ + public $error = null; + +/** + * Creates the controller to perform rendering on the error response. + * If the error is a CakeException it will be converted to either a 400 or a 500 + * code error depending on the code used to construct the error. + * + * @param string $method Method producing the error + * @param array $messages Error messages + */ + function __construct(Exception $exception) { + App::import('Core', 'Sanitize'); + + $this->controller = $this->_getController($exception); + + if (method_exists($this->controller, 'apperror')) { + return $this->controller->appError($exception); + } + $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); + $code = $exception->getCode(); + + $methodExists = method_exists($this, $method); + + if ($exception instanceof CakeException && !$methodExists) { + $method = '_cakeError'; + if ($template == 'internalError') { + $template = 'error500'; + } + } elseif (!$methodExists) { + $method = 'error500'; + if ($code >= 400) { + $method = 'error400'; + } + } + + if (Configure::read('debug') == 0) { + $parentClass = get_parent_class($this); + if ($parentClass != 'ErrorHandler') { + $method = 'error400'; + } + $parentMethods = (array)get_class_methods($parentClass); + if (in_array($method, $parentMethods)) { + $method = 'error400'; + } + if ($code == 500) { + $method = 'error500'; + } + } + $this->template = $template; + $this->method = $method; + $this->error = $exception; + } + +/** + * Get the controller instance to handle the exception. + * Override this method in subclasses to customize the controller used. + * This method returns the built in `CakeErrorController` normally, or if an error is repeated + * a bare controller will be used. + * + * @param Exception $exception The exception to get a controller for. + * @return Controller + */ + protected function _getController($exception) { + static $__previousError = null; + App::import('Controller', 'CakeError'); + + if ($__previousError != $exception) { + $__previousError = $exception; + $controller = new CakeErrorController(); + } else { + $controller = new Controller(); + $controller->viewPath = 'errors'; + } + 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() { + call_user_func_array(array($this, $this->method), array($this->error)); + } + +/** + * Generic handler for the internal framework errors CakePHP can generate. + * + * @param CakeExeption $error + * @return void + */ + protected function _cakeError(CakeException $error) { + $url = Router::normalize($this->controller->request->here); + $code = $error->getCode(); + $this->controller->response->statusCode($code); + $this->controller->set(array( + 'code' => $code, + 'url' => h($url), + 'name' => $error->getMessage(), + 'error' => $error, + )); + $this->controller->set($error->getAttributes()); + $this->_outputMessage($this->template); + } + +/** + * Convenience method to display a 400 series page. + * + * @param array $params Parameters for controller + */ + public function error400($error) { + $message = $error->getMessage(); + if (Configure::read('debug') == 0 && $error instanceof CakeException) { + $message = __('Not Found'); + } + $url = Router::normalize($this->controller->request->here); + $this->controller->response->statusCode($error->getCode()); + $this->controller->set(array( + 'name' => $message, + 'url' => h($url), + 'error' => $error, + )); + $this->_outputMessage('error400'); + } + +/** + * Convenience method to display a 500 page. + * + * @param array $params Parameters for controller + */ + public function error500($error) { + $url = Router::normalize($this->controller->request->here); + $code = ($error->getCode() > 500) ? $error->getCode() : 500; + $this->controller->response->statusCode($code); + $this->controller->set(array( + 'name' => __('An Internal Error Has Occurred'), + 'message' => h($url), + 'error' => $error, + )); + $this->_outputMessage('error500'); + } + +/** + * Generate the response using the controller object. + * + * @param string $template The template to render. + */ + protected function _outputMessage($template) { + $this->controller->render($template); + $this->controller->afterFilter(); + $this->controller->response->send(); + } +} diff --git a/cake/libs/exceptions.php b/cake/libs/exceptions.php index 1a3c62f90..daa1e7f39 100644 --- a/cake/libs/exceptions.php +++ b/cake/libs/exceptions.php @@ -19,90 +19,305 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -/* - * Exceptions used by Dispatcher +/** + * Represents an HTTP 400 error. + * + * @package cake.libs */ -class MissingControllerException extends RuntimeException { } -class MissingActionException extends RuntimeException { } -class PrivateActionException extends RuntimeException { } +class BadRequestException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Bad Request' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message = null, $code = 400) { + if (empty($message)) { + $message = 'Bad Request'; + } + parent::__construct($message, $code); + } +} /** - * Exceptions used by the ComponentCollection. + * Represents an HTTP 401 error. + * + * @package cake.libs */ -class MissingComponentFileException extends RuntimeException { } -class MissingComponentClassException extends RuntimeException { } +class UnauthorizedException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Unauthorized' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message = null, $code = 401) { + if (empty($message)) { + $message = 'Unauthorized'; + } + parent::__construct($message, $code); + } +} /** - * Runtime Exceptions for behaviors + * Represents an HTTP 403 error. + * + * @package cake.libs */ -class MissingBehaviorFileException extends RuntimeException { } -class MissingBehaviorClassException extends RuntimeException { } +class ForbiddenException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Forbidden' will be the message + * @param string $code Status code, defaults to 401 + */ + public function __construct($message = null, $code = 403) { + if (empty($message)) { + $message = 'Forbidden'; + } + parent::__construct($message, $code); + } +} /** - * Runtime Exceptions for Views + * Represents an HTTP 404 error. + * + * @package cake.libs */ -class MissingViewException extends RuntimeException { } -class MissingLayoutException extends RuntimeException { } +class NotFoundException extends RuntimeException { +/** + * Constructor + * + * @param string $message If no message is given 'Not Found' will be the message + * @param string $code Status code, defaults to 404 + */ + public function __construct($message = null, $code = 404) { + if (empty($message)) { + $message = 'Not Found'; + } + parent::__construct($message, $code); + } +} + +/** + * Represents an HTTP 500 error. + * + * @package cake.libs + */ +class InternalErrorException extends CakeException { +/** + * Constructor + * + * @param string $message If no message is given 'Not Found' will be the message + * @param string $code Status code, defaults to 404 + */ + public function __construct($message = null, $code = 500) { + if (empty($message)) { + $message = 'Internal Server Error'; + } + parent::__construct($message, $code); + } +} + +/** + * CakeException is used a base class for CakePHP's internal exceptions. + * In general framework errors are interpreted as 500 code errors. + * + * @package cake.libs + */ +class CakeException extends RuntimeException { +/** + * Array of attributes that are passed in from the constructor, and + * made available in the view when a development error is displayed. + * + * @var array + */ + protected $_attributes = array(); + +/** + * Template string that has attributes sprintf()'ed into it. + * + * @var string + */ + protected $_messageTemplate = ''; + +/** + * Constructor. + * + * Allows you to create exceptions that are treated as framework errors and disabled + * when debug = 0. + * + * @param mixed $message Either the string of the error message, or an array of attributes + * that are made available in the view, and sprintf()'d into CakeException::$_messageTemplate + * @param string $code The code of the error, is also the HTTP status code for the error. + */ + public function __construct($message, $code = 500) { + if (is_array($message)) { + $this->_attributes = $message; + $message = vsprintf(__($this->_messageTemplate), $message); + } + parent::__construct($message, $code); + } + +/** + * Get the passed in attributes + * + * @return array + */ + public function getAttributes() { + return $this->_attributes; + } +} + +/** + * Missing Controller exception - used when a controller + * cannot be found. + * + * @package cake.libs + */ +class MissingControllerException extends CakeException { + protected $_messageTemplate = 'Controller class %s could not be found.'; + + public function __construct($message, $code = 404) { + parent::__construct($message, $code); + } +} + +/** + * Missing Action exception - used when a controller action + * cannot be found. + * + * @package cake.libs + */ +class MissingActionException extends CakeException { + protected $_messageTemplate = 'Action %s::%s() could not be found.'; + + public function __construct($message, $code = 404) { + parent::__construct($message, $code); + } +} +/** + * Private Action exception - used when a controller action + * is protected, or starts with a `_`. + * + * @package cake.libs + */ +class PrivateActionException extends CakeException { + protected $_messageTemplate = 'Private Action %s::%s() is not directly accessible.'; + + public function __construct($message, $code = 404, Exception $previous = null) { + parent::__construct($message, $code, $previous); + } +} + +/** + * Used when a Component file cannot be found. + * + * @package cake.libs + */ +class MissingComponentFileException extends CakeException { + protected $_messageTemplate = 'Component File "%s" is missing.'; +} + +/** + * Used when a Component class cannot be found. + * + * @package cake.libs + */ +class MissingComponentClassException extends CakeException { + protected $_messageTemplate = 'Component class "%s" is missing.'; +} + +/** + * Used when a Behavior file cannot be found. + * + * @package cake.libs + */ +class MissingBehaviorFileException extends CakeException { } + +/** + * Used when a Behavior class cannot be found. + * + * @package cake.libs + */ +class MissingBehaviorClassException extends CakeException { } + +/** + * Used when a view file cannot be found. + * + * @package cake.libs + */ +class MissingViewException extends CakeException { + protected $_messageTemplate = 'View file "%s" is missing.'; +} + +/** + * Used when a layout file cannot be found. + * + * @package cake.libs + */ +class MissingLayoutException extends CakeException { + protected $_messageTemplate = 'Layout file "%s" is missing.'; +} + +/** + * Used when a helper file cannot be found. + * + * @package cake.libs + */ +class MissingHelperFileException extends CakeException { + protected $_messageTemplate = 'Helper File "%s" is missing.'; +} + +/** + * Used when a helper class cannot be found. + * + * @package cake.libs + */ +class MissingHelperClassException extends CakeException { + protected $_messageTemplate = 'Helper class "%s" is missing.'; +} + /** * Runtime Exceptions for ConnectionManager */ -class MissingDatabaseException extends RuntimeException {} -class MissingConnectionException extends RuntimeException {} +class MissingDatabaseException extends CakeException { + protected $_messageTemplate = 'Database connection "%s" could not be found.'; +} /** - * Exceptions used by the TaskCollection. + * Used when no connections can be found. + * + * @package cake.libs */ -class MissingTaskFileException extends RuntimeException { } -class MissingTaskClassException extends RuntimeException { } +class MissingConnectionException extends CakeException { + protected $_messageTemplate = 'Database connection "%s" is missing.'; +} + +/** + * Used when a Task file cannot be found. + * + * @package cake.libs + */ +class MissingTaskFileException extends CakeException { + protected $_messageTemplate = 'Task file "%s" is missing.'; +} + +/** + * Used when a Task class cannot be found. + * + * @package cake.libs + */ +class MissingTaskClassException extends CakeException { + protected $_messageTemplate = 'Task class "%s" is missing.'; +} /** * Exception class to be thrown when a database table is not found in the datasource * + * @package cake.libs */ -class MissingTableException extends RuntimeException { -/** - * The name of the model wanting to load the database table - * - * @var string - */ - protected $model; -/** - * The name of the missing table - * - * @var string - */ - protected $table; - -/** - * Exception costructor - * - * @param string $model The name of the model wanting to load the database table - * @param string $table The name of the missing table - * @return void - */ - public function __construct($model, $table) { - $this->model = $model; - $this->$table = $table; - $message = sprintf(__('Database table %s for model %s was not found.'), $table, $model); - parent::__construct($message); - } - -/** - * Returns the name of the model wanting to load the database table - * - * @return string - */ - public function getModel() { - return $this->model; - } - -/** - * Returns the name of the missing table - * - * @return string - */ - public function getTable() { - return $this->table; - } -} \ No newline at end of file +class MissingTableException extends CakeException { + protected $_messageTemplate = 'Database table %s for model %s was not found.'; +} diff --git a/cake/libs/model/behavior_collection.php b/cake/libs/model/behavior_collection.php index 6b5de5072..c339586ad 100644 --- a/cake/libs/model/behavior_collection.php +++ b/cake/libs/model/behavior_collection.php @@ -94,10 +94,16 @@ class BehaviorCollection extends ObjectCollection { $class = $name . 'Behavior'; if (!App::import('Behavior', $behavior)) { - throw new MissingBehaviorFileException(Inflector::underscore($behavior) . '.php'); + throw new MissingBehaviorFileException(array( + 'file' => Inflector::underscore($behavior) . '.php', + 'class' => $class + )); } if (!class_exists($class)) { - throw new MissingBehaviorClassException(Inflector::underscore($class)); + throw new MissingBehaviorClassException(array( + 'file' => Inflector::underscore($behavior) . '.php', + 'class' => $class + )); } if (!isset($this->{$name})) { diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index db56cc189..47a128663 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -222,7 +222,7 @@ class ConnectionManager { $this->_connectionsEnum[$name] = $this->__connectionData($config); } } else { - throw new MissingConnectionException('ConnectionManager'); + throw new MissingConnectionException(array('class' => 'ConnectionManager')); } } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 8cd852a14..9abd19c74 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -799,7 +799,10 @@ class Model extends Object { if ($db->isInterfaceSupported('listSources')) { $sources = $db->listSources(); if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) { - throw new MissingTableException($this->alias, $this->tablePrefix . $tableName); + throw new MissingTableException(array( + 'table' => $this->tablePrefix . $tableName, + 'class' => $this->alias + )); } $this->_schema = null; } @@ -2825,7 +2828,7 @@ class Model extends Object { } if (empty($db) || !is_object($db)) { - throw new MissingConnectionException($this->useDbConfig); + throw new MissingConnectionException(array('class' => $this->name)); } } diff --git a/cake/libs/object.php b/cake/libs/object.php index b4da0bd68..987ba0154 100644 --- a/cake/libs/object.php +++ b/cake/libs/object.php @@ -22,7 +22,7 @@ */ /** - * Object class, allowing __construct and __destruct in PHP4. + * Object class provides a few generic methods used in several subclasses. * * Also includes methods for logging and the special method RequestAction, * to call other Controllers' Actions from anywhere. @@ -155,34 +155,6 @@ class Object { } } -/** - * Used to report user friendly errors. - * If there is a file app/error.php or app/app_error.php this file will be loaded - * error.php is the AppError class it should extend ErrorHandler class. - * - * @param string $method Method to be called in the error class (AppError or ErrorHandler classes) - * @param array $messages Message that is to be displayed by the error class - * @return error message - */ - public function cakeError($method, $messages = array()) { - if (!class_exists('ErrorHandler')) { - App::import('Core', 'Error'); - - if (file_exists(APP . 'error.php')) { - include_once (APP . 'error.php'); - } elseif (file_exists(APP . 'app_error.php')) { - include_once (APP . 'app_error.php'); - } - } - - if (class_exists('AppError')) { - $error = new AppError($method, $messages); - } else { - $error = new ErrorHandler($method, $messages); - } - return $error; - } - /** * Checks for a persistent class file, if found file is opened and true returned * If file is not found a file is created and false returned diff --git a/cake/libs/view/elements/exception_stack_trace.ctp b/cake/libs/view/elements/exception_stack_trace.ctp new file mode 100644 index 000000000..9219e21ae --- /dev/null +++ b/cake/libs/view/elements/exception_stack_trace.ctp @@ -0,0 +1,24 @@ + +

Stack Trace

+
+getTraceAsString(); ?>
+
\ No newline at end of file diff --git a/cake/libs/view/errors/error404.ctp b/cake/libs/view/errors/error400.ctp similarity index 77% rename from cake/libs/view/errors/error404.ctp rename to cake/libs/view/errors/error400.ctp index 0f6b761c8..81a807b8b 100644 --- a/cake/libs/view/errors/error404.ctp +++ b/cake/libs/view/errors/error400.ctp @@ -20,5 +20,13 @@

: - '{$message}'"); ?> -

\ No newline at end of file + '{$url}'" + ); ?> +

+ 0 ): + echo $this->element('exception_stack_trace'); +endif; +?> \ No newline at end of file diff --git a/cake/libs/view/errors/error500.ctp b/cake/libs/view/errors/error500.ctp index fbd5a64bd..d05f4107a 100644 --- a/cake/libs/view/errors/error500.ctp +++ b/cake/libs/view/errors/error500.ctp @@ -19,6 +19,11 @@ ?>

- : - '{$message}'"); ?> + : +

+ 0 ): + echo $this->element('exception_stack_trace'); +endif; +?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_action.ctp b/cake/libs/view/errors/missing_action.ctp index 1a5872388..85aae2dac 100644 --- a/cake/libs/view/errors/missing_action.ctp +++ b/cake/libs/view/errors/missing_action.ctp @@ -30,10 +30,8 @@ <?php class extends AppController { - public $name = ''; - - function () { + function { } @@ -43,4 +41,5 @@ class extends AppController {

: -

\ No newline at end of file +

+element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_behavior_class.ctp b/cake/libs/view/errors/missing_behavior_class.ctp index e9bf56472..3bdc45a92 100644 --- a/cake/libs/view/errors/missing_behavior_class.ctp +++ b/cake/libs/view/errors/missing_behavior_class.ctp @@ -20,7 +20,7 @@

: - %s can not be found or does not exist.'), $behaviorClass); ?> + %s can not be found or does not exist.'), $class); ?>

: @@ -28,7 +28,7 @@

 <?php
-class  extends ModelBehavior {
+class  extends ModelBehavior {
 
 }
 ?>
@@ -36,4 +36,6 @@ class  extends ModelBehavior {
 

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_behavior_file.ctp b/cake/libs/view/errors/missing_behavior_file.ctp index 654537404..a5a800bc6 100644 --- a/cake/libs/view/errors/missing_behavior_file.ctp +++ b/cake/libs/view/errors/missing_behavior_file.ctp @@ -28,7 +28,7 @@

 <?php
-class  extends ModelBehavior {
+class  extends ModelBehavior {
 
 }
 ?>
@@ -37,3 +37,5 @@ class  extends ModelBehavior {
 	: 
 	
 

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_component_class.ctp b/cake/libs/view/errors/missing_component_class.ctp index e63440c00..85464acf6 100644 --- a/cake/libs/view/errors/missing_component_class.ctp +++ b/cake/libs/view/errors/missing_component_class.ctp @@ -20,15 +20,15 @@

: - ' . $component . 'Component', '' . $controller . 'Controller'); ?> + ' . $class . ''); ?>

: - ' . $component . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $class . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

 <?php
-class Component extends Object {
+class extends Component {
} ?> @@ -36,4 +36,6 @@ class Component extends Object {

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_component_file.ctp b/cake/libs/view/errors/missing_component_file.ctp index 44c607cd8..ea9df3b9c 100644 --- a/cake/libs/view/errors/missing_component_file.ctp +++ b/cake/libs/view/errors/missing_component_file.ctp @@ -24,11 +24,11 @@

: - ' . $component . 'Component', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?> + ' . $class . '', APP_DIR . DS . 'controllers' . DS . 'components' . DS . $file); ?>

 <?php
-class Component extends Object {
+class extends Component {
} ?> @@ -36,4 +36,6 @@ class Component extends Object {

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_connection.ctp b/cake/libs/view/errors/missing_connection.ctp index 51d082d31..82c62bbb0 100644 --- a/cake/libs/view/errors/missing_connection.ctp +++ b/cake/libs/view/errors/missing_connection.ctp @@ -20,7 +20,7 @@

: - +

: @@ -29,4 +29,6 @@

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_controller.ctp b/cake/libs/view/errors/missing_controller.ctp index 0c7dd798b..afcef66fc 100644 --- a/cake/libs/view/errors/missing_controller.ctp +++ b/cake/libs/view/errors/missing_controller.ctp @@ -30,11 +30,12 @@ <?php class extends AppController { - public $name = ''; } ?>

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> diff --git a/cake/libs/view/errors/missing_scaffolddb.ctp b/cake/libs/view/errors/missing_database.ctp similarity index 95% rename from cake/libs/view/errors/missing_scaffolddb.ctp rename to cake/libs/view/errors/missing_database.ctp index 05b248b28..19750015d 100644 --- a/cake/libs/view/errors/missing_scaffolddb.ctp +++ b/cake/libs/view/errors/missing_database.ctp @@ -29,4 +29,6 @@

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_helper_class.ctp b/cake/libs/view/errors/missing_helper_class.ctp index 7c8a79079..f98ae4262 100644 --- a/cake/libs/view/errors/missing_helper_class.ctp +++ b/cake/libs/view/errors/missing_helper_class.ctp @@ -20,7 +20,7 @@

: - %s can not be found or does not exist.'), $helperClass); ?> + %s can not be found or does not exist.'), $class); ?>

: @@ -28,7 +28,7 @@

 <?php
-class  extends AppHelper {
+class  extends AppHelper {
 
 }
 ?>
@@ -36,4 +36,6 @@ class  extends AppHelper {
 

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_helper_file.ctp b/cake/libs/view/errors/missing_helper_file.ctp index 1da5d577b..e7ca70cf7 100644 --- a/cake/libs/view/errors/missing_helper_file.ctp +++ b/cake/libs/view/errors/missing_helper_file.ctp @@ -28,7 +28,7 @@

 <?php
-class  extends AppHelper {
+class  extends AppHelper {
 
 }
 ?>
@@ -37,3 +37,5 @@ class  extends AppHelper {
 	: 
 	
 

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_layout.ctp b/cake/libs/view/errors/missing_layout.ctp index 02cfba190..128bbf3a5 100644 --- a/cake/libs/view/errors/missing_layout.ctp +++ b/cake/libs/view/errors/missing_layout.ctp @@ -29,4 +29,6 @@

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_model.ctp b/cake/libs/view/errors/missing_model.ctp deleted file mode 100644 index c3d7baa63..000000000 --- a/cake/libs/view/errors/missing_model.ctp +++ /dev/null @@ -1,41 +0,0 @@ - -

-

- : - %s could not be found.'), $model); ?> -

-

- : - ' . $model . '', APP_DIR . DS . 'models' . DS . Inflector::underscore($model) . '.php'); ?> -

-
-<?php
-class  extends AppModel {
-
-	public $name = '';
-
-}
-?>
-
-

- : - -

\ No newline at end of file diff --git a/cake/libs/view/errors/missing_table.ctp b/cake/libs/view/errors/missing_table.ctp index 3f0594e26..03ba1d55c 100644 --- a/cake/libs/view/errors/missing_table.ctp +++ b/cake/libs/view/errors/missing_table.ctp @@ -20,9 +20,11 @@

: - ' . $table . '', '' . $model . ''); ?> + ' . $table . '', '' . $class . ''); ?>

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/missing_view.ctp b/cake/libs/view/errors/missing_view.ctp index 121d97f9a..4c1e88335 100644 --- a/cake/libs/view/errors/missing_view.ctp +++ b/cake/libs/view/errors/missing_view.ctp @@ -20,7 +20,7 @@

: - ' . $controller . 'Controller::', '' . $action . '()'); ?> + ' . Inflector::camelize($this->request->controller) . 'Controller::', '' . $this->request->action . '()'); ?>

: @@ -29,4 +29,6 @@

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/private_action.ctp b/cake/libs/view/errors/private_action.ctp index ab9f13cdc..d26d98995 100644 --- a/cake/libs/view/errors/private_action.ctp +++ b/cake/libs/view/errors/private_action.ctp @@ -25,4 +25,6 @@

: -

\ No newline at end of file +

+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/errors/scaffold_error.ctp b/cake/libs/view/errors/scaffold_error.ctp index 7c1800b42..e9efe610c 100644 --- a/cake/libs/view/errors/scaffold_error.ctp +++ b/cake/libs/view/errors/scaffold_error.ctp @@ -32,4 +32,6 @@ function _scaffoldError() {
} ?> -
\ No newline at end of file +
+ +element('exception_stack_trace'); ?> \ No newline at end of file diff --git a/cake/libs/view/helper_collection.php b/cake/libs/view/helper_collection.php index 74683db93..faa63b14a 100644 --- a/cake/libs/view/helper_collection.php +++ b/cake/libs/view/helper_collection.php @@ -54,10 +54,16 @@ class HelperCollection extends ObjectCollection { $helperClass = $name . 'Helper'; if (!class_exists($helperClass)) { if (!App::import('Helper', $helper)) { - throw new MissingHelperFileException(Inflector::underscore($name) . '.php'); + throw new MissingHelperFileException(array( + 'class' => $helperClass, + 'file' => Inflector::underscore($name) . '.php' + )); } if (!class_exists($helperClass)) { - throw new MissingHelperClassException($helperClass); + throw new MissingHelperClassException(array( + 'class' => $helperClass, + 'file' => Inflector::underscore($name) . '.php' + )); } } $this->_loaded[$name] = new $helperClass($this->_View, $settings); @@ -73,10 +79,4 @@ class HelperCollection extends ObjectCollection { return $this->_loaded[$name]; } -} -/** - * Exceptions used by the HelperCollection. - */ -class MissingHelperFileException extends RuntimeException { } - -class MissingHelperClassException extends RuntimeException { } \ No newline at end of file +} \ No newline at end of file diff --git a/cake/libs/view/theme.php b/cake/libs/view/theme.php index 5706f9ba4..834fed182 100644 --- a/cake/libs/view/theme.php +++ b/cake/libs/view/theme.php @@ -17,6 +17,7 @@ * @since CakePHP(tm) v 0.10.0.1076 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::import('View', 'View'); /** * Theme view class diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php index 622f6f3e6..be32b3a20 100644 --- a/cake/libs/view/view.php +++ b/cake/libs/view/view.php @@ -791,7 +791,7 @@ class View extends Object { } } } - throw new MissingViewException($defaultPath . $name . $this->ext); + throw new MissingViewException(array('file' => $defaultPath . $name . $this->ext)); } /** @@ -824,7 +824,7 @@ class View extends Object { } } } - throw new MissingLayoutException($paths[0] . $file . $this->ext); + throw new MissingLayoutException(array('file' => $paths[0] . $file . $this->ext)); } /** diff --git a/cake/tests/cases/console/all_shells.test.php b/cake/tests/cases/console/all_shells.test.php index 42807f1d7..50f8763d9 100644 --- a/cake/tests/cases/console/all_shells.test.php +++ b/cake/tests/cases/console/all_shells.test.php @@ -39,6 +39,7 @@ class AllShellsTest extends PHPUnit_Framework_TestSuite { $path = CORE_TEST_CASES . DS . 'console' . DS . 'libs' . DS; $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'cake.test.php'); + $suite->addTestFile(CORE_TEST_CASES . DS . 'console' . DS . 'console_error_handler.test.php'); $tasks = array('acl', 'api', 'bake', 'schema', 'shell'); foreach ($tasks as $task) { $suite->addTestFile($path . $task . '.test.php'); diff --git a/cake/tests/cases/console/console_error_handler.test.php b/cake/tests/cases/console/console_error_handler.test.php new file mode 100644 index 000000000..d6e3b261e --- /dev/null +++ b/cake/tests/cases/console/console_error_handler.test.php @@ -0,0 +1,109 @@ +getMock('ConsoleErrorHandler', array('stderr'), array($exception)); + } + +/** + * test that the console error handler can deal with CakeExceptions. + * + * @return void + */ + function testCakeErrors() { + $exception = new MissingActionException('Missing action'); + $error = $this->getErrorHandler($exception); + + $error->expects($this->once())->method('stderr') + ->with($this->stringContains('Missing action')); + + $error->render(); + } + +/** + * test a non CakeException exception. + * + * @return void + */ + function testNonCakeExceptions() { + $exception = new InvalidArgumentException('Too many parameters.'); + $error = $this->getErrorHandler($exception); + + $error->expects($this->once())->method('stderr') + ->with($this->stringContains('Too many parameters.')); + + $error->render(); + } + +/** + * test a Error404 exception. + * + * @return void + */ + function testError404Exception() { + $exception = new NotFoundException('dont use me in cli.'); + $error = $this->getErrorHandler($exception); + + $error->expects($this->once())->method('stderr') + ->with($this->stringContains('dont use me in cli.')); + + $error->render(); + } + +/** + * test a Error500 exception. + * + * @return void + */ + function testError500Exception() { + $exception = new InternalErrorException('dont use me in cli.'); + $error = $this->getErrorHandler($exception); + + $error->expects($this->once())->method('stderr') + ->with($this->stringContains('dont use me in cli.')); + + $error->render(); + } + +/** + * 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->assertTrue(is_resource($error->stderr), 'No handle.'); + } +} \ No newline at end of file diff --git a/cake/tests/cases/console/libs/acl.test.php b/cake/tests/cases/console/libs/acl.test.php index 628a168b3..559e5eb3a 100644 --- a/cake/tests/cases/console/libs/acl.test.php +++ b/cake/tests/cases/console/libs/acl.test.php @@ -63,7 +63,7 @@ class AclShellTest extends CakeTestCase { Configure::write('Acl.classname', 'DbAcl'); $this->Dispatcher = $this->getMock( - 'ShellDispather', + 'ShellDispatcher', array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment', 'dispatch') ); $this->Task = $this->getMock( @@ -71,7 +71,8 @@ class AclShellTest extends CakeTestCase { array('in', 'out', 'hr', 'createFile', 'error', 'err'), array(&$this->Dispatcher) ); - $this->Task->Acl = new AclComponent(); + $collection = new ComponentCollection(); + $this->Task->Acl = new AclComponent($collection); $this->Task->params['datasource'] = 'test_suite'; } diff --git a/cake/tests/cases/console/libs/api.test.php b/cake/tests/cases/console/libs/api.test.php index aeea6c737..76f52b449 100644 --- a/cake/tests/cases/console/libs/api.test.php +++ b/cake/tests/cases/console/libs/api.test.php @@ -84,21 +84,22 @@ class ApiShellTest extends CakeTestCase { '4. constructClasses()', '5. disableCache()', '6. flash($message, $url, $pause = 1, $layout = \'flash\')', - '7. header($status)', - '8. httpCodes($code = NULL)', - '9. isAuthorized()', - '10. loadModel($modelClass = NULL, $id = NULL)', - '11. paginate($object = NULL, $scope = array (), $whitelist = array ())', - '12. postConditions($data = array (), $op = NULL, $bool = \'AND\', $exclusive = false)', - '13. redirect($url, $status = NULL, $exit = true)', - '14. referer($default = NULL, $local = false)', - '15. render($action = NULL, $layout = NULL, $file = NULL)', - '16. set($one, $two = NULL)', - '17. setAction($action)', - '18. shutdownProcess()', - '19. startupProcess()', - '20. validate()', - '21. validateErrors()' + '7. getResponse()', + '8. header($status)', + '9. httpCodes($code = NULL)', + '10. isAuthorized()', + '11. loadModel($modelClass = NULL, $id = NULL)', + '12. paginate($object = NULL, $scope = array (), $whitelist = array ())', + '13. postConditions($data = array (), $op = NULL, $bool = \'AND\', $exclusive = false)', + '14. redirect($url, $status = NULL, $exit = true)', + '15. referer($default = NULL, $local = false)', + '16. render($action = NULL, $layout = NULL, $file = NULL)', + '17. set($one, $two = NULL)', + '18. setAction($action)', + '19. shutdownProcess()', + '20. startupProcess()', + '21. validate()', + '22. validateErrors()' ); $this->Shell->expects($this->at(2))->method('out')->with($expected); diff --git a/cake/tests/cases/console/libs/bake.test.php b/cake/tests/cases/console/libs/bake.test.php index f11bf99be..370cabc90 100644 --- a/cake/tests/cases/console/libs/bake.test.php +++ b/cake/tests/cases/console/libs/bake.test.php @@ -91,10 +91,10 @@ class BakeShellTest extends CakeTestCase { if ($this->skipIf($userExists, 'User class exists, cannot test `bake all [param]`. %s')) { return; } - $this->Shell->Model = $this->getMock('ModelTask', array(), array(&$this->Dispatch)); - $this->Shell->Controller = $this->getMock('ControllerTask', array(), array(&$this->Dispatch)); - $this->Shell->View = $this->getMock('ModelTask', array(), array(&$this->Dispatch)); - $this->Shell->DbConfig = $this->getMock('DbConfigTask', array(), array(&$this->Dispatch)); + $this->Shell->Model = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); + $this->Shell->Controller = $this->getMock('ControllerTask', array(), array(&$this->Dispatcher)); + $this->Shell->View = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); + $this->Shell->DbConfig = $this->getMock('DbConfigTask', array(), array(&$this->Dispatcher)); $this->Shell->DbConfig->expects($this->once())->method('getConfig')->will($this->returnValue('test_suite')); diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 975b492c6..f9485a789 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -87,8 +87,8 @@ class FixtureTaskTest extends CakeTestCase { * @return void */ public function testConstruct() { - $this->Dispatch->params['working'] = DS . 'my' . DS . 'path'; - $Task = new FixtureTask($this->Dispatch); + $this->Dispatcher->params['working'] = DS . 'my' . DS . 'path'; + $Task = new FixtureTask($this->Dispatcher); $expected = DS . 'my' . DS . 'path' . DS . 'tests' . DS . 'fixtures' . DS; $this->assertEqual($Task->path, $expected); diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 52f086e4c..b81e3f3d8 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -179,7 +179,7 @@ class ModelTaskTest extends CakeTestCase { * @return void */ function testGetNameWithOutOfBoundsOption() { - $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(10, 1)); + $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(99, 1)); $this->Task->expects($this->once())->method('err'); $result = $this->Task->getName('test_suite'); diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 7cd608020..f8753b905 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -368,7 +368,7 @@ class TestTaskTest extends CakeTestCase { ) )); $keys = ClassRegistry::keys(); - $this->assertTrue(in_array('random', $keys)); + $this->assertTrue(in_array('test_task_comment', $keys)); $object =& $this->Task->buildTestSubject('Model', 'TestTaskComment'); $keys = ClassRegistry::keys(); diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php index 5348e01a1..f6717e6bb 100644 --- a/cake/tests/cases/dispatcher.test.php +++ b/cake/tests/cases/dispatcher.test.php @@ -720,7 +720,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return' => 1)); $this->fail('No exception thrown'); } catch (MissingControllerException $e) { - $this->assertEquals('SomeControllerController', $e->getMessage()); + $this->assertEquals('Controller class SomeControllerController could not be found.', $e->getMessage()); } } @@ -738,7 +738,9 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return' => 1)); $this->fail('No exception thrown'); } catch (PrivateActionException $e) { - $this->assertEquals('SomePagesController::_protected()', $e->getMessage()); + $this->assertEquals( + 'Private Action SomePagesController::_protected() is not directly accessible.', $e->getMessage() + ); } } @@ -756,7 +758,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception thrown'); } catch (MissingActionException $e) { - $this->assertEquals('SomePagesController::home()', $e->getMessage()); + $this->assertEquals('Action SomePagesController::home() could not be found.', $e->getMessage()); } } @@ -774,7 +776,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception thrown'); } catch (MissingActionException $e) { - $this->assertEquals('SomePagesController::redirect()', $e->getMessage()); + $this->assertEquals('Action SomePagesController::redirect() could not be found.', $e->getMessage()); } } @@ -1155,7 +1157,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('MyPluginController::not_here()', $e->getMessage()); + $this->assertEquals('Action MyPluginController::not_here() could not be found.', $e->getMessage()); } Router::reload(); @@ -1167,7 +1169,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('MyPluginController::param:value()', $e->getMessage()); + $this->assertEquals('Action MyPluginController::param:value() could not be found.', $e->getMessage()); } } @@ -1190,7 +1192,10 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (PrivateActionException $e) { - $this->assertEquals('TestDispatchPagesController::admin_index()', $e->getMessage()); + $this->assertEquals( + 'Private Action TestDispatchPagesController::admin_index() is not directly accessible.', + $e->getMessage() + ); } } @@ -1235,7 +1240,7 @@ class DispatcherTest extends CakeTestCase { $controller = $Dispatcher->dispatch($url, array('return'=> 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { - $this->assertEquals('SomePostsController::view()', $e->getMessage()); + $this->assertEquals('Action SomePostsController::view() could not be found.', $e->getMessage()); } $url = 'some_posts/something_else/param:value/param2:value2'; @@ -1274,14 +1279,14 @@ class DispatcherTest extends CakeTestCase { $Dispatcher->dispatch('theme/test_theme/../webroot/css/test_asset.css'); $this->fail('No exception'); } catch (MissingControllerException $e) { - $this->assertEquals('ThemeController', $e->getMessage()); + $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } try { $Dispatcher->dispatch('theme/test_theme/pdfs'); $this->fail('No exception'); } catch (MissingControllerException $e) { - $this->assertEquals('ThemeController', $e->getMessage()); + $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } ob_start(); diff --git a/cake/tests/cases/libs/all_libs.test.php b/cake/tests/cases/libs/all_libs.test.php index 905c23c1e..32a196953 100644 --- a/cake/tests/cases/libs/all_libs.test.php +++ b/cake/tests/cases/libs/all_libs.test.php @@ -39,7 +39,7 @@ 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.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 . 'log' . DS . 'file_log.test.php'); diff --git a/cake/tests/cases/libs/cake_request.test.php b/cake/tests/cases/libs/cake_request.test.php index e21450daf..8bded114f 100644 --- a/cake/tests/cases/libs/cake_request.test.php +++ b/cake/tests/cases/libs/cake_request.test.php @@ -678,10 +678,10 @@ class CakeRequestTestCase extends CakeTestCase { $request->addDetector('compare', array('env' => 'TEST_VAR', 'value' => 'something')); $_SERVER['TEST_VAR'] = 'something'; - $this->assertTrue($request->is('compare'), 'Value match failed %s.'); + $this->assertTrue($request->is('compare'), 'Value match failed.'); $_SERVER['TEST_VAR'] = 'wrong'; - $this->assertFalse($request->is('compare'), 'Value mis-match failed %s.'); + $this->assertFalse($request->is('compare'), 'Value mis-match failed.'); $request->addDetector('banana', array('env' => 'TEST_VAR', 'pattern' => '/^ban.*$/')); $_SERVER['TEST_VAR'] = 'banana'; diff --git a/cake/tests/cases/libs/controller/scaffold.test.php b/cake/tests/cases/libs/controller/scaffold.test.php index 1d08a91de..65de0bb1b 100644 --- a/cake/tests/cases/libs/controller/scaffold.test.php +++ b/cake/tests/cases/libs/controller/scaffold.test.php @@ -17,7 +17,8 @@ * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ -App::import('Core', 'Scaffold'); +App::import('Core', 'Scaffold', false); +App::import('Core', 'Controller', false); /** * ScaffoldMockController class @@ -789,7 +790,7 @@ class ScaffoldTest extends CakeTestCase { $this->Controller->theme = 'test_theme'; $this->Controller->view = 'Theme'; $this->Controller->constructClasses(); - $Scaffold =& new TestScaffoldMock($this->Controller, new CakeRequest()); + $Scaffold =& new TestScaffoldMock($this->Controller, $this->Controller->request); $this->assertEqual($this->Controller->view, 'Scaffold'); } diff --git a/cake/tests/cases/libs/debugger.test.php b/cake/tests/cases/libs/debugger.test.php index 3cce32740..ca332bd8c 100644 --- a/cake/tests/cases/libs/debugger.test.php +++ b/cake/tests/cases/libs/debugger.test.php @@ -216,7 +216,9 @@ class DebuggerTest extends CakeTestCase { $Controller->helpers = array('Html', 'Form'); $View = new View($Controller); $result = Debugger::exportVar($View); - $expected = 'ViewView::$base = NULL + $expected = 'View + View::$Helpers = HelperCollection object + View::$base = NULL View::$here = NULL View::$plugin = NULL View::$name = "" @@ -237,7 +239,6 @@ class DebuggerTest extends CakeTestCase { View::$cacheAction = false View::$validationErrors = array View::$hasRendered = false - View::$loaded = array View::$modelScope = false View::$model = NULL View::$association = NULL @@ -246,7 +247,8 @@ class DebuggerTest extends CakeTestCase { View::$modelId = NULL View::$uuids = array View::$output = false - View::$webroot = NULL'; + View::$webroot = NULL + View::$request = NULL'; $result = str_replace(array("\t", "\r\n", "\n"), "", strtolower($result)); $expected = str_replace(array("\t", "\r\n", "\n"), "", strtolower($expected)); $this->assertEqual($result, $expected); diff --git a/cake/tests/cases/libs/error.test.php b/cake/tests/cases/libs/error.test.php deleted file mode 100644 index 239a6e6c2..000000000 --- a/cake/tests/cases/libs/error.test.php +++ /dev/null @@ -1,628 +0,0 @@ - - * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) - * - * Licensed under The Open Group Test Suite 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 http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License - */ -if (class_exists('TestErrorHandler')) { - return; -} -if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { - define('CAKEPHP_UNIT_TEST_EXECUTION', 1); -} - -/** - * BlueberryComponent class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class BlueberryComponent extends Object { - -/** - * testName property - * - * @access public - * @return void - */ - public $testName = null; - -/** - * initialize method - * - * @access public - * @return void - */ - function initialize(&$controller) { - $this->testName = 'BlueberryComponent'; - } -} - -/** - * BlueberryDispatcher class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class BlueberryDispatcher extends Dispatcher { - -/** - * cakeError method - * - * @access public - * @return void - */ - function cakeError($method, $messages = array()) { - $error = new TestErrorHandler($method, $messages); - return $error; - } -} - -/** - * Short description for class. - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class AuthBlueberryUser extends CakeTestModel { - -/** - * name property - * - * @var string 'AuthBlueberryUser' - * @access public - */ - public $name = 'AuthBlueberryUser'; - -/** - * useTable property - * - * @var string - * @access public - */ - public $useTable = false; -} -if (!class_exists('AppController')) { - /** - * AppController class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ - class AppController extends Controller { - /** - * components property - * - * @access public - * @return void - */ - public $components = array('Blueberry'); - /** - * beforeRender method - * - * @access public - * @return void - */ - function beforeRender() { - echo $this->Blueberry->testName; - } - /** - * header method - * - * @access public - * @return void - */ - function header($header) { - echo $header; - } - /** - * _stop method - * - * @access public - * @return void - */ - function _stop($status = 0) { - echo 'Stopped with status: ' . $status; - } - } -} elseif (!defined('APP_CONTROLLER_EXISTS')){ - define('APP_CONTROLLER_EXISTS', true); -} -App::import('Core', array('Error', 'Controller')); - -/** - * TestErrorController class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class TestErrorController extends AppController { - -/** - * uses property - * - * @var array - * @access public - */ - public $uses = array(); - -/** - * index method - * - * @access public - * @return void - */ - function index() { - $this->autoRender = false; - return 'what up'; - } -} - -/** - * BlueberryController class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class BlueberryController extends AppController { - -/** - * name property - * - * @access public - * @return void - */ - public $name = 'BlueberryController'; - -/** - * uses property - * - * @access public - * @return void - */ - public $uses = array(); -} - -/** - * MyCustomErrorHandler class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class MyCustomErrorHandler extends ErrorHandler { - -/** - * custom error message type. - * - * @return void - */ - function missingWidgetThing() { - echo 'widget thing is missing'; - } - -/** - * stop method - * - * @access public - * @return void - */ - function _stop() { - return; - } -} - -/** - * TestErrorHandler class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class TestErrorHandler extends ErrorHandler { - -/** - * stop method - * - * @access public - * @return void - */ - function _stop() { - return; - } -} - -/** - * ErrorHandlerTest class - * - * @package cake - * @subpackage cake.tests.cases.libs - */ -class ErrorHandlerTest extends CakeTestCase { - -/** - * skip method - * - * @access public - * @return void - */ - function skip() { - $this->skipIf(PHP_SAPI === 'cli', '%s Cannot be run from console'); - } - -/** - * setup create a request object to get out of router later. - * - * @return void - */ - function setUp() { - $request = new CakeRequest(null, false); - $request->base = ''; - Router::setRequestInfo($request); - } - -/** - * test that methods declared in an ErrorHandler subclass are not converted - * into error404 when debug == 0 - * - * @return void - */ - function testSubclassMethodsNotBeingConvertedToError() { - $back = Configure::read('debug'); - Configure::write('debug', 2); - ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingWidgetThing', array('message' => 'doh!')); - $result = ob_get_clean(); - $this->assertEqual($result, 'widget thing is missing'); - - Configure::write('debug', 0); - ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingWidgetThing', array('message' => 'doh!')); - $result = ob_get_clean(); - $this->assertEqual($result, 'widget thing is missing', 'Method declared in subclass converted to error404. %s'); - - Configure::write('debug', 0); - ob_start(); - $ErrorHandler = new MyCustomErrorHandler('missingController', array( - 'className' => 'Missing', 'message' => 'Page not found' - )); - $result = ob_get_clean(); - $this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error404. %s'); - - Configure::write('debug', $back); - } - -/** - * testError method - * - * @access public - * @return void - */ - function testError() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found')); - ob_clean(); - ob_start(); - $TestErrorHandler->error(array( - 'code' => 404, - 'message' => 'Page not Found', - 'name' => "Couldn't find what you were looking for" - )); - $result = ob_get_clean(); - $this->assertPattern("/

Couldn't find what you were looking for<\/h2>/", $result); - $this->assertPattern('/Page not Found/', $result); - } - -/** - * testError404 method - * - * @access public - * @return void - */ - function testError404() { - App::build(array( - 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS) - ), true); - - ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found', 'url' => '/test_error')); - $result = ob_get_clean(); - $this->assertPattern('/

Not Found<\/h2>/', $result); - $this->assertPattern("/'\/test_error'<\/strong>/", $result); - - ob_start(); - $TestErrorHandler = new TestErrorHandler('error404', array('message' => 'Page not found')); - ob_get_clean(); - ob_start(); - $TestErrorHandler->error404(array( - 'url' => 'pages/pink', - 'message' => 'Page not found' - )); - $result = ob_get_clean(); - $this->assertNoPattern('##', $result); - - App::build(); - } - -/** - * testError500 method - * - * @access public - * @return void - */ - function testError500() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('error500', array( - 'message' => 'An Internal Error Has Occurred' - )); - $result = ob_get_clean(); - $this->assertPattern('/

An Internal Error Has Occurred<\/h2>/', $result); - - ob_start(); - $TestErrorHandler = new TestErrorHandler('error500', array( - 'message' => 'An Internal Error Has Occurred', - 'code' => '500' - )); - $result = ob_get_clean(); - $this->assertPattern('/

An Internal Error Has Occurred<\/h2>/', $result); - } - -/** - * testMissingController method - * - * @access public - * @return void - */ - function testMissingController() { - $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); - - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingController', array('className' => 'PostsController')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Controller<\/h2>/', $result); - $this->assertPattern('/PostsController<\/em>/', $result); - $this->assertPattern('/BlueberryComponent/', $result); - } - -/** - * testMissingAction method - * - * @access public - * @return void - */ - function testMissingAction() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingAction', array('className' => 'PostsController', 'action' => 'index')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Method in PostsController<\/h2>/', $result); - $this->assertPattern('/PostsController::<\/em>index\(\)<\/em>/', $result); - - ob_start(); - $dispatcher = new BlueberryDispatcher('/blueberry/inexistent'); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Method in BlueberryController<\/h2>/', $result); - $this->assertPattern('/BlueberryController::<\/em>inexistent\(\)<\/em>/', $result); - $this->assertNoPattern('/Location: (.*)\/users\/login/', $result); - $this->assertNoPattern('/Stopped with status: 0/', $result); - } - -/** - * testPrivateAction method - * - * @access public - * @return void - */ - function testPrivateAction() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('privateAction', array('className' => 'PostsController', 'action' => '_secretSauce')); - $result = ob_get_clean(); - $this->assertPattern('/

Private Method in PostsController<\/h2>/', $result); - $this->assertPattern('/PostsController::<\/em>_secretSauce\(\)<\/em>/', $result); - } - -/** - * testMissingTable method - * - * @access public - * @return void - */ - function testMissingTable() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingTable', array('className' => 'Article', 'table' => 'articles')); - $result = ob_get_clean(); - $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); - $this->assertPattern('/

Missing Database Table<\/h2>/', $result); - $this->assertPattern('/table articles<\/em> for model Article<\/em>/', $result); - } - -/** - * testMissingDatabase method - * - * @access public - * @return void - */ - function testMissingDatabase() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingDatabase', array()); - $result = ob_get_clean(); - $this->assertPattern('/HTTP\/1\.0 500 Internal Server Error/', $result); - $this->assertPattern('/

Missing Database Connection<\/h2>/', $result); - $this->assertPattern('/Confirm you have created the file/', $result); - } - -/** - * testMissingView method - * - * @access public - * @return void - */ - function testMissingView() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingView', array('className' => 'Pages', 'action' => 'display', 'file' => 'pages/about.ctp', 'base' => '')); - $expected = ob_get_clean(); - $this->assertPattern("/PagesController::/", $expected); - $this->assertPattern("/pages\/about.ctp/", $expected); - } - -/** - * testMissingLayout method - * - * @access public - * @return void - */ - function testMissingLayout() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingLayout', array( 'layout' => 'my_layout', 'file' => 'layouts/my_layout.ctp', 'base' => '')); - $expected = ob_get_clean(); - $this->assertPattern("/Missing Layout/", $expected); - $this->assertPattern("/layouts\/my_layout.ctp/", $expected); - } - -/** - * testMissingConnection method - * - * @access public - * @return void - */ - function testMissingConnection() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingConnection', array('className' => 'Article')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Database Connection<\/h2>/', $result); - $this->assertPattern('/Article requires a database connection/', $result); - } - -/** - * testMissingHelperFile method - * - * @access public - * @return void - */ - function testMissingHelperFile() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingHelperFile', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Helper File<\/h2>/', $result); - $this->assertPattern('/Create the class below in file:/', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * testMissingHelperClass method - * - * @access public - * @return void - */ - function testMissingHelperClass() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingHelperClass', array('helper' => 'MyCustom', 'file' => 'my_custom.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Helper Class<\/h2>/', $result); - $this->assertPattern('/The helper class MyCustomHelper<\/em> can not be found or does not exist./', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * test missingBehaviorFile method - * - * @access public - * @return void - */ - function testMissingBehaviorFile() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingBehaviorFile', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Behavior File<\/h2>/', $result); - $this->assertPattern('/Create the class below in file:/', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * test MissingBehaviorClass method - * - * @access public - * @return void - */ - function testMissingBehaviorClass() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingBehaviorClass', array('behavior' => 'MyCustom', 'file' => 'my_custom.php')); - $result = ob_get_clean(); - $this->assertPattern('/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', $result); - $this->assertPattern('/(\/|\\\)my_custom.php/', $result); - } - -/** - * testMissingComponentFile method - * - * @access public - * @return void - */ - function testMissingComponentFile() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingComponentFile', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Component File<\/h2>/', $result); - $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); - $this->assertPattern('/(\/|\\\)sidebox.php/', $result); - } - -/** - * testMissingComponentClass method - * - * @access public - * @return void - */ - function testMissingComponentClass() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingComponentClass', array('className' => 'PostsController', 'component' => 'Sidebox', 'file' => 'sidebox.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Component Class<\/h2>/', $result); - $this->assertPattern('/Create the class SideboxComponent<\/em> in file:/', $result); - $this->assertPattern('/(\/|\\\)sidebox.php/', $result); - } - -/** - * testMissingModel method - * - * @access public - * @return void - */ - function testMissingModel() { - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingModel', array('className' => 'Article', 'file' => 'article.php')); - $result = ob_get_clean(); - $this->assertPattern('/

Missing Model<\/h2>/', $result); - $this->assertPattern('/Article<\/em> could not be found./', $result); - $this->assertPattern('/(\/|\\\)article.php/', $result); - } - -/** - * testing that having a code => 500 in the cakeError call makes an - * internal server error. - * - * @return void - */ - function testThatCode500Works() { - Configure::write('debug', 0); - ob_start(); - $TestErrorHandler = new TestErrorHandler('missingTable', array( - 'className' => 'Article', - 'table' => 'articles', - 'code' => 500 - )); - $result = ob_get_clean(); - $this->assertPattern('/

An Internal Error Has Occurred<\/h2>/', $result); - } -} diff --git a/cake/tests/cases/libs/error_handler.test.php b/cake/tests/cases/libs/error_handler.test.php new file mode 100644 index 000000000..a57de787d --- /dev/null +++ b/cake/tests/cases/libs/error_handler.test.php @@ -0,0 +1,640 @@ + + * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The Open Group Test Suite 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 http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License + */ + +App::import('Core', array('ErrorHandler', 'Controller', 'Component')); + +/** + * Short description for class. + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class AuthBlueberryUser extends CakeTestModel { + +/** + * name property + * + * @var string 'AuthBlueberryUser' + * @access public + */ + public $name = 'AuthBlueberryUser'; + +/** + * useTable property + * + * @var string + * @access public + */ + public $useTable = false; +} +if (!class_exists('AppController')) { + /** + * AppController class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ + class AppController extends Controller { + /** + * components property + * + * @access public + * @return void + */ + public $components = array('Blueberry'); + /** + * beforeRender method + * + * @access public + * @return void + */ + function beforeRender() { + echo $this->Blueberry->testName; + } + /** + * header method + * + * @access public + * @return void + */ + function header($header) { + echo $header; + } + /** + * _stop method + * + * @access public + * @return void + */ + function _stop($status = 0) { + echo 'Stopped with status: ' . $status; + } + } +} elseif (!defined('APP_CONTROLLER_EXISTS')){ + define('APP_CONTROLLER_EXISTS', true); +} + +/** + * BlueberryComponent class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class BlueberryComponent extends Component { + +/** + * testName property + * + * @access public + * @return void + */ + public $testName = null; + +/** + * initialize method + * + * @access public + * @return void + */ + function initialize(&$controller) { + $this->testName = 'BlueberryComponent'; + } +} + +/** + * TestErrorController class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class TestErrorController extends AppController { + +/** + * uses property + * + * @var array + * @access public + */ + public $uses = array(); + +/** + * index method + * + * @access public + * @return void + */ + function index() { + $this->autoRender = false; + return 'what up'; + } +} + +/** + * BlueberryController class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class BlueberryController extends AppController { + +/** + * name property + * + * @access public + * @return void + */ + public $name = 'BlueberryController'; + +/** + * uses property + * + * @access public + * @return void + */ + public $uses = array(); +} + +/** + * MyCustomErrorHandler class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class MyCustomErrorHandler extends ErrorHandler { + +/** + * custom error message type. + * + * @return void + */ + function missingWidgetThing() { + echo 'widget thing is missing'; + } +} +/** + * Exception class for testing app error handlers and custom errors. + * + * @package cake.test.cases.libs + */ +class MissingWidgetThingException extends NotFoundException { } + + +/** + * ErrorHandlerTest class + * + * @package cake + * @subpackage cake.tests.cases.libs + */ +class ErrorHandlerTest extends CakeTestCase { + +/** + * skip method + * + * @access public + * @return void + */ + function skip() { + $this->skipIf(PHP_SAPI === 'cli', '%s Cannot be run from console'); + } + +/** + * setup create a request object to get out of router later. + * + * @return void + */ + function setUp() { + $request = new CakeRequest(null, false); + $request->base = ''; + Router::setRequestInfo($request); + $this->_debug = Configure::read('debug'); + } + + function teardown() { + Configure::write('debug', $this->_debug); + } + +/** + * 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 that methods declared in an ErrorHandler subclass are not converted + * into error400 when debug > 0 + * + * @return void + */ + function testSubclassMethodsNotBeingConvertedToError() { + Configure::write('debug', 2); + + $exception = new MissingWidgetThingException('Widget not found'); + $ErrorHandler = new MyCustomErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertEqual($result, 'widget thing is missing'); + } + +/** + * test that subclass methods are not converted when debug = 0 + * + * @return void + */ + function testSubclassMethodsNotBeingConvertedDebug0() { + Configure::write('debug', 0); + $exception = new MissingWidgetThingException('Widget not found'); + $ErrorHandler = new MyCustomErrorHandler($exception); + + $this->assertEqual('missingWidgetThing', $ErrorHandler->method); + + ob_start(); + $ErrorHandler->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. + * + * @return void + */ + function testSubclassConvertingFrameworkErrors() { + Configure::write('debug', 0); + + $exception = new MissingControllerException('PostsController'); + $ErrorHandler = new MyCustomErrorHandler($exception); + + $this->assertEqual('error400', $ErrorHandler->method); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern('/Not Found/', $result, 'Method declared in error handler not converted to error400. %s'); + } + +/** + * test things in the constructor. + * + * @return void + */ + function testConstruction() { + $exception = new NotFoundException('Page not found'); + $ErrorHandler = new ErrorHandler($exception); + + $this->assertType('CakeErrorController', $ErrorHandler->controller); + $this->assertEquals('error400', $ErrorHandler->method); + $this->assertEquals($exception, $ErrorHandler->error); + } + +/** + * test that method gets coerced when debug = 0 + * + * @return void + */ + function testErrorMethodCoercion() { + Configure::write('debug', 0); + $exception = new MissingActionException('Page not found'); + $ErrorHandler = new ErrorHandler($exception); + + $this->assertType('CakeErrorController', $ErrorHandler->controller); + $this->assertEquals('error400', $ErrorHandler->method); + $this->assertEquals($exception, $ErrorHandler->error); + } + +/** + * test that unknown exception types with valid status codes are treated correctly. + * + * @return void + */ + function testUnknownExceptionTypeWithExceptionThatHasA400Code() { + $exception = new MissingWidgetThingException('coding fail.'); + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404); + + ob_start(); + $ErrorHandler->render(); + $results = ob_get_clean(); + + $this->assertFalse(method_exists($ErrorHandler, 'missingWidgetThing'), 'no method should exist.'); + $this->assertEquals('error400', $ErrorHandler->method, 'incorrect method coercion.'); + } + +/** + * test that unknown exception types with valid status codes are treated correctly. + * + * @return void + */ + function testUnknownExceptionTypeWithNoCodeIsA500() { + $exception = new OutOfBoundsException('foul ball.'); + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); + + ob_start(); + $ErrorHandler->render(); + $results = ob_get_clean(); + + $this->assertEquals('error500', $ErrorHandler->method, 'incorrect method coercion.'); + } + +/** + * testerror400 method + * + * @access public + * @return void + */ + function testerror400() { + App::build(array( + 'views' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'libs' . DS . 'view' . DS) + ), true); + Router::reload(); + + $request = new CakeRequest('posts/view/1000', false); + Router::setRequestInfo($request); + + $exception = new NotFoundException('Custom message'); + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(404); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern('/

Custom message<\/h2>/', $result); + $this->assertPattern("/'\/posts\/view\/1000'<\/strong>/", $result); + + App::build(); + } + +/** + * test that error400 only modifies the messages on CakeExceptions. + * + * @return void + */ + function testerror400OnlyChangingCakeException() { + Configure::write('debug', 0); + + $exception = new NotFoundException('Custom message'); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + $this->assertContains('Custom message', $result); + + $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + $this->assertContains('Not Found', $result); + } +/** + * test that error400 doesn't expose XSS + * + * @return void + */ + function testError400NoInjection() { + Router::reload(); + + $request = new CakeRequest('pages/pink', false); + Router::setRequestInfo($request); + + $exception = new NotFoundException('Custom message'); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertNoPattern('##', $result); + } + +/** + * testError500 method + * + * @access public + * @return void + */ + function testError500Message() { + $exception = new InternalErrorException('An Internal Error Has Occurred'); + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once())->method('statusCode')->with(500); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern('/

An Internal Error Has Occurred<\/h2>/', $result); + } + +/** + * testMissingController method + * + * @access public + * @return void + */ + function testMissingController() { + $this->skipIf(defined('APP_CONTROLLER_EXISTS'), '%s Need a non-existent AppController'); + + $exception = new MissingControllerException(array('controller' => 'PostsController')); + $ErrorHandler = new ErrorHandler($exception); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + $this->assertPattern('/

Missing Controller<\/h2>/', $result); + $this->assertPattern('/PostsController<\/em>/', $result); + $this->assertPattern('/BlueberryComponent/', $result); + } + + + /* TODO: Integration test that needs to be moved + ob_start(); + $dispatcher = new Dispatcher('/blueberry/inexistent'); + $result = ob_get_clean(); + $this->assertPattern('/

Missing Method in BlueberryController<\/h2>/', $result); + $this->assertPattern('/BlueberryController::<\/em>inexistent\(\)<\/em>/', $result); + $this->assertNoPattern('/Location: (.*)\/users\/login/', $result); + $this->assertNoPattern('/Stopped with status: 0/', $result); + */ + +/** + * Returns an array of tests to run for the various CakeException classes. + * + * @return void + */ + public static function testProvider() { + return array( + array( + new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')), + array( + '/

Missing Method in PostsController<\/h2>/', + '/PostsController::<\/em>index\(\)<\/em>/' + ), + 404 + ), + array( + new PrivateActionException(array('controller' => 'PostsController' , 'action' => '_secretSauce')), + array( + '/

Private Method in PostsController<\/h2>/', + '/PostsController::<\/em>_secretSauce\(\)<\/em>/' + ), + 404 + ), + array( + new MissingTableException(array('table' => 'articles', 'class' => 'Article')), + array( + '/

Missing Database Table<\/h2>/', + '/table articles<\/em> for model Article<\/em>/' + ), + 500 + ), + array( + new MissingDatabaseException(array('connection' => 'default')), + array( + '/

Missing Database Connection<\/h2>/', + '/Confirm you have created the file/' + ), + 500 + ), + array( + new MissingViewException(array('file' => '/posts/about.ctp')), + array( + "/posts\/about.ctp/" + ), + 500 + ), + array( + new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')), + array( + "/Missing Layout/", + "/layouts\/my_layout.ctp/" + ), + 500 + ), + array( + new MissingConnectionException(array('class' => 'Article')), + array( + '/

Missing Database Connection<\/h2>/', + '/Article requires a database connection/' + ), + 500 + ), + array( + new MissingHelperFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')), + array( + '/

Missing Helper File<\/h2>/', + '/Create the class below in file:/', + '/(\/|\\\)my_custom.php/' + ), + 500 + ), + array( + new MissingHelperClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomHelper')), + array( + '/

Missing Helper Class<\/h2>/', + '/The helper class MyCustomHelper<\/em> can not be found or does not exist./', + '/(\/|\\\)my_custom.php/', + ), + 500 + ), + array( + new MissingBehaviorFileException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')), + array( + '/

Missing Behavior File<\/h2>/', + '/Create the class below in file:/', + '/(\/|\\\)my_custom.php/', + ), + 500 + ), + array( + new MissingBehaviorClassException(array('file' => 'my_custom.php', 'class' => 'MyCustomBehavior')), + array( + '/The behavior class MyCustomBehavior<\/em> can not be found or does not exist./', + '/(\/|\\\)my_custom.php/' + ), + 500 + ), + array( + new MissingComponentFileException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')), + array( + '/

Missing Component File<\/h2>/', + '/Create the class SideboxComponent<\/em> in file:/', + '/(\/|\\\)sidebox.php/' + ), + 500 + ), + array( + new MissingComponentClassException(array('file' => 'sidebox.php', 'class' => 'SideboxComponent')), + array( + '/

Missing Component Class<\/h2>/', + '/Create the class SideboxComponent<\/em> in file:/', + '/(\/|\\\)sidebox.php/' + ), + 500 + ) + + ); + } + +/** + * Test the various CakeException sub classes + * + * @dataProvider testProvider + * @return void + */ + function testCakeExceptionHandling($exception, $patterns, $code) { + $ErrorHandler = new ErrorHandler($exception); + $ErrorHandler->controller->response = $this->getMock('CakeResponse', array('statusCode')); + $ErrorHandler->controller->response->expects($this->once()) + ->method('statusCode') + ->with($code); + + ob_start(); + $ErrorHandler->render(); + $result = ob_get_clean(); + + foreach ($patterns as $pattern) { + $this->assertPattern($pattern, $result); + } + } +} diff --git a/cake/tests/cases/libs/view/helpers/rss.test.php b/cake/tests/cases/libs/view/helpers/rss.test.php index 7db36bbe3..3f7512d17 100644 --- a/cake/tests/cases/libs/view/helpers/rss.test.php +++ b/cake/tests/cases/libs/view/helpers/rss.test.php @@ -17,6 +17,7 @@ * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License */ +App::import('View', 'View'); App::import('Helper', array('Rss', 'Time')); /** diff --git a/cake/tests/lib/reporter/cake_html_reporter.php b/cake/tests/lib/reporter/cake_html_reporter.php index fb4840fef..a61366060 100755 --- a/cake/tests/lib/reporter/cake_html_reporter.php +++ b/cake/tests/lib/reporter/cake_html_reporter.php @@ -216,7 +216,9 @@ class CakeHtmlReporter extends CakeBaseReporter { public function paintDocumentEnd() { $baseDir = $this->params['baseDir']; include CAKE_TESTS_LIB . 'templates/footer.php'; - ob_end_flush(); + if (ob_get_length()) { + ob_end_flush(); + } } /**