diff --git a/.gitignore b/.gitignore index cfc5c7a4b..49926b62b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +app/config app/tmp vendors \ No newline at end of file diff --git a/app/config/database.php.default b/app/config/database.php.default index 5c20804d4..dda59ad15 100644 --- a/app/config/database.php.default +++ b/app/config/database.php.default @@ -1,5 +1,4 @@ dispatch($url); + $Dispatcher->dispatch(); } if (Configure::read() > 0) { echo ""; diff --git a/cake/bootstrap.php b/cake/bootstrap.php index 403ebdaf2..c50974478 100644 --- a/cake/bootstrap.php +++ b/cake/bootstrap.php @@ -1,48 +1,35 @@ = 5)); } -/** - * Configuration, directory layout and standard libraries - */ - if (!isset($bootstrap)) { - require CORE_PATH . 'cake' . DS . 'basics.php'; - $TIME_START = getMicrotime(); - require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; - require LIBS . 'object.php'; - require LIBS . 'inflector.php'; - require LIBS . 'configure.php'; - } - require LIBS . 'cache.php'; - - Configure::getInstance(); - - $url = null; - - App::import('Core', array('Dispatcher')); +require CORE_PATH . 'cake' . DS . 'basics.php'; +$TIME_START = getMicrotime(); +require CORE_PATH . 'cake' . DS . 'config' . DS . 'paths.php'; +require LIBS . 'object.php'; +require LIBS . 'inflector.php'; +require LIBS . 'configure.php'; +require LIBS . 'set.php'; +require LIBS . 'cache.php'; +Configure::getInstance(); +require CAKE . 'dispatcher.php'; ?> \ No newline at end of file diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index aefe126ea..1fce18a71 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -375,7 +375,7 @@ class ControllerTask extends Shell { $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action'=>'index'));\n"; } $actions .= "\t\t}\n"; - $actions .= "\t\tif (\$this->{$currentModelName}->del(\$id)) {\n"; + $actions .= "\t\tif (\$this->{$currentModelName}->delete(\$id)) {\n"; if ($wannaUseSession) { $actions .= "\t\t\t\$this->Session->setFlash(__('{$singularHumanName} deleted', true));\n"; $actions .= "\t\t\t\$this->redirect(array('action'=>'index'));\n"; diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index aa7c26b62..e16835240 100644 --- a/cake/libs/controller/controller.php +++ b/cake/libs/controller/controller.php @@ -1,26 +1,21 @@ name === null) { $r = null; if (!preg_match('/(.*)Controller/i', get_class($this), $r)) { - die (__("Controller::__construct() : Can not get or parse my own class name, exiting.")); + __("Controller::__construct() : Can not get or parse my own class name, exiting."); + $this->_stop(); } $this->name = $r[1]; } @@ -395,7 +391,9 @@ class Controller extends Object { $app = Set::normalize($appVars[$var]); $this->{$var} = Set::merge($app, $normal); } else { - $this->{$var} = Set::merge($this->{$var}, array_diff($appVars[$var], $this->{$var})); + $this->{$var} = Set::merge( + $this->{$var}, array_diff($appVars[$var], $this->{$var}) + ); } } } @@ -417,7 +415,9 @@ class Controller extends Object { $app = Set::normalize($appVars[$var]); $this->{$var} = Set::merge($normal, array_diff_assoc($app, $normal)); } else { - $this->{$var} = Set::merge($this->{$var}, array_diff($appVars[$var], $this->{$var})); + $this->{$var} = Set::merge( + $this->{$var}, array_diff($appVars[$var], $this->{$var}) + ); } } } @@ -462,7 +462,7 @@ class Controller extends Object { } /** * Loads and instantiates models required by this controller. - * If Controller::persistModel; is true, controller will create cached model instances on first request, + * If Controller::persistModel; is true, controller will cache model instances on first request, * additional request will used cached models. * If the model is non existent, it will throw a missing database table error, as Cake generates * dynamic models for the time being. @@ -498,13 +498,19 @@ class Controller extends Object { $this->modelNames[] = $modelClass; if (!PHP5) { - $this->{$modelClass} =& ClassRegistry::init(array('class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id)); + $this->{$modelClass} =& ClassRegistry::init(array( + 'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id + )); } else { - $this->{$modelClass} = ClassRegistry::init(array('class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id)); + $this->{$modelClass} = ClassRegistry::init(array( + 'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id + )); } if (!$this->{$modelClass}) { - return $this->cakeError('missingModel', array(array('className' => $modelClass, 'webroot' => '', 'base' => $this->base))); + return $this->cakeError('missingModel', array(array( + 'className' => $modelClass, 'webroot' => '', 'base' => $this->base + ))); } if ($this->persistModel === true) { @@ -522,7 +528,8 @@ class Controller extends Object { * Redirects to given $url, after turning off $this->autoRender. * Script execution is halted after the redirect. * - * @param mixed $url A string or array-based URL pointing to another location within the app, or an absolute URL + * @param mixed $url A string or array-based URL pointing to another location within the app, + * or an absolute URL * @param integer $status Optional HTTP status code (eg: 404) * @param boolean $exit If true, exit() will be called after the redirect * @return mixed void if $exit = false. Terminates script if $exit = true @@ -689,14 +696,17 @@ class Controller extends Object { return call_user_func_array(array(&$this, $action), $args); } /** - * Controller callback to tie into Auth component. Only called when AuthComponent::authorize is set to 'controller'. + * Controller callback to tie into Auth component. + * Only called when AuthComponent::authorize is set to 'controller'. * * @return bool true if authorized, false otherwise * @access public * @link http://book.cakephp.org/view/396/authorize */ function isAuthorized() { - trigger_error(sprintf(__('%s::isAuthorized() is not defined.', true), $this->name), E_USER_WARNING); + trigger_error(sprintf( + __('%s::isAuthorized() is not defined.', true), $this->name + ), E_USER_WARNING); return false; } /** @@ -776,8 +786,13 @@ class Controller extends Object { if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model')) { $models[] = Inflector::underscore($currentModel); } - if (isset($this->$currentModel) && is_a($this->$currentModel, 'Model') && !empty($this->$currentModel->validationErrors)) { - $View->validationErrors[Inflector::camelize($currentModel)] =& $this->$currentModel->validationErrors; + $isValidModel = ( + isset($this->$currentModel) && is_a($this->$currentModel, 'Model') && + !empty($this->$currentModel->validationErrors) + ); + if ($isValidModel) { + $View->validationErrors[Inflector::camelize($currentModel)] =& + $this->$currentModel->validationErrors; } } $models = array_diff(ClassRegistry::keys(), $models); @@ -785,7 +800,8 @@ class Controller extends Object { if (ClassRegistry::isKeySet($currentModel)) { $currentObject =& ClassRegistry::getObject($currentModel); if (is_a($currentObject, 'Model') && !empty($currentObject->validationErrors)) { - $View->validationErrors[Inflector::camelize($currentModel)] =& $currentObject->validationErrors; + $View->validationErrors[Inflector::camelize($currentModel)] =& + $currentObject->validationErrors; } } } @@ -821,7 +837,8 @@ class Controller extends Object { } if ($default != null) { - return $default; + $url = Router::url($default, true); + return $url; } return '/'; } @@ -863,9 +880,11 @@ class Controller extends Object { * Converts POST'ed form data to a model conditions array, suitable for use in a Model::find() call. * * @param array $data POST'ed data organized by model and field - * @param mixed $op A string containing an SQL comparison operator, or an array matching operators to fields + * @param mixed $op A string containing an SQL comparison operator, or an array matching operators + * to fields * @param string $bool SQL boolean operator: AND, OR, XOR, etc. - * @param boolean $exclusive If true, and $op is an array, fields not included in $op will not be included in the returned conditions + * @param boolean $exclusive If true, and $op is an array, fields not included in $op will not be + * included in the returned conditions * @return array An array of model conditions * @access public * @link http://book.cakephp.org/view/432/postConditions @@ -940,11 +959,16 @@ class Controller extends Object { if ($assoc && isset($this->{$object}->{$assoc})) { $object = $this->{$object}->{$assoc}; - } elseif ($assoc && isset($this->{$this->modelClass}) && isset($this->{$this->modelClass}->{$assoc})) { + } elseif ( + $assoc && isset($this->{$this->modelClass}) && + isset($this->{$this->modelClass}->{$assoc} + )) { $object = $this->{$this->modelClass}->{$assoc}; } elseif (isset($this->{$object})) { $object = $this->{$object}; - } elseif (isset($this->{$this->modelClass}) && isset($this->{$this->modelClass}->{$object})) { + } elseif ( + isset($this->{$this->modelClass}) && isset($this->{$this->modelClass}->{$object} + )) { $object = $this->{$this->modelClass}->{$object}; } } elseif (empty($object) || $object === null) { @@ -965,7 +989,11 @@ class Controller extends Object { } if (!is_object($object)) { - trigger_error(sprintf(__('Controller::paginate() - can\'t find model %1$s in controller %2$sController', true), $object, $this->name), E_USER_WARNING); + trigger_error(sprintf( + __('Controller::paginate() - can\'t find model %1$s in controller %2$sController', + true + ), $object, $this->name + ), E_USER_WARNING); return array(); } $options = array_merge($this->params, $this->params['url'], $this->passedArgs); @@ -1071,7 +1099,9 @@ class Controller extends Object { $page = $options['page'] = (integer)$page; if (method_exists($object, 'paginate')) { - $results = $object->paginate($conditions, $fields, $order, $limit, $page, $recursive, $extra); + $results = $object->paginate( + $conditions, $fields, $order, $limit, $page, $recursive, $extra + ); } else { $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); if ($recursive != $object->recursive) { @@ -1167,4 +1197,4 @@ class Controller extends Object { return false; } } -?> +?> \ No newline at end of file diff --git a/cake/libs/controller/scaffold.php b/cake/libs/controller/scaffold.php index 1c326cffe..2f9d34e8c 100644 --- a/cake/libs/controller/scaffold.php +++ b/cake/libs/controller/scaffold.php @@ -1,5 +1,4 @@ modelKey = $controller->modelKey; if (!is_object($this->controller->{$this->modelClass})) { - return $this->cakeError('missingModel', array(array('className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base))); + return $this->cakeError('missingModel', array(array( + 'className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base + ))); } $this->ScaffoldModel =& $this->controller->{$this->modelClass}; $this->scaffoldTitle = Inflector::humanize($this->viewPath); $this->scaffoldActions = $controller->scaffold; - $this->controller->pageTitle = __('Scaffold :: ', true) . Inflector::humanize($this->action) . ' :: ' . $this->scaffoldTitle; - + $this->controller->pageTitle = __('Scaffold :: ', true) + . Inflector::humanize($this->action) . ' :: ' . $this->scaffoldTitle; $modelClass = $this->controller->modelClass; $primaryKey = $this->ScaffoldModel->primaryKey; $displayField = $this->ScaffoldModel->displayField; @@ -166,13 +173,18 @@ class Scaffold extends Object { $scaffoldFields = array_keys($this->ScaffoldModel->schema()); $associations = $this->__associations(); - $this->controller->set(compact('modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', - 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations')); + $this->controller->set(compact( + 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', + 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations' + )); if ($this->controller->view && $this->controller->view !== 'Theme') { $this->controller->view = 'scaffold'; } $this->__scaffold($params); + $this->_validSession = ( + isset($this->controller->Session) && $this->controller->Session->valid() != false + ); } /** * Outputs the content of a scaffold method passing it through the Controller::afterFilter() @@ -196,16 +208,23 @@ class Scaffold extends Object { if (isset($params['pass'][0])) { $this->ScaffoldModel->id = $params['pass'][0]; - } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey))); + } elseif ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __("No id set for %s::view()", true), + Inflector::humanize($this->modelKey + ))); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey)), - '/' . Inflector::underscore($this->controller->viewPath)); + return $this->controller->flash(sprintf( + __("No id set for %s::view()", true), Inflector::humanize($this->modelKey)), + '/' . Inflector::underscore($this->controller->viewPath + )); } $this->ScaffoldModel->recursive = 1; $this->controller->data = $this->ScaffoldModel->read(); - $this->controller->set(Inflector::variable($this->controller->modelClass), $this->controller->data); + $this->controller->set( + Inflector::variable($this->controller->modelClass), $this->controller->data + ); $this->controller->render($this->action, $this->layout); $this->_output(); } elseif ($this->controller->_scaffoldError('view') === false) { @@ -222,7 +241,9 @@ class Scaffold extends Object { function __scaffoldIndex($params) { if ($this->controller->_beforeScaffold('index')) { $this->ScaffoldModel->recursive = 0; - $this->controller->set(Inflector::variable($this->controller->name), $this->controller->paginate()); + $this->controller->set( + Inflector::variable($this->controller->name), $this->controller->paginate() + ); $this->controller->render($this->action, $this->layout); $this->_output(); } elseif ($this->controller->_scaffoldError('index') === false) { @@ -263,11 +284,17 @@ class Scaffold extends Object { } if (!$this->ScaffoldModel->exists()) { - if (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey))); + if ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __("Invalid id for %s::edit()", true), + Inflector::humanize($this->modelKey) + )); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey)), $this->redirect); + return $this->controller->flash(sprintf( + __("Invalid id for %s::edit()", true), + Inflector::humanize($this->modelKey) + ), $this->redirect); } } } @@ -279,18 +306,26 @@ class Scaffold extends Object { if ($this->ScaffoldModel->save($this->controller->data)) { if ($this->controller->_afterScaffoldSave($action)) { - if (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success)); + if ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __('The %1$s has been %2$s', true), + Inflector::humanize($this->modelClass), $success + )); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success), $this->redirect); + return $this->controller->flash(sprintf( + __('The %1$s has been %2$s', true), + Inflector::humanize($this->modelClass), $success + ), $this->redirect); } } else { return $this->controller->_afterScaffoldSaveError($action); } } else { - if (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(__('Please correct errors below.', true)); + if ($this->_validSession) { + $this->controller->Session->setFlash( + __('Please correct errors below.', true + )); } } } @@ -304,7 +339,9 @@ class Scaffold extends Object { } foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) { - $varName = Inflector::variable(Inflector::pluralize(preg_replace('/(?:_id)$/', '', $assocData['foreignKey']))); + $varName = Inflector::variable(Inflector::pluralize( + preg_replace('/(?:_id)$/', '', $assocData['foreignKey']) + )); $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list')); } foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) { @@ -328,27 +365,42 @@ class Scaffold extends Object { if ($this->controller->_beforeScaffold('delete')) { if (isset($params['pass'][0])) { $id = $params['pass'][0]; - } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey))); + } elseif ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __("No id set for %s::delete()", true), Inflector::humanize($this->modelKey) + )); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey)), - '/' . Inflector::underscore($this->controller->viewPath)); + return $this->controller->flash(sprintf( + __("No id set for %s::delete()", true), Inflector::humanize($this->modelKey) + ), '/' . Inflector::underscore($this->controller->viewPath)); } - if ($this->ScaffoldModel->del($id)) { - if (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id)); + if ($this->ScaffoldModel->delete($id)) { + if ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __('The %1$s with id: %2$d has been deleted.', true), + Inflector::humanize($this->modelClass), $id + )); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath); + return $this->controller->flash(sprintf( + __('The %1$s with id: %2$d has been deleted.', true), + Inflector::humanize($this->modelClass), $id + ), '/' . $this->viewPath); } } else { - if (isset($this->controller->Session) && $this->controller->Session->valid() != false) { - $this->controller->Session->setFlash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id)); + if ($this->_validSession) { + $this->controller->Session->setFlash(sprintf( + __('There was an error deleting the %1$s with id: %2$d', true), + Inflector::humanize($this->modelClass), $id + )); $this->controller->redirect($this->redirect); } else { - return $this->controller->flash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath); + return $this->controller->flash(sprintf( + __('There was an error deleting the %1$s with id: %2$d', true), + Inflector::humanize($this->modelClass), $id + ), '/' . $this->viewPath); } } } elseif ($this->controller->_scaffoldError('delete') === false) { @@ -383,9 +435,14 @@ class Scaffold extends Object { if (isset($db)) { if (empty($this->scaffoldActions)) { - $this->scaffoldActions = array('index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete'); + $this->scaffoldActions = array( + 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete' + ); } elseif (!empty($admin) && $this->scaffoldActions === $admin) { - $this->scaffoldActions = array($admin .'_index', $admin .'_list', $admin .'_view', $admin .'_add', $admin .'_create', $admin .'_edit', $admin .'_update', $admin .'_delete'); + $this->scaffoldActions = array( + $admin .'_index', $admin .'_list', $admin .'_view', $admin .'_add', + $admin .'_create', $admin .'_edit', $admin .'_update', $admin .'_delete' + ); } if (in_array($params['action'], $this->scaffoldActions)) { @@ -419,13 +476,17 @@ class Scaffold extends Object { break; } } else { - return $this->cakeError('missingAction', array(array('className' => $this->controller->name . "Controller", - 'base' => $this->controller->base, - 'action' => $this->action, - 'webroot' => $this->controller->webroot))); + return $this->cakeError('missingAction', array(array( + 'className' => $this->controller->name . "Controller", + 'base' => $this->controller->base, + 'action' => $this->action, + 'webroot' => $this->controller->webroot + ))); } } else { - return $this->cakeError('missingDatabase', array(array('webroot' => $this->controller->webroot))); + return $this->cakeError('missingDatabase', array(array( + 'webroot' => $this->controller->webroot + ))); } } /** @@ -440,10 +501,17 @@ class Scaffold extends Object { foreach ($keys as $key => $type) { foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) { - $associations[$type][$assocKey]['primaryKey'] = $this->ScaffoldModel->{$assocKey}->primaryKey; - $associations[$type][$assocKey]['displayField'] = $this->ScaffoldModel->{$assocKey}->displayField; - $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey']; - $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($assocData['className'])); + $associations[$type][$assocKey]['primaryKey'] = + $this->ScaffoldModel->{$assocKey}->primaryKey; + + $associations[$type][$assocKey]['displayField'] = + $this->ScaffoldModel->{$assocKey}->displayField; + + $associations[$type][$assocKey]['foreignKey'] = + $assocData['foreignKey']; + + $associations[$type][$assocKey]['controller'] = + Inflector::pluralize(Inflector::underscore($assocData['className'])); } } return $associations; diff --git a/cake/libs/debugger.php b/cake/libs/debugger.php index c070d9098..bab67ae80 100644 --- a/cake/libs/debugger.php +++ b/cake/libs/debugger.php @@ -1,5 +1,4 @@ array( + 'trace' => '{:reference} - {:path}, line {:line}', + 'error' => "{:error} ({:code}): {:description} in [{:file}, line {:line}]" + ), + 'js' => array( + 'error' => '', + 'info' => '', + 'trace' => '
{:trace}', + 'code' => '', + 'context' => '', + 'links' => array() + ), + 'html' => array( + 'trace' => '
Trace', + 'context' => '{:trace}
Context' + ), + 'txt' => array( + 'error' => "{:error}: {:code} :: {:description} on line {:line} of {:path}\n{:info}", + 'context' => "Context:\n{:context}\n", + 'trace' => "Trace:\n{:trace}\n", + 'code' => '', + 'info' => '' + ), + 'base' => array( + 'traceLine' => '{:reference} - {:path}, line {:line}' + ) + ); + /** * Holds current output data when outputFormat is false. * * @var string * @access private */ - var $__data = array(); + var $_data = array(); + /** * Constructor. * */ function __construct() { $docRef = ini_get('docref_root'); + if (empty($docRef)) { ini_set('docref_root', 'http://php.net/'); } if (!defined('E_RECOVERABLE_ERROR')) { define('E_RECOVERABLE_ERROR', 4096); } + if (!defined('E_DEPRECATED')) { + define('E_DEPRECATED', 8192); + } + + $e = '{:error} ({:code}): {:description} '; + $e .= '[{:path}, line {:line}]'; + + $e .= ' '; + $this->_templates['js']['error'] = $e; + + $t = ' '; + $this->_templates['js']['info'] = $t; + + $links = array(); + $link = 'Code'; + $links['code'] = $link; + + $link = 'Context'; + $links['context'] = $link; + + $links['help'] = 'Help'; + $this->_templates['js']['links'] = $links; + + $this->_templates['js']['context'] = '{:context}
_templates['js']['context'] .= 'style="display: none;">{:context}'; + + $this->_templates['js']['code'] = '
{:code}
{:error} ({:code}) : {:description} '; + $e .= '[{:path}, line {:line}]'; + $this->_templates['html']['error'] = $e; + + $this->_templates['html']['context'] = '
Context '; + $this->_templates['html']['context'] .= ''; } + /** * Returns a reference to the Debugger singleton object instance. * @@ -113,6 +200,7 @@ class Debugger extends Object { } return $instance[0]; } + /** * Formats and outputs the contents of the supplied variable. * @@ -127,6 +215,7 @@ class Debugger extends Object { $_this = Debugger::getInstance(); pr($_this->exportVar($var)); } + /** * Creates a detailed stack trace log at the time of invocation, much like dump() * but to debug.log. @@ -175,7 +264,7 @@ class Debugger extends Object { if (empty($line)) { $line = '??'; } - $file = $_this->trimPath($file); + $path = $_this->trimPath($file); $info = compact('code', 'description', 'file', 'line'); if (!in_array($info, $_this->errors)) { @@ -214,15 +303,20 @@ class Debugger extends Object { $helpCode = null; if (!empty($_this->helpPath) && preg_match('/.*\[([0-9]+)\]$/', $description, $codes)) { if (isset($codes[1])) { - $helpCode = $codes[1]; + $helpID = $codes[1]; $description = trim(preg_replace('/\[[0-9]+\]$/', '', $description)); } } - echo $_this->_output($level, $error, $code, $helpCode, $description, $file, $line, $context); + $data = compact( + 'level', 'error', 'code', 'helpID', 'description', 'file', 'path', 'line', 'context' + ); + echo $_this->_output($data); if (Configure::read('log')) { - CakeLog::write($level, "{$error} ({$code}): {$description} in [{$file}, line {$line}]"); + $tpl = $_this->_templates['log']['error']; + $options = array('before' => '{:', 'after' => '}'); + CakeLog::write($level, String::insert($tpl, $data, $options)); } if ($error == 'Fatal Error') { @@ -230,6 +324,7 @@ class Debugger extends Object { } return true; } + /** * Outputs a stack trace based on the supplied options. * @@ -240,65 +335,66 @@ class Debugger extends Object { * @link http://book.cakephp.org/view/460/Using-the-Debugger-Class */ function trace($options = array()) { - $options = array_merge(array( - 'depth' => 999, - 'format' => '', - 'args' => false, - 'start' => 0, - 'scope' => null, - 'exclude' => null - ), - $options + $_this = Debugger::getInstance(); + $defaults = array( + 'depth' => 999, + 'format' => $_this->_outputFormat, + 'args' => false, + 'start' => 0, + 'scope' => null, + 'exclude' => null ); + $options += $defaults; $backtrace = debug_backtrace(); - $back = array(); $count = count($backtrace); + $back = array(); + + $_trace = array( + 'line' => '??', + 'file' => '[internal]', + 'class' => null, + 'function' => '[main]' + ); for ($i = $options['start']; $i < $count && $i < $options['depth']; $i++) { - $trace = array_merge( - array( - 'file' => '[internal]', - 'line' => '??' - ), - $backtrace[$i] - ); + $trace = array_merge(array('file' => '[internal]', 'line' => '??'), $backtrace[$i]); if (isset($backtrace[$i + 1])) { - $next = array_merge( - array( - 'line' => '??', - 'file' => '[internal]', - 'class' => null, - 'function' => '[main]' - ), - $backtrace[$i + 1] - ); - $function = $next['function']; + $next = array_merge($_trace, $backtrace[$i + 1]); + $reference = $next['function']; if (!empty($next['class'])) { - $function = $next['class'] . '::' . $function . '('; + $reference = $next['class'] . '::' . $reference . '('; if ($options['args'] && isset($next['args'])) { $args = array(); foreach ($next['args'] as $arg) { $args[] = Debugger::exportVar($arg); } - $function .= join(', ', $args); + $reference .= join(', ', $args); } - $function .= ')'; + $reference .= ')'; } } else { - $function = '[main]'; + $reference = '[main]'; } - if (in_array($function, array('call_user_func_array', 'trigger_error'))) { + if (in_array($reference, array('call_user_func_array', 'trigger_error'))) { continue; } if ($options['format'] == 'points' && $trace['file'] != '[internal]') { $back[] = array('file' => $trace['file'], 'line' => $trace['line']); - } elseif (empty($options['format'])) { - $back[] = $function . ' - ' . Debugger::trimPath($trace['file']) . ', line ' . $trace['line']; - } else { + } elseif ($options['format'] == 'array') { $back[] = $trace; + } else { + if (isset($_this->_templates[$options['format']]['traceLine'])) { + $tpl = $_this->_templates[$options['format']]['traceLine']; + } else { + $tpl = $_this->_templates['base']['traceLine']; + } + $trace['path'] = Debugger::trimPath($trace['file']); + $trace['reference'] = $reference; + unset($trace['object'], $trace['args']); + $back[] = String::insert($tpl, $trace, array('before' => '{:', 'after' => '}')); } } @@ -307,6 +403,7 @@ class Debugger extends Object { } return join("\n", $back); } + /** * Shortens file paths by replacing the application base path with 'APP', and the CakePHP core * path with 'CORE'. @@ -336,6 +433,7 @@ class Debugger extends Object { } return $path; } + /** * Grabs an excerpt from a file and highlights a given line of code * @@ -370,6 +468,7 @@ class Debugger extends Object { } return $lines; } + /** * Converts a variable to a string for debug output. * @@ -424,6 +523,7 @@ class Debugger extends Object { break; } } + /** * Handles object to string conversion. * @@ -454,98 +554,122 @@ class Debugger extends Object { } return join("\n", $out); } + /** - * Handles object conversion to debug string. + * Switches output format, updates format strings * - * @param string $var Object to convert + * @param string $format Format to use, including 'js' for JavaScript-enhanced HTML, 'html' for + * straight HTML output, or 'text' for unformatted text. * @access protected */ - function output($format = 'js') { + function output($format = null, $strings = array()) { $_this = Debugger::getInstance(); $data = null; - if ($format === true && !empty($_this->__data)) { - $data = $_this->__data; - $_this->__data = array(); + if (is_null($format)) { + return $_this->_outputFormat; + } + + if (!empty($strings)) { + if (isset($_this->_templates[$format])) { + if (isset($strings['links'])) { + $_this->_templates[$format]['links'] = array_merge( + $_this->_templates[$format]['links'], + $strings['links'] + ); + unset($strings['links']); + } + $_this->_templates[$format] = array_merge($_this->_templates[$format], $strings); + } else { + $_this->_templates[$format] = $strings; + } + return $_this->_templates[$format]; + } + + if ($format === true && !empty($_this->_data)) { + $data = $_this->_data; + $_this->_data = array(); $format = false; } $_this->_outputFormat = $format; return $data; } + /** - * Handles object conversion to debug string. + * Renders error messages * - * @param string $var Object to convert + * @param array $data Data about the current error * @access private */ - function _output($level, $error, $code, $helpCode, $description, $file, $line, $kontext) { - $files = $this->trace(array('start' => 2, 'format' => 'points')); - $listing = $this->excerpt($files[0]['file'], $files[0]['line'] - 1, 1); - $trace = $this->trace(array('start' => 2, 'depth' => '20')); - $context = array(); + function _output($data = array()) { + $defaults = array( + 'level' => 0, + 'error' => 0, + 'code' => 0, + 'helpID' => null, + 'description' => '', + 'file' => '', + 'line' => 0, + 'context' => array() + ); + $data += $defaults; - foreach ((array)$kontext as $var => $value) { + $files = $this->trace(array('start' => 2, 'format' => 'points')); + $code = $this->excerpt($files[0]['file'], $files[0]['line'] - 1, 1); + $trace = $this->trace(array('start' => 2, 'depth' => '20')); + $insertOpts = array('before' => '{:', 'after' => '}'); + $context = array(); + $links = array(); + $info = ''; + + foreach ((array)$data['context'] as $var => $value) { $context[] = "\${$var}\t=\t" . $this->exportVar($value, 1); } switch ($this->_outputFormat) { - default: - case 'js': - $link = "document.getElementById(\"CakeStackTrace" . count($this->errors) . "\").style.display = (document.getElementById(\"CakeStackTrace" . count($this->errors) . "\").style.display == \"none\" ? \"\" : \"none\")"; - $out = "{$error} ({$code}): {$description} [{$file}, line {$line}]"; - if (Configure::read() > 0) { - debug($out, false, false); - echo ' '; - } - break; - case 'html': - echo "{:context}
{$error} ({$code}) : {$description} [{$file}, line {$line}]"; - if (!empty($context)) { - echo "Context:\n" .implode("\n", $context) . "\n"; - } - echo "
Context"; - echo "" . implode("\n", $context) . "
Trace"; - break; - case 'text': - case 'txt': - echo "{$error}: {$code} :: {$description} on line {$line} of {$file}\n"; - if (!empty($context)) { - echo "Context:\n" .implode("\n", $context) . "\n"; - } - echo "Trace:\n" . $trace; - break; - case 'log': - $this->log(compact('error', 'code', 'description', 'line', 'file', 'context', 'trace')); - break; case false: - $this->__data[] = compact('error', 'code', 'description', 'line', 'file', 'context', 'trace'); - break; + $this->_data[] = compact('context', 'trace') + $data; + return; + case 'log': + $this->log(compact('context', 'trace') + $data); + return; } + + if (empty($this->_outputFormat) || !isset($this->_templates[$this->_outputFormat])) { + $this->_outputFormat = 'js'; + } + + $data['id'] = 'cakeErr' . count($this->errors); + $tpl = array_merge($this->_templates['base'], $this->_templates[$this->_outputFormat]); + $insert = array('context' => join("\n", $context), 'helpPath' => $this->helpPath) + $data; + + $detect = array('help' => 'helpID', 'context' => 'context'); + + if (isset($tpl['links'])) { + foreach ($tpl['links'] as $key => $val) { + if (isset($detect[$key]) && empty($insert[$detect[$key]])) { + continue; + } + $links[$key] = String::insert($val, $insert, $insertOpts); + } + } + + foreach (array('code', 'context', 'trace') as $key) { + if (empty($$key) || !isset($tpl[$key])) { + continue; + } + if (is_array($$key)) { + $$key = join("\n", $$key); + } + $info .= String::insert($tpl[$key], compact($key) + $insert, $insertOpts); + } + $links = join(' | ', $links); + unset($data['context']); + + echo String::insert($tpl['error'], compact('links', 'info') + $data, $insertOpts); } + /** * Verifies that the application's salt value has been changed from the default value. * @@ -557,9 +681,10 @@ class Debugger extends Object { trigger_error(__('Please change the value of \'Security.salt\' in app/config/core.php to a salt value specific to your application', true), E_USER_NOTICE); } } + /** - * Invokes the given debugger object as the current error handler, taking over control from the previous handler - * in a stack-like hierarchy. + * Invokes the given debugger object as the current error handler, taking over control from the + * previous handler in a stack-like hierarchy. * * @param object $debugger A reference to the Debugger object * @access public @@ -574,4 +699,5 @@ class Debugger extends Object { if (!defined('DISABLE_DEFAULT_ERROR_HANDLING')) { Debugger::invoke(Debugger::getInstance()); } + ?> \ No newline at end of file diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index 1becede48..817ecf592 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1,5 +1,4 @@ find('count', compact('conditions', 'recursive'))); - + $this->{$parent}->updateAll( array($assoc['counterCache'] => $count), array($this->{$parent}->escapeField() => $keys['old'][$foreignKey]) @@ -1645,17 +1642,11 @@ class Model extends Overloadable { return $db->update($this, $fields, null, $conditions); } /** - * Alias for del(). - * - * @param mixed $id ID of record to delete - * @param boolean $cascade Set to true to delete records that depend on this record - * @return boolean True on success - * @access public - * @see Model::del() + * @deprecated * @link http://book.cakephp.org/view/691/remove */ function remove($id = null, $cascade = true) { - return $this->del($id, $cascade); + return $this->delete($id, $cascade); } /** * Removes record for given ID. If no ID is given, the current ID is used. Returns true on success. @@ -1666,7 +1657,7 @@ class Model extends Overloadable { * @access public * @link http://book.cakephp.org/view/690/del */ - function del($id = null, $cascade = true) { + function delete($id = null, $cascade = true) { if (!empty($id)) { $this->id = $id; } @@ -1674,7 +1665,10 @@ class Model extends Overloadable { if ($this->exists() && $this->beforeDelete($cascade)) { $db =& ConnectionManager::getDataSource($this->useDbConfig); - if (!$this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array('break' => true, 'breakOn' => false))) { + $filters = $this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array( + 'break' => true, 'breakOn' => false + )); + if (!$filters) { return false; } $this->_deleteDependent($id, $cascade); @@ -1700,16 +1694,10 @@ class Model extends Overloadable { return false; } /** - * Alias for del(). - * - * @param mixed $id ID of record to delete - * @param boolean $cascade Set to true to delete records that depend on this record - * @return boolean True on success - * @access public - * @see Model::del() + * @deprecated */ - function delete($id = null, $cascade = true) { - return $this->del($id, $cascade); + function del($id = null, $cascade = true) { + return $this->delete($id, $cascade); } /** * Cascades model deletes through associated hasMany and hasOne child records. @@ -1737,7 +1725,9 @@ class Model extends Overloadable { if (isset($data['exclusive']) && $data['exclusive']) { $model->deleteAll($conditions); } else { - $records = $model->find('all', array('conditions' => $conditions, 'fields' => $model->primaryKey)); + $records = $model->find('all', array( + 'conditions' => $conditions, 'fields' => $model->primaryKey + )); if (!empty($records)) { foreach ($records as $record) { @@ -1762,14 +1752,18 @@ class Model extends Overloadable { $db =& ConnectionManager::getDataSource($this->useDbConfig); foreach ($this->hasAndBelongsToMany as $assoc => $data) { + $with = $data['with']; $records = $this->{$data['with']}->find('all', array( - 'conditions' => array_merge(array($this->{$data['with']}->escapeField($data['foreignKey']) => $id)), - 'fields' => $this->{$data['with']}->primaryKey, + 'conditions' => array_merge(array( + $this->{$with}->escapeField($data['foreignKey']) => $id + )), + 'fields' => $this->{$with}->primaryKey, 'recursive' => -1 )); if (!empty($records)) { foreach ($records as $record) { - $this->{$data['with']}->delete($record[$this->{$data['with']}->alias][$this->{$data['with']}->primaryKey]); + $id = $record[$this->{$with}->alias][$this->{$with}->primaryKey]; + $this->{$with}->delete($id); } } } @@ -1794,7 +1788,10 @@ class Model extends Overloadable { return $db->delete($this, $conditions); } else { $ids = Set::extract( - $this->find('all', array_merge(array('fields' => "{$this->alias}.{$this->primaryKey}", 'recursive' => 0), compact('conditions'))), + $this->find('all', array_merge(array( + 'fields' => "{$this->alias}.{$this->primaryKey}", + 'recursive' => 0), compact('conditions')) + ), "{n}.{$this->alias}.{$this->primaryKey}" ); @@ -1821,6 +1818,7 @@ class Model extends Overloadable { } } } + /** * Collects foreign keys from associations. * @@ -1837,6 +1835,7 @@ class Model extends Overloadable { } return $result; } + /** * Returns true if a record with the currently set ID exists. * @@ -1863,6 +1862,7 @@ class Model extends Overloadable { } return $this->__exists = ($this->find('count', $query) > 0); } + /** * Returns true if a record that meets given conditions exists. * @@ -1873,6 +1873,7 @@ class Model extends Overloadable { function hasAny($conditions = null) { return ($this->find('count', array('conditions' => $conditions, 'recursive' => -1)) != false); } + /** * Returns a result set array. * @@ -1894,8 +1895,10 @@ class Model extends Overloadable { * - If three fields are specified, they are used (in order) for key, value and group. * - Otherwise, first and second fields are used for key and value. * - * @param array $conditions SQL conditions array, or type of find operation (all / first / count / neighbors / list / threaded) - * @param mixed $fields Either a single string of a field name, or an array of field names, or options for matching + * @param array $conditions SQL conditions array, or type of find operation (all / first / count / + * neighbors / list / threaded) + * @param mixed $fields Either a single string of a field name, or an array of field names, or + * options for matching * @param string $order SQL ORDER BY conditions (e.g. "price DESC" or "name ASC") * @param integer $recursive The number of levels deep to fetch associated records * @return array Array of records @@ -1973,6 +1976,7 @@ class Model extends Overloadable { } } } + /** * Handles the before/after filter logic for find('first') operations. Only called by Model::find(). * @@ -1997,6 +2001,7 @@ class Model extends Overloadable { return $results[0]; } } + /** * Handles the before/after filter logic for find('count') operations. Only called by Model::find(). * @@ -2028,6 +2033,7 @@ class Model extends Overloadable { return false; } } + /** * Handles the before/after filter logic for find('list') operations. Only called by Model::find(). * @@ -2086,6 +2092,7 @@ class Model extends Overloadable { return Set::combine($results, $lst['keyPath'], $lst['valuePath'], $lst['groupPath']); } } + /** * Detects the previous field's value, then uses logic to find the 'wrapping' * rows and return them. @@ -2144,6 +2151,7 @@ class Model extends Overloadable { return $return; } } + /** * In the event of ambiguous results returned (multiple top level results, with different parent_ids) * top level results with different parent_ids to the first result will be dropped @@ -2190,6 +2198,7 @@ class Model extends Overloadable { return $return; } } + /** * Passes query results through model and behavior afterFilter() methods. * @@ -2205,6 +2214,7 @@ class Model extends Overloadable { } return $this->afterFind($results, $primary); } + /** * Called only when bindTo" . $trace. "
<?php';
+ $expected .= '
';
+ $this->assertEqual($result[0], $expected);
$return = Debugger::excerpt('[internal]', 2, 2);
$this->assertTrue(empty($return));
@@ -135,14 +139,60 @@ class DebuggerTest extends CakeTestCase {
ob_start();
Debugger::output('js');
$buzz .= '';
- $result = ob_get_clean();
- $this->assertPattern("/assertPattern('/Notice<\/b>/', $result);
- $this->assertPattern('/Undefined variable: buzz/', $result);
- $this->assertPattern('/]+>Code<\/a>/', $result);
- $this->assertPattern('/]+>Context<\/a>/', $result);
+ $result = explode('', ob_get_clean());
+ $this->assertTags($result[0], array(
+ 'a' => array(
+ 'href' => "javascript:void(0);",
+ 'onclick' => "document.getElementById('cakeErr4-trace').style.display = " .
+ "(document.getElementById('cakeErr4-trace').style.display == 'none'" .
+ " ? '' : 'none');"
+ ),
+ 'b' => array(), 'Notice', '/b', ' (8)'
+ ));
+
+ $this->assertPattern('/Undefined variable: buzz/', $result[1]);
+ $this->assertPattern('/]+>Code/', $result[1]);
+ $this->assertPattern('/]+>Context/', $result[2]);
set_error_handler('simpleTestErrorHandler');
}
+
+/**
+ * Tests that changes in output formats using Debugger::output() change the templates used.
+ *
+ * @return void
+ */
+ function testChangeOutputFormats() {
+ Debugger::invoke(Debugger::getInstance());
+ Debugger::output('js', array(
+ 'traceLine' => '{:reference} - {:path}, line {:line}'
+ ));
+ $result = Debugger::trace();
+ $this->assertPattern('/' . preg_quote('txmt://open?url=file:///', '/') . '/', $result);
+
+ Debugger::output('xml', array(
+ 'error' => '{:code}
Text here
', array('clean' => 'html', 'before' => ':', 'after' => '')); + $result = String::cleanInsert( + 'Text here
', + array('clean' => 'html', 'before' => ':', 'after' => '') + ); $this->assertEqual($result, 'Text here
'); } + +/** + * Tests that non-insertable variables (i.e. arrays) are skipped when used as values in + * String::insert(). + * + * @return void + */ + function testAutoIgnoreBadInsertData() { + $data = array('foo' => 'alpha', 'bar' => 'beta', 'fale' => array()); + $result = String::insert('(:foo > :bar || :fale!)', $data, array('clean' => 'text')); + $this->assertEqual($result, '(alpha > beta || !)'); + } + /** * testTokenize method * @@ -254,4 +278,5 @@ class StringTest extends CakeTestCase { $this->assertEqual($expected, $result); } } + ?> \ No newline at end of file diff --git a/index.php b/index.php index c6a3a1b18..c73b03a96 100644 --- a/index.php +++ b/index.php @@ -1,29 +1,25 @@ \ No newline at end of file