diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..49926b62b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +app/config +app/tmp +vendors \ No newline at end of file diff --git a/app/config/bootstrap.php b/app/config/bootstrap.php index b817172c7..924147237 100644 --- a/app/config/bootstrap.php +++ b/app/config/bootstrap.php @@ -1,44 +1,46 @@ \ No newline at end of file +/** + * As of 1.3, additional rules for the inflector are added below + * + * Inflector::rule('singular', array('rules' => array(), irregular' => array(), 'uninflected' => array())); + * Inflector::rule('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); + * + */ +?> diff --git a/app/config/core.php b/app/config/core.php index dfcba1ea5..01b8d563d 100644 --- a/app/config/core.php +++ b/app/config/core.php @@ -96,16 +96,30 @@ * To define a custom session handler, save it at /app/config/.php. * Set the value of 'Session.save' to to utilize it in CakePHP. * - * To use database sessions, execute the SQL file found at /app/config/sql/sessions.sql. + * To use database sessions, run the app/config/schema/sessions.php schema using + * the cake shell command: cake schema run create Sessions * */ Configure::write('Session.save', 'php'); +/** + * The model name to be used for the session model. + * + * 'Session.save' must be set to 'database' in order to utilize this constant. + * + * The model name set here should *not* be used elsewhere in your application. + */ + //Configure::write('Session.model', 'Session'); /** * The name of the table used to store CakePHP database sessions. * * 'Session.save' must be set to 'database' in order to utilize this constant. * * The table name set here should *not* include any table prefix defined elsewhere. + * + * Please note that if you set a value for Session.model (above), any value set for + * Session.table will be ignored. + * + * [Note: Session.table is deprecated as of CakePHP 1.3] */ //Configure::write('Session.table', 'cake_sessions'); /** 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 @@ value array of regex used to match words. - * If key matches then the value is returned. - * - * $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice'); - */ - $pluralRules = array(); -/** - * This is a key only array of plural words that should not be inflected. - * Notice the last comma - * - * $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox'); - */ - $uninflectedPlural = array(); -/** - * This is a key => value array of plural irregular words. - * If key matches then the value is returned. - * - * $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers') - */ - $irregularPlural = array(); -/** - * This is a key => value array of regex used to match words. - * If key matches then the value is returned. - * - * $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i') - */ - $singularRules = array(); -/** - * This is a key only array of singular words that should not be inflected. - * You should not have to change this value below if you do change it use same format - * as the $uninflectedPlural above. - */ - $uninflectedSingular = $uninflectedPlural; -/** - * This is a key => value array of singular irregular words. - * Most of the time this will be a reverse of the above $irregularPlural array - * You should not have to change this value below if you do change it use same format - * - * $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother') - */ - $irregularSingular = array_flip($irregularPlural); -?> \ No newline at end of file diff --git a/app/webroot/index.php b/app/webroot/index.php index 34837799b..526cecba3 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -1,27 +1,22 @@ dispatch($url); + $Dispatcher->dispatch(); } if (Configure::read() > 0) { echo ""; diff --git a/cake/VERSION.txt b/cake/VERSION.txt index 328fa2e81..3974acb41 100644 --- a/cake/VERSION.txt +++ b/cake/VERSION.txt @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -// +---------------------------------------------------------------------------------------------------+ // -// + $Id$ -// + Last Modified: $Date$ -// + Modified By: $LastChangedBy$ -// +---------------------------------------------------------------------------------------------------+ // -/////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +--------------------------------------------------------------------------------------------+ // // CakePHP Version +// +// Holds a static string representing the current version of CakePHP +// +// CakePHP(tm) : Rapid Development Framework (http://cakephp.org) +// Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) +// +// Licensed under The MIT License +// Redistributions of files must retain the above copyright notice. +// +// @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org) +// @link http://cakephp.org +// @package cake +// @subpackage cake.cake.libs +// @since CakePHP(tm) v 0.2.9 +// @license MIT License (http://www.opensource.org/licenses/mit-license.php) +// +--------------------------------------------------------------------------------------------+ // +//////////////////////////////////////////////////////////////////////////////////////////////////// -1.2.2.8120 \ No newline at end of file +1.3.0.0 \ No newline at end of file diff --git a/cake/basics.php b/cake/basics.php index 93bb05f24..cae6e65bd 100644 --- a/cake/basics.php +++ b/cake/basics.php @@ -830,7 +830,7 @@ if (!function_exists('file_put_contents')) { function array_intersect_key($arr1, $arr2) { $res = array(); foreach ($arr1 as $key => $value) { - if (isset($arr2[$key])) { + if (array_key_exists($key, $arr2)) { $res[$key] = $arr1[$key]; } } 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/config/config.php b/cake/config/config.php index 61c56e8ee..0ea8edad5 100644 --- a/cake/config/config.php +++ b/cake/config/config.php @@ -1,26 +1,23 @@ \ No newline at end of file diff --git a/cake/console/cake.php b/cake/console/cake.php index 823e6fc00..1c234e23a 100644 --- a/cake/console/cake.php +++ b/cake/console/cake.php @@ -198,7 +198,7 @@ class ShellDispatcher { */ function __buildPaths() { $paths = array(); - $pluginPaths = Configure::read('pluginPaths'); + $pluginPaths = App::path('plugins'); if (!class_exists('Folder')) { require LIBS . 'folder.php'; } @@ -214,7 +214,7 @@ class ShellDispatcher { } } - $vendorPaths = array_values(Configure::read('vendorPaths')); + $vendorPaths = array_values(App::path('vendors')); foreach ($vendorPaths as $vendorPath) { $path = rtrim($vendorPath, DS) . DS . 'shells' . DS; if (file_exists($path)) { @@ -222,7 +222,7 @@ class ShellDispatcher { } } - $this->shellPaths = array_values(array_unique(array_merge($paths, Configure::read('shellPaths')))); + $this->shellPaths = array_values(array_unique(array_merge($paths, App::path('shells')))); } /** * Initializes the environment and loads the Cake core. @@ -259,7 +259,7 @@ class ShellDispatcher { Configure::getInstance(file_exists(CONFIGS . 'bootstrap.php')); if (!file_exists(APP_PATH . 'config' . DS . 'core.php')) { - include_once CORE_PATH . 'cake' . DS . 'console' . DS . 'libs' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php'; + include_once CORE_PATH . 'cake' . DS . 'console' . DS . 'templates' . DS . 'skel' . DS . 'config' . DS . 'core.php'; Configure::buildPaths(array()); } @@ -548,7 +548,7 @@ class ShellDispatcher { foreach ($this->shellPaths as $path) { if (is_dir($path)) { - $shells = Configure::listObjects('file', $path); + $shells = App::objects('file', $path); $path = str_replace(CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS, 'CORE' . DS, $path); $path = str_replace(APP, 'APP' . DS, $path); $path = str_replace(ROOT, 'ROOT', $path); diff --git a/cake/console/libs/acl.php b/cake/console/libs/acl.php index 0e44bd82b..5a7873da8 100644 --- a/cake/console/libs/acl.php +++ b/cake/console/libs/acl.php @@ -205,7 +205,7 @@ class AclShell extends Shell { extract($this->__dataVars()); $data = array( $class => array( - 'id' => $this->args[1], + 'id' => $this->args[1], 'parent_id' => $this->args[2] ) ); @@ -336,7 +336,12 @@ class AclShell extends Shell { } $last = $n[$class]['rght']; $count = count($stack); - $this->out(str_repeat(' ', $count) . "[" . $n[$class]['id'] . "]" . $n[$class]['alias']."\n"); + $indent = str_repeat(' ', $count); + if ($n[$class]['alias']) { + $this->out($indent . "[" . $n[$class]['id'] . "]" . $n[$class]['alias']."\n"); + } else { + $this->out($indent . "[" . $n[$class]['id'] . "]" . $n[$class]['model'] . '.' . $n[$class]['foreign_key'] . "\n"); + } } $this->hr(); } diff --git a/cake/console/libs/api.php b/cake/console/libs/api.php index 741f2f66f..7ff0d73e0 100644 --- a/cake/console/libs/api.php +++ b/cake/console/libs/api.php @@ -82,7 +82,7 @@ class ApiShell extends Shell { $class = Inflector::camelize($file); } - $objects = Configure::listObjects('class', $path); + $objects = App::objects('class', $path); if (in_array($class, $objects)) { if (in_array($type, array('behavior', 'component', 'helper')) && $type !== $file) { if (!preg_match('/' . Inflector::camelize($type) . '$/', $class)) { @@ -151,17 +151,17 @@ class ApiShell extends Shell { $commands = array( 'path' => "\t\n" . - "\t\tEither a full path or type of class (model, behavior, controller, component, view, helper).\n". - "\t\tAvailable values:\n\n". - "\t\tbehavior\tLook for class in CakePHP behavior path\n". - "\t\tcache\tLook for class in CakePHP cache path\n". - "\t\tcontroller\tLook for class in CakePHP controller path\n". - "\t\tcomponent\tLook for class in CakePHP component path\n". - "\t\thelper\tLook for class in CakePHP helper path\n". - "\t\tmodel\tLook for class in CakePHP model path\n". - "\t\tview\tLook for class in CakePHP view path\n", + "\t\tEither a full path or type of class (model, behavior, controller, component, view, helper).\n". + "\t\tAvailable values:\n\n". + "\t\tbehavior\tLook for class in CakePHP behavior path\n". + "\t\tcache\tLook for class in CakePHP cache path\n". + "\t\tcontroller\tLook for class in CakePHP controller path\n". + "\t\tcomponent\tLook for class in CakePHP component path\n". + "\t\thelper\tLook for class in CakePHP helper path\n". + "\t\tmodel\tLook for class in CakePHP model path\n". + "\t\tview\tLook for class in CakePHP view path\n", 'className' => "\t\n" . - "\t\tA CakePHP core class name (e.g: Component, HtmlHelper).\n" + "\t\tA CakePHP core class name (e.g: Component, HtmlHelper).\n" ); $this->out($head); @@ -196,16 +196,16 @@ class ApiShell extends Shell { $contents = $File->read(); - if (preg_match_all('%(/\\*\\*[\\s\\S]*?\\*/)(\\s+function\\s+\\w+)(\\(.+\\))%', $contents, $result, PREG_PATTERN_ORDER)) { + if (preg_match_all('%(/\\*\\*[\\s\\S]*?\\*/)(\\s+function\\s+\\w+)(\\(.*\\))%', $contents, $result, PREG_PATTERN_ORDER)) { foreach ($result[2] as $key => $method) { $method = str_replace('function ', '', trim($method)); if (strpos($method, '__') === false && $method[0] != '_') { $parsed[$method] = array( - 'comment' => r(array('/*', '*/', '*'), '', trim($result[1][$key])), - 'method' => $method, - 'parameters' => trim($result[3][$key]), - ); + 'comment' => r(array('/*', '*/', '*'), '', trim($result[1][$key])), + 'method' => $method, + 'parameters' => trim($result[3][$key]) + ); } } } diff --git a/cake/console/libs/console.php b/cake/console/libs/console.php index e04ba782c..b9f2e6e96 100644 --- a/cake/console/libs/console.php +++ b/cake/console/libs/console.php @@ -58,7 +58,7 @@ class ConsoleShell extends Shell { function initialize() { require_once CAKE . 'dispatcher.php'; $this->Dispatcher = new Dispatcher(); - $this->models = Configure::listObjects('model'); + $this->models = App::objects('model'); App::import('Model', $this->models); foreach ($this->models as $model) { diff --git a/cake/console/libs/schema.php b/cake/console/libs/schema.php index 799bb0083..445ad1579 100644 --- a/cake/console/libs/schema.php +++ b/cake/console/libs/schema.php @@ -26,7 +26,7 @@ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ App::import('File'); -App::import('Model', 'Schema'); +App::import('Model', 'CakeSchema'); /** * Schema is a command-line database management utility for automating programmer chores. * diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 72f13d415..81f4fafbe 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -243,8 +243,11 @@ class ControllerTask extends Shell { * @access private */ function bakeActions($controllerName, $admin = null, $wannaUseSession = true) { - $currentModelName = $this->_modelName($controllerName); - if (!App::import('Model', $currentModelName)) { + $currentModelName = $modelImport = $this->_modelName($controllerName); + if ($this->plugin) { + $modelImport = $this->plugin . '.' . $modelImport; + } + if (!App::import('Model', $modelImport)) { $this->err(__('You must have a model for this class to build scaffold methods. Please try again.', true)); exit; } @@ -375,7 +378,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"; @@ -465,11 +468,11 @@ class ControllerTask extends Shell { $out .= "\tvar \$autoRender = false;\n}\n\n"; $out .= "class {$className}ControllerTest extends CakeTestCase {\n"; $out .= "\tvar \${$className} = null;\n\n"; - $out .= "\tfunction setUp() {\n\t\t\$this->{$className} = new Test{$className}();"; + $out .= "\tfunction startTest() {\n\t\t\$this->{$className} = new Test{$className}();"; $out .= "\n\t\t\$this->{$className}->constructClasses();\n\t}\n\n"; $out .= "\tfunction test{$className}ControllerInstance() {\n"; $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}Controller'));\n\t}\n\n"; - $out .= "\tfunction tearDown() {\n\t\tunset(\$this->{$className});\n\t}\n}\n"; + $out .= "\tfunction endTest() {\n\t\tunset(\$this->{$className});\n\t}\n}\n"; $path = CONTROLLER_TESTS; if (isset($this->plugin)) { diff --git a/cake/console/libs/tasks/db_config.php b/cake/console/libs/tasks/db_config.php index 8fa5f8c23..fcd71052e 100644 --- a/cake/console/libs/tasks/db_config.php +++ b/cake/console/libs/tasks/db_config.php @@ -281,7 +281,7 @@ class DbConfigTask extends Shell { if ($info['persistent'] === false) { $info['persistent'] = 'false'; } else { - $info['persistent'] = 'false'; + $info['persistent'] = ($info['persistent'] == true) ? 'true' : 'false'; } $oldConfigs[] = array( diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 464d5bae5..b4ae6feed 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -832,7 +832,7 @@ class ModelTask extends Shell { */ function fixture($model, $useTable = null) { if (!class_exists('CakeSchema')) { - App::import('Model', 'Schema'); + App::import('Model', 'CakeSchema'); } $out = "\nclass {$model}Fixture extends CakeTestFixture {\n"; $out .= "\tvar \$name = '$model';\n"; diff --git a/cake/console/libs/templates/skel/webroot/index.php b/cake/console/libs/templates/skel/webroot/index.php index 01be9dd64..59484d983 100644 --- a/cake/console/libs/templates/skel/webroot/index.php +++ b/cake/console/libs/templates/skel/webroot/index.php @@ -85,7 +85,7 @@ return; } else { $Dispatcher = new Dispatcher(); - $Dispatcher->dispatch($url); + $Dispatcher->dispatch(); } if (Configure::read() > 0) { echo ""; diff --git a/cake/console/libs/templates/views/form.ctp b/cake/console/libs/templates/views/form.ctp index 961d653a3..78ebdda7b 100644 --- a/cake/console/libs/templates/views/form.ctp +++ b/cake/console/libs/templates/views/form.ctp @@ -50,16 +50,16 @@
    -
  • link(__('Delete', true), array('action'=>'delete', \$form->value('{$modelClass}.{$primaryKey}')), null, sprintf(__('Are you sure you want to delete # %s?', true), \$form->value('{$modelClass}.{$primaryKey}'))); ?>";?>
  • +
  • link(__('Delete', true), array('action' => 'delete', \$form->value('{$modelClass}.{$primaryKey}')), null, sprintf(__('Are you sure you want to delete # %s?', true), \$form->value('{$modelClass}.{$primaryKey}'))); ?>";?>
  • -
  • link(__('List {$pluralHumanName}', true), array('action'=>'index'));?>";?>
  • +
  • link(__('List {$pluralHumanName}', true), array('action' => 'index'));?>";?>
  • $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { - echo "\t\t
  • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller'=> '{$details['controller']}', 'action'=>'index')); ?>
  • \n"; - echo "\t\t
  • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller'=> '{$details['controller']}', 'action'=>'add')); ?>
  • \n"; + echo "\t\t
  • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
  • \n"; + echo "\t\t
  • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
  • \n"; $done[] = $details['controller']; } } diff --git a/cake/console/libs/templates/views/index.ctp b/cake/console/libs/templates/views/index.ctp index ea864c17d..af2c5acb5 100644 --- a/cake/console/libs/templates/views/index.ctp +++ b/cake/console/libs/templates/views/index.ctp @@ -54,7 +54,7 @@ foreach (\${$pluralVar} as \${$singularVar}): foreach ($associations['belongsTo'] as $alias => $details) { if ($field === $details['foreignKey']) { $isKey = true; - echo "\t\t\n\t\t\tlink(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller'=> '{$details['controller']}', 'action'=>'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\n"; + echo "\t\t\n\t\t\tlink(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\n"; break; } } @@ -65,9 +65,9 @@ foreach (\${$pluralVar} as \${$singularVar}): } echo "\t\t\n"; - echo "\t\t\tlink(__('View', true), array('action'=>'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; - echo "\t\t\tlink(__('Edit', true), array('action'=>'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; - echo "\t\t\tlink(__('Delete', true), array('action'=>'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; + echo "\t\t\tlink(__('View', true), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; + echo "\t\t\tlink(__('Edit', true), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; + echo "\t\t\tlink(__('Delete', true), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; echo "\t\t\n"; echo "\t\n"; @@ -78,18 +78,18 @@ echo "\n";
    prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));?>\n";?> | numbers();?>\n"?> -next(__('next', true).' >>', array(), null, array('class'=>'disabled'));?>\n";?> +next(__('next', true).' >>', array(), null, array('class' => 'disabled'));?>\n";?>
      -
    • link(__('New {$singularHumanName}', true), array('action'=>'add')); ?>";?>
    • +
    • link(__('New {$singularHumanName}', true), array('action' => 'add')); ?>";?>
    • $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { - echo "\t\t
    • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller'=> '{$details['controller']}', 'action'=>'index')); ?>
    • \n"; - echo "\t\t
    • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller'=> '{$details['controller']}', 'action'=>'add')); ?>
    • \n"; + echo "\t\t
    • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
    • \n"; + echo "\t\t
    • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
    • \n"; $done[] = $details['controller']; } } diff --git a/cake/console/libs/templates/views/view.ctp b/cake/console/libs/templates/views/view.ctp index 24de7d1e8..a25b7574c 100644 --- a/cake/console/libs/templates/views/view.ctp +++ b/cake/console/libs/templates/views/view.ctp @@ -33,7 +33,7 @@ foreach ($fields as $field) { if ($field === $details['foreignKey']) { $isKey = true; echo "\t\t>\n"; - echo "\t\t>\n\t\t\tlink(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller'=> '{$details['controller']}', 'action'=>'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\t \n\t\t\n"; + echo "\t\t>\n\t\t\tlink(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\t \n\t\t\n"; break; } } @@ -49,17 +49,17 @@ foreach ($fields as $field) {
        link(__('Edit {$singularHumanName}', true), array('action'=>'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> \n"; - echo "\t\t
      • link(__('Delete {$singularHumanName}', true), array('action'=>'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
      • \n"; - echo "\t\t
      • link(__('List {$pluralHumanName}', true), array('action'=>'index')); ?>
      • \n"; - echo "\t\t
      • link(__('New {$singularHumanName}', true), array('action'=>'add')); ?>
      • \n"; + echo "\t\t
      • link(__('Edit {$singularHumanName}', true), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
      • \n"; + echo "\t\t
      • link(__('Delete {$singularHumanName}', true), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
      • \n"; + echo "\t\t
      • link(__('List {$pluralHumanName}', true), array('action' => 'index')); ?>
      • \n"; + echo "\t\t
      • link(__('New {$singularHumanName}', true), array('action' => 'add')); ?>
      • \n"; $done = array(); foreach ($associations as $type => $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { - echo "\t\t
      • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller'=> '{$details['controller']}', 'action'=>'index')); ?>
      • \n"; - echo "\t\t
      • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller'=> '{$details['controller']}', 'action'=>'add')); ?>
      • \n"; + echo "\t\t
      • link(__('List ".Inflector::humanize($details['controller'])."', true), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
      • \n"; + echo "\t\t
      • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
      • \n"; $done[] = $details['controller']; } } @@ -84,7 +84,7 @@ if (!empty($associations['hasOne'])) : \n";?>
          -
        • link(__('Edit ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller'=> '{$details['controller']}', 'action'=>'edit', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>
        • \n";?> +
        • link(__('Edit ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller' => '{$details['controller']}', 'action' => 'edit', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>
        • \n";?>
      @@ -131,9 +131,9 @@ echo "\t\n"; - echo "\t\t\t\tlink(__('View', true), array('controller'=> '{$details['controller']}', 'action'=>'view', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; - echo "\t\t\t\tlink(__('Edit', true), array('controller'=> '{$details['controller']}', 'action'=>'edit', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; - echo "\t\t\t\tlink(__('Delete', true), array('controller'=> '{$details['controller']}', 'action'=>'delete', \${$otherSingularVar}['{$details['primaryKey']}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; + echo "\t\t\t\tlink(__('View', true), array('controller' => '{$details['controller']}', 'action' => 'view', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; + echo "\t\t\t\tlink(__('Edit', true), array('controller' => '{$details['controller']}', 'action' => 'edit', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; + echo "\t\t\t\tlink(__('Delete', true), array('controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']), null, sprintf(__('Are you sure you want to delete # %s?', true), \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; echo "\t\t\t\n"; echo "\t\t\n"; @@ -143,7 +143,7 @@ echo "\t\n"; \n\n";?>
        -
      • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller'=> '{$details['controller']}', 'action'=>'add'));?>";?>
      • +
      • link(__('New ".Inflector::humanize(Inflector::underscore($alias))."', true), array('controller' => '{$details['controller']}', 'action' => 'add'));?>";?>
    diff --git a/cake/console/libs/testsuite.php b/cake/console/libs/testsuite.php index 72cefbcc2..caf760609 100644 --- a/cake/console/libs/testsuite.php +++ b/cake/console/libs/testsuite.php @@ -93,7 +93,7 @@ class TestSuiteShell extends Shell { require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php'; require_once CAKE . 'tests' . DS . 'lib' . DS . 'cli_reporter.php'; - $plugins = Configure::listObjects('plugin'); + $plugins = App::objects('plugin'); foreach ($plugins as $p) { $this->plugins[] = Inflector::underscore($p); } @@ -156,30 +156,30 @@ class TestSuiteShell extends Shell { function help() { $this->out('Usage: '); $this->out("\tcake testsuite category test_type file"); - $this->out("\t\t - category - \"app\", \"core\" or name of a plugin"); - $this->out("\t\t - test_type - \"case\", \"group\" or \"all\""); - $this->out("\t\t - test_file - file name with folder prefix and without the (test|group).php suffix"); + $this->out("\t\t- category - \"app\", \"core\" or name of a plugin"); + $this->out("\t\t- test_type - \"case\", \"group\" or \"all\""); + $this->out("\t\t- test_file - file name with folder prefix and without the (test|group).php suffix"); $this->out(''); $this->out('Examples: '); - $this->out("\t\t cake testsuite app all"); - $this->out("\t\t cake testsuite core all"); + $this->out("\t\tcake testsuite app all"); + $this->out("\t\tcake testsuite core all"); $this->out(''); - $this->out("\t\t cake testsuite app case behaviors/debuggable"); - $this->out("\t\t cake testsuite app case models/my_model"); - $this->out("\t\t cake testsuite app case controllers/my_controller"); + $this->out("\t\tcake testsuite app case behaviors/debuggable"); + $this->out("\t\tcake testsuite app case models/my_model"); + $this->out("\t\tcake testsuite app case controllers/my_controller"); $this->out(''); - $this->out("\t\t cake testsuite core case file"); - $this->out("\t\t cake testsuite core case router"); - $this->out("\t\t cake testsuite core case set"); + $this->out("\t\tcake testsuite core case file"); + $this->out("\t\tcake testsuite core case router"); + $this->out("\t\tcake testsuite core case set"); $this->out(''); - $this->out("\t\t cake testsuite app group mygroup"); - $this->out("\t\t cake testsuite core group acl"); - $this->out("\t\t cake testsuite core group socket"); + $this->out("\t\tcake testsuite app group mygroup"); + $this->out("\t\tcake testsuite core group acl"); + $this->out("\t\tcake testsuite core group socket"); $this->out(''); - $this->out("\t\t cake testsuite bugs case models/bug // for the plugin 'bugs' and its test case 'bug'"); - $this->out("\t\t cake testsuite bugs group bug // for the plugin bugs and its test group 'bug'"); - $this->out("\t\t cake testsuite bugs_me case models/bug // for the plugin 'bugs_me' and its test case 'bug'"); - $this->out("\t\t cake testsuite bugs_me group bug // for the plugin bugs_me and its test group 'bug'"); + $this->out("\t\tcake testsuite bugs case models/bug"); + $this->out("\t\t // for the plugin 'bugs' and its test case 'models/bug'"); + $this->out("\t\tcake testsuite bugs group bug"); + $this->out("\t\t // for the plugin bugs and its test group 'bug'"); $this->out(''); $this->out('Code Coverage Analysis: '); $this->out("\n\nAppend 'cov' to any of the above in order to enable code coverage analysis"); @@ -312,11 +312,19 @@ class TestSuiteShell extends Shell { ); if (array_key_exists($category, $paths)) { - $folder = $paths[$category]; + $folder = $paths[$category] . 'tests'; } else { - $folder = APP.'plugins'.DS.Inflector::underscore($category).DS; + $scoredCategory = Inflector::underscore($category); + $folder = APP . 'plugins' . DS . $scoredCategory . DS; + $pluginPaths = App::path('plugins'); + foreach ($pluginPaths as $path) { + if (file_exists($path . $scoredCategory . DS . 'tests')) { + $folder = $path . $scoredCategory . DS . 'tests'; + break; + } + } } - return $folder.'tests'; + return $folder; } /** * Sets some get vars needed for TestManager diff --git a/cake/dispatcher.php b/cake/dispatcher.php index de0267563..3752fdcd8 100644 --- a/cake/dispatcher.php +++ b/cake/dispatcher.php @@ -344,7 +344,8 @@ class Dispatcher extends Object { return $this->base = $base; } if (!$baseUrl) { - $base = dirname(env('PHP_SELF')); + $replace = array('<', '>', '*', '\'', '"'); + $base = str_replace($replace, '', dirname(env('PHP_SELF'))); if ($webroot === 'webroot' && $webroot === basename($base)) { $base = dirname($base); @@ -619,13 +620,13 @@ class Dispatcher extends Object { if ($pos > 0) { $plugin = substr($url, 0, $pos - 1); $url = str_replace($plugin . '/', '', $url); - $pluginPaths = Configure::read('pluginPaths'); + $pluginPaths = App::path('plugins'); $count = count($pluginPaths); for ($i = 0; $i < $count; $i++) { $paths[] = $pluginPaths[$i] . $plugin . DS . 'vendors' . DS; } } - $paths = array_merge($paths, Configure::read('vendorPaths')); + $paths = array_merge($paths, App::path('vendors')); foreach ($paths as $path) { if (is_file($path . $url) && file_exists($path . $url)) { diff --git a/cake/libs/cache/file.php b/cake/libs/cache/file.php index 29dde9249..abbd5a0e6 100644 --- a/cake/libs/cache/file.php +++ b/cake/libs/cache/file.php @@ -168,7 +168,6 @@ class FileEngine extends CacheEngine { if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) { $this->__File->close(); - $this->__File->delete(); return false; } $data = $this->__File->read(true); diff --git a/cake/libs/session.php b/cake/libs/cake_session.php similarity index 86% rename from cake/libs/session.php rename to cake/libs/cake_session.php index 88b90da52..f9b990e21 100644 --- a/cake/libs/session.php +++ b/cake/libs/cake_session.php @@ -27,16 +27,7 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -/** - * Database name for cake sessions. - * - */ -if (!class_exists('Set')) { - require LIBS . 'set.php'; -} -if (!class_exists('Security')) { - require LIBS . 'security.php'; -} + /** * Session class for Cake. * @@ -125,34 +116,52 @@ class CakeSession extends Object { * @access public */ function __construct($base = null, $start = true) { - if (Configure::read('Session.save') === 'database' && !class_exists('ConnectionManager')) { - App::import('Core', 'ConnectionManager'); - } + App::import('Core', 'Security'); + $this->time = time(); if (Configure::read('Session.checkAgent') === true || Configure::read('Session.checkAgent') === null) { if (env('HTTP_USER_AGENT') != null) { $this->_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt')); } } - $this->time = time(); + if (Configure::read('Session.save') === 'database') { + $modelName = Configure::read('Session.model'); + $database = Configure::read('Session.database'); + $table = Configure::read('Session.table'); - if ($start === true) { - $this->host = env('HTTP_HOST'); - - if (empty($base) || strpos($base, '?') === 0 || strpos($base, 'index.php') === 0) { - $this->path = '/'; - } else { - $this->path = $base; + if (empty($database)) { + $database = 'default'; } + if (empty($modelName)) { + ClassRegistry::init(array( + 'class' => Inflector::classify($table), + 'alias' => 'Session' + )); + } else { + ClassRegistry::init(array( + 'class' => $modelName, + 'alias' => 'Session' + )); + } + } + if ($start === true) { + if (!empty($base)) { + $this->path = $base; + if (strpos($base, 'index.php') !== false) { + $this->path = str_replace('index.php', '', $base); + } + if (strpos($base, '?') !== false) { + $this->path = str_replace('?', '', $base); + } + } + $this->host = env('HTTP_HOST'); if (strpos($this->host, ':') !== false) { $this->host = substr($this->host, 0, strpos($this->host, ':')); } - if (!class_exists('Security')) { App::import('Core', 'Security'); } - $this->sessionTime = $this->time + (Security::inactiveMins() * Configure::read('Session.timeout')); $this->security = Configure::read('Security.level'); } @@ -510,7 +519,7 @@ class CakeSession extends Object { array('Cache', 'read'), array('Cache', 'write'), array('Cache', 'delete'), - array('CakeSession', '__gc')); + array('Cache', 'gc')); break; default: if (empty($_SESSION)) { @@ -685,81 +694,64 @@ class CakeSession extends Object { /** * Method used to read from a database session. * - * @param mixed $key The key of the value to read + * @param mixed $id The key of the value to read * @return mixed The value of the key or false if it does not exist * @access private */ - function __read($key) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table'), false); - $row = $db->query("SELECT " . $db->name($table.'.data') . " FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key), false); + function __read($id) { + $model =& ClassRegistry::getObject('Session'); - if ($row && !isset($row[0][$table]) && isset($row[0][0])) { - $table = 0; - } + $row = $model->find('first', array( + 'conditions' => array($model->primaryKey => $id) + )); - if ($row && $row[0][$table]['data']) { - return $row[0][$table]['data']; - } else { + if (empty($row[$model->alias]['data'])) { return false; } + + return $row[$model->alias]['data']; } /** * Helper function called on write for database sessions. * - * @param mixed $key The name of the var - * @param mixed $value The value of the var - * @return boolean Success + * @param integer $id ID that uniquely identifies session in database + * @param mixed $data The value of the the data to be saved. + * @return boolean True for successful write, false otherwise. * @access private */ - function __write($key, $value) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - + function __write($id, $data) { switch (Configure::read('Security.level')) { - case 'high': - $factor = 10; - break; case 'medium': $factor = 100; break; case 'low': $factor = 300; break; + case 'high': default: $factor = 10; break; } - $expires = time() + Configure::read('Session.timeout') * $factor; - $row = $db->query("SELECT COUNT(id) AS count FROM " . $db->name($table) . " WHERE " - . $db->name('id') . " = " - . $db->value($key), false); - if ($row[0][0]['count'] > 0) { - $db->execute("UPDATE " . $db->name($table) . " SET " . $db->name('data') . " = " - . $db->value($value) . ", " . $db->name('expires') . " = " - . $db->value($expires) . " WHERE " . $db->name('id') . " = " - . $db->value($key)); - } else { - $db->execute("INSERT INTO " . $db->name($table) . " (" . $db->name('data') . "," - . $db->name('expires') . "," . $db->name('id') - . ") VALUES (" . $db->value($value) . ", " . $db->value($expires) . ", " - . $db->value($key) . ")"); - } - return true; + $expires = time() + Configure::read('Session.timeout') * $factor; + + $model =& ClassRegistry::getObject('Session'); + $return = $model->save(compact('id', 'data', 'expires')); + + return $return; } /** * Method called on the destruction of a database session. * - * @param integer $key Key that uniquely identifies session in database - * @return boolean Success + * @param integer $id ID that uniquely identifies session in database + * @return boolean True for successful delete, false otherwise. * @access private */ - function __destroy($key) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.id') . " = " . $db->value($key)); - return true; + function __destroy($id) { + $model =& ClassRegistry::getObject('Session'); + $return = $model->delete($id); + + return $return; } /** * Helper function called on gc for database sessions. @@ -769,10 +761,14 @@ class CakeSession extends Object { * @access private */ function __gc($expires = null) { - $db =& ConnectionManager::getDataSource(Configure::read('Session.database')); - $table = $db->fullTableName(Configure::read('Session.table')); - $db->execute("DELETE FROM " . $db->name($table) . " WHERE " . $db->name($table.'.expires') . " < ". $db->value(time())); - return true; + $model =& ClassRegistry::getObject('Session'); + + if (!$expires) { + $expires = time(); + } + + $return = $model->deleteAll(array($model->alias . ".expires <" => $expires), false, false); + return $return; } } ?> \ No newline at end of file diff --git a/cake/libs/socket.php b/cake/libs/cake_socket.php similarity index 100% rename from cake/libs/socket.php rename to cake/libs/cake_socket.php diff --git a/cake/libs/configure.php b/cake/libs/configure.php index 753549478..f73499d22 100644 --- a/cake/libs/configure.php +++ b/cake/libs/configure.php @@ -32,76 +32,6 @@ * @link http://book.cakephp.org/view/42/The-Configuration-Class */ class Configure extends Object { -/** - * List of additional path(s) where model files reside. - * - * @var array - * @access public - */ - var $modelPaths = array(); -/** - * List of additional path(s) where behavior files reside. - * - * @var array - * @access public - */ - var $behaviorPaths = array(); -/** - * List of additional path(s) where controller files reside. - * - * @var array - * @access public - */ - var $controllerPaths = array(); -/** - * List of additional path(s) where component files reside. - * - * @var array - * @access public - */ - var $componentPaths = array(); -/** - * List of additional path(s) where view files reside. - * - * @var array - * @access public - */ - var $viewPaths = array(); -/** - * List of additional path(s) where helper files reside. - * - * @var array - * @access public - */ - var $helperPaths = array(); -/** - * List of additional path(s) where plugins reside. - * - * @var array - * @access public - */ - var $pluginPaths = array(); -/** - * List of additional path(s) where vendor packages reside. - * - * @var array - * @access public - */ - var $vendorPaths = array(); -/** - * List of additional path(s) where locale files reside. - * - * @var array - * @access public - */ - var $localePaths = array(); -/** - * List of additional path(s) where console shell files reside. - * - * @var array - * @access public - */ - var $shellPaths = array(); /** * Current debug level. * @@ -117,13 +47,6 @@ class Configure extends Object { * @access private */ var $__cache = false; -/** - * Holds and key => value array of objects' types. - * - * @var array - * @access private - */ - var $__objects = array(); /** * Returns a singleton instance of the Configure class. * @@ -138,111 +61,6 @@ class Configure extends Object { } return $instance[0]; } -/** - * Returns an index of objects of the given type, with the physical path to each object. - * - * @param string $type Type of object, i.e. 'model', 'controller', 'helper', or 'plugin' - * @param mixed $path Optional - * @return Configure instance - * @access public - */ - function listObjects($type, $path = null, $cache = true) { - $objects = array(); - $extension = false; - $name = $type; - - if ($type === 'file' && !$path) { - return false; - } elseif ($type === 'file') { - $extension = true; - $name = $type . str_replace(DS, '', $path); - } - $_this =& Configure::getInstance(); - - if (empty($_this->__objects) && $cache === true) { - $_this->__objects = Cache::read('object_map', '_cake_core_'); - } - - if (empty($_this->__objects) || !isset($_this->__objects[$type]) || $cache !== true) { - $types = array( - 'model' => array('suffix' => '.php', 'base' => 'AppModel', 'core' => false), - 'behavior' => array('suffix' => '.php', 'base' => 'ModelBehavior'), - 'controller' => array('suffix' => '_controller.php', 'base' => 'AppController'), - 'component' => array('suffix' => '.php', 'base' => null), - 'view' => array('suffix' => '.php', 'base' => null), - 'helper' => array('suffix' => '.php', 'base' => 'AppHelper'), - 'plugin' => array('suffix' => '', 'base' => null), - 'vendor' => array('suffix' => '', 'base' => null), - 'class' => array('suffix' => '.php', 'base' => null), - 'file' => array('suffix' => '.php', 'base' => null) - ); - - if (!isset($types[$type])) { - return false; - } - $objects = array(); - - if (empty($path)) { - $path = $_this->{$type . 'Paths'}; - if (isset($types[$type]['core']) && $types[$type]['core'] === false) { - array_pop($path); - } - } - $items = array(); - - foreach ((array)$path as $dir) { - if ($type === 'file' || $type === 'class' || strpos($dir, $type) !== false) { - $items = $_this->__list($dir, $types[$type]['suffix'], $extension); - $objects = array_merge($items, array_diff($objects, $items)); - } - } - - if ($type !== 'file') { - foreach ($objects as $key => $value) { - $objects[$key] = Inflector::camelize($value); - } - } - if ($cache === true && !empty($objects)) { - $_this->__objects[$name] = $objects; - $_this->__cache = true; - } else { - return $objects; - } - } - return $_this->__objects[$name]; - } -/** - * Returns an array of filenames of PHP files in the given directory. - * - * @param string $path Path to scan for files - * @param string $suffix if false, return only directories. if string, match and return files - * @return array List of directories or files in directory - */ - function __list($path, $suffix = false, $extension = false) { - if (!class_exists('Folder')) { - require LIBS . 'folder.php'; - } - $items = array(); - $Folder =& new Folder($path); - $contents = $Folder->read(false, true); - - if (is_array($contents)) { - if (!$suffix) { - return $contents[0]; - } else { - foreach ($contents[1] as $item) { - if (substr($item, - strlen($suffix)) === $suffix) { - if ($extension) { - $items[] = $item; - } else { - $items[] = substr($item, 0, strlen($item) - strlen($suffix)); - } - } - } - } - } - return $items; - } /** * Used to store a dynamic variable in the Configure instance. * @@ -254,7 +72,7 @@ class Configure extends Object { * 'key1' => 'value of the Configure::One[key1]', * 'key2' => 'value of the Configure::One[key2]' * ); - * + * * Configure::write(array( * 'One.key1' => 'value of the Configure::One[key1]', * 'One.key2' => 'value of the Configure::One[key2]' @@ -403,7 +221,7 @@ class Configure extends Object { include(CACHE . 'persistent' . DS . $fileName . '.php'); $found = true; } else { - foreach (Configure::corePaths('cake') as $key => $path) { + foreach (App::core('cake') as $key => $path) { if (file_exists($path . DS . 'config' . DS . $fileName . '.php')) { include($path . DS . 'config' . DS . $fileName . '.php'); $found = true; @@ -479,57 +297,6 @@ class Configure extends Object { } Configure::__writeConfig($content, $name, $write); } -/** - * Returns a key/value list of all paths where core libs are found. - * Passing $type only returns the values for a given value of $key. - * - * @param string $type valid values are: 'model', 'behavior', 'controller', 'component', - * 'view', 'helper', 'datasource', 'libs', and 'cake' - * @return array numeric keyed array of core lib paths - * @access public - */ - function corePaths($type = null) { - $paths = Cache::read('core_paths', '_cake_core_'); - if (!$paths) { - $paths = array(); - $openBasedir = ini_get('open_basedir'); - if ($openBasedir) { - $all = explode(PATH_SEPARATOR, $openBasedir); - $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all)))); - } else { - $all = explode(PATH_SEPARATOR, ini_get('include_path')); - $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all)))); - } - foreach ($all as $path) { - if ($path !== DS) { - $path = rtrim($path, DS); - } - if (empty($path) || $path === '.') { - continue; - } - $cake = $path . DS . 'cake' . DS; - $libs = $cake . 'libs' . DS; - if (is_dir($libs)) { - $paths['libs'][] = $libs; - $paths['model'][] = $libs . 'model' . DS; - $paths['behavior'][] = $libs . 'model' . DS . 'behaviors' . DS; - $paths['controller'][] = $libs . 'controller' . DS; - $paths['component'][] = $libs . 'controller' . DS . 'components' . DS; - $paths['view'][] = $libs . 'view' . DS; - $paths['helper'][] = $libs . 'view' . DS . 'helpers' . DS; - $paths['cake'][] = $cake; - $paths['vendor'][] = $path . DS . 'vendors' . DS; - $paths['shell'][] = $cake . 'console' . DS . 'libs' . DS; - break; - } - } - Cache::write('core_paths', array_filter($paths), '_cake_core_'); - } - if ($type && isset($paths[$type])) { - return $paths[$type]; - } - return $paths; - } /** * Creates a cached version of a configuration file. * Appends values passed from Configure::store() to the cached file @@ -582,56 +349,25 @@ class Configure extends Object { return $name; } /** - * Build path references. Merges the supplied $paths - * with the base paths and the default core paths. - * - * @param array $paths paths defines in config/bootstrap.php - * @return void - * @access public + * @deprecated + * @see App::objects() + */ + function listObjects($type, $path = null, $cache = true) { + return App::objects($type, $path, $cache); + } +/** + * @deprecated + * @see App::core() + */ + function corePaths($type = null) { + return App::core($type); + } +/** + * @deprecated + * @see App::build() */ function buildPaths($paths) { - $_this =& Configure::getInstance(); - $core = $_this->corePaths(); - $basePaths = array( - 'model' => array(MODELS), - 'behavior' => array(BEHAVIORS), - 'controller' => array(CONTROLLERS), - 'component' => array(COMPONENTS), - 'view' => array(VIEWS), - 'helper' => array(HELPERS), - 'plugin' => array(APP . 'plugins' . DS), - 'vendor' => array(APP . 'vendors' . DS, VENDORS), - 'locale' => array(APP . 'locale' . DS), - 'shell' => array(), - 'datasource' => array(MODELS . 'datasources') - ); - - foreach ($basePaths as $type => $default) { - $pathsVar = $type . 'Paths'; - $merge = array(); - - if (isset($core[$type])) { - $merge = $core[$type]; - } - if ($type === 'model' || $type === 'controller' || $type === 'helper') { - $merge = array_merge(array(APP), $merge); - } - - if (!is_array($default)) { - $default = array($default); - } - $_this->{$pathsVar} = $default; - - if (isset($paths[$pathsVar]) && !empty($paths[$pathsVar])) { - $path = array_flip(array_flip((array_merge( - $_this->{$pathsVar}, (array)$paths[$pathsVar], $merge - )))); - $_this->{$pathsVar} = array_values($path); - } else { - $path = array_flip(array_flip((array_merge($_this->{$pathsVar}, $merge)))); - $_this->{$pathsVar} = array_values($path); - } - } + return App::build($paths); } /** * Loads app/config/bootstrap.php. @@ -692,9 +428,9 @@ class Configure extends Object { } Cache::config('default'); } - Configure::buildPaths(compact( - 'modelPaths', 'viewPaths', 'controllerPaths', 'helperPaths', 'componentPaths', - 'behaviorPaths', 'pluginPaths', 'vendorPaths', 'localePaths', 'shellPaths' + App::build(compact( + 'models', 'views', 'controllers', 'helpers', 'components', + 'behaviors', 'plugins', 'vendors', 'locales', 'shells' )); } } @@ -718,6 +454,96 @@ class Configure extends Object { * @subpackage cake.cake.libs */ class App extends Object { +/** + * List of object types and their properties + * + * @var array + * @access public + */ + var $types = array( + 'class' => array('suffix' => '.php', 'extends' => null, 'core' => true), + 'file' => array('suffix' => '.php', 'extends' => null, 'core' => true), + 'model' => array('suffix' => '.php', 'extends' => 'AppModel', 'core' => false), + 'behavior' => array('suffix' => '.php', 'extends' => 'ModelBehavior', 'core' => true), + 'controller' => array('suffix' => '_controller.php', 'extends' => 'AppController', 'core' => true), + 'component' => array('suffix' => '.php', 'extends' => null, 'core' => true), + 'view' => array('suffix' => '.php', 'extends' => null, 'core' => true), + 'helper' => array('suffix' => '.php', 'extends' => 'AppHelper', 'core' => true), + 'vendor' => array('suffix' => '', 'extends' => null, 'core' => true), + 'shell' => array('suffix' => '.php', 'extends' => 'Shell', 'core' => true), + 'plugin' => array('suffix' => '', 'extends' => null, 'core' => true) + ); + +/** + * List of additional path(s) where model files reside. + * + * @var array + * @access public + */ + var $models = array(); +/** + * List of additional path(s) where behavior files reside. + * + * @var array + * @access public + */ + var $behaviors = array(); +/** + * List of additional path(s) where controller files reside. + * + * @var array + * @access public + */ + var $controllers = array(); +/** + * List of additional path(s) where component files reside. + * + * @var array + * @access public + */ + var $components = array(); +/** + * List of additional path(s) where view files reside. + * + * @var array + * @access public + */ + var $views = array(); +/** + * List of additional path(s) where helper files reside. + * + * @var array + * @access public + */ + var $helpers = array(); +/** + * List of additional path(s) where plugins reside. + * + * @var array + * @access public + */ + var $plugins = array(); +/** + * List of additional path(s) where vendor packages reside. + * + * @var array + * @access public + */ + var $vendors = array(); +/** + * List of additional path(s) where locale files reside. + * + * @var array + * @access public + */ + var $locales = array(); +/** + * List of additional path(s) where console shell files reside. + * + * @var array + * @access public + */ + var $shells = array(); /** * Paths to search for files. * @@ -760,6 +586,201 @@ class App extends Object { * @access private */ var $__loaded = array(); +/** + * Holds and key => value array of object types. + * + * @var array + * @access private + */ + var $__objects = array(); +/** + * Used to read information stored path + * + * Usage + * App::path('models'); will return all paths for models + * + * @param string $type type of path + * @return string array + * @access public + */ + function path($type) { + $_this =& App::getInstance(); + if (!isset($_this->{$type})) { + return array(); + } + return $_this->{$type}; + } +/** + * Build path references. Merges the supplied $paths + * with the base paths and the default core paths. + * + * @param array $paths paths defines in config/bootstrap.php + * @param boolean $reset true will set paths, false merges paths [default] false + * @return void + * @access public + */ + function build($paths = array(), $reset = false) { + $_this =& App::getInstance(); + $defaults = array( + 'models' => array(MODELS), + 'behaviors' => array(BEHAVIORS), + 'datasources' => array(MODELS . 'datasources'), + 'controllers' => array(CONTROLLERS), + 'components' => array(COMPONENTS), + 'views' => array(VIEWS), + 'helpers' => array(HELPERS), + 'locales' => array(APP . 'locale' . DS), + 'shells' => array(APP . 'vendors' . DS . 'shells', VENDORS . 'shells'), + 'vendors' => array(APP . 'vendors' . DS, VENDORS), + 'plugins' => array(APP . 'plugins' . DS), + ); + + if ($reset == true) { + foreach ($paths as $type => $new) { + $_this->{$type} = (array)$new; + } + return $paths; + } + + $core = $_this->core(); + $app = array('models' => true, 'controllers' => true, 'helpers' => true); + + foreach ($defaults as $type => $default) { + $merge = array(); + + if (isset($app[$type])) { + $merge = array(APP); + } + if (isset($core[$type])) { + $merge = array_merge($merge, (array)$core[$type]); + } + + $_this->{$type} = $default; + + if (!empty($paths[$type])) { + $path = array_flip(array_flip((array_merge( + $_this->{$type}, (array)$paths[$type], $merge + )))); + $_this->{$type} = array_values($path); + } else { + $path = array_flip(array_flip((array_merge($_this->{$type}, $merge)))); + $_this->{$type} = array_values($path); + } + } + } +/** + * Returns a key/value list of all paths where core libs are found. + * Passing $type only returns the values for a given value of $key. + * + * @param string $type valid values are: 'model', 'behavior', 'controller', 'component', + * 'view', 'helper', 'datasource', 'libs', and 'cake' + * @return array numeric keyed array of core lib paths + * @access public + */ + function core($type = null) { + $paths = Cache::read('core_paths', '_cake_core_'); + if (!$paths) { + $paths = array(); + $openBasedir = ini_get('open_basedir'); + if ($openBasedir) { + $all = explode(PATH_SEPARATOR, $openBasedir); + $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all)))); + } else { + $all = explode(PATH_SEPARATOR, ini_get('include_path')); + $all = array_flip(array_flip((array_merge(array(CAKE_CORE_INCLUDE_PATH), $all)))); + } + foreach ($all as $path) { + if ($path !== DS) { + $path = rtrim($path, DS); + } + if (empty($path) || $path === '.') { + continue; + } + $cake = $path . DS . 'cake' . DS; + $libs = $cake . 'libs' . DS; + if (is_dir($libs)) { + $paths['cake'][] = $cake; + $paths['libs'][] = $libs; + $paths['models'][] = $libs . 'model' . DS; + $paths['behaviors'][] = $libs . 'model' . DS . 'behaviors' . DS; + $paths['controllers'][] = $libs . 'controller' . DS; + $paths['components'][] = $libs . 'controller' . DS . 'components' . DS; + $paths['views'][] = $libs . 'view' . DS; + $paths['helpers'][] = $libs . 'view' . DS . 'helpers' . DS; + $paths['vendors'][] = $path . DS . 'vendors' . DS; + $paths['shells'][] = $cake . 'console' . DS . 'libs' . DS; + break; + } + } + Cache::write('core_paths', array_filter($paths), '_cake_core_'); + } + if ($type && isset($paths[$type])) { + return $paths[$type]; + } + return $paths; + } +/** + * Returns an index of objects of the given type, with the physical path to each object. + * + * @param string $type Type of object, i.e. 'model', 'controller', 'helper', or 'plugin' + * @param mixed $path Optional + * @return Configure instance + * @access public + */ + function objects($type, $path = null, $cache = true) { + $objects = array(); + $extension = false; + $name = $type; + + if ($type === 'file' && !$path) { + return false; + } elseif ($type === 'file') { + $extension = true; + $name = $type . str_replace(DS, '', $path); + } + $_this =& App::getInstance(); + + if (empty($_this->__objects) && $cache === true) { + $_this->__objects = Cache::read('object_map', '_cake_core_'); + } + + if (empty($_this->__objects) || !isset($_this->__objects[$type]) || $cache !== true) { + $types = $_this->types; + + if (!isset($types[$type])) { + return false; + } + $objects = array(); + + if (empty($path)) { + $path = $_this->{"{$type}s"}; + if (isset($types[$type]['core']) && $types[$type]['core'] === false) { + array_pop($path); + } + } + $items = array(); + + foreach ((array)$path as $dir) { + if ($type === 'file' || $type === 'class' || strpos($dir, $type) !== false) { + $items = $_this->__list($dir, $types[$type]['suffix'], $extension); + $objects = array_merge($items, array_diff($objects, $items)); + } + } + + if ($type !== 'file') { + foreach ($objects as $key => $value) { + $objects[$key] = Inflector::camelize($value); + } + } + if ($cache === true && !empty($objects)) { + $_this->__objects[$name] = $objects; + $_this->__cache = true; + } else { + return $objects; + } + } + return $_this->__objects[$name]; + } /** * Finds classes based on $name or specific file(s) to search. * @@ -779,6 +800,7 @@ class App extends Object { * @access public */ function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { + $_this =& App::getInstance(); $plugin = $directory = null; if (is_array($type)) { @@ -827,12 +849,13 @@ class App extends Object { if ($name != null && strpos($name, '.') !== false) { list($plugin, $name) = explode('.', $name); + $plugin = Inflector::camelize($plugin); } - $_this =& App::getInstance(); + $_this->return = $return; if (isset($ext)) { - $file = Inflector::underscore($name) . ".$ext"; + $file = Inflector::underscore($name) . ".{$ext}"; } $ext = $_this->__settings($type, $plugin, $parent); @@ -868,7 +891,6 @@ class App extends Object { foreach ($paths as $key => $value) { $_this->search[$key] = $value . $ext['path']; } - $plugin = Inflector::camelize($plugin); } } @@ -904,7 +926,7 @@ class App extends Object { static $instance = array(); if (!$instance) { $instance[0] =& new App(); - $instance[0]->__map = Cache::read('file_map', '_cake_core_'); + $instance[0]->__map = (array)Cache::read('file_map', '_cake_core_'); } return $instance[0]; } @@ -985,12 +1007,11 @@ class App extends Object { * @param string $file full path to file * @param string $name unique name for this map * @param string $type type object being mapped - * @param string $plugin if object is from a plugin, the name of the plugin + * @param string $plugin camelized if object is from a plugin, the name of the plugin * @access private */ function __map($file, $name, $type, $plugin) { if ($plugin) { - $plugin = Inflector::camelize($plugin); $this->__map['Plugin'][$plugin][$type][$name] = $file; } else { $this->__map[$type][$name] = $file; @@ -1001,14 +1022,12 @@ class App extends Object { * * @param string $name unique name * @param string $type type object - * @param string $plugin if object is from a plugin, the name of the plugin + * @param string $plugin camelized if object is from a plugin, the name of the plugin * @return mixed, file path if found, false otherwise * @access private */ function __mapped($name, $type, $plugin) { if ($plugin) { - $plugin = Inflector::camelize($plugin); - if (isset($this->__map['Plugin'][$plugin][$type]) && isset($this->__map['Plugin'][$plugin][$type][$name])) { return $this->__map['Plugin'][$plugin][$type][$name]; } @@ -1037,7 +1056,7 @@ class App extends Object { * Returns a prefix or suffix needed for loading files. * * @param string $type type of object - * @param string $plugin name of plugin + * @param string $plugin camelized name of plugin * @param boolean $parent false will not attempt to load parent * @return array * @access private @@ -1048,8 +1067,7 @@ class App extends Object { } if ($plugin) { - $plugin = Inflector::underscore($plugin); - $name = Inflector::camelize($plugin); + $pluginPath = Inflector::underscore($plugin); } $path = null; $load = strtolower($type); @@ -1057,42 +1075,42 @@ class App extends Object { switch ($load) { case 'model': if (!class_exists('Model')) { - App::import('Core', 'Model', false, Configure::corePaths('model')); + App::import('Core', 'Model', false, App::core('models')); } if (!class_exists('AppModel')) { - App::import($type, 'AppModel', false, Configure::read('modelPaths')); + App::import($type, 'AppModel', false, App::path('models')); } if ($plugin) { - if (!class_exists($name . 'AppModel')) { - App::import($type, $plugin . '.' . $name . 'AppModel', false, array(), $plugin . DS . $plugin . '_app_model.php'); + if (!class_exists($plugin . 'AppModel')) { + App::import($type, $plugin . '.' . $plugin . 'AppModel', false, array(), $pluginPath . DS . $pluginPath . '_app_model.php'); } - $path = $plugin . DS . 'models' . DS; + $path = $pluginPath . DS . 'models' . DS; } return array('class' => null, 'suffix' => null, 'path' => $path); break; case 'behavior': if ($plugin) { - $path = $plugin . DS . 'models' . DS . 'behaviors' . DS; + $path = $pluginPath . DS . 'models' . DS . 'behaviors' . DS; } return array('class' => $type, 'suffix' => null, 'path' => $path); break; case 'controller': App::import($type, 'AppController', false); if ($plugin) { - App::import($type, $plugin . '.' . $name . 'AppController', false, array(), $plugin . DS . $plugin . '_app_controller.php'); - $path = $plugin . DS . 'controllers' . DS; + App::import($type, $plugin . '.' . $plugin . 'AppController', false, array(), $pluginPath . DS . $pluginPath . '_app_controller.php'); + $path = $pluginPath . DS . 'controllers' . DS; } return array('class' => $type, 'suffix' => $type, 'path' => $path); break; case 'component': if ($plugin) { - $path = $plugin . DS . 'controllers' . DS . 'components' . DS; + $path = $pluginPath . DS . 'controllers' . DS . 'components' . DS; } return array('class' => $type, 'suffix' => null, 'path' => $path); break; case 'view': if ($plugin) { - $path = $plugin . DS . 'views' . DS; + $path = $pluginPath . DS . 'views' . DS; } return array('class' => $type, 'suffix' => null, 'path' => $path); break; @@ -1101,13 +1119,13 @@ class App extends Object { App::import($type, 'AppHelper', false); } if ($plugin) { - $path = $plugin . DS . 'views' . DS . 'helpers' . DS; + $path = $pluginPath . DS . 'views' . DS . 'helpers' . DS; } return array('class' => $type, 'suffix' => null, 'path' => $path); break; case 'vendor': if ($plugin) { - $path = $plugin . DS . 'vendors' . DS; + $path = $pluginPath . DS . 'vendors' . DS; } return array('class' => null, 'suffix' => null, 'path' => $path); break; @@ -1128,7 +1146,7 @@ class App extends Object { $type = strtolower($type); if ($type === 'core') { - $path = Configure::corePaths(); + $path = App::core(); $paths = array(); foreach ($path as $key => $value) { @@ -1139,8 +1157,7 @@ class App extends Object { } return $paths; } - - if ($paths = Configure::read($type . 'Paths')) { + if ($paths = App::path($type .'s')) { return $paths; } @@ -1162,18 +1179,49 @@ class App extends Object { * * @param string $name name of object * @param string $type type of object - * @param string $plugin name of plugin + * @param string $plugin camelized name of plugin * @return void * @access private */ function __remove($name, $type, $plugin) { if ($plugin) { - $plugin = Inflector::camelize($plugin); unset($this->__map['Plugin'][$plugin][$type][$name]); } else { unset($this->__map[$type][$name]); } } +/** + * Returns an array of filenames of PHP files in the given directory. + * + * @param string $path Path to scan for files + * @param string $suffix if false, return only directories. if string, match and return files + * @return array List of directories or files in directory + */ + function __list($path, $suffix = false, $extension = false) { + if (!class_exists('Folder')) { + require LIBS . 'folder.php'; + } + $items = array(); + $Folder =& new Folder($path); + $contents = $Folder->read(false, true); + + if (is_array($contents)) { + if (!$suffix) { + return $contents[0]; + } else { + foreach ($contents[1] as $item) { + if (substr($item, - strlen($suffix)) === $suffix) { + if ($extension) { + $items[] = $item; + } else { + $items[] = substr($item, 0, strlen($item) - strlen($suffix)); + } + } + } + } + } + return $items; + } /** * Object destructor. * @@ -1184,7 +1232,7 @@ class App extends Object { */ function __destruct() { if ($this->__cache) { - $core = Configure::corePaths('cake'); + $core = App::core('cake'); unset($this->__paths[rtrim($core[0], DS)]); Cache::write('dir_map', array_filter($this->__paths), '_cake_core_'); Cache::write('file_map', array_filter($this->__map), '_cake_core_'); diff --git a/cake/libs/controller/components/auth.php b/cake/libs/controller/components/auth.php index d2f2bede9..a68e5b6f2 100644 --- a/cake/libs/controller/components/auth.php +++ b/cake/libs/controller/components/auth.php @@ -263,6 +263,9 @@ class AuthComponent extends Object { */ function startup(&$controller) { $methods = array_flip($controller->methods); + $action = strtolower($controller->params['action']); + $allowedActions = array_map('strtolower', $this->allowedActions); + $isErrorOrTests = ( strtolower($controller->name) == 'cakeerror' || (strtolower($controller->name) == 'tests' && Configure::read() > 0) @@ -273,7 +276,7 @@ class AuthComponent extends Object { $isMissingAction = ( $controller->scaffold === false && - !isset($methods[strtolower($controller->params['action'])]) + !isset($methods[$action]) ); if ($isMissingAction) { @@ -295,7 +298,7 @@ class AuthComponent extends Object { $isAllowed = ( $this->allowedActions == array('*') || - in_array($controller->params['action'], $this->allowedActions) + in_array($action, $allowedActions) ); if ($loginAction != $url && $isAllowed) { @@ -337,6 +340,11 @@ class AuthComponent extends Object { if (!$this->user()) { if (!$this->RequestHandler->isAjax()) { $this->Session->setFlash($this->authError, 'default', array(), 'auth'); + if (!empty($controller->params['url']) && count($controller->params['url']) >= 2) { + $query = $controller->params['url']; + unset($query['url'], $query['ext']); + $url .= Router::queryString($query, array()); + } $this->Session->write('Auth.redirect', $url); $controller->redirect($loginAction); return false; diff --git a/cake/libs/controller/components/email.php b/cake/libs/controller/components/email.php index c8a368b3d..352471959 100644 --- a/cake/libs/controller/components/email.php +++ b/cake/libs/controller/components/email.php @@ -345,6 +345,7 @@ class EmailComponent extends Object{ $this->bcc = array(); $this->subject = null; $this->additionalParams = null; + $this->smtpError = null; $this->__header = array(); $this->__boundary = null; $this->__message = array(); @@ -631,7 +632,9 @@ class EmailComponent extends Object{ * @access private */ function __strip($value, $message = false) { - $search = '%0a|%0d|Content-(?:Type|Transfer-Encoding)\:|charset\=|mime-version\:|multipart/mixed|(?:to|b?cc)\:.*'; + $search = '%0a|%0d|Content-(?:Type|Transfer-Encoding)\:'; + $search .= '|charset\=|mime-version\:|multipart/mixed|(?:[^a-z]to|b?cc)\:.*'; + if ($message !== true) { $search .= '|\r|\n'; } @@ -662,7 +665,7 @@ class EmailComponent extends Object{ * @access private */ function __smtp() { - App::import('Core', array('Socket')); + App::import('Core', array('CakeSocket')); $this->__smtpConnection =& new CakeSocket(array_merge(array('protocol'=>'smtp'), $this->smtpOptions)); @@ -673,7 +676,13 @@ class EmailComponent extends Object{ return false; } - if (!$this->__smtpSend('HELO cake', '250')) { + if (isset($this->smtpOptions['client'])) { + $host = $this->smtpOptions['client']; + } else { + $host = env('HTTP_HOST'); + } + + if (!$this->__smtpSend("HELO {$host}", '250')) { return false; } diff --git a/cake/libs/controller/components/request_handler.php b/cake/libs/controller/components/request_handler.php index b4f9adead..8887ff443 100644 --- a/cake/libs/controller/components/request_handler.php +++ b/cake/libs/controller/components/request_handler.php @@ -524,6 +524,7 @@ class RequestHandlerComponent extends Object { return $this->ext; } + $types = $type; if (is_string($type)) { $types = array($type); } @@ -550,7 +551,11 @@ class RequestHandlerComponent extends Object { return $accepts[0]; } - $accepts = array_intersect($this->__acceptTypes, $accepts); + $acceptedTypes = array(); + foreach ($this->__acceptTypes as $type) { + $acceptedTypes[] = $this->mapType($type); + } + $accepts = array_intersect($acceptedTypes, $accepts); return $accepts[0]; } /** diff --git a/cake/libs/controller/components/session.php b/cake/libs/controller/components/session.php index f5164d4a6..f97312553 100644 --- a/cake/libs/controller/components/session.php +++ b/cake/libs/controller/components/session.php @@ -25,7 +25,7 @@ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ if (!class_exists('cakesession')) { - require LIBS . 'session.php'; + require LIBS . 'cake_session.php'; } /** * Session Component. diff --git a/cake/libs/controller/controller.php b/cake/libs/controller/controller.php index 8b78ebfc5..3b7694e3a 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]; } @@ -393,9 +389,13 @@ class Controller extends Object { if ($var === 'components') { $normal = Set::normalize($this->{$var}); $app = Set::normalize($appVars[$var]); - $this->{$var} = Set::merge($normal, $app); + if ($app !== $normal) { + $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}) + ); } } } @@ -415,9 +415,13 @@ class Controller extends Object { if ($var === 'components') { $normal = Set::normalize($this->{$var}); $app = Set::normalize($appVars[$var]); - $this->{$var} = Set::merge($normal, array_diff_assoc($app, $normal)); + if ($app !== $normal) { + $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}) + ); } } } @@ -462,7 +466,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 +502,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 +532,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 +700,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 +790,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 +804,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 +841,8 @@ class Controller extends Object { } if ($default != null) { - return $default; + $url = Router::url($default, true); + return $url; } return '/'; } @@ -863,9 +884,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 +963,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 +993,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); @@ -1026,6 +1058,14 @@ class Controller extends Object { if (!isset($defaults['conditions'])) { $defaults['conditions'] = array(); } + + $type = 'all'; + + if (isset($defaults[0])) { + $type = $defaults[0]; + unset($defaults[0]); + } + extract($options = array_merge(array('page' => 1, 'limit' => 20), $defaults, $options)); if (is_array($scope) && !empty($scope)) { @@ -1036,12 +1076,7 @@ class Controller extends Object { if ($recursive === null) { $recursive = $object->recursive; } - $type = 'all'; - if (isset($defaults[0])) { - $type = $defaults[0]; - unset($defaults[0]); - } $extra = array_diff_key($defaults, compact( 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' )); @@ -1068,7 +1103,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) { @@ -1164,4 +1201,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..b8e4d7531 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; $singularVar = Inflector::variable($modelClass); $pluralVar = Inflector::variable($this->controller->name); - $singularHumanName = Inflector::humanize($modelClass); - $pluralHumanName = Inflector::humanize($this->controller->name); + $singularHumanName = Inflector::humanize(Inflector::underscore($modelClass)); + $pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name)); $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 dfd2150ad..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 

    {:trace}

    ', + 'context' => '
    Context 

    {: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'] = '
    _templates['js']['context'] .= 'style="display: none;">{:context}
    '; + + $this->_templates['js']['code'] = '
    _templates['js']['code'] .= 'style="display: none;">
    {:code}
    '; + + + $e = '
    {:error} ({:code}) : {:description} ';
    +		$e .= '[{:path}, line {:line}]
    '; + $this->_templates['html']['error'] = $e; + + $this->_templates['html']['context'] = '
    Context ';
    +		$this->_templates['html']['context'] .= '

    {: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. @@ -144,7 +233,8 @@ class Debugger extends Object { if (is_object($trace[0]['object']) && isset($trace[0]['object']->_reporter->_test_stack)) { $stack = $trace[0]['object']->_reporter->_test_stack; - $source = "[". $stack[0].", ". $stack[2] ."::" . $stack[3] ."()]\n"; + $source = sprintf('[%1$s, %3$s::%2$s()]' . "\n", + array_shift($stack), array_pop($stack), array_pop($stack)); } CakeLog::write($level, $source . $_this->exportVar($var)); @@ -174,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)) { @@ -213,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') { @@ -229,6 +324,7 @@ class Debugger extends Object { } return true; } + /** * Outputs a stack trace based on the supplied options. * @@ -239,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' => '}')); } } @@ -306,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'. @@ -335,6 +433,7 @@ class Debugger extends Object { } return $path; } + /** * Grabs an excerpt from a file and highlights a given line of code * @@ -369,6 +468,7 @@ class Debugger extends Object { } return $lines; } + /** * Converts a variable to a string for debug output. * @@ -423,6 +523,7 @@ class Debugger extends Object { break; } } + /** * Handles object to string conversion. * @@ -453,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 "
    {$error} ({$code}) : {$description} [{$file}, line {$line}]
    "; - if (!empty($context)) { - echo "Context:\n" .implode("\n", $context) . "\n"; - } - echo "
    Context 

    " . implode("\n", $context) . "

    "; - echo "
    Trace 

    " . $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. * @@ -556,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 @@ -573,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/file.php b/cake/libs/file.php index e22031749..b57cb4c72 100644 --- a/cake/libs/file.php +++ b/cake/libs/file.php @@ -366,12 +366,13 @@ class File extends Object { function md5($maxsize = 5) { if ($maxsize === true) { return md5_file($this->path); - } else { - $size = $this->size(); - if ($size && $size < ($maxsize * 1024) * 1024) { - return md5_file($this->path); - } } + + $size = $this->size(); + if ($size && $size < ($maxsize * 1024) * 1024) { + return md5_file($this->path); + } + return false; } /** diff --git a/cake/libs/http_socket.php b/cake/libs/http_socket.php index a98fd2bfb..3802a8756 100644 --- a/cake/libs/http_socket.php +++ b/cake/libs/http_socket.php @@ -22,7 +22,7 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -App::import('Core', array('Socket', 'Set', 'Router')); +App::import('Core', array('CakeSocket', 'Set', 'Router')); /** * Cake network socket connection class. * @@ -40,7 +40,8 @@ class HttpSocket extends CakeSocket { */ var $description = 'HTTP-based DataSource Interface'; /** - * When one activates the $quirksMode by setting it to true, all checks meant to enforce RFC 2616 (HTTP/1.1 specs) + * When one activates the $quirksMode by setting it to true, all checks meant to + * enforce RFC 2616 (HTTP/1.1 specs). * will be disabled and additional measures to deal with non-standard responses will be enabled. * * @var boolean @@ -143,10 +144,10 @@ class HttpSocket extends CakeSocket { */ function __construct($config = array()) { if (is_string($config)) { - $this->configUri($config); + $this->_configUri($config); } elseif (is_array($config)) { if (isset($config['request']['uri']) && is_string($config['request']['uri'])) { - $this->configUri($config['request']['uri']); + $this->_configUri($config['request']['uri']); unset($config['request']['uri']); } $this->config = Set::merge($this->config, $config); @@ -172,7 +173,7 @@ class HttpSocket extends CakeSocket { if (!isset($request['uri'])) { $request['uri'] = null; } - $uri = $this->parseUri($request['uri']); + $uri = $this->_parseUri($request['uri']); if (!isset($uri['host'])) { $host = $this->config['host']; @@ -183,10 +184,10 @@ class HttpSocket extends CakeSocket { } $request['uri'] = $this->url($request['uri']); - $request['uri'] = $this->parseUri($request['uri'], true); + $request['uri'] = $this->_parseUri($request['uri'], true); $this->request = Set::merge($this->request, $this->config['request'], $request); - $this->configUri($this->request['uri']); + $this->_configUri($this->request['uri']); if (isset($host)) { $this->config['host'] = $host; @@ -194,7 +195,7 @@ class HttpSocket extends CakeSocket { $cookies = null; if (is_array($this->request['header'])) { - $this->request['header'] = $this->parseHeader($this->request['header']); + $this->request['header'] = $this->_parseHeader($this->request['header']); if (!empty($this->request['cookies'])) { $cookies = $this->buildCookies($this->request['cookies']); } @@ -209,7 +210,7 @@ class HttpSocket extends CakeSocket { } if (is_array($this->request['body'])) { - $this->request['body'] = $this->httpSerialize($this->request['body']); + $this->request['body'] = $this->_httpSerialize($this->request['body']); } if (!empty($this->request['body']) && !isset($this->request['header']['Content-Type'])) { @@ -221,10 +222,10 @@ class HttpSocket extends CakeSocket { } $connectionType = @$this->request['header']['Connection']; - $this->request['header'] = $this->buildHeader($this->request['header']).$cookies; + $this->request['header'] = $this->_buildHeader($this->request['header']).$cookies; if (empty($this->request['line'])) { - $this->request['line'] = $this->buildRequestLine($this->request); + $this->request['line'] = $this->_buildRequestLine($this->request); } if ($this->quirksMode === false && $this->request['line'] === false) { @@ -252,7 +253,7 @@ class HttpSocket extends CakeSocket { $this->disconnect(); } - $this->response = $this->parseResponse($response); + $this->response = $this->_parseResponse($response); if (!empty($this->response['cookies'])) { $this->config['request']['cookies'] = array_merge($this->config['request']['cookies'], $this->response['cookies']); } @@ -262,7 +263,7 @@ class HttpSocket extends CakeSocket { /** * Issues a GET request to the specified URI, query, and request. * - * @param mixed $uri URI to request (see {@link parseUri()}) + * @param mixed $uri URI to request (see {@link _parseUri()}) * @param array $query Query to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request @@ -270,13 +271,13 @@ class HttpSocket extends CakeSocket { */ function get($uri = null, $query = array(), $request = array()) { if (!empty($query)) { - $uri =$this->parseUri($uri); + $uri =$this->_parseUri($uri); if (isset($uri['query'])) { $uri['query'] = array_merge($uri['query'], $query); } else { $uri['query'] = $query; } - $uri = $this->buildUri($uri); + $uri = $this->_buildUri($uri); } $request = Set::merge(array('method' => 'GET', 'uri' => $uri), $request); @@ -286,7 +287,7 @@ class HttpSocket extends CakeSocket { /** * Issues a POST request to the specified URI, query, and request. * - * @param mixed $uri URI to request (see {@link parseUri()}) + * @param mixed $uri URI to request (see {@link _parseUri()}) * @param array $query Query to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request @@ -299,7 +300,7 @@ class HttpSocket extends CakeSocket { /** * Issues a PUT request to the specified URI, query, and request. * - * @param mixed $uri URI to request (see {@link parseUri()}) + * @param mixed $uri URI to request (see {@link _parseUri()}) * @param array $query Query to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request @@ -312,7 +313,7 @@ class HttpSocket extends CakeSocket { /** * Issues a DELETE request to the specified URI, query, and request. * - * @param mixed $uri URI to request (see {@link parseUri()}) + * @param mixed $uri URI to request (see {@link _parseUri()}) * @param array $query Query to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request @@ -346,16 +347,16 @@ class HttpSocket extends CakeSocket { } $base = array_merge($this->config['request']['uri'], array('scheme' => array('http', 'https'), 'port' => array(80, 443))); - $url = $this->parseUri($url, $base); + $url = $this->_parseUri($url, $base); if (empty($url)) { $url = $this->config['request']['uri']; } if (!empty($uriTemplate)) { - return $this->buildUri($url, $uriTemplate); + return $this->_buildUri($url, $uriTemplate); } - return $this->buildUri($url); + return $this->_buildUri($url); } /** * Parses the given message and breaks it down in parts. @@ -364,7 +365,7 @@ class HttpSocket extends CakeSocket { * @return array Parsed message (with indexed elements such as raw, status, header, body) * @access protected */ - function parseResponse($message) { + function _parseResponse($message) { if (is_array($message)) { return $message; } elseif (!is_string($message)) { @@ -394,12 +395,12 @@ class HttpSocket extends CakeSocket { $response['status']['reason-phrase'] = $match[3]; } - $response['header'] = $this->parseHeader($response['raw']['header']); - $decoded = $this->decodeBody($response['raw']['body'], @$response['header']['Transfer-Encoding']); + $response['header'] = $this->_parseHeader($response['raw']['header']); + $decoded = $this->_decodeBody($response['raw']['body'], @$response['header']['Transfer-Encoding']); $response['body'] = $decoded['body']; if (!empty($decoded['header'])) { - $response['header'] = $this->parseHeader($this->buildHeader($response['header']).$this->buildHeader($decoded['header'])); + $response['header'] = $this->_parseHeader($this->_buildHeader($response['header']).$this->_buildHeader($decoded['header'])); } if (!empty($response['header'])) { @@ -423,7 +424,7 @@ class HttpSocket extends CakeSocket { * @return mixed Array or false * @access protected */ - function decodeBody($body, $encoding = 'chunked') { + function _decodeBody($body, $encoding = 'chunked') { if (!is_string($body)) { return false; } @@ -434,7 +435,7 @@ class HttpSocket extends CakeSocket { if (!is_callable(array(&$this, $decodeMethod))) { if (!$this->quirksMode) { - trigger_error(sprintf(__('HttpSocket::decodeBody - Unknown encoding: %s. Activate quirks mode to surpress error.', true), h($encoding)), E_USER_WARNING); + trigger_error(sprintf(__('HttpSocket::_decodeBody - Unknown encoding: %s. Activate quirks mode to surpress error.', true), h($encoding)), E_USER_WARNING); } return array('body' => $body, 'header' => false); } @@ -448,7 +449,7 @@ class HttpSocket extends CakeSocket { * @return mixed Array or false * @access protected */ - function decodeChunkedBody($body) { + function _decodeChunkedBody($body) { if (!is_string($body)) { return false; } @@ -459,7 +460,7 @@ class HttpSocket extends CakeSocket { while ($chunkLength !== 0) { if (!preg_match("/^([0-9a-f]+) *(?:;(.+)=(.+))?\r\n/iU", $body, $match)) { if (!$this->quirksMode) { - trigger_error(__('HttpSocket::decodeChunkedBody - Could not parse malformed chunk. Activate quirks mode to do this.', true), E_USER_WARNING); + trigger_error(__('HttpSocket::_decodeChunkedBody - Could not parse malformed chunk. Activate quirks mode to do this.', true), E_USER_WARNING); return false; } break; @@ -498,26 +499,26 @@ class HttpSocket extends CakeSocket { $entityHeader = false; if (!empty($body)) { - $entityHeader = $this->parseHeader($body); + $entityHeader = $this->_parseHeader($body); } return array('body' => $decodedBody, 'header' => $entityHeader); } /** * Parses and sets the specified URI into current request configuration. * - * @param mixed $uri URI (see {@link parseUri()}) + * @param mixed $uri URI (see {@link _parseUri()}) * @return array Current configuration settings * @access protected */ - function configUri($uri = null) { + function _configUri($uri = null) { if (empty($uri)) { return false; } if (is_array($uri)) { - $uri = $this->parseUri($uri); + $uri = $this->_parseUri($uri); } else { - $uri = $this->parseUri($uri, true); + $uri = $this->_parseUri($uri, true); } if (!isset($uri['host'])) { @@ -542,18 +543,18 @@ class HttpSocket extends CakeSocket { * @return string A fully qualified URL formated according to $uriTemplate * @access protected */ - function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { + function _buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { if (is_string($uri)) { $uri = array('host' => $uri); } - $uri = $this->parseUri($uri, true); + $uri = $this->_parseUri($uri, true); if (!is_array($uri) || empty($uri)) { return false; } $uri['path'] = preg_replace('/^\//', null, $uri['path']); - $uri['query'] = $this->httpSerialize($uri['query']); + $uri['query'] = $this->_httpSerialize($uri['query']); $stripIfEmpty = array( 'query' => '?%query', 'fragment' => '#%fragment', @@ -589,7 +590,7 @@ class HttpSocket extends CakeSocket { * @return array Parsed URI * @access protected */ - function parseUri($uri = null, $base = array()) { + function _parseUri($uri = null, $base = array()) { $uriBase = array( 'scheme' => array('http', 'https'), 'host' => null, @@ -631,7 +632,7 @@ class HttpSocket extends CakeSocket { } if (array_key_exists('query', $uri)) { - $uri['query'] = $this->parseQuery($uri['query']); + $uri['query'] = $this->_parseQuery($uri['query']); } if (!array_intersect_key($uriBase, $uri)) { @@ -647,13 +648,13 @@ class HttpSocket extends CakeSocket { * - ?key[]=value1&key[]=value2 * * A leading '?' mark in $query is optional and does not effect the outcome of this function. For the complete capabilities of this implementation - * take a look at HttpSocketTest::testParseQuery() + * take a look at HttpSocketTest::testparseQuery() * * @param mixed $query A query string to parse into an array or an array to return directly "as is" * @return array The $query parsed into a possibly multi-level array. If an empty $query is given, an empty array is returned. * @access protected */ - function parseQuery($query) { + function _parseQuery($query) { if (is_array($query)) { return $query; } @@ -710,13 +711,13 @@ class HttpSocket extends CakeSocket { * @return string Request line * @access protected */ - function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { + function _buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { $asteriskMethods = array('OPTIONS'); if (is_string($request)) { $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match); if (!$this->quirksMode && (!$isValid || ($match[2] == '*' && !in_array($match[3], $asteriskMethods)))) { - trigger_error(__('HttpSocket::buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.', true), E_USER_WARNING); + trigger_error(__('HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.', true), E_USER_WARNING); return false; } return $request; @@ -726,12 +727,12 @@ class HttpSocket extends CakeSocket { return false; } - $request['uri'] = $this->parseUri($request['uri']); + $request['uri'] = $this->_parseUri($request['uri']); $request = array_merge(array('method' => 'GET'), $request); - $request['uri'] = $this->buildUri($request['uri'], '/%path?%query'); + $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query'); if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) { - trigger_error(sprintf(__('HttpSocket::buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', true), join(',', $asteriskMethods)), E_USER_WARNING); + trigger_error(sprintf(__('HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', true), join(',', $asteriskMethods)), E_USER_WARNING); return false; } return $request['method'].' '.$request['uri'].' '.$versionToken.$this->lineBreak; @@ -743,7 +744,7 @@ class HttpSocket extends CakeSocket { * @return string Serialized variable * @access protected */ - function httpSerialize($data = array()) { + function _httpSerialize($data = array()) { if (is_string($data)) { return $data; } @@ -759,7 +760,7 @@ class HttpSocket extends CakeSocket { * @return string Header built from array * @access protected */ - function buildHeader($header, $mode = 'standard') { + function _buildHeader($header, $mode = 'standard') { if (is_string($header)) { return $header; } elseif (!is_array($header)) { @@ -773,7 +774,7 @@ class HttpSocket extends CakeSocket { } foreach ((array)$contents as $content) { $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content); - $field = $this->escapeToken($field); + $field = $this->_escapeToken($field); $returnHeader .= $field.': '.$contents.$this->lineBreak; } @@ -788,7 +789,7 @@ class HttpSocket extends CakeSocket { * @return array Parsed header * @access protected */ - function parseHeader($header) { + function _parseHeader($header) { if (is_array($header)) { foreach ($header as $field => $value) { unset($header[$field]); @@ -814,7 +815,7 @@ class HttpSocket extends CakeSocket { $value = trim($value); $value = preg_replace("/[\t ]\r\n/", "\r\n", $value); - $field = $this->unescapeToken($field); + $field = $this->_unescapeToken($field); $field = strtolower($field); preg_match_all('/(?:^|(?<=-))[a-z]/U', $field, $offsets, PREG_OFFSET_CAPTURE); @@ -846,7 +847,7 @@ class HttpSocket extends CakeSocket { $cookies = array(); foreach ((array)$header['Set-Cookie'] as $cookie) { $parts = preg_split('/(? $cookie) { - $header[] = $name.'='.$this->escapeToken($cookie['value'], array(';')); + $header[] = $name.'='.$this->_escapeToken($cookie['value'], array(';')); } - $header = $this->buildHeader(array('Cookie' => $header), 'pragmatic'); + $header = $this->_buildHeader(array('Cookie' => $header), 'pragmatic'); return $header; } -/** - * undocumented function - * - * @return void - * @access public - */ - function saveCookies() { - - } -/** - * undocumented function - * - * @return void - * @access public - */ - function loadCookies() { - - } /** * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) * @@ -906,8 +889,8 @@ class HttpSocket extends CakeSocket { * @access protected * @todo Test $chars parameter */ - function unescapeToken($token, $chars = null) { - $regex = '/"(['.join('', $this->__tokenEscapeChars(true, $chars)).'])"/'; + function _unescapeToken($token, $chars = null) { + $regex = '/"(['.join('', $this->_tokenEscapeChars(true, $chars)).'])"/'; $token = preg_replace($regex, '\\1', $token); return $token; } @@ -919,8 +902,8 @@ class HttpSocket extends CakeSocket { * @access protected * @todo Test $chars parameter */ - function escapeToken($token, $chars = null) { - $regex = '/(['.join('', $this->__tokenEscapeChars(true, $chars)).'])/'; + function _escapeToken($token, $chars = null) { + $regex = '/(['.join('', $this->_tokenEscapeChars(true, $chars)).'])/'; $token = preg_replace($regex, '"\\1"', $token); return $token; } @@ -929,10 +912,10 @@ class HttpSocket extends CakeSocket { * * @param boolean $hex true to get them as HEX values, false otherwise * @return array Escape chars - * @access private + * @access protected * @todo Test $chars parameter */ - function __tokenEscapeChars($hex = true, $chars = null) { + function _tokenEscapeChars($hex = true, $chars = null) { if (!empty($chars)) { $escape = $chars; } else { diff --git a/cake/libs/i18n.php b/cake/libs/i18n.php index 850ac5782..3693bf35d 100644 --- a/cake/libs/i18n.php +++ b/cake/libs/i18n.php @@ -251,11 +251,11 @@ class I18n extends Object { $this->__noLocale = true; $core = true; $merge = array(); - $searchPaths = Configure::read('localePaths'); - $plugins = Configure::listObjects('plugin'); + $searchPaths = App::path('locales'); + $plugins = App::objects('plugin'); if (!empty($plugins)) { - $pluginPaths = Configure::read('pluginPaths'); + $pluginPaths = App::path('plugins'); foreach ($plugins as $plugin) { $plugin = Inflector::underscore($plugin); diff --git a/cake/libs/inflector.php b/cake/libs/inflector.php index 3dc5b2fc5..47fdc3979 100644 --- a/cake/libs/inflector.php +++ b/cake/libs/inflector.php @@ -1,5 +1,4 @@ test(); * * @package cake * @subpackage cake.cake.libs * @link http://book.cakephp.org/view/491/Inflector */ class Inflector extends Object { -/** - * Pluralized words. - * - * @var array - * @access private - **/ - var $pluralized = array(); -/** - * List of pluralization rules in the form of pattern => replacement. - * - * @var array - * @access public - * @link http://book.cakephp.org/view/47/Custom-Inflections - **/ - var $pluralRules = array(); -/** - * Singularized words. - * - * @var array - * @access private - **/ - var $singularized = array(); -/** - * List of singularization rules in the form of pattern => replacement. - * - * @var array - * @access public - * @link http://book.cakephp.org/view/47/Custom-Inflections - **/ - var $singularRules = array(); -/** - * Plural rules from inflections.php - * - * @var array - * @access private - **/ - var $__pluralRules = array(); -/** - * Un-inflected plural rules from inflections.php - * - * @var array - * @access private - **/ - var $__uninflectedPlural = array(); -/** - * Irregular plural rules from inflections.php - * - * @var array - * @access private - **/ - var $__irregularPlural = array(); -/** - * Singular rules from inflections.php - * - * @var array - * @access private - **/ - var $__singularRules = array(); -/** - * Un-inflectd singular rules from inflections.php - * - * @var array - * @access private - **/ - var $__uninflectedSingular = array(); -/** - * Irregular singular rules from inflections.php - * - * @var array - * @access private - **/ - var $__irregularSingular = array(); -/** - * Gets a reference to the Inflector object instance - * - * @return object - * @access public - */ - function &getInstance() { - static $instance = array(); - if (!$instance) { - $instance[0] =& new Inflector(); - if (file_exists(CONFIGS.'inflections.php')) { - include(CONFIGS.'inflections.php'); - $instance[0]->__pluralRules = $pluralRules; - $instance[0]->__uninflectedPlural = $uninflectedPlural; - $instance[0]->__irregularPlural = $irregularPlural; - $instance[0]->__singularRules = $singularRules; - $instance[0]->__uninflectedSingular = $uninflectedPlural; - $instance[0]->__irregularSingular = array_flip($irregularPlural); - } - } - return $instance[0]; - } /** - * Initializes plural inflection rules. + * Plural inflector rules * - * @return void - * @access private - */ - function __initPluralRules() { - $corePluralRules = array( + * @var array + * @access protected + **/ + var $_plural = array( + 'rules' => array( '/(s)tatus$/i' => '\1\2tatuses', '/(quiz)$/i' => '\1zes', '/^(ox)$/i' => '\1\2en', @@ -170,21 +67,12 @@ class Inflector extends Object { '/(ax|cris|test)is$/i' => '\1es', '/s$/' => 's', '/^$/' => '', - '/$/' => 's'); - - $coreUninflectedPlural = array( - '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', 'Amoyese', - 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', - 'cod', 'coitus', 'Congoese', 'contretemps', 'corps', 'debris', 'diabetes', 'djinn', 'eland', 'elk', - 'equipment', 'Faroese', 'flounder', 'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti', - 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'Kiplingese', - 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', 'media', 'mews', 'moose', 'mumps', 'Nankingese', 'news', - 'nexus', 'Niasese', 'Pekingese', 'People', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese', 'proceedings', - 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass', 'series', 'Shavese', 'shears', - 'siemens', 'species', 'swine', 'testes', 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', - 'whiting', 'wildebeest', 'Yengeese'); - - $coreIrregularPlural = array( + '/$/' => 's', + ), + 'uninflected' => array( + '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', 'people' + ), + 'irregular' => array( 'atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers', @@ -202,6 +90,7 @@ class Inflector extends Object { 'mongoose' => 'mongooses', 'move' => 'moves', 'mythos' => 'mythoi', + 'niche' => 'niches', 'numen' => 'numina', 'occiput' => 'occiputs', 'octopus' => 'octopuses', @@ -213,67 +102,18 @@ class Inflector extends Object { 'soliloquy' => 'soliloquies', 'testis' => 'testes', 'trilby' => 'trilbys', - 'turf' => 'turfs'); + 'turf' => 'turfs' + ) + ); - $pluralRules = Set::pushDiff($this->__pluralRules, $corePluralRules); - $uninflected = Set::pushDiff($this->__uninflectedPlural, $coreUninflectedPlural); - $irregular = Set::pushDiff($this->__irregularPlural, $coreIrregularPlural); - - $this->pluralRules = array('pluralRules' => $pluralRules, 'uninflected' => $uninflected, 'irregular' => $irregular); - $this->pluralized = array(); - } /** - * Return $word in plural form. + * Singular inflector rules * - * @param string $word Word in singular - * @return string Word in plural - * @access public - * @static - * @link http://book.cakephp.org/view/572/Class-methods - */ - function pluralize($word) { - $_this =& Inflector::getInstance(); - if (!isset($_this->pluralRules) || empty($_this->pluralRules)) { - $_this->__initPluralRules(); - } - - if (isset($_this->pluralized[$word])) { - return $_this->pluralized[$word]; - } - extract($_this->pluralRules); - - if (!isset($regexUninflected) || !isset($regexIrregular)) { - $regexUninflected = __enclose(join( '|', $uninflected)); - $regexIrregular = __enclose(join( '|', array_keys($irregular))); - $_this->pluralRules['regexUninflected'] = $regexUninflected; - $_this->pluralRules['regexIrregular'] = $regexIrregular; - } - - if (preg_match('/(.*)\\b(' . $regexIrregular . ')$/i', $word, $regs)) { - $_this->pluralized[$word] = $regs[1] . substr($word, 0, 1) . substr($irregular[strtolower($regs[2])], 1); - return $_this->pluralized[$word]; - } - - if (preg_match('/^(' . $regexUninflected . ')$/i', $word, $regs)) { - $_this->pluralized[$word] = $word; - return $word; - } - - foreach ($pluralRules as $rule => $replacement) { - if (preg_match($rule, $word)) { - $_this->pluralized[$word] = preg_replace($rule, $replacement, $word); - return $_this->pluralized[$word]; - } - } - } -/** - * Initializes singular inflection rules. - * - * @return void + * @var array * @access protected - */ - function __initSingularRules() { - $coreSingularRules = array( + **/ + var $_singular = array( + 'rules' => array( '/(s)tatuses$/i' => '\1\2tatus', '/^(.*)(menu)s$/i' => '\1\2', '/(quiz)zes$/i' => '\\1', @@ -306,58 +146,142 @@ class Inflector extends Object { '/(c)hildren$/i' => '\1\2hild', '/(n)ews$/i' => '\1\2ews', '/^(.*us)$/' => '\\1', - '/s$/i' => ''); + '/s$/i' => '' + ), + 'uninflected' => array( + '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss' + ), + 'irregular' => array() + ); - $coreUninflectedSingular = array( - '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss', 'Amoyese', - 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', - 'cod', 'coitus', 'Congoese', 'contretemps', 'corps', 'debris', 'diabetes', 'djinn', 'eland', 'elk', - 'equipment', 'Faroese', 'flounder', 'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti', - 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'Kiplingese', - 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', 'media', 'mews', 'moose', 'mumps', 'Nankingese', 'news', - 'nexus', 'Niasese', 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese', 'proceedings', - 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass', 'series', 'Shavese', 'shears', - 'siemens', 'species', 'swine', 'testes', 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', - 'whiting', 'wildebeest', 'Yengeese'); +/** + * Words that should not be inflected + * + * @var array + * @access protected + **/ + var $_uninflected = array( + 'Amoyese', 'bison', 'Borghese', 'bream', 'breeches', 'britches', 'buffalo', 'cantus', + 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'Congoese', 'contretemps', 'corps', + 'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder', + 'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti', + 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', + 'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', 'media', + 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', + 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese', + 'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors', + 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes', + 'trousers', 'trout','tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest', + 'Yengeese' + ); - $coreIrregularSingular = array( - 'atlases' => 'atlas', - 'beefs' => 'beef', - 'brothers' => 'brother', - 'children' => 'child', - 'corpuses' => 'corpus', - 'cows' => 'cow', - 'ganglions' => 'ganglion', - 'genies' => 'genie', - 'genera' => 'genus', - 'graffiti' => 'graffito', - 'hoofs' => 'hoof', - 'loaves' => 'loaf', - 'men' => 'man', - 'monies' => 'money', - 'mongooses' => 'mongoose', - 'moves' => 'move', - 'mythoi' => 'mythos', - 'numina' => 'numen', - 'occiputs' => 'occiput', - 'octopuses' => 'octopus', - 'opuses' => 'opus', - 'oxen' => 'ox', - 'penises' => 'penis', - 'people' => 'person', - 'sexes' => 'sex', - 'soliloquies' => 'soliloquy', - 'testes' => 'testis', - 'trilbys' => 'trilby', - 'turfs' => 'turf'); +/** + * Cached array identity map of pluralized words. + * + * @var array + * @access protected + **/ + var $_pluralized = array(); - $singularRules = Set::pushDiff($this->__singularRules, $coreSingularRules); - $uninflected = Set::pushDiff($this->__uninflectedSingular, $coreUninflectedSingular); - $irregular = Set::pushDiff($this->__irregularSingular, $coreIrregularSingular); +/** + * Cached array identity map of singularized words. + * + * @var array + * @access protected + **/ + var $_singularized = array(); - $this->singularRules = array('singularRules' => $singularRules, 'uninflected' => $uninflected, 'irregular' => $irregular); - $this->singularized = array(); +/** + * Gets a reference to the Inflector object instance + * + * @return object + * @access public + */ + function &getInstance() { + static $instance = array(); + + if (!$instance) { + $instance[0] =& new Inflector(); + } + return $instance[0]; } + +/** + * Adds custom inflection $rules, of either 'plural' or 'singular' $type. + * + * @param string $type The type of inflection, either 'singular' or 'plural' + * @param array $rules Array of rules to be added. Example usage: + * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables')); + * Inflector::rules('plural', array( + * 'rules' => array('/^(inflect)ors$/i' => '\1ables'), + * 'uninflected' => array('dontinflectme'), + * 'irregular' => array('red' => 'redlings') + * )); + * @access public + * @return void + * @static + */ + function rules($type, $rules = array()) { + $_this =& Inflector::getInstance(); + $type = '_'.$type; + + foreach ($rules as $rule => $pattern) { + if (is_array($pattern)) { + $_this->{$type}[$rule] = array_merge($pattern, $_this->{$type}[$rule]); + unset($rules[$rule], $_this->{$type}['cache' . ucfirst($rule)], $_this->{$type}['merged'][$rule]); + } + } + $_this->{$type}['rules'] = array_merge($rules, $_this->{$type}['rules']); + + } + +/** + * Return $word in plural form. + * + * @param string $word Word in singular + * @return string Word in plural + * @access public + * @static + * @link http://book.cakephp.org/view/572/Class-methods + */ + function pluralize($word) { + $_this =& Inflector::getInstance(); + + if (isset($_this->_pluralized[$word])) { + return $_this->_pluralized[$word]; + } + + if (!isset($_this->_plural['merged']['irregular'])) { + $_this->_plural['merged']['irregular'] = $_this->_plural['irregular']; + } + + if (!isset($_this->plural['merged']['uninflected'])) { + $_this->_plural['merged']['uninflected'] = array_merge($_this->_plural['uninflected'], $_this->_uninflected); + } + + if (!isset($_this->_plural['cacheUninflected']) || !isset($_this->_plural['cacheIrregular'])) { + $_this->_plural['cacheUninflected'] = '(?:' . join( '|', $_this->_plural['merged']['uninflected']) . ')'; + $_this->_plural['cacheIrregular'] = '(?:' . join( '|', array_keys($_this->_plural['merged']['irregular'])) . ')'; + } + + if (preg_match('/(.*)\\b(' . $_this->_plural['cacheIrregular'] . ')$/i', $word, $regs)) { + $_this->_pluralized[$word] = $regs[1] . substr($word, 0, 1) . substr($_this->_plural['merged']['irregular'][strtolower($regs[2])], 1); + return $_this->_pluralized[$word]; + } + + if (preg_match('/^(' . $_this->_plural['cacheUninflected'] . ')$/i', $word, $regs)) { + $_this->_pluralized[$word] = $word; + return $word; + } + + foreach ($_this->_plural['rules'] as $rule => $replacement) { + if (preg_match($rule, $word)) { + $_this->_pluralized[$word] = preg_replace($rule, $replacement, $word); + return $_this->_pluralized[$word]; + } + } + } + /** * Return $word in singular form. * @@ -369,41 +293,44 @@ class Inflector extends Object { */ function singularize($word) { $_this =& Inflector::getInstance(); - if (!isset($_this->singularRules) || empty($_this->singularRules)) { - $_this->__initSingularRules(); + + if (isset($_this->_singularized[$word])) { + return $_this->_singularized[$word]; } - if (isset($_this->singularized[$word])) { - return $_this->singularized[$word]; - } - extract($_this->singularRules); - - if (!isset($regexUninflected) || !isset($regexIrregular)) { - $regexUninflected = __enclose(join( '|', $uninflected)); - $regexIrregular = __enclose(join( '|', array_keys($irregular))); - $_this->singularRules['regexUninflected'] = $regexUninflected; - $_this->singularRules['regexIrregular'] = $regexIrregular; + if (!isset($_this->_singular['merged']['uninflected'])) { + $_this->_singular['merged']['uninflected'] = array_merge($_this->_singular['uninflected'], $_this->_uninflected); } - if (preg_match('/(.*)\\b(' . $regexIrregular . ')$/i', $word, $regs)) { - $_this->singularized[$word] = $regs[1] . substr($word, 0, 1) . substr($irregular[strtolower($regs[2])], 1); - return $_this->singularized[$word]; + if (!isset($_this->_singular['merged']['irregular'])) { + $_this->_singular['merged']['irregular'] = array_merge($_this->_singular['irregular'], array_flip($_this->_plural['irregular'])); } - if (preg_match('/^(' . $regexUninflected . ')$/i', $word, $regs)) { - $_this->singularized[$word] = $word; + if (!isset($_this->_singular['cacheUninflected']) || !isset($_this->_singular['cacheIrregular'])) { + $_this->_singular['cacheUninflected'] = '(?:' . join( '|', $_this->_singular['merged']['uninflected']) . ')'; + $_this->_singular['cacheIrregular'] = '(?:' . join( '|', array_keys($_this->_singular['merged']['irregular'])) . ')'; + } + + if (preg_match('/(.*)\\b(' . $_this->_singular['cacheIrregular'] . ')$/i', $word, $regs)) { + $_this->_singularized[$word] = $regs[1] . substr($word, 0, 1) . substr($_this->_singular['merged']['irregular'][strtolower($regs[2])], 1); + return $_this->_singularized[$word]; + } + + if (preg_match('/^(' . $_this->_singular['cacheUninflected'] . ')$/i', $word, $regs)) { + $_this->_singularized[$word] = $word; return $word; } - foreach ($singularRules as $rule => $replacement) { + foreach ($_this->_singular['rules'] as $rule => $replacement) { if (preg_match($rule, $word)) { - $_this->singularized[$word] = preg_replace($rule, $replacement, $word); - return $_this->singularized[$word]; + $_this->_singularized[$word] = preg_replace($rule, $replacement, $word); + return $_this->_singularized[$word]; } } - $_this->singularized[$word] = $word; + $_this->_singularized[$word] = $word; return $word; } + /** * Returns the given lower_case_and_underscored_word as a CamelCased word. * @@ -416,6 +343,7 @@ class Inflector extends Object { function camelize($lowerCaseAndUnderscoredWord) { return str_replace(" ", "", ucwords(str_replace("_", " ", $lowerCaseAndUnderscoredWord))); } + /** * Returns the given camelCasedWord as an underscored_word. * @@ -428,6 +356,7 @@ class Inflector extends Object { function underscore($camelCasedWord) { return strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $camelCasedWord)); } + /** * Returns the given underscored_word_group as a Human Readable Word Group. * (Underscores are replaced by spaces and capitalized following words.) @@ -441,6 +370,7 @@ class Inflector extends Object { function humanize($lowerCaseAndUnderscoredWord) { return ucwords(str_replace("_", " ", $lowerCaseAndUnderscoredWord)); } + /** * Returns corresponding table name for given model $className. ("people" for the model class "Person"). * @@ -453,6 +383,7 @@ class Inflector extends Object { function tableize($className) { return Inflector::pluralize(Inflector::underscore($className)); } + /** * Returns Cake model class name ("Person" for the database table "people".) for given database table. * @@ -465,6 +396,7 @@ class Inflector extends Object { function classify($tableName) { return Inflector::camelize(Inflector::singularize($tableName)); } + /** * Returns camelBacked version of an underscored string. * @@ -479,22 +411,28 @@ class Inflector extends Object { $replace = strtolower(substr($string, 0, 1)); return preg_replace('/\\w/', $replace, $string, 1); } + /** * Returns a string with all spaces converted to underscores (by default), accented * characters converted to non-accented characters, and non word characters removed. * - * @param string $string - * @param string $replacement + * @param string $string the string you want to slug + * @param string $replacement will replace keys in map + * @param array $map extra elements to map to the replacement * @return string * @access public * @static * @link http://book.cakephp.org/view/572/Class-methods */ - function slug($string, $replacement = '_') { - if (!class_exists('String')) { - require LIBS . 'string.php'; + function slug($string, $replacement = '_', $map = array()) { + if (is_array($replacement)) { + $map = $replacement; + $replacement = '_'; } - $map = array( + + $quotedReplacement = preg_quote($replacement, '/'); + + $default = array( '/à|á|å|â/' => 'a', '/è|é|ê|ẽ|ë/' => 'e', '/ì|í|î/' => 'i', @@ -511,18 +449,10 @@ class Inflector extends Object { '/ß/' => 'ss', '/[^\w\s]/' => ' ', '/\\s+/' => $replacement, - String::insert('/^[:replacement]+|[:replacement]+$/', array('replacement' => preg_quote($replacement, '/'))) => '', + sprintf('/^[%s]+|[%s]+$/', $quotedReplacement, $quotedReplacement) => '', ); + $map = array_merge($default, $map); return preg_replace(array_keys($map), array_values($map), $string); } } -/** - * Enclose a string for preg matching. - * - * @param string $string String to enclose - * @return string Enclosed string - */ - function __enclose($string) { - return '(?:' . $string . ')'; - } ?> \ No newline at end of file diff --git a/cake/libs/model/behaviors/tree.php b/cake/libs/model/behaviors/tree.php index 9d379368f..da23c193d 100644 --- a/cake/libs/model/behaviors/tree.php +++ b/cake/libs/model/behaviors/tree.php @@ -877,9 +877,10 @@ class TreeBehavior extends ModelBehavior { $scope['NOT'][$Model->alias . '.' . $Model->primaryKey] = $Model->id; } } + $name = $Model->alias . '.' . $right; list($edge) = array_values($Model->find('first', array( 'conditions' => $scope, - 'fields' => $db->calculate($Model, 'max', array($right)), + 'fields' => $db->calculate($Model, 'max', array($name, $right)), 'recursive' => $recursive ))); return (empty($edge[$right])) ? 0 : $edge[$right]; @@ -895,9 +896,10 @@ class TreeBehavior extends ModelBehavior { */ function __getMin($Model, $scope, $left, $recursive = -1) { $db =& ConnectionManager::getDataSource($Model->useDbConfig); + $name = $Model->alias . '.' . $left; list($edge) = array_values($Model->find('first', array( 'conditions' => $scope, - 'fields' => $db->calculate($Model, 'min', array($left)), + 'fields' => $db->calculate($Model, 'min', array($name, $left)), 'recursive' => $recursive ))); return (empty($edge[$left])) ? 0 : $edge[$left]; diff --git a/cake/libs/model/schema.php b/cake/libs/model/cake_schema.php similarity index 99% rename from cake/libs/model/schema.php rename to cake/libs/model/cake_schema.php index d3e2811ab..31e7e9cfe 100644 --- a/cake/libs/model/schema.php +++ b/cake/libs/model/cake_schema.php @@ -198,7 +198,7 @@ class CakeSchema extends Object { } if (!is_array($models) && $models !== false) { - $models = Configure::listObjects('model'); + $models = App::objects('model'); } if (is_array($models)) { diff --git a/cake/libs/model/datasources/datasource.php b/cake/libs/model/datasources/datasource.php index 6736f62a6..4fa8fba2e 100644 --- a/cake/libs/model/datasources/datasource.php +++ b/cake/libs/model/datasources/datasource.php @@ -241,13 +241,14 @@ class DataSource extends Object { if ($this->cacheSources === false) { return null; } - if (isset($this->__descriptions[$model->tablePrefix . $model->table])) { - return $this->__descriptions[$model->tablePrefix . $model->table]; + $table = $this->fullTableName($model, false); + if (isset($this->__descriptions[$table])) { + return $this->__descriptions[$table]; } - $cache = $this->__cacheDescription($model->tablePrefix . $model->table); + $cache = $this->__cacheDescription($table); if ($cache !== null) { - $this->__descriptions[$model->tablePrefix . $model->table] =& $cache; + $this->__descriptions[$table] =& $cache; return $cache; } return null; diff --git a/cake/libs/model/datasources/dbo/dbo_mssql.php b/cake/libs/model/datasources/dbo/dbo_mssql.php index 88938ba3b..766b70be1 100644 --- a/cake/libs/model/datasources/dbo/dbo_mssql.php +++ b/cake/libs/model/datasources/dbo/dbo_mssql.php @@ -221,7 +221,7 @@ class DboMssql extends DboSource { 'null' => (strtoupper($column[0]['Null']) == 'YES'), 'default' => preg_replace("/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $column[0]['Default']), 'length' => intval($column[0]['Length']), - 'key' => ($column[0]['Key'] == '1') + 'key' => ($column[0]['Key'] == '1') ? 'primary' : false ); if ($fields[$field]['default'] === 'null') { $fields[$field]['default'] = null; @@ -341,17 +341,18 @@ class DboMssql extends DboSource { if (!empty($values)) { $fields = array_combine($fields, $values); } + $primaryKey = $this->_getPrimaryKey($model); - if (array_key_exists($model->primaryKey, $fields)) { - if (empty($fields[$model->primaryKey])) { - unset($fields[$model->primaryKey]); + if (array_key_exists($primaryKey, $fields)) { + if (empty($fields[$primaryKey])) { + unset($fields[$primaryKey]); } else { - $this->_execute("SET IDENTITY_INSERT " . $this->fullTableName($model) . " ON"); + $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' ON'); } } $result = parent::create($model, array_keys($fields), array_values($fields)); - if (array_key_exists($model->primaryKey, $fields) && !empty($fields[$model->primaryKey])) { - $this->_execute("SET IDENTITY_INSERT " . $this->fullTableName($model) . " OFF"); + if (array_key_exists($primaryKey, $fields) && !empty($fields[$primaryKey])) { + $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' OFF'); } return $result; } @@ -383,7 +384,7 @@ class DboMssql extends DboSource { $error = mssql_get_last_message($this->connection); if ($error) { - if (!preg_match('/contexto de la base de datos a|contesto di database|changed database/i', $error)) { + if (!preg_match('/contexto de la base de datos a|contesto di database|changed database|datenbankkontext/i', $error)) { return $error; } } @@ -631,6 +632,29 @@ class DboMssql extends DboSource { return false; } } +/** + * Inserts multiple values into a table + * + * @param string $table + * @param string $fields + * @param array $values + * @access protected + */ + function insertMulti($table, $fields, $values) { + $primaryKey = $this->_getPrimaryKey($table); + $hasPrimaryKey = $primaryKey != null && ( + (is_array($fields) && in_array($primaryKey, $fields) + || (is_string($fields) && strpos($fields, $this->startQuote . $primaryKey . $this->endQuote) !== false)) + ); + + if ($hasPrimaryKey) { + $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' ON'); + } + parent::insertMulti($table, $fields, $values); + if ($hasPrimaryKey) { + $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' OFF'); + } + } /** * Generate a database-native column schema string * @@ -680,5 +704,27 @@ class DboMssql extends DboSource { } return $join; } +/** + * Makes sure it will return the primary key + * + * @param mixed $model + * @access protected + * @return string + */ + function _getPrimaryKey($model) { + if (is_object($model)) { + $schema = $model->schema(); + } else { + $schema = $this->describe($model); + } + + foreach ($schema as $field => $props) { + if (isset($props['key']) && $props['key'] == 'primary') { + return $field; + } + } + + return null; + } } ?> \ No newline at end of file diff --git a/cake/libs/model/datasources/dbo/dbo_mysqli.php b/cake/libs/model/datasources/dbo/dbo_mysqli.php index 12121a711..c0d238079 100644 --- a/cake/libs/model/datasources/dbo/dbo_mysqli.php +++ b/cake/libs/model/datasources/dbo/dbo_mysqli.php @@ -232,20 +232,6 @@ class DboMysqli extends DboMysqlBase { return $data; } -/** - * Begin a transaction - * - * @param unknown_type $model - * @return boolean True on success, false on fail - * (i.e. if the database/model does not support transactions). - */ - function begin(&$model) { - if (parent::begin($model) && $this->execute('START TRANSACTION')) { - $this->_transactionStarted = true; - return true; - } - return false; - } /** * Returns a formatted error message from previous database operation. * diff --git a/cake/libs/model/datasources/dbo/dbo_oracle.php b/cake/libs/model/datasources/dbo/dbo_oracle.php index d35b5900a..f7ec6f06e 100644 --- a/cake/libs/model/datasources/dbo/dbo_oracle.php +++ b/cake/libs/model/datasources/dbo/dbo_oracle.php @@ -454,6 +454,7 @@ class DboOracle extends DboSource { while($r = $this->fetchRow()) { $sources[] = strtolower($r[0]['name']); } + parent::listSources($sources); return $sources; } /** @@ -834,8 +835,7 @@ class DboOracle extends DboSource { switch($column) { case 'date': - $date = new DateTime($data); - $data = $date->format('Y-m-d H:i:s'); + $data = date('Y-m-d H:i:s', strtotime($data)); $data = "TO_DATE('$data', 'YYYY-MM-DD HH24:MI:SS')"; break; case 'integer' : diff --git a/cake/libs/model/datasources/dbo/dbo_postgres.php b/cake/libs/model/datasources/dbo/dbo_postgres.php index bd6e984bb..2298fc019 100644 --- a/cake/libs/model/datasources/dbo/dbo_postgres.php +++ b/cake/libs/model/datasources/dbo/dbo_postgres.php @@ -275,6 +275,9 @@ class DboPostgres extends DboSource { case 'inet': case 'float': case 'integer': + case 'date': + case 'datetime': + case 'timestamp': if ($data === '') { return $read ? 'NULL' : 'DEFAULT'; } diff --git a/cake/libs/model/datasources/dbo/dbo_sqlite.php b/cake/libs/model/datasources/dbo/dbo_sqlite.php index b51132185..c365b6fe0 100644 --- a/cake/libs/model/datasources/dbo/dbo_sqlite.php +++ b/cake/libs/model/datasources/dbo/dbo_sqlite.php @@ -88,7 +88,7 @@ class DboSqlite extends DboSource { 'primary_key' => array('name' => 'integer primary key'), 'string' => array('name' => 'varchar', 'limit' => '255'), 'text' => array('name' => 'text'), - 'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'), + 'integer' => array('name' => 'integer', 'limit' => 11, 'formatter' => 'intval'), 'float' => array('name' => 'float', 'formatter' => 'floatval'), 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), @@ -190,18 +190,19 @@ class DboSqlite extends DboSource { foreach ($result as $column) { $fields[$column[0]['name']] = array( - 'type' => $this->column($column[0]['type']), - 'null' => !$column[0]['notnull'], - 'default' => $column[0]['dflt_value'], - 'length' => $this->length($column[0]['type']) + 'type' => $this->column($column[0]['type']), + 'null' => !$column[0]['notnull'], + 'default' => $column[0]['dflt_value'], + 'length' => $this->length($column[0]['type']) ); if ($column[0]['pk'] == 1) { + $colLength = $this->length($column[0]['type']); $fields[$column[0]['name']] = array( - 'type' => $fields[$column[0]['name']]['type'], - 'null' => false, - 'default' => $column[0]['dflt_value'], - 'key' => $this->index['PRI'], - 'length' => 11 + 'type' => $fields[$column[0]['name']]['type'], + 'null' => false, + 'default' => $column[0]['dflt_value'], + 'key' => $this->index['PRI'], + 'length'=> ($colLength != null) ? $colLength : 11 ); } } @@ -449,34 +450,34 @@ class DboSqlite extends DboSource { } $real = $this->columns[$type]; - if (isset($column['key']) && $column['key'] == 'primary') { - $out = $this->name($name) . ' ' . $this->columns['primary_key']['name']; - } else { - $out = $this->name($name) . ' ' . $real['name']; - - if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) { - if (isset($column['length'])) { - $length = $column['length']; - } elseif (isset($column['limit'])) { - $length = $column['limit']; - } elseif (isset($real['length'])) { - $length = $real['length']; - } else { - $length = $real['limit']; - } - $out .= '(' . $length . ')'; - } - if (isset($column['key']) && $column['key'] == 'primary') { - $out .= ' NOT NULL'; - } elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) { - $out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL'; - } elseif (isset($column['default'])) { - $out .= ' DEFAULT ' . $this->value($column['default'], $type); - } elseif (isset($column['null']) && $column['null'] == true) { - $out .= ' DEFAULT NULL'; - } elseif (isset($column['null']) && $column['null'] == false) { - $out .= ' NOT NULL'; + $out = $this->name($name) . ' ' . $real['name']; + if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') { + return $this->name($name) . ' ' . $this->columns['primary_key']['name']; + } + if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) { + if (isset($column['length'])) { + $length = $column['length']; + } elseif (isset($column['limit'])) { + $length = $column['limit']; + } elseif (isset($real['length'])) { + $length = $real['length']; + } else { + $length = $real['limit']; } + $out .= '(' . $length . ')'; + } + if (isset($column['key']) && $column['key'] == 'primary' && $type == 'integer') { + $out .= ' ' . $this->columns['primary_key']['name']; + } elseif (isset($column['key']) && $column['key'] == 'primary') { + $out .= ' NOT NULL'; + } elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) { + $out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL'; + } elseif (isset($column['default'])) { + $out .= ' DEFAULT ' . $this->value($column['default'], $type); + } elseif (isset($column['null']) && $column['null'] == true) { + $out .= ' DEFAULT NULL'; + } elseif (isset($column['null']) && $column['null'] == false) { + $out .= ' NOT NULL'; } return $out; } diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index f2aa64ebc..1ad21c115 100644 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -627,16 +627,22 @@ class DboSource extends DataSource { $queryData['fields'] = $this->fields($model); } - foreach ($model->__associations as $type) { - foreach ($model->{$type} as $assoc => $assocData) { - if ($model->recursive > -1) { - $linkModel =& $model->{$assoc}; - $external = isset($assocData['external']); + $_associations = $model->__associations; - if ($model->useDbConfig == $linkModel->useDbConfig) { - if (true === $this->generateAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null)) { - $linkedModels[] = $type . '/' . $assoc; - } + if ($model->recursive == -1) { + $_associations = array(); + } else if ($model->recursive == 0) { + unset($_associations[2], $_associations[3]); + } + + foreach ($_associations as $type) { + foreach ($model->{$type} as $assoc => $assocData) { + $linkModel =& $model->{$assoc}; + $external = isset($assocData['external']); + + if ($model->useDbConfig == $linkModel->useDbConfig) { + if (true === $this->generateAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null)) { + $linkedModels[$type . '/' . $assoc] = true; } } } @@ -653,12 +659,12 @@ class DboSource extends DataSource { $filtered = $this->__filterResults($resultSet, $model); - if ($model->recursive > 0) { - foreach ($model->__associations as $type) { + if ($model->recursive > -1) { + foreach ($_associations as $type) { foreach ($model->{$type} as $assoc => $assocData) { $linkModel =& $model->{$assoc}; - if (!in_array($type . '/' . $assoc, $linkedModels)) { + if (empty($linkedModels[$type . '/' . $assoc])) { if ($model->useDbConfig == $linkModel->useDbConfig) { $db =& $this; } else { @@ -852,11 +858,8 @@ class DboSource extends DataSource { foreach ($fetch as $j => $data) { if ( - (isset($data[$with]) && $data[$with][$foreignKey] === $row[$model->alias][$model->primaryKey]) && - (!in_array($data[$with][$joinKeys[1]], $uniqueIds)) + (isset($data[$with]) && $data[$with][$foreignKey] === $row[$model->alias][$model->primaryKey]) ) { - $uniqueIds[] = $data[$with][$joinKeys[1]]; - if ($habtmFieldsCount <= 2) { unset($data[$with]); } diff --git a/cake/libs/model/model.php b/cake/libs/model/model.php index d1da65496..deb859f1c 100644 --- a/cake/libs/model/model.php +++ b/cake/libs/model/model.php @@ -1,5 +1,4 @@ useTable = $table; } + + if ($ds !== null) { + $this->useDbConfig = $ds; + } if (is_subclass_of($this, 'AppModel')) { $appVars = get_class_vars('AppModel'); @@ -815,13 +816,18 @@ class Model extends Overloadable { * @access public */ function deconstruct($field, $data) { + if (!is_array($data)) { + return $data; + } + $copy = $data; $type = $this->getColumnType($field); - $db =& ConnectionManager::getDataSource($this->useDbConfig); if (in_array($type, array('datetime', 'timestamp', 'date', 'time'))) { $useNewDate = (isset($data['year']) || isset($data['month']) || isset($data['day']) || isset($data['hour']) || isset($data['minute'])); $dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec'); + + $db =& ConnectionManager::getDataSource($this->useDbConfig); $format = $db->columns[$type]['format']; $date = array(); @@ -1010,7 +1016,10 @@ class Model extends Overloadable { } if ($id !== null && $id !== false) { - $this->data = $this->find(array($this->alias . '.' . $this->primaryKey => $id), $fields); + $this->data = $this->find('first', array( + 'conditions' => array($this->alias . '.' . $this->primaryKey => $id), + 'fields' => $fields + )); return $this->data; } else { return false; @@ -1210,7 +1219,7 @@ class Model extends Overloadable { foreach ($this->_schema as $field => $properties) { if ($this->primaryKey === $field) { $fInfo = $this->_schema[$field]; - $isUUID = ($fInfo['length'] === 36 && + $isUUID = ($fInfo['length'] == 36 && ($fInfo['type'] === 'string' || $fInfo['type'] === 'binary') ); if (empty($this->data[$this->alias][$this->primaryKey]) && $isUUID) { @@ -1279,7 +1288,7 @@ class Model extends Overloadable { )); $isUUID = !empty($this->{$join}->primaryKey) && ( - $this->{$join}->_schema[$this->{$join}->primaryKey]['length'] === 36 && ( + $this->{$join}->_schema[$this->{$join}->primaryKey]['length'] == 36 && ( $this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'string' || $this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'binary' ) @@ -1374,16 +1383,15 @@ class Model extends Overloadable { $conditions = ($recursive == 1) ? (array)$assoc['counterScope'] : array(); if (isset($keys['old'][$foreignKey])) { - if ($keys['old'][$foreignKey] == $keys[$foreignKey]) { - continue; - } - $conditions[$fkQuoted] = $keys['old'][$foreignKey]; - $count = intval($this->find('count', compact('conditions', 'recursive'))); + if ($keys['old'][$foreignKey] != $keys[$foreignKey]) { + $conditions[$fkQuoted] = $keys['old'][$foreignKey]; + $count = intval($this->find('count', compact('conditions', 'recursive'))); - $this->{$parent}->updateAll( - array($assoc['counterCache'] => $count), - array($this->{$parent}->escapeField() => $keys['old'][$foreignKey]) - ); + $this->{$parent}->updateAll( + array($assoc['counterCache'] => $count), + array($this->{$parent}->escapeField() => $keys['old'][$foreignKey]) + ); + } } $conditions[$fkQuoted] = $keys[$foreignKey]; @@ -1420,7 +1428,7 @@ class Model extends Overloadable { return array(); } $old = $this->find('first', array( - 'conditions' => array('id' => $this->id), + 'conditions' => array($this->primaryKey => $this->id), 'fields' => array_values($included), 'recursive' => -1 )); @@ -1464,7 +1472,7 @@ class Model extends Overloadable { if (Set::numeric(array_keys($data))) { while ($validates) { foreach ($data as $key => $record) { - if (!$currentValidates = $this->__save($this, $record, $options)) { + if (!$currentValidates = $this->__save($record, $options)) { $validationErrors[$key] = $this->validationErrors; } @@ -1517,7 +1525,7 @@ class Model extends Overloadable { if (isset($associations[$association])) { switch ($associations[$association]) { case 'belongsTo': - if ($this->__save($this->{$association}, $values, $options)) { + if ($this->{$association}->__save($values, $options)) { $data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id; } else { $validationErrors[$association] = $this->{$association}->validationErrors; @@ -1530,7 +1538,7 @@ class Model extends Overloadable { } } } - if (!$this->__save($this, $data, $options)) { + if (!$this->__save($data, $options)) { $validationErrors[$this->alias] = $this->validationErrors; $validates = false; } @@ -1548,7 +1556,7 @@ class Model extends Overloadable { switch ($type) { case 'hasOne': $values[$this->{$type}[$association]['foreignKey']] = $this->id; - if (!$this->__save($this->{$association}, $values, $options)) { + if (!$this->{$association}->__save($values, $options)) { $validationErrors[$association] = $this->{$association}->validationErrors; $validates = false; } @@ -1621,12 +1629,12 @@ class Model extends Overloadable { * @access private * @see Model::saveAll() */ - function __save(&$model, $data, $options) { + function __save($data, $options) { if ($options['validate'] === 'first' || $options['validate'] === 'only') { - if (!($model->create($data) && $model->validates($options))) { + if (!($this->create($data) && $this->validates($options))) { return false; } - } elseif (!($model->create(null) !== null && $model->save($data, $options))) { + } elseif (!($this->create(null) !== null && $this->save($data, $options))) { return false; } return true; @@ -1646,17 +1654,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. @@ -1667,7 +1669,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; } @@ -1675,7 +1677,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); @@ -1701,16 +1706,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. @@ -1738,7 +1737,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) { @@ -1763,14 +1764,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); } } } @@ -1795,12 +1800,15 @@ 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}" ); if (empty($ids)) { - return false; + return true; } if ($callbacks) { @@ -1822,6 +1830,7 @@ class Model extends Overloadable { } } } + /** * Collects foreign keys from associations. * @@ -1838,6 +1847,7 @@ class Model extends Overloadable { } return $result; } + /** * Returns true if a record with the currently set ID exists. * @@ -1853,7 +1863,7 @@ class Model extends Overloadable { if ($this->getID() === false || $this->useTable === false) { return false; } - if ($this->__exists !== null && $reset !== true) { + if (!empty($this->__exists) && $reset !== true) { return $this->__exists; } $conditions = array($this->alias . '.' . $this->primaryKey => $this->getID()); @@ -1864,6 +1874,7 @@ class Model extends Overloadable { } return $this->__exists = ($this->find('count', $query) > 0); } + /** * Returns true if a record that meets given conditions exists. * @@ -1874,6 +1885,7 @@ class Model extends Overloadable { function hasAny($conditions = null) { return ($this->find('count', array('conditions' => $conditions, 'recursive' => -1)) != false); } + /** * Returns a result set array. * @@ -1895,8 +1907,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 @@ -1974,6 +1988,7 @@ class Model extends Overloadable { } } } + /** * Handles the before/after filter logic for find('first') operations. Only called by Model::find(). * @@ -1998,6 +2013,7 @@ class Model extends Overloadable { return $results[0]; } } + /** * Handles the before/after filter logic for find('count') operations. Only called by Model::find(). * @@ -2029,6 +2045,7 @@ class Model extends Overloadable { return false; } } + /** * Handles the before/after filter logic for find('list') operations. Only called by Model::find(). * @@ -2087,6 +2104,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. @@ -2145,6 +2163,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 @@ -2191,6 +2210,7 @@ class Model extends Overloadable { return $return; } } + /** * Passes query results through model and behavior afterFilter() methods. * @@ -2206,6 +2226,7 @@ class Model extends Overloadable { } return $this->afterFind($results, $primary); } + /** * Called only when bindTo() is used. * This resets the association arrays for the model back @@ -2234,6 +2255,7 @@ class Model extends Overloadable { $this->__backAssociation = array(); return true; } + /** * Returns false if any fields passed match any (by default, all if $or = false) of their matching values. * @@ -2276,6 +2298,7 @@ class Model extends Overloadable { } return ($this->find('count', array('conditions' => $fields, 'recursive' => -1)) == 0); } + /** * Returns a resultset for a given SQL statement. Custom SQL queries should be performed with this method. * @@ -2289,6 +2312,7 @@ class Model extends Overloadable { $db =& ConnectionManager::getDataSource($this->useDbConfig); return call_user_func_array(array(&$db, 'query'), $params); } + /** * Returns true if all fields pass validation. * @@ -2304,6 +2328,7 @@ class Model extends Overloadable { } return $errors; } + /** * Returns an array of fields that have failed validation. * @@ -2454,6 +2479,7 @@ class Model extends Overloadable { $this->validate = $_validate; return $this->validationErrors; } + /** * Marks a field as invalid, optionally setting the name of validation * rule (in case of multiple validation for field) that was broken. @@ -2469,6 +2495,7 @@ class Model extends Overloadable { } $this->validationErrors[$field] = $value; } + /** * Returns true if given field name is a foreign key in this model. * @@ -2485,6 +2512,7 @@ class Model extends Overloadable { } return in_array($field, $foreignKeys); } + /** * Returns the display field for this model. * @@ -2495,6 +2523,7 @@ class Model extends Overloadable { function getDisplayField() { return $this->displayField; } + /** * Escapes the field name and prepends the model name. Escaping is done according to the current database driver's rules. * @@ -2516,6 +2545,7 @@ class Model extends Overloadable { } return $db->name($alias . '.' . $field); } + /** * Returns the current record's ID * @@ -2548,6 +2578,7 @@ class Model extends Overloadable { return false; } + /** * Returns the ID of the last record this model inserted. * @@ -2557,6 +2588,7 @@ class Model extends Overloadable { function getLastInsertID() { return $this->getInsertID(); } + /** * Returns the ID of the last record this model inserted. * @@ -2566,6 +2598,7 @@ class Model extends Overloadable { function getInsertID() { return $this->__insertID; } + /** * Sets the ID of the last record this model inserted * @@ -2659,7 +2692,12 @@ class Model extends Overloadable { } return array_keys($this->{$type}); } else { - $assoc = array_merge($this->hasOne, $this->hasMany, $this->belongsTo, $this->hasAndBelongsToMany); + $assoc = array_merge( + $this->hasOne, + $this->hasMany, + $this->belongsTo, + $this->hasAndBelongsToMany + ); if (array_key_exists($type, $assoc)) { foreach ($this->__associations as $a) { if (isset($this->{$a}[$type])) { @@ -2673,7 +2711,8 @@ class Model extends Overloadable { } } /** - * Gets the name and fields to be used by a join model. This allows specifying join fields in the association definition. + * Gets the name and fields to be used by a join model. This allows specifying join fields + * in the association definition. * * @param object $model The model to be joined * @param mixed $with The 'with' key of the model association @@ -2687,16 +2726,19 @@ class Model extends Overloadable { } elseif (is_array($assoc)) { $with = key($assoc); return array($with, array_unique(array_merge($assoc[$with], $keys))); - } else { - trigger_error(sprintf(__('Invalid join model settings in %s', true), $model->alias), E_USER_WARNING); } + trigger_error( + sprintf(__('Invalid join model settings in %s', true), $model->alias), + E_USER_WARNING + ); } /** * Called before each find operation. Return false if you want to halt the find * call, otherwise return the (modified) query data. * * @param array $queryData Data used to execute this query, i.e. conditions, order, etc. - * @return mixed true if the operation should continue, false if it should abort; or, modified $queryData to continue with new $queryData + * @return mixed true if the operation should continue, false if it should abort; or, modified + * $queryData to continue with new $queryData * @access public * @link http://book.cakephp.org/view/680/beforeFind */ @@ -2737,7 +2779,7 @@ class Model extends Overloadable { function afterSave($created) { } /** - * Called after every deletion operation. + * Called before every deletion operation. * * @param boolean $cascade If true records that depend on this record will also be deleted * @return boolean True if the operation should continue, false if it should abort @@ -2823,43 +2865,6 @@ class Model extends Overloadable { */ function __wakeup() { } -/** - * @deprecated - * @see Model::find('all') - */ - function findAll($conditions = null, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) { - //trigger_error(__('(Model::findAll) Deprecated, use Model::find("all")', true), E_USER_WARNING); - return $this->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive')); - } -/** - * @deprecated - * @see Model::find('count') - */ - function findCount($conditions = null, $recursive = 0) { - //trigger_error(__('(Model::findCount) Deprecated, use Model::find("count")', true), E_USER_WARNING); - return $this->find('count', compact('conditions', 'recursive')); - } -/** - * @deprecated - * @see Model::find('threaded') - */ - function findAllThreaded($conditions = null, $fields = null, $order = null) { - //trigger_error(__('(Model::findAllThreaded) Deprecated, use Model::find("threaded")', true), E_USER_WARNING); - return $this->find('threaded', compact('conditions', 'fields', 'order')); - } -/** - * @deprecated - * @see Model::find('neighbors') - */ - function findNeighbours($conditions = null, $field, $value) { - //trigger_error(__('(Model::findNeighbours) Deprecated, use Model::find("neighbors")', true), E_USER_WARNING); - $query = compact('conditions', 'field', 'value'); - $query['fields'] = $field; - if (is_array($field)) { - $query['field'] = $field[0]; - } - return $this->find('neighbors', $query); - } } if (!defined('CAKEPHP_UNIT_TEST_EXECUTION')) { Overloadable::overload('Model'); diff --git a/cake/libs/model/behavior.php b/cake/libs/model/model_behavior.php similarity index 100% rename from cake/libs/model/behavior.php rename to cake/libs/model/model_behavior.php diff --git a/cake/libs/router.php b/cake/libs/router.php index 4071c6f12..868e553cb 100644 --- a/cake/libs/router.php +++ b/cake/libs/router.php @@ -593,7 +593,7 @@ class Router extends Object { $params = array('prefix' => $this->__admin, $this->__admin => true); } - if ($plugins = Configure::listObjects('plugin')) { + if ($plugins = App::objects('plugin')) { foreach ($plugins as $key => $value) { $plugins[$key] = Inflector::underscore($value); } diff --git a/cake/libs/set.php b/cake/libs/set.php index bed03379a..d48adc7de 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -918,7 +918,7 @@ class Set extends Object { * to null (useful for Set::merge). You can optionally group the values by what is obtained when * following the path specified in $groupPath. * - * @param array $data Array from where to extract keys and values + * @param mixed $data Array or object from where to extract keys and values * @param mixed $path1 As an array, or as a dot-separated string. * @param mixed $path2 As an array, or as a dot-separated string. * @param string $groupPath As an array, or as a dot-separated string. diff --git a/cake/libs/string.php b/cake/libs/string.php index 8c73551a6..6ea6bfd55 100644 --- a/cake/libs/string.php +++ b/cake/libs/string.php @@ -1,27 +1,22 @@ 'Bob', '65')); - * Returns: My name is Bob and I am 65 years old. + * Replaces variable placeholders inside a $str with any given $data. Each key in the $data array + * corresponds to a variable placeholder name in $str. + * Example: String::insert(':name is :age years old.', array('name' => 'Bob', '65')); + * Returns: Bob is 65 years old. * * Available $options are: * before: The character or string in front of the name of the variable placeholder (Defaults to ':') * after: The character or string after the name of the variable placeholder (Defaults to null) * escape: The character or string used to escape the before character / string (Defaults to '\') - * format: A regex to use for matching variable placeholders. Default is: '/(? val array where each key stands for a placeholder variable name to be replaced with val + * @param string $data A key => val array where each key stands for a placeholder variable name + * to be replaced with val * @param string $options An array of options, see description above * @return string * @access public @@ -237,6 +241,8 @@ class String extends Object { $str = substr_replace($str, $val, $pos, 1); } } else { + asort($data); + $hashKeys = array_map('md5', array_keys($data)); $tempData = array_combine(array_keys($data), array_values($hashKeys)); foreach ($tempData as $key => $hashVal) { @@ -245,6 +251,9 @@ class String extends Object { } $dataReplacements = array_combine($hashKeys, array_values($data)); foreach ($dataReplacements as $tmpHash => $data) { + if (is_array($data)) { + $data = ''; + } $str = str_replace($tmpHash, $data, $str); } } @@ -258,15 +267,17 @@ class String extends Object { return String::cleanInsert($str, $options); } /** - * Cleans up a Set::insert formated string with given $options depending on the 'clean' key in $options. The default method used is - * text but html is also available. The goal of this function is to replace all whitespace and uneeded markup around placeholders - * that did not get replaced by Set::insert. + * Cleans up a Set::insert formated string with given $options depending on the 'clean' key in + * $options. The default method used is text but html is also available. The goal of this function + * is to replace all whitespace and uneeded markup around placeholders that did not get replaced + * by Set::insert. * * @param string $str * @param string $options * @return string * @access public * @static + * @see Set::insert() */ function cleanInsert($str, $options) { $clean = $options['clean']; diff --git a/cake/libs/validation.php b/cake/libs/validation.php index 339d8668d..be0d20c2a 100644 --- a/cake/libs/validation.php +++ b/cake/libs/validation.php @@ -798,6 +798,7 @@ class Validation extends Object { * an optional fragment (anchor tag) * * @param string $check Value to check + * @param boolean $strict Require URL to be prefixed by a valid scheme (one of http(s)/ftp(s)/file/news/gopher) * @return boolean Success * @access public */ @@ -925,4 +926,4 @@ class Validation extends Object { $this->errors = array(); } } -?> \ No newline at end of file +?> diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index fc12c7ac2..076622c73 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -591,7 +591,7 @@ class Helper extends Overloadable { if (is_array($result)) { $view =& ClassRegistry::getObject('view'); - if (isset($result[$view->fieldSuffix])) { + if (array_key_exists($view->fieldSuffix, $result)) { $result = $result[$view->fieldSuffix]; } } diff --git a/cake/libs/view/helpers/ajax.php b/cake/libs/view/helpers/ajax.php index bc4aad584..97d5c9580 100644 --- a/cake/libs/view/helpers/ajax.php +++ b/cake/libs/view/helpers/ajax.php @@ -81,7 +81,8 @@ class AjaxHelper extends AppHelper { */ var $dragOptions = array( 'handle', 'revert', 'snap', 'zindex', 'constraint', 'change', 'ghosting', - 'starteffect', 'reverteffect', 'endeffect' + 'starteffect', 'reverteffect', 'endeffect', 'scroll', 'scrollSensitivity', + 'onStart', 'onDrag', 'onEnd' ); /** * Options for droppable. diff --git a/cake/libs/view/helpers/cache.php b/cake/libs/view/helpers/cache.php index dd4f1b499..d8e60b12f 100644 --- a/cake/libs/view/helpers/cache.php +++ b/cake/libs/view/helpers/cache.php @@ -264,7 +264,8 @@ class CacheHelper extends AppHelper { $controller->params = $this->params = unserialize(stripslashes(\'' . addslashes(serialize($this->params)) . '\')); $controller->action = $this->action = unserialize(\'' . serialize($this->action) . '\'); $controller->data = $this->data = unserialize(stripslashes(\'' . addslashes(serialize($this->data)) . '\')); - $controller->themeWeb = $this->themeWeb = \'' . $this->themeWeb . '\';'; + $controller->themeWeb = $this->themeWeb = \'' . $this->themeWeb . '\'; + Router::setRequestInfo(array($this->params, array(\'base\' => $this->base, \'webroot\' => $this->webroot)));'; if ($useCallbacks == true) { $file .= ' @@ -275,7 +276,6 @@ class CacheHelper extends AppHelper { } $file .= ' - Router::setRequestInfo(array($this->params, array(\'base\' => $this->base, \'webroot\' => $this->webroot))); $loadedHelpers = array(); $loadedHelpers = $this->_loadHelpers($loadedHelpers, $this->helpers); foreach (array_keys($loadedHelpers) as $helper) { diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index 7988220a1..6394ce5ee 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -563,7 +563,8 @@ class FormHelper extends AppHelper { /** * Generates a form input element complete with label and wrapper div * - * Options - See each field type method for more information. + * Options - See each field type method for more information. Any options that are part of + * $attributes or $options for the different type methods can be included in $options for input(). * * - 'type' - Force the type of widget you want. e.g. ```type => 'select'``` * - 'label' - control the label @@ -852,11 +853,14 @@ class FormHelper extends AppHelper { } elseif (!empty($value) && $value === $options['value']) { $options['checked'] = 'checked'; } - - $output = $this->hidden($fieldName, array( + $hiddenOptions = array( 'id' => $options['id'] . '_', 'name' => $options['name'], 'value' => '0', 'secure' => false - )); + ); + if (isset($options['disabled']) && $options['disabled'] == true) { + $hiddenOptions['disabled'] = 'disabled'; + } + $output = $this->hidden($fieldName, $hiddenOptions); return $this->output($output . sprintf( $this->Html->tags['checkbox'], @@ -935,7 +939,7 @@ class FormHelper extends AppHelper { if (!isset($value) || $value === '') { $hidden = $this->hidden($fieldName, array( - 'id' => $attributes['id'] . '_', 'value' => '' + 'id' => $attributes['id'] . '_', 'value' => '', 'name' => $attributes['name'] )); } $out = $hidden . join($inbetween, $out); diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index 4599723b6..38d7ee1c3 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -325,8 +325,10 @@ class HtmlHelper extends AppHelper { /** * Creates a link element for CSS stylesheets. * - * @param mixed $path The name of a CSS style sheet in /app/webroot/css, or an array containing names of CSS stylesheets in that directory. - * @param string $rel Rel attribute. Defaults to "stylesheet". + * @param mixed $path The name of a CSS style sheet or an array containing names of + * CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot + * of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css. + * @param string $rel Rel attribute. Defaults to "stylesheet". If equal to 'import' the stylesheet will be imported. * @param array $htmlAttributes Array of HTML attributes. * @param boolean $inline If set to false, the generated tag appears in the head tag of the layout. * @return string CSS or