From 798a9d5e43ae81e0b12d8ac6002b172a20ede47b Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Apr 2009 23:15:28 -0400 Subject: [PATCH 001/207] Adding `cake bake model all`. --- cake/console/libs/tasks/model.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 464d5bae5..558250d48 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -64,6 +64,9 @@ class ModelTask extends Shell { } if (!empty($this->args[0])) { + if (strtolower($this->args[0]) == 'all') { + return $this->all(); + } $model = Inflector::camelize($this->args[0]); if ($this->bake($model)) { if ($this->_checkUnitTest()) { @@ -72,6 +75,31 @@ class ModelTask extends Shell { } } } +/** + * Bake all models at once. + * + * @return void + **/ + function all() { + $ds = 'default'; + if (isset($this->params['connection'])) { + $ds = $this->params['connection']; + } + $this->listAll($ds, false); + foreach ($this->__tables as $table) { + $modelClass = Inflector::classify($table); + $this->out(sprintf(__('Baking %s', true), $modelClass)); + + if (App::import('Model', $modelClass)) { + $object = new $modelClass(); + $modelExists = true; + } else { + App::import('Model'); + $object = new Model(array('name' => $modelClass, 'ds' => $ds)); + } + $this->bake($object, false); + } + } /** * Handles interactive baking * From f0543987e1608b5df334101ea9c42d536705a112 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Apr 2009 23:36:57 -0400 Subject: [PATCH 002/207] Adding `cake bake controller all` --- cake/console/libs/tasks/controller.php | 44 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index aefe126ea..491fb64e6 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -70,6 +70,9 @@ class ControllerTask extends Shell { } if (isset($this->args[0])) { + if (strtolower($this->args[0]) == 'all') { + return $this->all(); + } $controller = Inflector::camelize($this->args[0]); $actions = null; if (isset($this->args[1]) && $this->args[1] == 'scaffold') { @@ -95,6 +98,28 @@ class ControllerTask extends Shell { } } } +/** + * Bake All the controllers at once. Will only bake controllers for models that exist. + * + * @access public + * @return void + **/ + function all() { + $ds = 'default'; + $ds = 'default'; + if (isset($this->params['connection'])) { + $ds = $this->params['connection']; + } + $controllers = $this->listAll($ds, false); + foreach ($this->__tables as $table) { + $model = $this->_modelName($table); + $controller = $this->_controllerName($model); + if (App::import('Model', $model)) { + $actions = $this->bakeActions($controller); + $this->bake($controller, $actions); + } + } + } /** * Interactive * @@ -488,10 +513,11 @@ class ControllerTask extends Shell { * Outputs and gets the list of possible models or controllers from database * * @param string $useDbConfig Database configuration name + * @param boolean $interactive Whether you are using listAll interactively and want options output. * @return array Set of controllers * @access public */ - function listAll($useDbConfig = 'default') { + function listAll($useDbConfig = 'default', $interactive = true) { $db =& ConnectionManager::getDataSource($useDbConfig); $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; if ($usePrefix) { @@ -511,14 +537,16 @@ class ControllerTask extends Shell { } $this->__tables = $tables; - $this->out('Possible Controllers based on your current database:'); - $this->_controllerNames = array(); - $count = count($tables); - for ($i = 0; $i < $count; $i++) { - $this->_controllerNames[] = $this->_controllerName($this->_modelName($tables[$i])); - $this->out($i + 1 . ". " . $this->_controllerNames[$i]); + if ($interactive == true) { + $this->out('Possible Controllers based on your current database:'); + $this->_controllerNames = array(); + $count = count($tables); + for ($i = 0; $i < $count; $i++) { + $this->_controllerNames[] = $this->_controllerName($this->_modelName($tables[$i])); + $this->out($i + 1 . ". " . $this->_controllerNames[$i]); + } + return $this->_controllerNames; } - return $this->_controllerNames; } /** From 73b9cbfeadc47223bf8151982bdbbc396710e0b6 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Apr 2009 23:43:06 -0400 Subject: [PATCH 003/207] Adding help text entries for controller all and model all. --- cake/console/libs/tasks/controller.php | 1 + cake/console/libs/tasks/model.php | 1 + 2 files changed, 2 insertions(+) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 491fb64e6..ff1921fa2 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -597,6 +597,7 @@ class ControllerTask extends Shell { $this->out("\n\tcontroller scaffold\n\t\tbakes controller with scaffold actions.\n\t\t(index, view, add, edit, delete)"); $this->out("\n\tcontroller scaffold admin\n\t\tbakes a controller with scaffold actions for both public and Configure::read('Routing.admin')"); $this->out("\n\tcontroller admin\n\t\tbakes a controller with scaffold actions only for Configure::read('Routing.admin')"); + $this->out("\n\tcontroller all\n\t\tbakes all controllers with CRUD methods."); $this->out(""); $this->_stop(); } diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 558250d48..4a334529b 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -847,6 +847,7 @@ class ModelTask extends Shell { $this->out('Commands:'); $this->out("\n\tmodel\n\t\tbakes model in interactive mode."); $this->out("\n\tmodel \n\t\tbakes model file with no associations or validation"); + $this->out("\n\tmodel all\n\t\tbakes all model files with associations and validation"); $this->out(""); $this->_stop(); } From 1291d4f02527e82fdaa3eac19cf88aa79fb06214 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Apr 2009 23:55:34 -0400 Subject: [PATCH 004/207] Adding `cake bake view all` --- cake/console/libs/tasks/view.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index 4dfdc5089..83050228c 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -114,6 +114,10 @@ class ViewTask extends Shell { if (!$action) { $action = $this->template; } + + if (strtolower($this->args[0]) == 'all') { + return $this->all(); + } if (in_array($action, $this->scaffoldActions)) { $this->bake($action, true); @@ -146,6 +150,30 @@ class ViewTask extends Shell { } } } +/** + * Bake All views for All controllers. + * + * @return void + **/ + function all() { + $ds = 'default'; + $actions = $this->scaffoldActions; + $tables = $this->Controller->listAll($ds, false); + foreach ($tables as $table) { + $model = $this->_modelName($table); + $this->controllerName = $this->_controllerName($model); + $this->controllerPath = Inflector::underscore($this->controllerName); + if (App::import('Model', $model)) { + $vars = $this->__loadController(); + if ($vars) { + foreach ($actions as $action) { + $content = $this->getContent($action, $vars); + $this->bake($action, $content); + } + } + } + } + } /** * Handles interactive baking * From f7a7b077408926e0c46fafa63e5b14c2a7e4cdc8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Apr 2009 23:58:36 -0400 Subject: [PATCH 005/207] Turning off interactive for bake all commands. --- cake/console/libs/tasks/controller.php | 5 +++-- cake/console/libs/tasks/model.php | 2 ++ cake/console/libs/tasks/view.php | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index ff1921fa2..ca05b0b28 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -105,11 +105,11 @@ class ControllerTask extends Shell { * @return void **/ function all() { - $ds = 'default'; $ds = 'default'; if (isset($this->params['connection'])) { $ds = $this->params['connection']; } + $this->interactive = false; $controllers = $this->listAll($ds, false); foreach ($this->__tables as $table) { $model = $this->_modelName($table); @@ -547,6 +547,7 @@ class ControllerTask extends Shell { } return $this->_controllerNames; } + return $this->__tables; } /** @@ -557,7 +558,7 @@ class ControllerTask extends Shell { */ function getName() { $useDbConfig = 'default'; - $controllers = $this->listAll($useDbConfig, 'Controllers'); + $controllers = $this->listAll($useDbConfig); $enteredController = ''; while ($enteredController == '') { diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 4a334529b..baffcd724 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -86,6 +86,8 @@ class ModelTask extends Shell { $ds = $this->params['connection']; } $this->listAll($ds, false); + $this->interactive = false; + foreach ($this->__tables as $table) { $modelClass = Inflector::classify($table); $this->out(sprintf(__('Baking %s', true), $modelClass)); diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index 83050228c..b85dac809 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -159,6 +159,7 @@ class ViewTask extends Shell { $ds = 'default'; $actions = $this->scaffoldActions; $tables = $this->Controller->listAll($ds, false); + $this->interactive = false; foreach ($tables as $table) { $model = $this->_modelName($table); $this->controllerName = $this->_controllerName($model); From b5cc69c37c454e4152c5b93fb4ee40448bea5a8c Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 28 Apr 2009 20:32:15 -0400 Subject: [PATCH 006/207] Adding Fixture task to bake. --- cake/console/libs/bake.php | 8 +- cake/console/libs/tasks/fixture.php | 139 ++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 cake/console/libs/tasks/fixture.php diff --git a/cake/console/libs/bake.php b/cake/console/libs/bake.php index f891ca2a4..1a21780e8 100644 --- a/cake/console/libs/bake.php +++ b/cake/console/libs/bake.php @@ -40,7 +40,7 @@ class BakeShell extends Shell { * @var array * @access public */ - var $tasks = array('Project', 'DbConfig', 'Model', 'Controller', 'View', 'Plugin', 'Test'); + var $tasks = array('Project', 'DbConfig', 'Model', 'Controller', 'View', 'Plugin', 'Fixture', 'Test'); /** * Override loadTasks() to handle paths * @@ -49,7 +49,7 @@ class BakeShell extends Shell { function loadTasks() { parent::loadTasks(); $task = Inflector::classify($this->command); - if (isset($this->{$task}) && !in_array($task, array('Project', 'DbConfig'))) { + if (isset($this->{$task}) && !in_array($task, array('Project', 'DbConfig', 'Fixture'))) { $path = Inflector::underscore(Inflector::pluralize($this->command)); $this->{$task}->path = $this->params['working'] . DS . $path . DS; if (!is_dir($this->{$task}->path)) { @@ -82,6 +82,7 @@ class BakeShell extends Shell { $this->out('[V]iew'); $this->out('[C]ontroller'); $this->out('[P]roject'); + $this->out('[F]ixture'); $this->out('[Q]uit'); $classToBake = strtoupper($this->in(__('What would you like to Bake?', true), array('D', 'M', 'V', 'C', 'P', 'Q'))); @@ -101,6 +102,9 @@ class BakeShell extends Shell { case 'P': $this->Project->execute(); break; + case 'F': + $this->Fixture->execute(); + break; case 'Q': exit(0); break; diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php new file mode 100644 index 000000000..051234385 --- /dev/null +++ b/cake/console/libs/tasks/fixture.php @@ -0,0 +1,139 @@ +path = $this->params['working'] . DS . 'tests' . DS . 'fixtures' . DS; + } +/** + * Execution method always used for tasks + * + * @access public + */ + function execute() { + if (empty($this->args)) { + $this->__interactive(); + } + + if (isset($this->args[0])) { + if (strtolower($this->args[0]) == 'all') { + return $this->all(); + } + $controller = Inflector::camelize($this->args[0]); + $actions = null; + if (isset($this->args[1]) && $this->args[1] == 'scaffold') { + $this->out('Baking scaffold for ' . $controller); + $actions = $this->bakeActions($controller); + } else { + $actions = 'scaffold'; + } + if ($this->bake($controller, $actions)) { + if ($this->_checkUnitTest()) { + $this->bakeTest($controller); + } + } + } + } + +/** + * Bake All the Fixtures at once. Will only bake fixtures for models that exist. + * + * @access public + * @return void + **/ + function all() { + $ds = 'default'; + if (isset($this->params['connection'])) { + $ds = $this->params['connection']; + } + } + +/** + * Interactive baking function + * + * @access private + */ + function __interactive($modelName = false) { + + } + +/** + * Assembles and writes a Fixture file + * + * @return string Baked fixture + * @access private + */ + function bake() { + + } + +/** + * Displays help contents + * + * @access public + */ + function help() { + $this->hr(); + $this->out("Usage: cake bake fixture ..."); + $this->hr(); + $this->out('Commands:'); + $this->out("\n\fixture \n\t\tbakes fixture with specified name."); + $this->out("\n\fixture all\n\t\tbakes all fixtures."); + $this->out(""); + $this->_stop(); + } +} +?> From 802ed73c0a7a03c6dc5c53cd127f6f9f1f2f208b Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 28 Apr 2009 20:44:23 -0400 Subject: [PATCH 007/207] Adding getConfig() so other tasks can pick connections more easily. --- cake/console/libs/tasks/db_config.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cake/console/libs/tasks/db_config.php b/cake/console/libs/tasks/db_config.php index 8fa5f8c23..856b1226c 100644 --- a/cake/console/libs/tasks/db_config.php +++ b/cake/console/libs/tasks/db_config.php @@ -349,5 +349,25 @@ class DbConfigTask extends Shell { $filename = $this->path.'database.php'; return $this->createFile($filename, $out); } + +/** + * Get a user specified Connection name + * + * @return void + **/ + function getConfig() { + $useDbConfig = 'default'; + $configs = get_class_vars('DATABASE_CONFIG'); + + if (!is_array($configs)) { + return $this->execute(); + } + + $connections = array_keys($configs); + if (count($connections) > 1) { + $useDbConfig = $this->in(__('Use Database Config', true) .':', $connections, 'default'); + } + return $useDbConfig; + } } ?> \ No newline at end of file From 0b40e5c709ea16ae865574f32763a3a859bb9f94 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 28 Apr 2009 20:45:07 -0400 Subject: [PATCH 008/207] Refactoring out to use DbConfig::getConfig Continuing fixture bake --- cake/console/libs/tasks/fixture.php | 9 +++++++-- cake/console/libs/tasks/model.php | 14 ++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 051234385..8ae1534f3 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -42,7 +42,7 @@ class FixtureTask extends Shell { * @var array * @access public */ - var $tasks = array('Model'); + var $tasks = array('DbConfig', 'Model'); /** * path to fixtures directory * @@ -107,7 +107,12 @@ class FixtureTask extends Shell { * @access private */ function __interactive($modelName = false) { - + $this->interactive = true; + $this->hr(); + $this->out(sprintf("Bake Fixture\nPath: %s", $this->path)); + $this->hr(); + + $useDbConfig = $this->DbConfig->getConfig(); } /** diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index baffcd724..b8bfcb7d2 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -117,18 +117,8 @@ class ModelTask extends Shell { $primaryKey = 'id'; $validate = array(); $associations = array('belongsTo'=> array(), 'hasOne'=> array(), 'hasMany' => array(), 'hasAndBelongsToMany'=> array()); - - $useDbConfig = 'default'; - $configs = get_class_vars('DATABASE_CONFIG'); - - if (!is_array($configs)) { - return $this->DbConfig->execute(); - } - - $connections = array_keys($configs); - if (count($connections) > 1) { - $useDbConfig = $this->in(__('Use Database Config', true) .':', $connections, 'default'); - } + + $useDbConfig = $this->DbConfig->getConfig(); $currentModelName = $this->getName($useDbConfig); $db =& ConnectionManager::getDataSource($useDbConfig); From d705e8943ab28839781483fa22974cadc3480806 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 28 Apr 2009 21:20:34 -0400 Subject: [PATCH 009/207] Refactoring table naming interaction into getTable() --- cake/console/libs/tasks/model.php | 52 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index b8bfcb7d2..d4e19f96d 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -119,33 +119,10 @@ class ModelTask extends Shell { $associations = array('belongsTo'=> array(), 'hasOne'=> array(), 'hasMany' => array(), 'hasAndBelongsToMany'=> array()); $useDbConfig = $this->DbConfig->getConfig(); - $currentModelName = $this->getName($useDbConfig); + $useTable = $this->getTable($currentModelName, $useDbConfig); $db =& ConnectionManager::getDataSource($useDbConfig); - $useTable = Inflector::tableize($currentModelName); - $fullTableName = $db->fullTableName($useTable, false); - $tableIsGood = false; - - if (array_search($useTable, $this->__tables) === false) { - $this->out(''); - $this->out(sprintf(__("Given your model named '%s', Cake would expect a database table named %s", true), $currentModelName, $fullTableName)); - $tableIsGood = $this->in(__('Do you want to use this table?', true), array('y','n'), 'y'); - } - - if (low($tableIsGood) == 'n' || low($tableIsGood) == 'no') { - $useTable = $this->in(__('What is the name of the table (enter "null" to use NO table)?', true)); - } - - while ($tableIsGood == false && low($useTable) != 'null') { - if (is_array($this->__tables) && !in_array($useTable, $this->__tables)) { - $fullTableName = $db->fullTableName($useTable, false); - $this->out($fullTableName . ' does not exist.'); - $useTable = $this->in(__('What is the name of the table (enter "null" to use NO table)?', true)); - $tableIsGood = false; - } else { - $tableIsGood = true; - } - } + $fullTableName = $db->fullTableName($useTable); $wannaDoValidation = $this->in(__('Would you like to supply validation criteria for the fields in your model?', true), array('y','n'), 'y'); @@ -794,6 +771,29 @@ class ModelTask extends Shell { } } } +/** + * Interact with the user to determine the table name of a particular model + * + * @param string $modelName Name of the model you want a table for. + * @param string $useDbConfig Name of the database config you want to get tables from. + * @return void + **/ + function getTable($modelName, $useDbConfig) { + $db =& ConnectionManager::getDataSource($useDbConfig); + $useTable = Inflector::tableize($modelName); + $fullTableName = $db->fullTableName($useTable, false); + $tableIsGood = false; + + if (array_search($useTable, $this->__tables) === false) { + $this->out(''); + $this->out(sprintf(__("Given your model named '%s', Cake would expect a database table named '%s'", true), $modelName, $fullTableName)); + $tableIsGood = $this->in(__('Do you want to use this table?', true), array('y','n'), 'y'); + } + if (low($tableIsGood) == 'n' || low($tableIsGood) == 'no') { + $useTable = $this->in(__('What is the name of the table (enter "null" to use NO table)?', true)); + } + return $useTable; + } /** * Forces the user to specify the model he wants to bake, and returns the selected model name. * @@ -818,13 +818,11 @@ class ModelTask extends Shell { $enteredModel = ''; } } - if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) { $currentModelName = $this->_modelNames[intval($enteredModel) - 1]; } else { $currentModelName = $enteredModel; } - return $currentModelName; } /** From 0b2232d05a1daf2630e8d30c2022c278053fa8b9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 20:52:12 -0400 Subject: [PATCH 010/207] Updating fixture task. Refactored methods. Multiple rows can now be generated. --- cake/console/libs/tasks/fixture.php | 189 +++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 15 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 8ae1534f3..f28193b82 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -57,6 +57,9 @@ class FixtureTask extends Shell { */ function initialize() { $this->path = $this->params['working'] . DS . 'tests' . DS . 'fixtures' . DS; + if (!class_exists('CakeSchema')) { + App::import('Model', 'Schema'); + } } /** * Execution method always used for tasks @@ -72,19 +75,7 @@ class FixtureTask extends Shell { if (strtolower($this->args[0]) == 'all') { return $this->all(); } - $controller = Inflector::camelize($this->args[0]); - $actions = null; - if (isset($this->args[1]) && $this->args[1] == 'scaffold') { - $this->out('Baking scaffold for ' . $controller); - $actions = $this->bakeActions($controller); - } else { - $actions = 'scaffold'; - } - if ($this->bake($controller, $actions)) { - if ($this->_checkUnitTest()) { - $this->bakeTest($controller); - } - } + $model = Inflector::camelize($this->args[0]); } } @@ -113,16 +104,184 @@ class FixtureTask extends Shell { $this->hr(); $useDbConfig = $this->DbConfig->getConfig(); + $modelName = $this->Model->getName($useDbConfig); + $useTable = $this->Model->getTable($modelName, $useDbConfig); + $importOptions = $this->importOptions($modelName); + $this->bake($modelName, $useTable, $importOptions); + } +/** + * Interacts with the User to setup an array of import options. For a fixture. + * + * @param string $modelName Name of model you are dealing with. + * @return array Array of import options. + **/ + function importOptions($modelName) { + $options = array(); + $doSchema = $this->in('Would you like to import schema for this fixture?', array('y', 'n'), 'n'); + if ($doSchema == 'y') { + $options['schema'] = $modelName; + } + $doRecords = $this->in('Would you like to import records for this fixture?', array('y', 'n'), 'n'); + if ($doRecords == 'y') { + $options['records'] = true; + } + return $options; } /** * Assembles and writes a Fixture file * + * @param string $model Name of model to bake. + * @param string $useTable Name of table to use. + * @param array $importOptions Options for var $import * @return string Baked fixture * @access private */ - function bake() { - + function bake($model, $useTable = false, $importOptions = array()) { + $out = "\nclass {$model}Fixture extends CakeTestFixture {\n"; + $out .= "\tvar \$name = '$model';\n"; + + if (!$useTable) { + $useTable = Inflector::tableize($model); + } elseif ($useTable != Inflector::tableize($model)) { + $out .= "\tvar \$table = '$useTable';\n"; + } + + $modelImport = $recordImport = null; + if (!empty($importOptions)) { + if (isset($importOptions['schema'])) { + $modelImport = "'model' => '{$importOptions['schema']}'"; + } + if (isset($importOptions['records'])) { + $recordImport = ", 'records' => true"; + } + $out .= sprintf("\tvar \$import = array(%s%s);\n", $modelImport, $recordImport); + } + + $this->_Schema = new CakeSchema(); + $data = $this->_Schema->read(array('models' => false)); + + if (!isset($data['tables'][$useTable])) { + $this->err('Could not find your selected table ' . $useTable); + return false; + } + + $tableInfo = $data['tables'][$useTable]; + if (is_null($modelImport)) { + $out .= $this->_generateSchema($tableInfo); + } + + if (is_null($recordImport)) { + $recordCount = 1; + if (isset($this->params['count'])) { + $recordCount = $this->params['count']; + } + $out .= $this->_generateRecords($tableInfo, $recordCount); + } + $out .= "}\n"; + + $path = TESTS . DS . 'fixtures' . DS; + if (isset($this->plugin)) { + $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; + $path = APP . $pluginPath . 'tests' . DS . 'fixtures' . DS; + } + $filename = Inflector::underscore($model).'_fixture.php'; + $header = '$Id'; + $content = ""; + $this->out("\nBaking test fixture for $model..."); + $this->createFile($path . $filename, $content); + } + +/** + * Generates a string representation of a schema. + * + * @param array $table Table schema array + * @return string fields definitions + **/ + function _generateSchema($tableInfo) { + $cols = array(); + $out = "\n\tvar \$fields = array(\n"; + foreach ($tableInfo as $field => $fieldInfo) { + if (is_array($fieldInfo)) { + if ($field != 'indexes') { + $col = "\t\t'{$field}' => array('type'=>'" . $fieldInfo['type'] . "', "; + $col .= join(', ', $this->_Schema->__values($fieldInfo)); + } else { + $col = "\t\t'indexes' => array("; + $props = array(); + foreach ((array)$fieldInfo as $key => $index) { + $props[] = "'{$key}' => array(".join(', ', $this->_Schema->__values($index)).")"; + } + $col .= join(', ', $props); + } + $col .= ")"; + $cols[] = $col; + } + } + $out .= join(",\n", $cols); + $out .= "\n\t);\n"; + return $out; + } + +/** + * Generate String representation of Records + * + * @param array $table Table schema array + * @return string + **/ + function _generateRecords($tableInfo, $recordCount = 1) { + $out = "\t\$records = array(\n"; + + for ($i = 0; $i < $recordCount; $i++) { + $records = array(); + foreach ($tableInfo as $field => $fieldInfo) { + if (empty($fieldInfo['type'])) { + continue; + } + switch ($fieldInfo['type']) { + case 'integer': + $insert = $i + 1; + break; + case 'string'; + $insert = "Lorem ipsum dolor sit amet"; + if (!empty($fieldInfo['length'])) { + $insert = substr($insert, 0, (int)$value['length'] - 2); + } + $insert = "'$insert'"; + break; + case 'datetime': + $ts = date('Y-m-d H:i:s'); + $insert = "'$ts'"; + break; + case 'date': + $ts = date('Y-m-d'); + $insert = "'$ts'"; + break; + case 'time': + $ts = date('H:i:s'); + $insert = "'$ts'"; + break; + case 'boolean': + $insert = 1; + break; + case 'text': + $insert = "'Lorem ipsum dolor sit amet, aliquet feugiat."; + $insert .= " Convallis morbi fringilla gravida,"; + $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin"; + $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla"; + $insert .= " vestibulum massa neque ut et, id hendrerit sit,"; + $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus"; + $insert .= " duis vestibulum nunc mattis convallis.'"; + break; + } + $records[] = "\t\t\t'$field' => $insert"; + } + $out .= "\t\tarray(\n"; + $out .= implode(",\n", $records); + $out .= "\n\t\t),\n"; + } + $out .= "\t);\n"; + return $out; } /** From f992406501e78df94487152d46bded282ee9b644 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 21:18:08 -0400 Subject: [PATCH 011/207] Removing fixture generation from ModelTask --- cake/console/libs/tasks/model.php | 218 ++++++++---------------------- 1 file changed, 54 insertions(+), 164 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index d4e19f96d..ff9910b0b 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -52,7 +52,7 @@ class ModelTask extends Shell { * @var array * @access public */ - var $tasks = array('DbConfig'); + var $tasks = array('DbConfig', 'Fixture'); /** * Execution method always used for tasks * @@ -673,67 +673,61 @@ class ModelTask extends Shell { * @access private */ function bakeTest($className, $useTable = null, $associations = array()) { - $results = $this->fixture($className, $useTable); + $this->fixture($className, $useTable); - if ($results) { - $fixtureInc = 'app'; - if ($this->plugin) { - $fixtureInc = 'plugin.'.Inflector::underscore($this->plugin); - } + $fixtureInc = 'app'; + if ($this->plugin) { + $fixtureInc = 'plugin.'.Inflector::underscore($this->plugin); + } - $fixture[] = "'{$fixtureInc}." . Inflector::underscore($className) ."'"; + $fixture[] = "'{$fixtureInc}." . Inflector::underscore($className) ."'"; - if (!empty($associations)) { - $assoc[] = Set::extract($associations, 'belongsTo.{n}.className'); - $assoc[] = Set::extract($associations, 'hasOne.{n}.className'); - $assoc[] = Set::extract($associations, 'hasMany.{n}.className'); - foreach ($assoc as $key => $value) { - if (is_array($value)) { - foreach ($value as $class) { - $fixture[] = "'{$fixtureInc}." . Inflector::underscore($class) ."'"; - } + if (!empty($associations)) { + $assoc[] = Set::extract($associations, 'belongsTo.{n}.className'); + $assoc[] = Set::extract($associations, 'hasOne.{n}.className'); + $assoc[] = Set::extract($associations, 'hasMany.{n}.className'); + foreach ($assoc as $key => $value) { + if (is_array($value)) { + foreach ($value as $class) { + $fixture[] = "'{$fixtureInc}." . Inflector::underscore($class) ."'"; } } } - $fixture = join(", ", $fixture); - - $import = $className; - if (isset($this->plugin)) { - $import = $this->plugin . '.' . $className; - } - - $out = "App::import('Model', '$import');\n\n"; - $out .= "class {$className}TestCase extends CakeTestCase {\n"; - $out .= "\tvar \${$className} = null;\n"; - $out .= "\tvar \$fixtures = array($fixture);\n\n"; - $out .= "\tfunction startTest() {\n"; - $out .= "\t\t\$this->{$className} =& ClassRegistry::init('{$className}');\n"; - $out .= "\t}\n\n"; - $out .= "\tfunction test{$className}Instance() {\n"; - $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}'));\n"; - $out .= "\t}\n\n"; - $out .= "\tfunction test{$className}Find() {\n"; - $out .= "\t\t\$this->{$className}->recursive = -1;\n"; - $out .= "\t\t\$results = \$this->{$className}->find('first');\n\t\t\$this->assertTrue(!empty(\$results));\n\n"; - $out .= "\t\t\$expected = array('$className' => array(\n$results\n\t\t));\n"; - $out .= "\t\t\$this->assertEqual(\$results, \$expected);\n"; - $out .= "\t}\n"; - $out .= "}\n"; - - $path = MODEL_TESTS; - if (isset($this->plugin)) { - $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; - $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'models' . DS; - } - - $filename = Inflector::underscore($className).'.test.php'; - $this->out("\nBaking unit test for $className..."); - - $header = '$Id'; - $content = ""; - return $this->createFile($path . $filename, $content); } - return false; + $fixture = join(", ", $fixture); + + $import = $className; + if (isset($this->plugin)) { + $import = $this->plugin . '.' . $className; + } + + $out = "App::import('Model', '$import');\n\n"; + $out .= "class {$className}TestCase extends CakeTestCase {\n"; + $out .= "\tvar \${$className} = null;\n"; + $out .= "\tvar \$fixtures = array($fixture);\n\n"; + $out .= "\tfunction startTest() {\n"; + $out .= "\t\t\$this->{$className} =& ClassRegistry::init('{$className}');\n"; + $out .= "\t}\n\n"; + $out .= "\tfunction endTest() {\n"; + $out .= "\t\tunset(\$this->{$className});\n"; + $out .= "\t}\n\n"; + $out .= "\tfunction test{$className}Instance() {\n"; + $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}'));\n"; + $out .= "\t}\n\n"; + $out .= "}\n"; + + $path = MODEL_TESTS; + if (isset($this->plugin)) { + $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; + $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'models' . DS; + } + + $filename = Inflector::underscore($className).'.test.php'; + $this->out("\nBaking unit test for $className..."); + + $header = '$Id'; + $content = ""; + return $this->createFile($path . $filename, $content); } /** * outputs the a list of possible models or controllers from database @@ -842,116 +836,12 @@ class ModelTask extends Shell { $this->_stop(); } /** - * Builds the tests fixtures for the model and create the file + * Interact with FixtureTask to automatically bake fixtures when baking models. * - * @param string $model the name of the model - * @param string $useTable table name - * @return array $records, used in ModelTask::bakeTest() to create $expected - * @todo move this to a task - */ - function fixture($model, $useTable = null) { - if (!class_exists('CakeSchema')) { - App::import('Model', 'Schema'); - } - $out = "\nclass {$model}Fixture extends CakeTestFixture {\n"; - $out .= "\tvar \$name = '$model';\n"; - - if (!$useTable) { - $useTable = Inflector::tableize($model); - } else { - $out .= "\tvar \$table = '$useTable';\n"; - } - $schema = new CakeSchema(); - $data = $schema->read(array('models' => false)); - - if (!isset($data['tables'][$useTable])) { - return false; - } - $tables[$model] = $data['tables'][$useTable]; - - foreach ($tables as $table => $fields) { - if (!is_numeric($table) && $table !== 'missing') { - $out .= "\tvar \$fields = array(\n"; - $records = array(); - if (is_array($fields)) { - $cols = array(); - foreach ($fields as $field => $value) { - if ($field != 'indexes') { - if (is_string($value)) { - $type = $value; - $value = array('type'=> $type); - } - $col = "\t\t'{$field}' => array('type'=>'" . $value['type'] . "', "; - - switch ($value['type']) { - case 'integer': - $insert = 1; - break; - case 'string'; - $insert = "Lorem ipsum dolor sit amet"; - if (!empty($value['length'])) { - $insert = substr($insert, 0, (int)$value['length'] - 2); - } - $insert = "'$insert'"; - break; - case 'datetime': - $ts = date('Y-m-d H:i:s'); - $insert = "'$ts'"; - break; - case 'date': - $ts = date('Y-m-d'); - $insert = "'$ts'"; - break; - case 'time': - $ts = date('H:i:s'); - $insert = "'$ts'"; - break; - case 'boolean': - $insert = 1; - break; - case 'text': - $insert = - "'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida,"; - $insert .= "phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam,"; - $insert .= "vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit,"; - $insert .= "feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.'"; - break; - } - $records[] = "\t\t'$field' => $insert"; - unset($value['type']); - $col .= join(', ', $schema->__values($value)); - } else { - $col = "\t\t'indexes' => array("; - $props = array(); - foreach ((array)$value as $key => $index) { - $props[] = "'{$key}' => array(".join(', ', $schema->__values($index)).")"; - } - $col .= join(', ', $props); - } - $col .= ")"; - $cols[] = $col; - } - $out .= join(",\n", $cols); - } - $out .= "\n\t);\n"; - } - } - $records = join(",\n", $records); - $out .= "\tvar \$records = array(array(\n$records\n\t));\n"; - $out .= "}\n"; - $path = TESTS . DS . 'fixtures' . DS; - if (isset($this->plugin)) { - $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; - $path = APP . $pluginPath . 'tests' . DS . 'fixtures' . DS; - } - $filename = Inflector::underscore($model).'_fixture.php'; - $header = '$Id'; - $content = ""; - $this->out("\nBaking test fixture for $model..."); - if ($this->createFile($path . $filename, $content)) { - return str_replace("\t\t", "\t\t\t", $records); - } - return false; + * @return null. + **/ + function fixture($className, $useTable = null) { + $this->Fixture->bake($className, $useTable); } } ?> \ No newline at end of file From aad2bd702dca4b538c2f6defdf63cad4ec19377a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:17:08 -0400 Subject: [PATCH 012/207] Adding test case for Model Task --- .../cases/console/libs/tasks/model.test.php | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 cake/tests/cases/console/libs/tasks/model.test.php diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php new file mode 100644 index 000000000..b9557d809 --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -0,0 +1,123 @@ +Dispatcher =& new TestModelTaskMockShellDispatcher(); + $this->Task =& new MockModelTask($this->Dispatcher); + $this->Task->Dispatch = new $this->Dispatcher; + } +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + unset($this->Task, $this->Dispatcher); + ClassRegistry::flush(); + } +/** + * Test that listAll scans the database connection and lists all the tables in it.s + * + * @return void + **/ + function testListAll() { + $this->Task->expectCallCount('out', 3); + $this->Task->expectAt(1, 'out', array('1. Article')); + $this->Task->expectAt(2, 'out', array('2. Comment')); + $this->Task->listAll('test_suite'); + } + +/** + * Test that listAll scans the database connection and lists all the tables in it.s + * + * @return void + **/ + function testGetName() { + $this->Task->setReturnValue('in', 1); + + //test quit. + $this->Task->setReturnValueAt(0, 'in', 'q'); + $this->Task->expectOnce('_stop'); + $this->Task->getName('test_suite'); + + $this->Task->setReturnValueAt(1, 'in', 1); + $result = $this->Task->getName('test_suite'); + $expected = 'Article'; + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(2, 'in', 2); + $result = $this->Task->getName('test_suite'); + $expected = 'Comment'; + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(3, 'in', 10); + $result = $this->Task->getName('test_suite'); + $this->Task->expectOnce('err'); + } +} +?> \ No newline at end of file From 80287223f18b7963bbd2cec9d321222cc483c16c Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:25:42 -0400 Subject: [PATCH 013/207] Additional Test for ModelTask --- cake/console/libs/tasks/model.php | 6 +++++ .../cases/console/libs/tasks/model.test.php | 23 ++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index ff9910b0b..df5021749 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -53,6 +53,12 @@ class ModelTask extends Shell { * @access public */ var $tasks = array('DbConfig', 'Fixture'); +/** + * Holds tables found on connection. + * + * @var array + **/ + var $__tables = array(); /** * Execution method always used for tasks * diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index b9557d809..c3fe80066 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -100,7 +100,6 @@ class ModelTaskTest extends CakeTestCase { function testGetName() { $this->Task->setReturnValue('in', 1); - //test quit. $this->Task->setReturnValueAt(0, 'in', 'q'); $this->Task->expectOnce('_stop'); $this->Task->getName('test_suite'); @@ -109,15 +108,33 @@ class ModelTaskTest extends CakeTestCase { $result = $this->Task->getName('test_suite'); $expected = 'Article'; $this->assertEqual($result, $expected); - + $this->Task->setReturnValueAt(2, 'in', 2); $result = $this->Task->getName('test_suite'); $expected = 'Comment'; $this->assertEqual($result, $expected); - + $this->Task->setReturnValueAt(3, 'in', 10); $result = $this->Task->getName('test_suite'); $this->Task->expectOnce('err'); } + +/** + * Test table name interactions + * + * @return void + **/ + function testGetTableName() { + $this->Task->setReturnValueAt(0, 'in', 'y'); + $result = $this->Task->getTable('Article', 'test_suite'); + $expected = 'articles'; + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(1, 'in', 'n'); + $this->Task->setReturnValueAt(2, 'in', 'my_table'); + $result = $this->Task->getTable('Article', 'test_suite'); + $expected = 'my_table'; + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file From 2b87be1d7c0d322ea4cce4f2b324d94668221e5a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:40:49 -0400 Subject: [PATCH 014/207] Updating FixtureTask help Adding test case for FixtureTask --- cake/console/libs/tasks/fixture.php | 7 +- .../cases/console/libs/tasks/fixture.test.php | 121 ++++++++++++++++++ .../cases/console/libs/tasks/model.test.php | 6 +- 3 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 cake/tests/cases/console/libs/tasks/fixture.test.php diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index f28193b82..cd9b8b33b 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -291,11 +291,12 @@ class FixtureTask extends Shell { */ function help() { $this->hr(); - $this->out("Usage: cake bake fixture ..."); + $this->out("Usage: cake bake fixture "); $this->hr(); $this->out('Commands:'); - $this->out("\n\fixture \n\t\tbakes fixture with specified name."); - $this->out("\n\fixture all\n\t\tbakes all fixtures."); + $this->out("\nfixture \n\tbakes fixture with specified name."); + $this->out("\nfixture -count \n\tbakes fixture with records."); + $this->out("\nfixture all\n\tbakes all fixtures."); $this->out(""); $this->_stop(); } diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php new file mode 100644 index 000000000..60abb371e --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -0,0 +1,121 @@ +Dispatcher =& new TestFixtureTaskMockShellDispatcher(); + $this->Task =& new MockFixtureTask($this->Dispatcher); + $this->Task->Dispatch = new $this->Dispatcher; + } +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + unset($this->Task, $this->Dispatcher); + ClassRegistry::flush(); + } +/** + * test that initialize sets the path + * + * @return void + **/ + function testInitialize() { + $this->Task->params['working'] = '/my/path'; + $this->Task->initialize(); + + $expected = '/my/path/tests/fixtures/'; + $this->assertEqual($this->Task->path, $expected); + } +/** + * test import option array generation + * + * @return void + **/ + function testImportOptions() { + $this->Task->setReturnValueAt(0, 'in', 'y'); + $this->Task->setReturnValueAt(1, 'in', 'y'); + + $result = $this->Task->importOptions('Article'); + $expected = array('schema' => 'Article', 'records' => true); + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(2, 'in', 'n'); + $this->Task->setReturnValueAt(3, 'in', 'n'); + + $result = $this->Task->importOptions('Article'); + $expected = array(); + $this->assertEqual($result, $expected); + } + +} +?> \ No newline at end of file diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index c3fe80066..5f6a35e01 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -57,7 +57,11 @@ Mock::generatePartial( * @subpackage cake.tests.cases.console.libs.tasks */ class ModelTaskTest extends CakeTestCase { - +/** + * fixtures + * + * @var array + **/ var $fixtures = array('core.article', 'core.comment'); /** * setUp method From d3fe3d59593f63e97624baee5873e1b44695fdf5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:42:11 -0400 Subject: [PATCH 015/207] Adding fixture baking --- cake/console/libs/tasks/fixture.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index cd9b8b33b..fa307a7f7 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -76,6 +76,7 @@ class FixtureTask extends Shell { return $this->all(); } $model = Inflector::camelize($this->args[0]); + return $this->bake($model); } } From 40ebdf8aac62eab983c22f3d001c547d24e8bbee Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:50:43 -0400 Subject: [PATCH 016/207] Adding fixture all command. Fixing errors with maxlength and timestamp fields Adding return for ModelTask::listAll() --- cake/console/libs/tasks/fixture.php | 12 +++++++++++- cake/console/libs/tasks/model.php | 1 + cake/tests/cases/console/libs/tasks/model.test.php | 6 +++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index fa307a7f7..a9f5b8054 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -91,6 +91,12 @@ class FixtureTask extends Shell { if (isset($this->params['connection'])) { $ds = $this->params['connection']; } + $this->interactive = false; + $tables = $this->Model->listAll($ds, false); + foreach ($tables as $table) { + $model = $this->_modelName($table); + $this->bake($model); + } } /** @@ -246,10 +252,14 @@ class FixtureTask extends Shell { case 'string'; $insert = "Lorem ipsum dolor sit amet"; if (!empty($fieldInfo['length'])) { - $insert = substr($insert, 0, (int)$value['length'] - 2); + $insert = substr($insert, 0, (int)$fieldInfo['length'] - 2); } $insert = "'$insert'"; break; + case 'timestamp': + $ts = time(); + $insert = "'$ts'"; + break; case 'datetime': $ts = date('Y-m-d H:i:s'); $insert = "'$ts'"; diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index df5021749..bcb38a01a 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -770,6 +770,7 @@ class ModelTask extends Shell { $this->out($i + 1 . ". " . $this->_modelNames[$i]); } } + return $this->__tables; } /** * Interact with the user to determine the table name of a particular model diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 5f6a35e01..954c5f2ad 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -74,6 +74,7 @@ class ModelTaskTest extends CakeTestCase { $this->Task =& new MockModelTask($this->Dispatcher); $this->Task->Dispatch = new $this->Dispatcher; } + /** * tearDown method * @@ -84,6 +85,7 @@ class ModelTaskTest extends CakeTestCase { unset($this->Task, $this->Dispatcher); ClassRegistry::flush(); } + /** * Test that listAll scans the database connection and lists all the tables in it.s * @@ -93,7 +95,9 @@ class ModelTaskTest extends CakeTestCase { $this->Task->expectCallCount('out', 3); $this->Task->expectAt(1, 'out', array('1. Article')); $this->Task->expectAt(2, 'out', array('2. Comment')); - $this->Task->listAll('test_suite'); + $result = $this->Task->listAll('test_suite'); + $expected = array('articles', 'comments'); + $this->assertEqual($result, $expected); } /** From 1cc3a6ecfb9e882a53384fe3f16776c5050b08fc Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Apr 2009 22:50:57 -0400 Subject: [PATCH 017/207] Removing unused variable. --- cake/console/libs/tasks/controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index ca05b0b28..ec69bb21f 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -110,7 +110,7 @@ class ControllerTask extends Shell { $ds = $this->params['connection']; } $this->interactive = false; - $controllers = $this->listAll($ds, false); + $this->listAll($ds, false); foreach ($this->__tables as $table) { $model = $this->_modelName($table); $controller = $this->_controllerName($model); From 6180ca80c9ae24537463ed667ccfe05a58055894 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 3 May 2009 20:48:13 -0400 Subject: [PATCH 018/207] Adding common parameter handling for connection and plugin params. --- cake/console/libs/bake.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cake/console/libs/bake.php b/cake/console/libs/bake.php index 1a21780e8..6277342d5 100644 --- a/cake/console/libs/bake.php +++ b/cake/console/libs/bake.php @@ -52,6 +52,12 @@ class BakeShell extends Shell { if (isset($this->{$task}) && !in_array($task, array('Project', 'DbConfig', 'Fixture'))) { $path = Inflector::underscore(Inflector::pluralize($this->command)); $this->{$task}->path = $this->params['working'] . DS . $path . DS; + if (isset($this->params['connection'])) { + $this->{$task}->connection = $this->params['connection']; + } + if (isset($this->params['plugin'])) { + $this->{$task}->plugin = $this->params['plugin']; + } if (!is_dir($this->{$task}->path)) { $this->err(sprintf(__("%s directory could not be found.\nBe sure you have created %s", true), $task, $this->{$task}->path)); $this->_stop(); From e21cc3db72bd7c63e9bb87cb0d6fdd7c24637592 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 3 May 2009 21:43:22 -0400 Subject: [PATCH 019/207] Adding test cases for bake() Adding support for -connection param Adding partial support for -plugin param Separating file writing and code generation functions. Updating help() --- cake/console/libs/tasks/fixture.php | 64 ++++++++++++++----- .../cases/console/libs/tasks/fixture.test.php | 50 ++++++++++++++- 2 files changed, 96 insertions(+), 18 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index a9f5b8054..8af08bdba 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -50,6 +50,12 @@ class FixtureTask extends Shell { * @access public */ var $path = null; +/** + * The db connection being used for baking + * + * @var string + **/ + var $connection = null; /** * Override initialize * @@ -63,6 +69,7 @@ class FixtureTask extends Shell { } /** * Execution method always used for tasks + * Handles dispatching to interactive, named, or all processess. * * @access public */ @@ -87,12 +94,11 @@ class FixtureTask extends Shell { * @return void **/ function all() { - $ds = 'default'; - if (isset($this->params['connection'])) { - $ds = $this->params['connection']; + if (!isset($this->connection)) { + $this->connection = 'default'; } $this->interactive = false; - $tables = $this->Model->listAll($ds, false); + $tables = $this->Model->listAll($this->connection, false); foreach ($tables as $table) { $model = $this->_modelName($table); $this->bake($model); @@ -110,9 +116,12 @@ class FixtureTask extends Shell { $this->out(sprintf("Bake Fixture\nPath: %s", $this->path)); $this->hr(); - $useDbConfig = $this->DbConfig->getConfig(); - $modelName = $this->Model->getName($useDbConfig); - $useTable = $this->Model->getTable($modelName, $useDbConfig); + $useDbConfig = $this->connection; + if (!isset($this->connection)) { + $this->connection = $this->DbConfig->getConfig(); + } + $modelName = $this->Model->getName($this->connection); + $useTable = $this->Model->getTable($modelName, $this->connection); $importOptions = $this->importOptions($modelName); $this->bake($modelName, $useTable, $importOptions); } @@ -145,7 +154,7 @@ class FixtureTask extends Shell { * @access private */ function bake($model, $useTable = false, $importOptions = array()) { - $out = "\nclass {$model}Fixture extends CakeTestFixture {\n"; + $out = "class {$model}Fixture extends CakeTestFixture {\n"; $out .= "\tvar \$name = '$model';\n"; if (!$useTable) { @@ -160,13 +169,16 @@ class FixtureTask extends Shell { $modelImport = "'model' => '{$importOptions['schema']}'"; } if (isset($importOptions['records'])) { - $recordImport = ", 'records' => true"; + $recordImport = "'records' => true"; + } + if ($modelImport && $recordImport) { + $modelImport .= ', '; } $out .= sprintf("\tvar \$import = array(%s%s);\n", $modelImport, $recordImport); } $this->_Schema = new CakeSchema(); - $data = $this->_Schema->read(array('models' => false)); + $data = $this->_Schema->read(array('models' => false, 'connection' => $this->connection)); if (!isset($data['tables'][$useTable])) { $this->err('Could not find your selected table ' . $useTable); @@ -186,15 +198,29 @@ class FixtureTask extends Shell { $out .= $this->_generateRecords($tableInfo, $recordCount); } $out .= "}\n"; + $this->generateFixtureFile($model, $out); + return $out; + } - $path = TESTS . DS . 'fixtures' . DS; +/** + * Generate the fixture file, and write to disk + * + * @param string $model name of the model being generated + * @param string $fixture Contents of the fixture file. + * @access public + * @return void + **/ + function generateFixtureFile($model, $fixture) { + //@todo fix plugin pathing. + $path = $this->path; if (isset($this->plugin)) { $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; $path = APP . $pluginPath . 'tests' . DS . 'fixtures' . DS; } - $filename = Inflector::underscore($model).'_fixture.php'; - $header = '$Id'; - $content = ""; + $filename = Inflector::underscore($model) . '_fixture.php'; + $content = ""; $this->out("\nBaking test fixture for $model..."); $this->createFile($path . $filename, $content); } @@ -226,7 +252,7 @@ class FixtureTask extends Shell { } } $out .= join(",\n", $cols); - $out .= "\n\t);\n"; + $out .= "\n\t);\n\n"; return $out; } @@ -237,7 +263,7 @@ class FixtureTask extends Shell { * @return string **/ function _generateRecords($tableInfo, $recordCount = 1) { - $out = "\t\$records = array(\n"; + $out = "\tvar \$records = array(\n"; for ($i = 0; $i < $recordCount; $i++) { $records = array(); @@ -306,9 +332,13 @@ class FixtureTask extends Shell { $this->hr(); $this->out('Commands:'); $this->out("\nfixture \n\tbakes fixture with specified name."); - $this->out("\nfixture -count \n\tbakes fixture with records."); $this->out("\nfixture all\n\tbakes all fixtures."); $this->out(""); + $this->out('Parameters:'); + $this->out("\t-count The number of records to include in the fixture(s)."); + $this->out("\t-connection Which database configuration to use for baking."); + $this->out("\t-plugin lowercased_underscored name of plugin to bake fixtures for."); + $this->out(""); $this->_stop(); } } diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 60abb371e..0f8f2a3c6 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -108,7 +108,7 @@ class FixtureTaskTest extends CakeTestCase { $result = $this->Task->importOptions('Article'); $expected = array('schema' => 'Article', 'records' => true); $this->assertEqual($result, $expected); - + $this->Task->setReturnValueAt(2, 'in', 'n'); $this->Task->setReturnValueAt(3, 'in', 'n'); @@ -116,6 +116,54 @@ class FixtureTaskTest extends CakeTestCase { $expected = array(); $this->assertEqual($result, $expected); } +/** + * Test that bake works + * + * @return void + **/ + function testBake() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $result = $this->Task->bake('Article'); + $this->assertPattern('/class ArticleFixture extends CakeTestFixture/', $result); + $this->assertPattern('/var \$fields/', $result); + $this->assertPattern('/var \$records/', $result); + $this->assertNoPattern('/var \$import/', $result); + + $result = $this->Task->bake('Article', 'comments'); + $this->assertPattern('/class ArticleFixture extends CakeTestFixture/', $result); + $this->assertPattern('/var \$name \= \'Article\';/', $result); + $this->assertPattern('/var \$table \= \'comments\';/', $result); + + $result = $this->Task->bake('Article', 'comments', array('records' => true)); + $this->assertPattern("/var \\\$import \= array\('records' \=\> true\);/", $result); + $this->assertNoPattern('/var \$records/', $result); + + $result = $this->Task->bake('Article', 'comments', array('schema' => 'Article')); + $this->assertPattern("/var \\\$import \= array\('model' \=\> 'Article'\);/", $result); + $this->assertNoPattern('/var \$fields/', $result); + + $result = $this->Task->bake('Article', 'comments', array('schema' => 'Article', 'records' => true)); + $this->assertPattern("/var \\\$import \= array\('model' \=\> 'Article'\, 'records' \=\> true\);/", $result); + $this->assertNoPattern('/var \$fields/', $result); + $this->assertNoPattern('/var \$records/', $result); + } +/** + * Test that file generation includes headers and correct path for plugins. + * + * @return void + **/ + function testGenerateFixtureFile() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $filename = '/my/path/article_fixture.php'; + + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/my fixture/'))); + $result = $this->Task->generateFixtureFile('Article', 'my fixture'); + + $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/\<\?php(.*)\?\>/ms'))); + $result = $this->Task->generateFixtureFile('Article', 'my fixture'); + } } ?> \ No newline at end of file From f4dc4bc1ede057ce55dec929f8e1f7f464f08225 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 4 May 2009 23:08:15 -0400 Subject: [PATCH 020/207] Adding test cases to FixtureTask. Removing useless param. --- cake/console/libs/tasks/fixture.php | 2 +- .../cases/console/libs/tasks/fixture.test.php | 59 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 8af08bdba..52cf69a8b 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -110,7 +110,7 @@ class FixtureTask extends Shell { * * @access private */ - function __interactive($modelName = false) { + function __interactive() { $this->interactive = true; $this->hr(); $this->out(sprintf("Bake Fixture\nPath: %s", $this->path)); diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 0f8f2a3c6..871efbbb2 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -50,6 +50,11 @@ Mock::generatePartial( 'FixtureTask', 'MockFixtureTask', array('in', 'out', 'err', 'createFile', '_stop') ); + +Mock::generatePartial( + 'Shell', 'MockFixtureModelTask', + array('in', 'out', 'err', 'createFile', '_stop', 'getName', 'getTable', 'listAll') +); /** * FixtureTaskTest class * @@ -71,7 +76,8 @@ class FixtureTaskTest extends CakeTestCase { */ function startTest() { $this->Dispatcher =& new TestFixtureTaskMockShellDispatcher(); - $this->Task =& new MockFixtureTask($this->Dispatcher); + $this->Task =& new MockFixtureTask(); + $this->Task->Model =& new MockFixtureModelTask(); $this->Task->Dispatch = new $this->Dispatcher; } /** @@ -116,6 +122,57 @@ class FixtureTaskTest extends CakeTestCase { $expected = array(); $this->assertEqual($result, $expected); } +/** + * test that execute passes runs bake depending with named model. + * + * @return void + **/ + function testExecuteWithNamedModel() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('article'); + $filename = '/my/path/article_fixture.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticleFixture/'))); + $this->Task->execute(); + } + +/** + * test that execute runs all() when args[0] = all + * + * @return void + **/ + function testExecuteIntoAll() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('all'); + $this->Task->Model->setReturnValue('listAll', array('articles', 'comments')); + + $filename = '/my/path/article_fixture.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticleFixture/'))); + $this->Task->execute(); + + $filename = '/my/path/comment_fixture.php'; + $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/class CommentFixture/'))); + $this->Task->execute(); + } + +/** + * test interactive mode of execute + * + * @return void + **/ + function testExecuteInteractive() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + + $this->Task->setReturnValue('in', 'y'); + $this->Task->Model->setReturnValue('getName', 'Article'); + $this->Task->Model->setReturnValue('getTable', 'articles', array('Article')); + + $filename = '/my/path/article_fixture.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticleFixture/'))); + $this->Task->execute(); + } /** * Test that bake works * From bb2f6b2ef52c17ed6b2dce8f61a82ec764f1d839 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 5 May 2009 00:10:24 -0400 Subject: [PATCH 021/207] Consolidating $useDbConfig to $this->connection. Updating test cases. --- cake/console/libs/tasks/model.php | 81 +++++++++++-------- .../cases/console/libs/tasks/model.test.php | 9 ++- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index bcb38a01a..8ba548d96 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -39,6 +39,13 @@ class ModelTask extends Shell { * @access public */ var $plugin = null; +/** + * Name of the db connection used. + * + * @var string + * @access public + */ + var $connection = null; /** * path to MODELS directory * @@ -87,9 +94,8 @@ class ModelTask extends Shell { * @return void **/ function all() { - $ds = 'default'; - if (isset($this->params['connection'])) { - $ds = $this->params['connection']; + if (!isset($this->params['connection'])) { + $this->connection = 'default'; } $this->listAll($ds, false); $this->interactive = false; @@ -121,20 +127,21 @@ class ModelTask extends Shell { $useTable = null; $primaryKey = 'id'; - $validate = array(); - $associations = array('belongsTo'=> array(), 'hasOne'=> array(), 'hasMany' => array(), 'hasAndBelongsToMany'=> array()); - - $useDbConfig = $this->DbConfig->getConfig(); - $currentModelName = $this->getName($useDbConfig); - $useTable = $this->getTable($currentModelName, $useDbConfig); - $db =& ConnectionManager::getDataSource($useDbConfig); + $validate = $associations = array(); + + if (empty($this->connection)) { + $this->connection = $this->DbConfig->getConfig(); + } + $currentModelName = $this->getName(); + $useTable = $this->getTable($currentModelName); + $db =& ConnectionManager::getDataSource($this->connection); $fullTableName = $db->fullTableName($useTable); $wannaDoValidation = $this->in(__('Would you like to supply validation criteria for the fields in your model?', true), array('y','n'), 'y'); if (in_array($useTable, $this->__tables)) { App::import('Model'); - $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $useDbConfig)); + $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection)); $fields = $tempModel->schema(); if (!array_key_exists('id', $fields)) { @@ -162,7 +169,7 @@ class ModelTask extends Shell { $this->hr(); $this->out("Name: " . $currentModelName); - if ($useDbConfig !== 'default') { + if ($this->connection !== 'default') { $this->out("DB Config: " . $useDbConfig); } if ($fullTableName !== Inflector::tableize($currentModelName)) { @@ -205,7 +212,7 @@ class ModelTask extends Shell { $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); if (low($looksGood) == 'y' || low($looksGood) == 'yes') { - if ($this->bake($currentModelName, $associations, $validate, $primaryKey, $useTable, $useDbConfig)) { + if ($this->bake($currentModelName, $associations, $validate, $primaryKey, $useTable, $this->connection)) { if ($this->_checkUnitTest()) { $this->bakeTest($currentModelName, $useTable, $associations); } @@ -233,7 +240,6 @@ class ModelTask extends Shell { } $validate = array(); - $options = array(); if (class_exists('Validation')) { @@ -242,29 +248,32 @@ class ModelTask extends Shell { } foreach ($fields as $fieldName => $field) { - $prompt = 'Field: ' . $fieldName . "\n"; - $prompt .= 'Type: ' . $field['type'] . "\n"; - $prompt .= '---------------------------------------------------------------'."\n"; - $prompt .= 'Please select one of the following validation options:'."\n"; - $prompt .= '---------------------------------------------------------------'."\n"; + if ($this->interactive) { + $this->out(''); + $this->out(sprintf(__('Field: %s', true), $fieldName)); + $this->out(sprintf(__('Type: %s', true), $field['type'])); + $this->hr(); + $this->out(__('Please select one of the following validation options:', true)); + $this->hr(); + } sort($options); - - $skip = 1; + $prompt = ''; + $default = 1; foreach ($options as $key => $option) { if ($option{0} != '_' && strtolower($option) != 'getinstance') { - $prompt .= "{$skip} - {$option}\n"; - $choices[$skip] = strtolower($option); - $skip++; + $prompt .= "{$default} - {$option}\n"; + $choices[$default] = strtolower($option); + $default++; } } $methods = array_flip($choices); - $prompt .= "{$skip} - Do not do any validation on this field.\n"; - $prompt .= "... or enter in a valid regex validation string.\n"; + $prompt .= sprintf(__("%s - Do not do any validation on this field.\n", true), $default); + $prompt .= __("... or enter in a valid regex validation string.\n", true); - $guess = $skip; + $guess = $default; if ($field['null'] != 1 && $fieldName != $model->primaryKey && !in_array($fieldName, array('created', 'modified', 'updated'))) { if ($fieldName == 'email') { $guess = $methods['email']; @@ -280,12 +289,11 @@ class ModelTask extends Shell { } if ($interactive === true) { - $this->out(''); $choice = $this->in($prompt, null, $guess); } else { $choice = $guess; } - if ($choice != $skip) { + if ($choice != $default) { if (is_numeric($choice) && isset($choices[$choice])) { $validate[$fieldName] = $choices[$choice]; } else { @@ -305,7 +313,6 @@ class ModelTask extends Shell { * @access public */ function doAssociations(&$model, $interactive = true) { - if (!is_object($model)) { return false; } @@ -735,13 +742,17 @@ class ModelTask extends Shell { $content = ""; return $this->createFile($path . $filename, $content); } + /** * outputs the a list of possible models or controllers from database * * @param string $useDbConfig Database configuration name * @access public */ - function listAll($useDbConfig = 'default', $interactive = true) { + function listAll($useDbConfig = null, $interactive = true) { + if (!isset($useDbConfig)) { + $useDbConfig = $this->connection; + } $db =& ConnectionManager::getDataSource($useDbConfig); $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; if ($usePrefix) { @@ -779,7 +790,10 @@ class ModelTask extends Shell { * @param string $useDbConfig Name of the database config you want to get tables from. * @return void **/ - function getTable($modelName, $useDbConfig) { + function getTable($modelName, $useDbConfig = null) { + if (!isset($useDbConfig)) { + $useDbConfig = $this->connection; + } $db =& ConnectionManager::getDataSource($useDbConfig); $useTable = Inflector::tableize($modelName); $fullTableName = $db->fullTableName($useTable, false); @@ -801,7 +815,7 @@ class ModelTask extends Shell { * @return string the model name * @access public */ - function getName($useDbConfig) { + function getName($useDbConfig = null) { $this->listAll($useDbConfig); $enteredModel = ''; @@ -848,6 +862,7 @@ class ModelTask extends Shell { * @return null. **/ function fixture($className, $useTable = null) { + $this->Fixture->connection = $this->connection; $this->Fixture->bake($className, $useTable); } } diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 954c5f2ad..256367340 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -63,6 +63,7 @@ class ModelTaskTest extends CakeTestCase { * @var array **/ var $fixtures = array('core.article', 'core.comment'); + /** * setUp method * @@ -92,12 +93,18 @@ class ModelTaskTest extends CakeTestCase { * @return void **/ function testListAll() { - $this->Task->expectCallCount('out', 3); $this->Task->expectAt(1, 'out', array('1. Article')); $this->Task->expectAt(2, 'out', array('2. Comment')); $result = $this->Task->listAll('test_suite'); $expected = array('articles', 'comments'); $this->assertEqual($result, $expected); + + $this->Task->expectAt(4, 'out', array('1. Article')); + $this->Task->expectAt(5, 'out', array('2. Comment')); + $this->Task->connection = 'test_suite'; + $result = $this->Task->listAll(); + $expected = array('articles', 'comments'); + $this->assertEqual($result, $expected); } /** From 37d81cb92d00dfdaadb3ab93846d72a9dd7a63c5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 5 May 2009 00:43:29 -0400 Subject: [PATCH 022/207] Adding __() Refactoring duplicate code, and pulling out separate methods. --- cake/console/libs/tasks/model.php | 114 ++++++++++++++++-------------- 1 file changed, 59 insertions(+), 55 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 8ba548d96..8e1164e57 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -59,7 +59,7 @@ class ModelTask extends Shell { * @var array * @access public */ - var $tasks = array('DbConfig', 'Fixture'); + var $tasks = array('DbConfig', 'Fixture', 'Test'); /** * Holds tables found on connection. * @@ -106,7 +106,6 @@ class ModelTask extends Shell { if (App::import('Model', $modelClass)) { $object = new $modelClass(); - $modelExists = true; } else { App::import('Model'); $object = new Model(array('name' => $modelClass, 'ds' => $ds)); @@ -125,7 +124,6 @@ class ModelTask extends Shell { $this->hr(); $this->interactive = true; - $useTable = null; $primaryKey = 'id'; $validate = $associations = array(); @@ -137,29 +135,24 @@ class ModelTask extends Shell { $db =& ConnectionManager::getDataSource($this->connection); $fullTableName = $db->fullTableName($useTable); - $wannaDoValidation = $this->in(__('Would you like to supply validation criteria for the fields in your model?', true), array('y','n'), 'y'); - if (in_array($useTable, $this->__tables)) { App::import('Model'); $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection)); - $fields = $tempModel->schema(); if (!array_key_exists('id', $fields)) { - foreach ($fields as $name => $field) { - if (isset($field['key']) && $field['key'] == 'primary') { - break; - } - } - $primaryKey = $this->in(__('What is the primaryKey?', true), null, $name); + $primaryKey = $this->findPrimaryKey($fields); } } - if (array_search($useTable, $this->__tables) !== false && (low($wannaDoValidation) == 'y' || low($wannaDoValidation) == 'yes')) { + $prompt = __('Would you like to supply validation criteria for the fields in your model?', true); + $wannaDoValidation = $this->in($prompt, array('y','n'), 'y'); + if (array_search($useTable, $this->__tables) !== false && strtolower($wannaDoValidation) == 'y') { $validate = $this->doValidation($tempModel); } - $wannaDoAssoc = $this->in(__('Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)?', true), array('y','n'), 'y'); - if ((low($wannaDoAssoc) == 'y' || low($wannaDoAssoc) == 'yes')) { + $prompt = __('Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)?', true); + $wannaDoAssoc = $this->in($prompt, array('y','n'), 'y'); + if (strtolower($wannaDoAssoc) == 'y') { $associations = $this->doAssociations($tempModel); } @@ -170,48 +163,29 @@ class ModelTask extends Shell { $this->out("Name: " . $currentModelName); if ($this->connection !== 'default') { - $this->out("DB Config: " . $useDbConfig); + $this->out(sprintf(__("DB Config: %s", true), $useDbConfig)); } if ($fullTableName !== Inflector::tableize($currentModelName)) { - $this->out("DB Table: " . $fullTableName); + $this->out(sprintf(__("DB Table: %s", true), $fullTableName)); } if ($primaryKey != 'id') { - $this->out("Primary Key: " . $primaryKey); + $this->out(sprintf(__("Primary Key: %s", true), $primaryKey)); } if (!empty($validate)) { - $this->out("Validation: " . print_r($validate, true)); + $this->out(sprintf(__("Validation: %s", true), print_r($validate, true))); } if (!empty($associations)) { - $this->out("Associations:"); - - if (!empty($associations['belongsTo'])) { - for ($i = 0; $i < count($associations['belongsTo']); $i++) { - $this->out(" $currentModelName belongsTo {$associations['belongsTo'][$i]['alias']}"); - } - } - - if (!empty($associations['hasOne'])) { - for ($i = 0; $i < count($associations['hasOne']); $i++) { - $this->out(" $currentModelName hasOne {$associations['hasOne'][$i]['alias']}"); - } - } - - if (!empty($associations['hasMany'])) { - for ($i = 0; $i < count($associations['hasMany']); $i++) { - $this->out(" $currentModelName hasMany {$associations['hasMany'][$i]['alias']}"); - } - } - - if (!empty($associations['hasAndBelongsToMany'])) { - for ($i = 0; $i < count($associations['hasAndBelongsToMany']); $i++) { - $this->out(" $currentModelName hasAndBelongsToMany {$associations['hasAndBelongsToMany'][$i]['alias']}"); - } + $this->out(__("Associations:", true)); + $assocKeys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); + foreach ($assocKeys as $assocKey) { + $this->_printAssociation($currentModelName, $assocKey, $associations); } } + $this->hr(); $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); - - if (low($looksGood) == 'y' || low($looksGood) == 'yes') { + + if (strtolower($looksGood) == 'y') { if ($this->bake($currentModelName, $associations, $validate, $primaryKey, $useTable, $this->connection)) { if ($this->_checkUnitTest()) { $this->bakeTest($currentModelName, $useTable, $associations); @@ -221,6 +195,37 @@ class ModelTask extends Shell { return false; } } +/** + * Print out all the associations of a particular type + * + * @param string $modelName Name of the model relations belong to. + * @param string $type Name of association you want to see. i.e. 'belongsTo' + * @param string $associations Collection of associations. + * @access public + * @return void + **/ + function _printAssociation($modelName, $type, $associations) { + if (!empty($associations[$type])) { + for ($i = 0; $i < count($associations[$type]); $i++) { + $out = "\t" . $modelName . ' ' . $type . ' ' . $associations[$type][$i]['alias']; + $this->out($out); + } + } + } +/** + * Finds a primary Key in a list of fields. + * + * @param array $fields Array of fields that might have a primary key. + * @return string Name of field that is a primary key. + **/ + function findPrimaryKey($fields) { + foreach ($fields as $name => $field) { + if (isset($field['key']) && $field['key'] == 'primary') { + break; + } + } + return $this->in(__('What is the primaryKey?', true), null, $name); + } /** * Handles associations * @@ -229,7 +234,7 @@ class ModelTask extends Shell { * @return array $validate * @access public */ - function doValidation(&$model, $interactive = true) { + function doValidation(&$model) { if (!is_object($model)) { return false; } @@ -238,9 +243,7 @@ class ModelTask extends Shell { if (empty($fields)) { return false; } - - $validate = array(); - $options = array(); + $validate = $options = array(); if (class_exists('Validation')) { $parent = get_class_methods(get_parent_class('Validation')); @@ -308,11 +311,10 @@ class ModelTask extends Shell { * Handles associations * * @param object $model - * @param boolean $interactive * @return array $assocaitons * @access public */ - function doAssociations(&$model, $interactive = true) { + function doAssociations(&$model) { if (!is_object($model)) { return false; } @@ -327,7 +329,9 @@ class ModelTask extends Shell { $primaryKey = $model->primaryKey; $foreignKey = $this->_modelKey($model->name); - $associations = array('belongsTo' => array(), 'hasMany' => array(), 'hasOne'=> array(), 'hasAndBelongsToMany' => array()); + $associations = array( + 'belongsTo' => array(), 'hasMany' => array(), 'hasOne'=> array(), 'hasAndBelongsToMany' => array() + ); $possibleKeys = array(); //Look for belongsTo @@ -392,11 +396,11 @@ class ModelTask extends Shell { } } - if ($interactive !== true) { + if ($this->interactive !== true) { unset($associations['hasOne']); } - if ($interactive === true) { + if ($this->interactive === true) { $this->hr(); if (empty($associations)) { $this->out(__('None found.', true)); @@ -526,7 +530,7 @@ class ModelTask extends Shell { if (is_object($name)) { if (!is_array($associations)) { $associations = $this->doAssociations($name, $associations); - $validate = $this->doValidation($name, $associations); + $validate = $this->doValidation($name); } $primaryKey = $name->primaryKey; $useTable = $name->table; From fd5b422357bd73a7146c9135c314c351b4cae2a2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 7 May 2009 23:59:43 -0400 Subject: [PATCH 023/207] Fixing error when no connection is specified and bake fixture Foo is used. --- cake/console/libs/tasks/fixture.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 52cf69a8b..5d19da9f1 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -79,11 +79,14 @@ class FixtureTask extends Shell { } if (isset($this->args[0])) { + if (!isset($this->connection)) { + $this->connection = 'default'; + } if (strtolower($this->args[0]) == 'all') { return $this->all(); } $model = Inflector::camelize($this->args[0]); - return $this->bake($model); + $this->bake($model); } } @@ -94,9 +97,6 @@ class FixtureTask extends Shell { * @return void **/ function all() { - if (!isset($this->connection)) { - $this->connection = 'default'; - } $this->interactive = false; $tables = $this->Model->listAll($this->connection, false); foreach ($tables as $table) { From fae7ed55841038b17e2f1fdf4abbb09bd29071a5 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 8 May 2009 00:49:26 -0400 Subject: [PATCH 024/207] Refactoring model task. Starting to refactor validation generation to enable multiple validation. --- cake/console/libs/tasks/model.php | 185 +++++++++++------- .../cases/console/libs/tasks/model.test.php | 83 ++++++++ 2 files changed, 202 insertions(+), 66 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 8e1164e57..80b61d3c6 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -39,6 +39,7 @@ class ModelTask extends Shell { * @access public */ var $plugin = null; + /** * Name of the db connection used. * @@ -46,6 +47,7 @@ class ModelTask extends Shell { * @access public */ var $connection = null; + /** * path to MODELS directory * @@ -53,6 +55,7 @@ class ModelTask extends Shell { * @access public */ var $path = MODELS; + /** * tasks * @@ -60,12 +63,21 @@ class ModelTask extends Shell { * @access public */ var $tasks = array('DbConfig', 'Fixture', 'Test'); + /** * Holds tables found on connection. * * @var array **/ var $__tables = array(); + +/** + * Holds validation method map. + * + * @var array + **/ + var $__validations = array(); + /** * Execution method always used for tasks * @@ -77,42 +89,53 @@ class ModelTask extends Shell { } if (!empty($this->args[0])) { + $this->interactive = false; + if (!isset($this->connection)) { + $this->connection = 'default'; + } if (strtolower($this->args[0]) == 'all') { return $this->all(); } $model = Inflector::camelize($this->args[0]); - if ($this->bake($model)) { + $object = $this->_getModelObject($model); + if ($this->bake($object, false)) { if ($this->_checkUnitTest()) { $this->bakeTest($model); } } } } + /** * Bake all models at once. * * @return void **/ function all() { - if (!isset($this->params['connection'])) { - $this->connection = 'default'; - } $this->listAll($ds, false); - $this->interactive = false; foreach ($this->__tables as $table) { $modelClass = Inflector::classify($table); $this->out(sprintf(__('Baking %s', true), $modelClass)); - - if (App::import('Model', $modelClass)) { - $object = new $modelClass(); - } else { - App::import('Model'); - $object = new Model(array('name' => $modelClass, 'ds' => $ds)); - } + $this->_getModelObject($modelClass); $this->bake($object, false); } } +/** + * Get a model object for a class name. + * + * @param string $className Name of class you want model to be. + * @return object Model instance + **/ + function _getModelObject($className) { + if (App::import('Model', $className)) { + $object = new $className(); + } else { + App::import('Model'); + $object = new Model(array('name' => $className, 'ds' => $this->connection)); + } + return $object; + } /** * Handles interactive baking * @@ -178,7 +201,7 @@ class ModelTask extends Shell { $this->out(__("Associations:", true)); $assocKeys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); foreach ($assocKeys as $assocKey) { - $this->_printAssociation($currentModelName, $assocKey, $associations); + $this->printAssociation($currentModelName, $assocKey, $associations); } } @@ -195,6 +218,7 @@ class ModelTask extends Shell { return false; } } + /** * Print out all the associations of a particular type * @@ -204,7 +228,7 @@ class ModelTask extends Shell { * @access public * @return void **/ - function _printAssociation($modelName, $type, $associations) { + function printAssociation($modelName, $type, $associations) { if (!empty($associations[$type])) { for ($i = 0; $i < count($associations[$type]); $i++) { $out = "\t" . $modelName . ' ' . $type . ' ' . $associations[$type][$i]['alias']; @@ -212,11 +236,13 @@ class ModelTask extends Shell { } } } + /** * Finds a primary Key in a list of fields. * * @param array $fields Array of fields that might have a primary key. * @return string Name of field that is a primary key. + * @access public **/ function findPrimaryKey($fields) { foreach ($fields as $name => $field) { @@ -226,8 +252,9 @@ class ModelTask extends Shell { } return $this->in(__('What is the primaryKey?', true), null, $name); } + /** - * Handles associations + * Handles Generation and user interaction for creating validation. * * @param object $model * @param boolean $interactive @@ -243,65 +270,91 @@ class ModelTask extends Shell { if (empty($fields)) { return false; } - $validate = $options = array(); - + $validate = array(); + $this->initValidations(); + foreach ($fields as $fieldName => $field) { + $validation = $this->fieldValidation($fieldName, $field, $model->primaryKey); + if (!empty($validation)) { + $validate[$fieldName] = $validation; + } + } + return $validate; + } +/** + * Populate the __validations array + * + * @return void + **/ + function initValidations() { + $options = $choices = array(); if (class_exists('Validation')) { $parent = get_class_methods(get_parent_class('Validation')); $options = array_diff(get_class_methods('Validation'), $parent); } - - foreach ($fields as $fieldName => $field) { - if ($this->interactive) { - $this->out(''); - $this->out(sprintf(__('Field: %s', true), $fieldName)); - $this->out(sprintf(__('Type: %s', true), $field['type'])); - $this->hr(); - $this->out(__('Please select one of the following validation options:', true)); - $this->hr(); + sort($options); + $default = 1; + foreach ($options as $key => $option) { + if ($option{0} != '_' && strtolower($option) != 'getinstance') { + $choices[$default] = strtolower($option); + $default++; } - - sort($options); - $prompt = ''; - $default = 1; - foreach ($options as $key => $option) { - if ($option{0} != '_' && strtolower($option) != 'getinstance') { - $prompt .= "{$default} - {$option}\n"; - $choices[$default] = strtolower($option); - $default++; - } + } + $this->__validations = $choices; + return $choices; + } +/** + * Does individual field validation handling. + * + * @param string $fieldName Name of field to be validated. + * @param array $metaData metadata for field + * @return array Array of validation for the field. + **/ + function fieldValidation($fieldName, $metaData, $primaryKey = 'id') { + $defaultChoice = count($this->__validations); + $validate = array(); + if ($this->interactive) { + $this->out(''); + $this->out(sprintf(__('Field: %s', true), $fieldName)); + $this->out(sprintf(__('Type: %s', true), $metaData['type'])); + $this->hr(); + $this->out(__('Please select one of the following validation options:', true)); + $this->hr(); + } + $methods = array_flip($this->__validations); + $prompt = ''; + for ($i = 1; $i < $defaultChoice; $i++) { + $prompt .= $i . ' - ' . $this->__validations[$i] . "\n"; + } + $prompt .= sprintf(__("%s - Do not do any validation on this field.\n", true), $defaultChoice); + $prompt .= __("... or enter in a valid regex validation string.\n", true); + + $guess = $defaultChoice; + if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) { + if ($fieldName == 'email') { + $guess = $methods['email']; + } elseif ($metaData['type'] == 'string') { + $guess = $methods['notempty']; + } elseif ($metaData['type'] == 'integer') { + $guess = $methods['numeric']; + } elseif ($metaData['type'] == 'boolean') { + $guess = $methods['numeric']; + } elseif ($metaData['type'] == 'datetime' || $metaData['type'] == 'date') { + $guess = $methods['date']; + } elseif ($metaData['type'] == 'time') { + $guess = $methods['time']; } + } - $methods = array_flip($choices); - - $prompt .= sprintf(__("%s - Do not do any validation on this field.\n", true), $default); - $prompt .= __("... or enter in a valid regex validation string.\n", true); - - $guess = $default; - if ($field['null'] != 1 && $fieldName != $model->primaryKey && !in_array($fieldName, array('created', 'modified', 'updated'))) { - if ($fieldName == 'email') { - $guess = $methods['email']; - } elseif ($field['type'] == 'string') { - $guess = $methods['notempty']; - } elseif ($field['type'] == 'integer') { - $guess = $methods['numeric']; - } elseif ($field['type'] == 'boolean') { - $guess = $methods['numeric']; - } elseif ($field['type'] == 'datetime') { - $guess = $methods['date']; - } - } - - if ($interactive === true) { - $choice = $this->in($prompt, null, $guess); + if ($this->interactive === true) { + $choice = $this->in($prompt, null, $guess); + } else { + $choice = $guess; + } + if ($choice != $defaultChoice) { + if (is_numeric($choice) && isset($choices[$choice])) { + $validate[$fieldName] = $choices[$choice]; } else { - $choice = $guess; - } - if ($choice != $default) { - if (is_numeric($choice) && isset($choices[$choice])) { - $validate[$fieldName] = $choices[$choice]; - } else { - $validate[$fieldName] = $choice; - } + $validate[$fieldName] = $choice; } } return $validate; diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 256367340..91cc646a6 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -50,6 +50,10 @@ Mock::generatePartial( 'ModelTask', 'MockModelTask', array('in', 'out', 'err', 'createFile', '_stop') ); + +Mock::generate( + 'Model', 'MockModelTaskModel' +); /** * ModelTaskTest class * @@ -151,5 +155,84 @@ class ModelTaskTest extends CakeTestCase { $expected = 'my_table'; $this->assertEqual($result, $expected); } +/** + * test that initializing the validations works. + * + * @return void + **/ + function testInitValidations() { + $result = $this->Task->initValidations(); + $this->assertTrue(in_array('notempty', $result)); + } +/** + * test that individual field validation works, with interactive = false + * + * @return void + **/ + function testNoInteractiveFieldValidation() { + $this->Task->interactive = false; + + $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); + } +/** + * test the validation Generation routine + * + * @return void + **/ + function testDoValidation() { + $Model =& new MockModelTaskModel(); + $Model->setReturnValue('schema', array( + 'id' => array( + 'type' => 'integer', + 'length' => 11, + 'null' => false, + 'key' => 'primary', + ), + 'name' => array( + 'type' => 'string', + 'length' => 20, + 'null' => false, + ), + 'email' => array( + 'type' => 'string', + 'length' => 255, + 'null' => false, + ), + 'some_date' => array( + 'type' => 'date', + 'length' => '', + 'null' => false, + ), + 'some_time' => array( + 'type' => 'time', + 'length' => '', + 'null' => false, + ), + 'created' => array( + 'type' => 'datetime', + 'length' => '', + 'null' => false, + ) + )); + $this->Task->interactive = false; + + $result = $this->Task->doValidation($Model); + $expected = array( + 'name' => array( + 'notEmpty' => array('rule' => 'notEmpty') + ), + 'email' => array( + 'email' => array('rule' => 'email'), + ), + 'some_date' => array( + 'date' => array('rule' => 'date') + ), + 'some_time' => array( + 'time' => array('rule' => 'time') + ), + ); + debug($result); + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file From 103b97493a39553d6f40c269d328b135bc2be394 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 8 May 2009 01:09:19 -0400 Subject: [PATCH 025/207] Adding test cases for validation generation Updating validation generation functions. --- cake/console/libs/tasks/model.php | 98 +++++++++++-------- .../cases/console/libs/tasks/model.test.php | 43 ++++++-- 2 files changed, 91 insertions(+), 50 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 80b61d3c6..f37f0a1fc 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -201,7 +201,7 @@ class ModelTask extends Shell { $this->out(__("Associations:", true)); $assocKeys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); foreach ($assocKeys as $assocKey) { - $this->printAssociation($currentModelName, $assocKey, $associations); + $this->_printAssociation($currentModelName, $assocKey, $associations); } } @@ -225,10 +225,10 @@ class ModelTask extends Shell { * @param string $modelName Name of the model relations belong to. * @param string $type Name of association you want to see. i.e. 'belongsTo' * @param string $associations Collection of associations. - * @access public + * @access protected * @return void **/ - function printAssociation($modelName, $type, $associations) { + function _printAssociation($modelName, $type, $associations) { if (!empty($associations[$type])) { for ($i = 0; $i < count($associations[$type]); $i++) { $out = "\t" . $modelName . ' ' . $type . ' ' . $associations[$type][$i]['alias']; @@ -311,50 +311,62 @@ class ModelTask extends Shell { **/ function fieldValidation($fieldName, $metaData, $primaryKey = 'id') { $defaultChoice = count($this->__validations); - $validate = array(); - if ($this->interactive) { - $this->out(''); - $this->out(sprintf(__('Field: %s', true), $fieldName)); - $this->out(sprintf(__('Type: %s', true), $metaData['type'])); - $this->hr(); - $this->out(__('Please select one of the following validation options:', true)); - $this->hr(); - } - $methods = array_flip($this->__validations); - $prompt = ''; - for ($i = 1; $i < $defaultChoice; $i++) { - $prompt .= $i . ' - ' . $this->__validations[$i] . "\n"; - } - $prompt .= sprintf(__("%s - Do not do any validation on this field.\n", true), $defaultChoice); - $prompt .= __("... or enter in a valid regex validation string.\n", true); + $validate = $alredyChosen = array(); - $guess = $defaultChoice; - if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) { - if ($fieldName == 'email') { - $guess = $methods['email']; - } elseif ($metaData['type'] == 'string') { - $guess = $methods['notempty']; - } elseif ($metaData['type'] == 'integer') { - $guess = $methods['numeric']; - } elseif ($metaData['type'] == 'boolean') { - $guess = $methods['numeric']; - } elseif ($metaData['type'] == 'datetime' || $metaData['type'] == 'date') { - $guess = $methods['date']; - } elseif ($metaData['type'] == 'time') { - $guess = $methods['time']; + $anotherValidator = 'y'; + while ($anotherValidator == 'y') { + if ($this->interactive) { + $this->out(''); + $this->out(sprintf(__('Field: %s', true), $fieldName)); + $this->out(sprintf(__('Type: %s', true), $metaData['type'])); + $this->hr(); + $this->out(__('Please select one of the following validation options:', true)); + $this->hr(); } - } - if ($this->interactive === true) { - $choice = $this->in($prompt, null, $guess); - } else { - $choice = $guess; - } - if ($choice != $defaultChoice) { - if (is_numeric($choice) && isset($choices[$choice])) { - $validate[$fieldName] = $choices[$choice]; + $prompt = ''; + for ($i = 1; $i < $defaultChoice; $i++) { + $prompt .= $i . ' - ' . $this->__validations[$i] . "\n"; + } + $prompt .= sprintf(__("%s - Do not do any validation on this field.\n", true), $defaultChoice); + $prompt .= __("... or enter in a valid regex validation string.\n", true); + + $methods = array_flip($this->__validations); + $guess = $defaultChoice; + if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) { + if ($fieldName == 'email') { + $guess = $methods['email']; + } elseif ($metaData['type'] == 'string') { + $guess = $methods['notempty']; + } elseif ($metaData['type'] == 'integer') { + $guess = $methods['numeric']; + } elseif ($metaData['type'] == 'boolean') { + $guess = $methods['numeric']; + } elseif ($metaData['type'] == 'datetime' || $metaData['type'] == 'date') { + $guess = $methods['date']; + } elseif ($metaData['type'] == 'time') { + $guess = $methods['time']; + } + } + + if ($this->interactive === true) { + $choice = $this->in($prompt, null, $guess); + $alreadyChosen[] = $choice; } else { - $validate[$fieldName] = $choice; + $choice = $guess; + } + $validatorName = $this->__validations[$choice]; + if ($choice != $defaultChoice) { + if (is_numeric($choice) && isset($this->__validations[$choice])) { + $validate[$validatorName] = $this->__validations[$choice]; + } else { + $validate[$validatorName] = $choice; + } + } + if ($this->interactive == true) { + $anotherValidator = $this->in(__('Would you like to add another validation rule?', true), array('y', 'n'), 'n'); + } else { + $anotherValidator = 'n'; } } return $validate; diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 91cc646a6..0143a64ec 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -164,23 +164,53 @@ class ModelTaskTest extends CakeTestCase { $result = $this->Task->initValidations(); $this->assertTrue(in_array('notempty', $result)); } + /** * test that individual field validation works, with interactive = false + * tests the guessing features of validation * * @return void **/ - function testNoInteractiveFieldValidation() { + function testFieldValidationGuessing() { $this->Task->interactive = false; + $this->Task->initValidations(); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); + $expected = array('notempty' => 'notempty'); + + $result = $this->Task->fieldValidation('text', array('type' => 'date', 'length' => 10, 'null' => false)); + $expected = array('date' => 'date'); + + $result = $this->Task->fieldValidation('text', array('type' => 'time', 'length' => 10, 'null' => false)); + $expected = array('time' => 'time'); + + $result = $this->Task->fieldValidation('email', array('type' => 'string', 'length' => 10, 'null' => false)); + $expected = array('email' => 'email'); + + $result = $this->Task->fieldValidation('test', array('type' => 'integer', 'length' => 10, 'null' => false)); + $expected = array('numeric' => 'numeric'); + + $result = $this->Task->fieldValidation('test', array('type' => 'boolean', 'length' => 10, 'null' => false)); + $expected = array('numeric' => 'numeric'); } + +/** + * test that interactive field validation works and returns multiple validators. + * + * @return void + **/ + function testInteractiveFieldValidation() { + + } + /** * test the validation Generation routine * * @return void **/ - function testDoValidation() { + function testNonInteractiveDoValidation() { $Model =& new MockModelTaskModel(); + $Model->primaryKey = 'id'; $Model->setReturnValue('schema', array( 'id' => array( 'type' => 'integer', @@ -219,19 +249,18 @@ class ModelTaskTest extends CakeTestCase { $result = $this->Task->doValidation($Model); $expected = array( 'name' => array( - 'notEmpty' => array('rule' => 'notEmpty') + 'notempty' => 'notempty' ), 'email' => array( - 'email' => array('rule' => 'email'), + 'email' => 'email', ), 'some_date' => array( - 'date' => array('rule' => 'date') + 'date' => 'date' ), 'some_time' => array( - 'time' => array('rule' => 'time') + 'time' => 'time' ), ); - debug($result); $this->assertEqual($result, $expected); } } From 8775f153757ed6e1007f3021da45a28461cbaa9d Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 00:35:03 -0400 Subject: [PATCH 026/207] Updating multiple validation generation. Adding test coverage for interactive validations. --- cake/console/libs/tasks/model.php | 8 ++++++-- cake/tests/cases/console/libs/tasks/model.test.php | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index f37f0a1fc..4d4cfa661 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -311,7 +311,7 @@ class ModelTask extends Shell { **/ function fieldValidation($fieldName, $metaData, $primaryKey = 'id') { $defaultChoice = count($this->__validations); - $validate = $alredyChosen = array(); + $validate = $alreadyChosen = array(); $anotherValidator = 'y'; while ($anotherValidator == 'y') { @@ -351,6 +351,10 @@ class ModelTask extends Shell { if ($this->interactive === true) { $choice = $this->in($prompt, null, $guess); + if (in_array($choice, $alreadyChosen)) { + $this->out(__('You have already chosen that validation rule, please choose again', true)); + continue; + } $alreadyChosen[] = $choice; } else { $choice = $guess; @@ -363,7 +367,7 @@ class ModelTask extends Shell { $validate[$validatorName] = $choice; } } - if ($this->interactive == true) { + if ($this->interactive == true && $choice != $defaultChoice) { $anotherValidator = $this->in(__('Would you like to add another validation rule?', true), array('y', 'n'), 'n'); } else { $anotherValidator = 'n'; diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 0143a64ec..07dcabed0 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -200,7 +200,16 @@ class ModelTaskTest extends CakeTestCase { * @return void **/ function testInteractiveFieldValidation() { - + $this->Task->initValidations(); + $this->Task->interactive = true; + $this->Task->setReturnValueAt(0, 'in', '20'); + $this->Task->setReturnValueAt(1, 'in', 'y'); + $this->Task->setReturnValueAt(2, 'in', '16'); + $this->Task->setReturnValueAt(3, 'in', 'n'); + + $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); + $expected = array('notempty' => 'notempty', 'maxlength' => 'maxlength'); + $this->assertEqual($result, $expected); } /** From 11e2912945ab5b6cc4afee91d1f243b618253cf4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 01:00:14 -0400 Subject: [PATCH 027/207] Making output fit nicely on 80col display. --- cake/console/libs/tasks/model.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 4d4cfa661..75a16b2f4 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -167,13 +167,13 @@ class ModelTask extends Shell { } } - $prompt = __('Would you like to supply validation criteria for the fields in your model?', true); + $prompt = __("Would you like to supply validation criteria \nfor the fields in your model?", true); $wannaDoValidation = $this->in($prompt, array('y','n'), 'y'); if (array_search($useTable, $this->__tables) !== false && strtolower($wannaDoValidation) == 'y') { $validate = $this->doValidation($tempModel); } - $prompt = __('Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)?', true); + $prompt = __("Would you like to define model associations\n(hasMany, hasOne, belongsTo, etc.)?", true); $wannaDoAssoc = $this->in($prompt, array('y','n'), 'y'); if (strtolower($wannaDoAssoc) == 'y') { $associations = $this->doAssociations($tempModel); @@ -352,7 +352,7 @@ class ModelTask extends Shell { if ($this->interactive === true) { $choice = $this->in($prompt, null, $guess); if (in_array($choice, $alreadyChosen)) { - $this->out(__('You have already chosen that validation rule, please choose again', true)); + $this->out(__("You have already chosen that validation rule,\nplease choose again", true)); continue; } $alreadyChosen[] = $choice; @@ -874,7 +874,7 @@ class ModelTask extends Shell { if (array_search($useTable, $this->__tables) === false) { $this->out(''); - $this->out(sprintf(__("Given your model named '%s', Cake would expect a database table named '%s'", true), $modelName, $fullTableName)); + $this->out(sprintf(__("Given your model named '%s',\nCake would expect a database table named '%s'", true), $modelName, $fullTableName)); $tableIsGood = $this->in(__('Do you want to use this table?', true), array('y','n'), 'y'); } if (low($tableIsGood) == 'n' || low($tableIsGood) == 'no') { @@ -894,7 +894,7 @@ class ModelTask extends Shell { $enteredModel = ''; while ($enteredModel == '') { - $enteredModel = $this->in(__("Enter a number from the list above, type in the name of another model, or 'q' to exit", true), null, 'q'); + $enteredModel = $this->in(__("Enter a number from the list above,\ntype in the name of another model, or 'q' to exit", true), null, 'q'); if ($enteredModel === 'q') { $this->out(__("Exit", true)); @@ -902,7 +902,7 @@ class ModelTask extends Shell { } if ($enteredModel == '' || intval($enteredModel) > count($this->_modelNames)) { - $this->err(__("The model name you supplied was empty, or the number you selected was not an option. Please try again.", true)); + $this->err(__("The model name you supplied was empty,\nor the number you selected was not an option. Please try again.", true)); $enteredModel = ''; } } From 31a266fc4c311b8bdef93db3e1f8f6a7eb436b2e Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 02:20:46 -0400 Subject: [PATCH 028/207] Refactoring association generation. --- cake/console/libs/tasks/model.php | 169 ++++++++++++++++++------------ 1 file changed, 104 insertions(+), 65 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 75a16b2f4..4ab1c25b5 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -387,83 +387,22 @@ class ModelTask extends Shell { if (!is_object($model)) { return false; } + App::import('Model'); $this->out(__('One moment while the associations are detected.', true)); $fields = $model->schema(); - if (empty($fields)) { return false; } - $primaryKey = $model->primaryKey; - $foreignKey = $this->_modelKey($model->name); - $associations = array( 'belongsTo' => array(), 'hasMany' => array(), 'hasOne'=> array(), 'hasAndBelongsToMany' => array() ); $possibleKeys = array(); - //Look for belongsTo - $i = 0; - foreach ($fields as $fieldName => $field) { - $offset = strpos($fieldName, '_id'); - if ($fieldName != $model->primaryKey && $offset !== false) { - $tmpModelName = $this->_modelNameFromKey($fieldName); - $associations['belongsTo'][$i]['alias'] = $tmpModelName; - $associations['belongsTo'][$i]['className'] = $tmpModelName; - $associations['belongsTo'][$i]['foreignKey'] = $fieldName; - $i++; - } - } - //Look for hasOne and hasMany and hasAndBelongsToMany - $i = $j = 0; - - foreach ($this->__tables as $otherTable) { - App::import('Model'); - $tmpModelName = $this->_modelName($otherTable); - $tempOtherModel = & new Model(array('name' => $tmpModelName, 'table' => $otherTable, 'ds' => $model->useDbConfig)); - $modelFieldsTemp = $tempOtherModel->schema(); - - $offset = strpos($otherTable, $model->table . '_'); - $otherOffset = strpos($otherTable, '_' . $model->table); - - foreach ($modelFieldsTemp as $fieldName => $field) { - if ($field['type'] == 'integer' || $field['type'] == 'string') { - $possibleKeys[$otherTable][] = $fieldName; - } - if ($fieldName != $model->primaryKey && $fieldName == $foreignKey && $offset === false && $otherOffset === false) { - $associations['hasOne'][$j]['alias'] = $tempOtherModel->name; - $associations['hasOne'][$j]['className'] = $tempOtherModel->name; - $associations['hasOne'][$j]['foreignKey'] = $fieldName; - - $associations['hasMany'][$j]['alias'] = $tempOtherModel->name; - $associations['hasMany'][$j]['className'] = $tempOtherModel->name; - $associations['hasMany'][$j]['foreignKey'] = $fieldName; - $j++; - } - } - - if ($offset !== false) { - $offset = strlen($model->table . '_'); - $tmpModelName = $this->_modelName(substr($otherTable, $offset)); - $associations['hasAndBelongsToMany'][$i]['alias'] = $tmpModelName; - $associations['hasAndBelongsToMany'][$i]['className'] = $tmpModelName; - $associations['hasAndBelongsToMany'][$i]['foreignKey'] = $foreignKey; - $associations['hasAndBelongsToMany'][$i]['associationForeignKey'] = $this->_modelKey($tmpModelName); - $associations['hasAndBelongsToMany'][$i]['joinTable'] = $otherTable; - $i++; - } - - if ($otherOffset !== false) { - $tmpModelName = $this->_modelName(substr($otherTable, 0, $otherOffset)); - $associations['hasAndBelongsToMany'][$i]['alias'] = $tmpModelName; - $associations['hasAndBelongsToMany'][$i]['className'] = $tmpModelName; - $associations['hasAndBelongsToMany'][$i]['foreignKey'] = $foreignKey; - $associations['hasAndBelongsToMany'][$i]['associationForeignKey'] = $this->_modelKey($tmpModelName); - $associations['hasAndBelongsToMany'][$i]['joinTable'] = $otherTable; - $i++; - } - } + $associations = $this->_findBelongsTo($model, $associations); + $associations = $this->_findHasOneAndMany($model, $associations); + $associations = $this->_findHasAndBelongsToMany($model, $associations); if ($this->interactive !== true) { unset($associations['hasOne']); @@ -583,6 +522,104 @@ class ModelTask extends Shell { } return $associations; } + +/** + * Find belongsTo relations and add them to the associations list. + * + * @param object $model Model instance of model being generated. + * @param array $associations Array of inprogress associations + * @return array $associations with belongsTo added in. + **/ + function _findBelongsTo(&$model, $associations) { + $fields = $model->schema(); + foreach ($fields as $fieldName => $field) { + $offset = strpos($fieldName, '_id'); + if ($fieldName != $model->primaryKey && $offset !== false) { + $tmpModelName = $this->_modelNameFromKey($fieldName); + $assoc = array( + 'alias' => $tmpModelName, + 'className' => $tmpModelName, + 'foreignKey' => $fieldName, + ); + $associations['belongsTo'][] = $assoc; + } + } + return $associations; + } + +/** + * Find the hasOne and HasMany relations and add them to associations list + * + * @param object $model Model instance being generated + * @param array $associations Array of inprogress associations + * @return array $associations with hasOne and hasMany added in. + **/ + function _findHasOneAndMany(&$model, $associations) { + $foreignKey = $this->_modelKey($model->name); + var_dump($foreignKey); + foreach ($this->__tables as $otherTable) { + $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable)); + $modelFieldsTemp = $tempOtherModel->schema(); + + $pattern = '/_' . preg_quote($otherTable, '/') . '|' . preg_quote($otherTable, '/') . '_/'; + $possibleJoinTable = preg_match($pattern , $model->table); + foreach ($modelFieldsTemp as $fieldName => $field) { + if ($fieldName != $model->primaryKey && $fieldName == $foreignKey && $possibleJoinTable == false) { + $assoc = array( + 'alias' => $tempOtherModel->name, + 'className' => $tempOtherModel->name, + 'foreignKey' => $fieldName + ); + $associations['hasOne'][] = $assoc; + $associations['hasMany'][] = $assoc; + } + } + } + return $associations; + } + +/** + * Find the hasAndBelongsToMany relations and add them to associations list + * + * @param object $model Model instance being generated + * @param array $associations Array of inprogress associations + * @return array $associations with hasAndBelongsToMany added in. + **/ + function _findHasAndBelongsToMany(&$model, $associations) { + $foreignKey = $this->_modelKey($model->name); + foreach ($this->__tables as $otherTable) { + $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable)); + $modelFieldsTemp = $tempOtherModel->schema(); + + $offset = strpos($otherTable, $model->table . '_'); + $otherOffset = strpos($otherTable, '_' . $model->table); + + if ($offset !== false) { + $offset = strlen($model->table . '_'); + $habtmName = $this->_modelName(substr($otherTable, $offset)); + $assoc = array( + 'alias' => $habtmName, + 'className' => $habtmName, + 'foreignKey' => $foreignKey, + 'associationForeignKey' => $this->_modelKey($habtmName), + 'joinTable' => $otherTable + ); + $associations['hasAndBelongsToMany'][] = $assoc; + } elseif ($otherOffset !== false) { + $habtmName = $this->_modelName(substr($otherTable, 0, $otherOffset)); + $assoc = array( + 'alias' => $habtmName, + 'className' => $habtmName, + 'foreignKey' => $foreignKey, + 'associationForeignKey' => $this->_modelKey($habtmName), + 'joinTable' => $otherTable + ); + $associations['hasAndBelongsToMany'][] = $assoc; + } + } + return $associations; + } + /** * Assembles and writes a Model file. * @@ -913,6 +950,7 @@ class ModelTask extends Shell { } return $currentModelName; } + /** * Displays help contents * @@ -929,6 +967,7 @@ class ModelTask extends Shell { $this->out(""); $this->_stop(); } + /** * Interact with FixtureTask to automatically bake fixtures when baking models. * From 046764146979ff3aab6dcd86d3c3b85d06688285 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 02:22:29 -0400 Subject: [PATCH 029/207] minor cleanup --- cake/console/libs/tasks/model.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 4ab1c25b5..61c27fa8d 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -536,12 +536,11 @@ class ModelTask extends Shell { $offset = strpos($fieldName, '_id'); if ($fieldName != $model->primaryKey && $offset !== false) { $tmpModelName = $this->_modelNameFromKey($fieldName); - $assoc = array( + $associations['belongsTo'][] = array( 'alias' => $tmpModelName, 'className' => $tmpModelName, 'foreignKey' => $fieldName, ); - $associations['belongsTo'][] = $assoc; } } return $associations; @@ -556,7 +555,6 @@ class ModelTask extends Shell { **/ function _findHasOneAndMany(&$model, $associations) { $foreignKey = $this->_modelKey($model->name); - var_dump($foreignKey); foreach ($this->__tables as $otherTable) { $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable)); $modelFieldsTemp = $tempOtherModel->schema(); @@ -597,24 +595,22 @@ class ModelTask extends Shell { if ($offset !== false) { $offset = strlen($model->table . '_'); $habtmName = $this->_modelName(substr($otherTable, $offset)); - $assoc = array( + $associations['hasAndBelongsToMany'][] = array( 'alias' => $habtmName, 'className' => $habtmName, 'foreignKey' => $foreignKey, 'associationForeignKey' => $this->_modelKey($habtmName), 'joinTable' => $otherTable ); - $associations['hasAndBelongsToMany'][] = $assoc; } elseif ($otherOffset !== false) { $habtmName = $this->_modelName(substr($otherTable, 0, $otherOffset)); - $assoc = array( + $associations['hasAndBelongsToMany'][] = array( 'alias' => $habtmName, 'className' => $habtmName, 'foreignKey' => $foreignKey, 'associationForeignKey' => $this->_modelKey($habtmName), 'joinTable' => $otherTable ); - $associations['hasAndBelongsToMany'][] = $assoc; } } return $associations; From 4b4875e0a91a7929f3d8c9b8e12a0240b12d9a6d Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 21:28:51 -0400 Subject: [PATCH 030/207] Renaming methods, fixing issue with habtm bleed through. Added test cases for all relation generation. --- cake/console/libs/tasks/model.php | 16 +-- .../cases/console/libs/tasks/model.test.php | 115 ++++++++++++++++-- 2 files changed, 116 insertions(+), 15 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 61c27fa8d..a982cfb28 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -400,9 +400,9 @@ class ModelTask extends Shell { ); $possibleKeys = array(); - $associations = $this->_findBelongsTo($model, $associations); - $associations = $this->_findHasOneAndMany($model, $associations); - $associations = $this->_findHasAndBelongsToMany($model, $associations); + $associations = $this->findBelongsTo($model, $associations); + $associations = $this->findHasOneAndMany($model, $associations); + $associations = $this->findHasAndBelongsToMany($model, $associations); if ($this->interactive !== true) { unset($associations['hasOne']); @@ -530,7 +530,7 @@ class ModelTask extends Shell { * @param array $associations Array of inprogress associations * @return array $associations with belongsTo added in. **/ - function _findBelongsTo(&$model, $associations) { + function findBelongsTo(&$model, $associations) { $fields = $model->schema(); foreach ($fields as $fieldName => $field) { $offset = strpos($fieldName, '_id'); @@ -553,14 +553,14 @@ class ModelTask extends Shell { * @param array $associations Array of inprogress associations * @return array $associations with hasOne and hasMany added in. **/ - function _findHasOneAndMany(&$model, $associations) { + function findHasOneAndMany(&$model, $associations) { $foreignKey = $this->_modelKey($model->name); foreach ($this->__tables as $otherTable) { $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable)); $modelFieldsTemp = $tempOtherModel->schema(); - $pattern = '/_' . preg_quote($otherTable, '/') . '|' . preg_quote($otherTable, '/') . '_/'; - $possibleJoinTable = preg_match($pattern , $model->table); + $pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/'; + $possibleJoinTable = preg_match($pattern , $otherTable); foreach ($modelFieldsTemp as $fieldName => $field) { if ($fieldName != $model->primaryKey && $fieldName == $foreignKey && $possibleJoinTable == false) { $assoc = array( @@ -583,7 +583,7 @@ class ModelTask extends Shell { * @param array $associations Array of inprogress associations * @return array $associations with hasAndBelongsToMany added in. **/ - function _findHasAndBelongsToMany(&$model, $associations) { + function findHasAndBelongsToMany(&$model, $associations) { $foreignKey = $this->_modelKey($model->name); foreach ($this->__tables as $otherTable) { $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable)); diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 07dcabed0..c5f74d89b 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -66,7 +66,7 @@ class ModelTaskTest extends CakeTestCase { * * @var array **/ - var $fixtures = array('core.article', 'core.comment'); + var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); /** * setUp method @@ -98,16 +98,21 @@ class ModelTaskTest extends CakeTestCase { **/ function testListAll() { $this->Task->expectAt(1, 'out', array('1. Article')); - $this->Task->expectAt(2, 'out', array('2. Comment')); + $this->Task->expectAt(2, 'out', array('2. ArticlesTag')); + $this->Task->expectAt(3, 'out', array('3. Comment')); + $this->Task->expectAt(4, 'out', array('4. Tag')); $result = $this->Task->listAll('test_suite'); - $expected = array('articles', 'comments'); + $expected = array('articles', 'articles_tags', 'comments', 'tags'); $this->assertEqual($result, $expected); - $this->Task->expectAt(4, 'out', array('1. Article')); - $this->Task->expectAt(5, 'out', array('2. Comment')); + $this->Task->expectAt(6, 'out', array('1. Article')); + $this->Task->expectAt(7, 'out', array('2. ArticlesTag')); + $this->Task->expectAt(8, 'out', array('3. Comment')); + $this->Task->expectAt(9, 'out', array('4. Tag')); + $this->Task->connection = 'test_suite'; $result = $this->Task->listAll(); - $expected = array('articles', 'comments'); + $expected = array('articles', 'articles_tags', 'comments', 'tags'); $this->assertEqual($result, $expected); } @@ -128,7 +133,7 @@ class ModelTaskTest extends CakeTestCase { $expected = 'Article'; $this->assertEqual($result, $expected); - $this->Task->setReturnValueAt(2, 'in', 2); + $this->Task->setReturnValueAt(2, 'in', 3); $result = $this->Task->getName('test_suite'); $expected = 'Comment'; $this->assertEqual($result, $expected); @@ -272,5 +277,101 @@ class ModelTaskTest extends CakeTestCase { ); $this->assertEqual($result, $expected); } + +/** + * test that finding primary key works + * + * @return void + **/ + function testFindPrimaryKey() { + $fields = array( + 'one' => array(), + 'two' => array(), + 'key' => array('key' => 'primary') + ); + $this->Task->expectAt(0, 'in', array('*', null, 'key')); + $this->Task->setReturnValue('in', 'my_field'); + $result = $this->Task->findPrimaryKey($fields); + $expected = 'my_field'; + $this->assertEqual($result, $expected); + } + +/** + * test that belongsTo generation works. + * + * @return void + **/ + function testBelongsToGeneration() { + $model = new Model(array('ds' => 'test_suite', 'name' => 'Comment')); + $result = $this->Task->findBelongsTo($model, array()); + $expected = array( + 'belongsTo' => array( + array( + 'alias' => 'Article', + 'className' => 'Article', + 'foreignKey' => 'article_id', + ), + array( + 'alias' => 'User', + 'className' => 'User', + 'foreignKey' => 'user_id', + ), + ) + ); + $this->assertEqual($result, $expected); + } + +/** + * test that hasOne and/or hasMany relations are generated properly. + * + * @return void + **/ + function testHasManyHasOneGeneration() { + $model = new Model(array('ds' => 'test_suite', 'name' => 'Article')); + $this->Task->connection = 'test_suite'; + $this->Task->listAll(); + $result = $this->Task->findHasOneAndMany($model, array()); + $expected = array( + 'hasMany' => array( + array( + 'alias' => 'Comment', + 'className' => 'Comment', + 'foreignKey' => 'article_id', + ), + ), + 'hasOne' => array( + array( + 'alias' => 'Comment', + 'className' => 'Comment', + 'foreignKey' => 'article_id', + ), + ), + ); + $this->assertEqual($result, $expected); + } + +/** + * test that habtm generation works + * + * @return void + **/ + function testHasAndBelongsToManyGeneration() { + $model = new Model(array('ds' => 'test_suite', 'name' => 'Article')); + $this->Task->connection = 'test_suite'; + $this->Task->listAll(); + $result = $this->Task->findHasAndBelongsToMany($model, array()); + $expected = array( + 'hasAndBelongsToMany' => array( + array( + 'alias' => 'Tag', + 'className' => 'Tag', + 'foreignKey' => 'article_id', + 'joinTable' => 'articles_tags', + 'associationForeignKey' => 'tag_id', + ), + ), + ); + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file From 5c48603bd0e655da4a932c166dfbad54973a5b3e Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 9 May 2009 23:32:22 -0400 Subject: [PATCH 031/207] Refactoring methods, adding self join association detection. Test cases updated. --- cake/console/libs/tasks/model.php | 103 ++++++++++-------- .../cases/console/libs/tasks/model.test.php | 74 +++++++++++-- 2 files changed, 124 insertions(+), 53 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index a982cfb28..7d72dbf21 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -78,6 +78,15 @@ class ModelTask extends Shell { **/ var $__validations = array(); +/** + * startup method + * + * @return void + **/ + function startup() { + App::import('Core', 'Model'); + } + /** * Execution method always used for tasks * @@ -127,13 +136,8 @@ class ModelTask extends Shell { * @param string $className Name of class you want model to be. * @return object Model instance **/ - function _getModelObject($className) { - if (App::import('Model', $className)) { - $object = new $className(); - } else { - App::import('Model'); - $object = new Model(array('name' => $className, 'ds' => $this->connection)); - } + function &_getModelObject($className) { + $object = new Model(array('name' => $className, 'ds' => $this->connection)); return $object; } /** @@ -159,7 +163,6 @@ class ModelTask extends Shell { $fullTableName = $db->fullTableName($useTable); if (in_array($useTable, $this->__tables)) { - App::import('Model'); $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection)); $fields = $tempModel->schema(); if (!array_key_exists('id', $fields)) { @@ -387,7 +390,6 @@ class ModelTask extends Shell { if (!is_object($model)) { return false; } - App::import('Model'); $this->out(__('One moment while the associations are detected.', true)); $fields = $model->schema(); @@ -415,38 +417,7 @@ class ModelTask extends Shell { } else { $this->out(__('Please confirm the following associations:', true)); $this->hr(); - foreach ($associations as $type => $settings) { - if (!empty($associations[$type])) { - $count = count($associations[$type]); - $response = 'y'; - for ($i = 0; $i < $count; $i++) { - $prompt = "{$model->name} {$type} {$associations[$type][$i]['alias']}"; - $response = $this->in("{$prompt}?", array('y','n'), 'y'); - - if ('n' == low($response) || 'no' == low($response)) { - unset($associations[$type][$i]); - } else { - if ($model->name === $associations[$type][$i]['alias']) { - if ($type === 'belongsTo') { - $alias = 'Parent' . $associations[$type][$i]['alias']; - } - if ($type === 'hasOne' || $type === 'hasMany') { - $alias = 'Child' . $associations[$type][$i]['alias']; - } - - $alternateAlias = $this->in(sprintf(__('This is a self join. Use %s as the alias', true), $alias), array('y', 'n'), 'y'); - - if ('n' == low($alternateAlias) || 'no' == low($alternateAlias)) { - $associations[$type][$i]['alias'] = $this->in(__('Specify an alternate alias.', true)); - } else { - $associations[$type][$i]['alias'] = $alias; - } - } - } - } - $associations[$type] = array_merge($associations[$type]); - } - } + $associations = $this->confirmAssociations($model, $associations); } $wannaDoMoreAssoc = $this->in(__('Would you like to define some additional model associations?', true), array('y','n'), 'n'); @@ -534,13 +505,19 @@ class ModelTask extends Shell { $fields = $model->schema(); foreach ($fields as $fieldName => $field) { $offset = strpos($fieldName, '_id'); - if ($fieldName != $model->primaryKey && $offset !== false) { + if ($fieldName != $model->primaryKey && $fieldName != 'parent_id' && $offset !== false) { $tmpModelName = $this->_modelNameFromKey($fieldName); $associations['belongsTo'][] = array( 'alias' => $tmpModelName, 'className' => $tmpModelName, 'foreignKey' => $fieldName, ); + } elseif ($fieldName == 'parent_id') { + $associations['belongsTo'][] = array( + 'alias' => 'Parent' . $model->name, + 'className' => $model->name, + 'foreignKey' => $fieldName, + ); } } return $associations; @@ -561,16 +538,29 @@ class ModelTask extends Shell { $pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/'; $possibleJoinTable = preg_match($pattern , $otherTable); + if ($possibleJoinTable == true) { + continue; + } foreach ($modelFieldsTemp as $fieldName => $field) { - if ($fieldName != $model->primaryKey && $fieldName == $foreignKey && $possibleJoinTable == false) { + $assoc = false; + if ($fieldName != $model->primaryKey && $fieldName == $foreignKey) { $assoc = array( 'alias' => $tempOtherModel->name, 'className' => $tempOtherModel->name, 'foreignKey' => $fieldName ); + } elseif ($otherTable == $model->table && $fieldName == 'parent_id') { + $assoc = array( + 'alias' => 'Child' . $model->name, + 'className' => $model->name, + 'foreignKey' => $fieldName + ); + } + if ($assoc) { $associations['hasOne'][] = $assoc; $associations['hasMany'][] = $assoc; } + } } return $associations; @@ -615,6 +605,33 @@ class ModelTask extends Shell { } return $associations; } +/** + * Interact with the user and confirm associations. + * + * @param array $model Temporary Model instance. + * @param array $associations Array of associations to be confirmed. + * @return array Array of confirmed associations + **/ + function confirmAssociations(&$model, $associations) { + foreach ($associations as $type => $settings) { + if (!empty($associations[$type])) { + $count = count($associations[$type]); + $response = 'y'; + for ($i = 0; $i < $count; $i++) { + $prompt = "{$model->name} {$type} {$associations[$type][$i]['alias']}"; + $response = $this->in("{$prompt}?", array('y','n'), 'y'); + + if ('n' == low($response)) { + unset($associations[$type][$i]); + } elseif ($type == 'hasMany') { + unset($associations['hasOne'][$i]); + } + } + $associations[$type] = array_merge($associations[$type]); + } + } + return $associations; + } /** * Assembles and writes a Model file. diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index c5f74d89b..065d76afa 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -39,6 +39,7 @@ if (!class_exists('ShellDispatcher')) { if (!class_exists('ModelTask')) { require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'model.php'; + require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php'; } Mock::generatePartial( @@ -54,6 +55,10 @@ Mock::generatePartial( Mock::generate( 'Model', 'MockModelTaskModel' ); + +Mock::generate( + 'FixtureTask', 'MockModelTaskFixtureTask' +); /** * ModelTaskTest class * @@ -66,7 +71,7 @@ class ModelTaskTest extends CakeTestCase { * * @var array **/ - var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); + var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag', 'core.category_thread'); /** * setUp method @@ -99,20 +104,22 @@ class ModelTaskTest extends CakeTestCase { function testListAll() { $this->Task->expectAt(1, 'out', array('1. Article')); $this->Task->expectAt(2, 'out', array('2. ArticlesTag')); - $this->Task->expectAt(3, 'out', array('3. Comment')); - $this->Task->expectAt(4, 'out', array('4. Tag')); + $this->Task->expectAt(3, 'out', array('3. CategoryThread')); + $this->Task->expectAt(4, 'out', array('4. Comment')); + $this->Task->expectAt(5, 'out', array('5. Tag')); $result = $this->Task->listAll('test_suite'); - $expected = array('articles', 'articles_tags', 'comments', 'tags'); + $expected = array('articles', 'articles_tags', 'category_threads', 'comments', 'tags'); $this->assertEqual($result, $expected); - $this->Task->expectAt(6, 'out', array('1. Article')); - $this->Task->expectAt(7, 'out', array('2. ArticlesTag')); - $this->Task->expectAt(8, 'out', array('3. Comment')); - $this->Task->expectAt(9, 'out', array('4. Tag')); + $this->Task->expectAt(7, 'out', array('1. Article')); + $this->Task->expectAt(8, 'out', array('2. ArticlesTag')); + $this->Task->expectAt(9, 'out', array('3. CategoryThread')); + $this->Task->expectAt(10, 'out', array('4. Comment')); + $this->Task->expectAt(11, 'out', array('5. Tag')); $this->Task->connection = 'test_suite'; $result = $this->Task->listAll(); - $expected = array('articles', 'articles_tags', 'comments', 'tags'); + $expected = array('articles', 'articles_tags', 'category_threads', 'comments', 'tags'); $this->assertEqual($result, $expected); } @@ -133,7 +140,7 @@ class ModelTaskTest extends CakeTestCase { $expected = 'Article'; $this->assertEqual($result, $expected); - $this->Task->setReturnValueAt(2, 'in', 3); + $this->Task->setReturnValueAt(2, 'in', 4); $result = $this->Task->getName('test_suite'); $expected = 'Comment'; $this->assertEqual($result, $expected); @@ -319,6 +326,20 @@ class ModelTaskTest extends CakeTestCase { ) ); $this->assertEqual($result, $expected); + + + $model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread')); + $result = $this->Task->findBelongsTo($model, array()); + $expected = array( + 'belongsTo' => array( + array( + 'alias' => 'ParentCategoryThread', + 'className' => 'CategoryThread', + 'foreignKey' => 'parent_id', + ), + ) + ); + $this->assertEqual($result, $expected); } /** @@ -348,6 +369,27 @@ class ModelTaskTest extends CakeTestCase { ), ); $this->assertEqual($result, $expected); + + + $model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread')); + $result = $this->Task->findHasOneAndMany($model, array()); + $expected = array( + 'hasOne' => array( + array( + 'alias' => 'ChildCategoryThread', + 'className' => 'CategoryThread', + 'foreignKey' => 'parent_id', + ), + ), + 'hasMany' => array( + array( + 'alias' => 'ChildCategoryThread', + 'className' => 'CategoryThread', + 'foreignKey' => 'parent_id', + ), + ) + ); + $this->assertEqual($result, $expected); } /** @@ -373,5 +415,17 @@ class ModelTaskTest extends CakeTestCase { ); $this->assertEqual($result, $expected); } + +/** + * Ensure that the fixutre object is correctly called. + * + * @return void + **/ + function testFixture() { + $this->Task->Fixture =& new MockModelTaskFixtureTask(); + $this->Task->Fixture->expectAt(0, 'bake', array('Article', 'articles')); + $this->Task->fixture('Article', 'articles'); + } + } ?> \ No newline at end of file From ec443c43718076b00ef481e1091414253c8399bd Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 01:04:40 -0400 Subject: [PATCH 032/207] Moving method and adding tests. --- cake/console/libs/tasks/model.php | 173 ++++++++++-------- .../cases/console/libs/tasks/model.test.php | 33 ++++ 2 files changed, 134 insertions(+), 72 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 7d72dbf21..e5f90484c 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -130,6 +130,7 @@ class ModelTask extends Shell { $this->bake($object, false); } } + /** * Get a model object for a class name. * @@ -140,6 +141,7 @@ class ModelTask extends Shell { $object = new Model(array('name' => $className, 'ds' => $this->connection)); return $object; } + /** * Handles interactive baking * @@ -326,7 +328,7 @@ class ModelTask extends Shell { $this->out(__('Please select one of the following validation options:', true)); $this->hr(); } - + $prompt = ''; for ($i = 1; $i < $defaultChoice; $i++) { $prompt .= $i . ' - ' . $this->__validations[$i] . "\n"; @@ -419,77 +421,7 @@ class ModelTask extends Shell { $this->hr(); $associations = $this->confirmAssociations($model, $associations); } - - $wannaDoMoreAssoc = $this->in(__('Would you like to define some additional model associations?', true), array('y','n'), 'n'); - - while ((low($wannaDoMoreAssoc) == 'y' || low($wannaDoMoreAssoc) == 'yes')) { - $assocs = array(1 => 'belongsTo', 2 => 'hasOne', 3 => 'hasMany', 4 => 'hasAndBelongsToMany'); - $bad = true; - while ($bad) { - $this->out(__('What is the association type?', true)); - $prompt = "1. belongsTo\n"; - $prompt .= "2. hasOne\n"; - $prompt .= "3. hasMany\n"; - $prompt .= "4. hasAndBelongsToMany\n"; - $assocType = intval($this->in($prompt, null, __("Enter a number", true))); - - if (intval($assocType) < 1 || intval($assocType) > 4) { - $this->out(__('The selection you entered was invalid. Please enter a number between 1 and 4.', true)); - } else { - $bad = false; - } - } - $this->out(__('For the following options be very careful to match your setup exactly. Any spelling mistakes will cause errors.', true)); - $this->hr(); - $alias = $this->in(__('What is the alias for this association?', true)); - $className = $this->in(sprintf(__('What className will %s use?', true), $alias), null, $alias ); - $suggestedForeignKey = null; - if ($assocType == '1') { - $showKeys = $possibleKeys[$model->table]; - $suggestedForeignKey = $this->_modelKey($alias); - } else { - $otherTable = Inflector::tableize($className); - if (in_array($otherTable, $this->__tables)) { - if ($assocType < '4') { - $showKeys = $possibleKeys[$otherTable]; - } else { - $showKeys = null; - } - } else { - $otherTable = $this->in(__('What is the table for this model?', true)); - $showKeys = $possibleKeys[$otherTable]; - } - $suggestedForeignKey = $this->_modelKey($model->name); - } - if (!empty($showKeys)) { - $this->out(__('A helpful List of possible keys', true)); - for ($i = 0; $i < count($showKeys); $i++) { - $this->out($i + 1 . ". " . $showKeys[$i]); - } - $foreignKey = $this->in(__('What is the foreignKey?', true), null, __("Enter a number", true)); - if (intval($foreignKey) > 0 && intval($foreignKey) <= $i ) { - $foreignKey = $showKeys[intval($foreignKey) - 1]; - } - } - if (!isset($foreignKey)) { - $foreignKey = $this->in(__('What is the foreignKey? Specify your own.', true), null, $suggestedForeignKey); - } - if ($assocType == '4') { - $associationForeignKey = $this->in(__('What is the associationForeignKey?', true), null, $this->_modelKey($model->name)); - $joinTable = $this->in(__('What is the joinTable?', true)); - } - $associations[$assocs[$assocType]] = array_values((array)$associations[$assocs[$assocType]]); - $count = count($associations[$assocs[$assocType]]); - $i = ($count > 0) ? $count : 0; - $associations[$assocs[$assocType]][$i]['alias'] = $alias; - $associations[$assocs[$assocType]][$i]['className'] = $className; - $associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey; - if ($assocType == '4') { - $associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey; - $associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable; - } - $wannaDoMoreAssoc = $this->in(__('Define another association?', true), array('y','n'), 'y'); - } + $associations = $this->doMoreAssociations($model, $associations); } return $associations; } @@ -605,6 +537,7 @@ class ModelTask extends Shell { } return $associations; } + /** * Interact with the user and confirm associations. * @@ -633,6 +566,100 @@ class ModelTask extends Shell { return $associations; } +/** + * Interact with the user and generate additional non-conventional associations + * + * @param object $model Temporary model instance + * @param array $associations Array of associations. + * @return array Array of associations. + **/ + function doMoreAssociations($model, $associations) { + $prompt = __('Would you like to define some additional model associations?', true); + $wannaDoMoreAssoc = $this->in($prompt, array('y','n'), 'n'); + $possibleKeys = $this->_generatePossibleKeys(); + while (low($wannaDoMoreAssoc) == 'y') { + $assocs = array(1 => 'belongsTo', 2 => 'hasOne', 3 => 'hasMany', 4 => 'hasAndBelongsToMany'); + $this->out(__('What is the association type?', true)); + $prompt = "1. belongsTo\n"; + $prompt .= "2. hasOne\n"; + $prompt .= "3. hasMany\n"; + $prompt .= "4. hasAndBelongsToMany\n"; + $assocType = intval($this->in($prompt, array_keys($assocs), __("Enter a number", true))); + + $this->out(__("For the following options be very careful to match your setup exactly.\nAny spelling mistakes will cause errors.", true)); + $this->hr(); + + $alias = $this->in(__('What is the alias for this association?', true)); + $className = $this->in(sprintf(__('What className will %s use?', true), $alias), null, $alias ); + $suggestedForeignKey = null; + + if ($assocType == '1') { + $showKeys = $possibleKeys[$model->table]; + $suggestedForeignKey = $this->_modelKey($alias); + } else { + $otherTable = Inflector::tableize($className); + if (in_array($otherTable, $this->__tables)) { + if ($assocType < '4') { + $showKeys = $possibleKeys[$otherTable]; + } else { + $showKeys = null; + } + } else { + $otherTable = $this->in(__('What is the table for this model?', true)); + $showKeys = $possibleKeys[$otherTable]; + } + $suggestedForeignKey = $this->_modelKey($model->name); + } + if (!empty($showKeys)) { + $this->out(__('A helpful List of possible keys', true)); + for ($i = 0; $i < count($showKeys); $i++) { + $this->out($i + 1 . ". " . $showKeys[$i]); + } + $foreignKey = $this->in(__('What is the foreignKey?', true), null, __("Enter a number", true)); + if (intval($foreignKey) > 0 && intval($foreignKey) <= $i ) { + $foreignKey = $showKeys[intval($foreignKey) - 1]; + } + } + if (!isset($foreignKey)) { + $foreignKey = $this->in(__('What is the foreignKey? Specify your own.', true), null, $suggestedForeignKey); + } + if ($assocType == '4') { + $associationForeignKey = $this->in(__('What is the associationForeignKey?', true), null, $this->_modelKey($model->name)); + $joinTable = $this->in(__('What is the joinTable?', true)); + } + $associations[$assocs[$assocType]] = array_values((array)$associations[$assocs[$assocType]]); + $count = count($associations[$assocs[$assocType]]); + $i = ($count > 0) ? $count : 0; + $associations[$assocs[$assocType]][$i]['alias'] = $alias; + $associations[$assocs[$assocType]][$i]['className'] = $className; + $associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey; + if ($assocType == '4') { + $associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey; + $associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable; + } + $wannaDoMoreAssoc = $this->in(__('Define another association?', true), array('y','n'), 'y'); + } + return $associations; + } + +/** + * Finds all possible keys to use on custom associations. + * + * @return array array of tables and possible keys + **/ + function _generatePossibleKeys() { + $possible = array(); + foreach ($this->__tables as $otherTable) { + $tempOtherModel = & new Model(array('table' => $otherTable, 'ds' => $this->connection)); + $modelFieldsTemp = $tempOtherModel->schema(); + foreach ($modelFieldsTemp as $fieldName => $field) { + if ($field['type'] == 'integer' || $field['type'] == 'string') { + $possible[$otherTable][] = $fieldName; + } + } + } + return $possible; + } /** * Assembles and writes a Model file. * @@ -906,6 +933,7 @@ class ModelTask extends Shell { } return $this->__tables; } + /** * Interact with the user to determine the table name of a particular model * @@ -932,6 +960,7 @@ class ModelTask extends Shell { } return $useTable; } + /** * Forces the user to specify the model he wants to bake, and returns the selected model name. * diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 065d76afa..0fbde6017 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -427,5 +427,38 @@ class ModelTaskTest extends CakeTestCase { $this->Task->fixture('Article', 'articles'); } +/** + * test confirming of associations, and that when an association is hasMany + * a question for the hasOne is also not asked. + * + * @return void + **/ + function testConfirmAssociations() { + $associations = array( + 'hasOne' => array( + array( + 'alias' => 'ChildCategoryThread', + 'className' => 'CategoryThread', + 'foreignKey' => 'parent_id', + ), + ), + 'hasMany' => array( + array( + 'alias' => 'ChildCategoryThread', + 'className' => 'CategoryThread', + 'foreignKey' => 'parent_id', + ), + ) + ); + $model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread')); + $this->Task->setReturnValueAt(0, 'in', 'y'); + $result = $this->Task->confirmAssociations($model, $associations); + $this->assertTrue(empty($result['hasOne'])); + + $this->Task->setReturnValue('in', 'n'); + $result = $this->Task->confirmAssociations($model, $associations); + $this->assertTrue(empty($result['hasMany'])); + $this->assertTrue(empty($result['hasOne'])); + } } ?> \ No newline at end of file From d066a4a0d678dd6afd178f43a31ce97eb96d3361 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 01:35:59 -0400 Subject: [PATCH 033/207] Extracting method out. --- cake/console/libs/tasks/model.php | 53 ++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index e5f90484c..6ec8c1a41 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -142,6 +142,32 @@ class ModelTask extends Shell { return $object; } +/** + * Generate a key value list of options and a prompt. + * + * @param array $options Array of options to use for the selections. indexes must start at 0 + * @param string $prompt Prompt to use for options list. + * @param integer $default The default option for the given prompt. + * @return result of user choice. + **/ + function inOptions($options, $prompt = null, $default = null) { + $valid = false; + $max = count($options); + while (!$valid) { + foreach ($options as $i => $option) { + $this->out($i + 1 .'. ' . $option); + } + if (empty($prompt)) { + $prompt = __('Make a selection from the choices above', true); + } + $choice = $this->in($prompt, null, $default); + if (intval($choice) > 0 && intval($choice) <= $max) { + $valid = true; + } + } + return $choice - 1; + } + /** * Handles interactive baking * @@ -578,14 +604,10 @@ class ModelTask extends Shell { $wannaDoMoreAssoc = $this->in($prompt, array('y','n'), 'n'); $possibleKeys = $this->_generatePossibleKeys(); while (low($wannaDoMoreAssoc) == 'y') { - $assocs = array(1 => 'belongsTo', 2 => 'hasOne', 3 => 'hasMany', 4 => 'hasAndBelongsToMany'); + $assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); $this->out(__('What is the association type?', true)); - $prompt = "1. belongsTo\n"; - $prompt .= "2. hasOne\n"; - $prompt .= "3. hasMany\n"; - $prompt .= "4. hasAndBelongsToMany\n"; - $assocType = intval($this->in($prompt, array_keys($assocs), __("Enter a number", true))); - + $assocType = intval($this->inOptions($assocs, __('Enter a number',true))); + $this->out(__("For the following options be very careful to match your setup exactly.\nAny spelling mistakes will cause errors.", true)); $this->hr(); @@ -593,13 +615,13 @@ class ModelTask extends Shell { $className = $this->in(sprintf(__('What className will %s use?', true), $alias), null, $alias ); $suggestedForeignKey = null; - if ($assocType == '1') { + if ($assocType == 0) { $showKeys = $possibleKeys[$model->table]; $suggestedForeignKey = $this->_modelKey($alias); } else { $otherTable = Inflector::tableize($className); if (in_array($otherTable, $this->__tables)) { - if ($assocType < '4') { + if ($assocType < 3) { $showKeys = $possibleKeys[$otherTable]; } else { $showKeys = null; @@ -612,18 +634,13 @@ class ModelTask extends Shell { } if (!empty($showKeys)) { $this->out(__('A helpful List of possible keys', true)); - for ($i = 0; $i < count($showKeys); $i++) { - $this->out($i + 1 . ". " . $showKeys[$i]); - } - $foreignKey = $this->in(__('What is the foreignKey?', true), null, __("Enter a number", true)); - if (intval($foreignKey) > 0 && intval($foreignKey) <= $i ) { - $foreignKey = $showKeys[intval($foreignKey) - 1]; - } + $foreignKey = $this->inOptions($showKeys, __('What is the foreignKey?', true)); + $foreignKey = $showKeys[intval($foreignKey)]; } if (!isset($foreignKey)) { $foreignKey = $this->in(__('What is the foreignKey? Specify your own.', true), null, $suggestedForeignKey); } - if ($assocType == '4') { + if ($assocType == 3) { $associationForeignKey = $this->in(__('What is the associationForeignKey?', true), null, $this->_modelKey($model->name)); $joinTable = $this->in(__('What is the joinTable?', true)); } @@ -633,7 +650,7 @@ class ModelTask extends Shell { $associations[$assocs[$assocType]][$i]['alias'] = $alias; $associations[$assocs[$assocType]][$i]['className'] = $className; $associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey; - if ($assocType == '4') { + if ($assocType == 3) { $associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey; $associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable; } From 6be70c3cfa7ab5bfa9a9e66f2d230f7fec4e280e Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 11:01:15 -0400 Subject: [PATCH 034/207] Adding test coverage for inOptions. --- .../cases/console/libs/tasks/model.test.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 0fbde6017..a5f684e6a 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -460,5 +460,25 @@ class ModelTaskTest extends CakeTestCase { $this->assertTrue(empty($result['hasMany'])); $this->assertTrue(empty($result['hasOne'])); } + +/** + * test that inOptions generates questions and only accepts a valid answer + * + * @return void + **/ + function testInOptions() { + $options = array('one', 'two', 'three'); + $this->Task->expectAt(0, 'out', array('1. one')); + $this->Task->expectAt(1, 'out', array('2. two')); + $this->Task->expectAt(2, 'out', array('3. three')); + $this->Task->setReturnValueAt(0, 'in', 10); + + $this->Task->expectAt(3, 'out', array('1. one')); + $this->Task->expectAt(4, 'out', array('2. two')); + $this->Task->expectAt(5, 'out', array('3. three')); + $this->Task->setReturnValueAt(1, 'in', 2); + $result = $this->Task->inOptions($options, 'Pick a number'); + $this->assertEqual($result, 1); + } } ?> \ No newline at end of file From ef519621b476f398ea65324384e837833a427b64 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 12:11:20 -0400 Subject: [PATCH 035/207] Adding tests for doAssociations --- .../cases/console/libs/tasks/model.test.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index a5f684e6a..9c49bde37 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -416,6 +416,36 @@ class ModelTaskTest extends CakeTestCase { $this->assertEqual($result, $expected); } +/** + * test non interactive doAssociations + * + * @return void + **/ + function testDoAssociationsNonInteractive() { + $this->Task->connection = 'test_suite'; + $this->Task->interactive = false; + $model = new Model(array('ds' => 'test_suite', 'name' => 'Article')); + $result = $this->Task->doAssociations($model); + $expected = array( + 'hasMany' => array( + array( + 'alias' => 'Comment', + 'className' => 'Comment', + 'foreignKey' => 'article_id', + ), + ), + 'hasAndBelongsToMany' => array( + array( + 'alias' => 'Tag', + 'className' => 'Tag', + 'foreignKey' => 'article_id', + 'joinTable' => 'articles_tags', + 'associationForeignKey' => 'tag_id', + ), + ), + ); + + } /** * Ensure that the fixutre object is correctly called. * @@ -448,6 +478,13 @@ class ModelTaskTest extends CakeTestCase { 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), + ), + 'belongsTo' => array( + array( + 'alias' => 'User', + 'className' => 'User', + 'foreignKey' => 'user_id', + ), ) ); $model = new Model(array('ds' => 'test_suite', 'name' => 'CategoryThread')); From 4b75c6b78e849d0bf74d3d1e9115d853e12c40f0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 12:43:38 -0400 Subject: [PATCH 036/207] minor cleanup --- cake/console/libs/tasks/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 6ec8c1a41..39307355b 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -972,7 +972,7 @@ class ModelTask extends Shell { $this->out(sprintf(__("Given your model named '%s',\nCake would expect a database table named '%s'", true), $modelName, $fullTableName)); $tableIsGood = $this->in(__('Do you want to use this table?', true), array('y','n'), 'y'); } - if (low($tableIsGood) == 'n' || low($tableIsGood) == 'no') { + if (strtolower($tableIsGood) == 'n') { $useTable = $this->in(__('What is the name of the table (enter "null" to use NO table)?', true)); } return $useTable; From 328756f6865c3374f29343db7c385e39e1c9b4ba Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 13:33:05 -0400 Subject: [PATCH 037/207] Adding fixture template --- .../libs/templates/objects/fixture.ctp | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 cake/console/libs/templates/objects/fixture.ctp diff --git a/cake/console/libs/templates/objects/fixture.ctp b/cake/console/libs/templates/objects/fixture.ctp new file mode 100644 index 000000000..23484a3cd --- /dev/null +++ b/cake/console/libs/templates/objects/fixture.ctp @@ -0,0 +1,40 @@ + + +/* Fixture generated on: */ +class Fixture extends CakeTestFixture { + var $name = ''; + + var $table = ''; + + + var $import = ; + + + var $fields = ; + + + var $records = ; + +} +'; ?> \ No newline at end of file From a6d16500a95920301852ce8d04e323507ccecb92 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 13:33:52 -0400 Subject: [PATCH 038/207] Adding CodeGenerator in a temporary place. --- cake/console/libs/tasks/fixture.php | 95 +++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 5d19da9f1..64ad60299 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -342,4 +342,99 @@ class FixtureTask extends Shell { $this->_stop(); } } + +/** + * Similar to View but has no dependancy on controller + * + **/ +class CodeGenerator { +/** + * variables to add to template scope + * + * @var array + **/ + var $templateVars = array(); +/** + * set the paths for the code generator to search for templates + * + * @param array $paths Array of paths to look in + * @access public + * @return void + **/ + function setPaths($paths) { + $this->_paths = $paths; + } + +/** + * Find a template + * + * @param string $directory Subdirectory to look for ie. 'views', 'objects' + * @param string $filename lower_case_underscored filename you want. + * @access public + * @return string filename or false if scan failed. + **/ + function _findTemplate($directory, $filename) { + foreach ($this->_paths as $path) { + $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; + if (file_exists($templatePath) && is_file($templatePath)) { + return $templatePath; + } + } + return false; + } + +/** + * Set variable values to the template scope + * + * @param mixed $one A string or an array of data. + * @param mixed $two Value in case $one is a string (which then works as the key). + * Unused if $one is an associative array, otherwise serves as the values to $one's keys. + * @return void + */ + function set($one, $two = null) { + $data = null; + if (is_array($one)) { + if (is_array($two)) { + $data = array_combine($one, $two); + } else { + $data = $one; + } + } else { + $data = array($one => $two); + } + + if ($data == null) { + return false; + } + + foreach ($data as $name => $value) { + $this->viewVars[$name] = $value; + } + } + +/** + * Runs the template + * + * @param string $directory directory / type of thing you want + * @param string $filename template name + * @param string $vars Additional vars to set to template scope. + * @access public + * @return contents of generated code template + **/ + function generate($directory, $filename, $vars = null) { + if ($vars !== null) { + $this->set($vars); + } + $templateFile = $this->_findTemplate($directory, $filename); + if ($templateFile) { + extract($this->templateVars); + ob_start(); + ob_implicit_flush(0); + include($templatePath); + $content = ob_get_clean(); + return $content; + } + return ''; + } +} ?> From 3ea2b5a87d3b3c03ff4c326e78eaa47d3fa6bf02 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 10 May 2009 22:16:38 -0400 Subject: [PATCH 039/207] Moving CodeGenerator class into bake shell. Updating FixtureTask and test cases. Updating template for fixtures. --- cake/console/libs/bake.php | 95 ++++++++++++ cake/console/libs/tasks/fixture.php | 136 +++--------------- .../libs/templates/objects/fixture.ctp | 8 +- .../cases/console/libs/tasks/fixture.test.php | 8 +- 4 files changed, 128 insertions(+), 119 deletions(-) diff --git a/cake/console/libs/bake.php b/cake/console/libs/bake.php index 6277342d5..bce32a767 100644 --- a/cake/console/libs/bake.php +++ b/cake/console/libs/bake.php @@ -218,4 +218,99 @@ class BakeShell extends Shell { } } + +/** + * Similar to View but has no dependancy on controller + * + **/ +class CodeGenerator { +/** + * variables to add to template scope + * + * @var array + **/ + var $templateVars = array(); +/** + * set the paths for the code generator to search for templates + * + * @param array $paths Array of paths to look in + * @access public + * @return void + **/ + function setPaths($paths) { + $this->_paths = $paths; + } + +/** + * Find a template + * + * @param string $directory Subdirectory to look for ie. 'views', 'objects' + * @param string $filename lower_case_underscored filename you want. + * @access public + * @return string filename or false if scan failed. + **/ + function _findTemplate($directory, $filename) { + foreach ($this->_paths as $path) { + $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; + if (file_exists($templatePath) && is_file($templatePath)) { + return $templatePath; + } + } + return false; + } + +/** + * Set variable values to the template scope + * + * @param mixed $one A string or an array of data. + * @param mixed $two Value in case $one is a string (which then works as the key). + * Unused if $one is an associative array, otherwise serves as the values to $one's keys. + * @return void + */ + function set($one, $two = null) { + $data = null; + if (is_array($one)) { + if (is_array($two)) { + $data = array_combine($one, $two); + } else { + $data = $one; + } + } else { + $data = array($one => $two); + } + + if ($data == null) { + return false; + } + + foreach ($data as $name => $value) { + $this->templateVars[$name] = $value; + } + } + +/** + * Runs the template + * + * @param string $directory directory / type of thing you want + * @param string $filename template name + * @param string $vars Additional vars to set to template scope. + * @access public + * @return contents of generated code template + **/ + function generate($directory, $filename, $vars = null) { + if ($vars !== null) { + $this->set($vars); + } + $templateFile = $this->_findTemplate($directory, $filename); + if ($templateFile) { + extract($this->templateVars); + ob_start(); + ob_implicit_flush(0); + include($templateFile); + $content = ob_get_clean(); + return $content; + } + return ''; + } +} ?> \ No newline at end of file diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index 64ad60299..e5e8541b6 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -154,16 +154,14 @@ class FixtureTask extends Shell { * @access private */ function bake($model, $useTable = false, $importOptions = array()) { - $out = "class {$model}Fixture extends CakeTestFixture {\n"; - $out .= "\tvar \$name = '$model';\n"; - + $table = $schema = $records = $import = null; if (!$useTable) { $useTable = Inflector::tableize($model); } elseif ($useTable != Inflector::tableize($model)) { - $out .= "\tvar \$table = '$useTable';\n"; + $table = $useTable; } - $modelImport = $recordImport = null; + $modelImport = $import = $recordImport = null; if (!empty($importOptions)) { if (isset($importOptions['schema'])) { $modelImport = "'model' => '{$importOptions['schema']}'"; @@ -174,7 +172,7 @@ class FixtureTask extends Shell { if ($modelImport && $recordImport) { $modelImport .= ', '; } - $out .= sprintf("\tvar \$import = array(%s%s);\n", $modelImport, $recordImport); + $import = sprintf("array(%s%s);\n", $modelImport, $recordImport); } $this->_Schema = new CakeSchema(); @@ -187,7 +185,7 @@ class FixtureTask extends Shell { $tableInfo = $data['tables'][$useTable]; if (is_null($modelImport)) { - $out .= $this->_generateSchema($tableInfo); + $schema = $this->_generateSchema($tableInfo); } if (is_null($recordImport)) { @@ -195,10 +193,9 @@ class FixtureTask extends Shell { if (isset($this->params['count'])) { $recordCount = $this->params['count']; } - $out .= $this->_generateRecords($tableInfo, $recordCount); + $records = $this->_generateRecords($tableInfo, $recordCount); } - $out .= "}\n"; - $this->generateFixtureFile($model, $out); + $out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import', 'fields')); return $out; } @@ -210,7 +207,10 @@ class FixtureTask extends Shell { * @access public * @return void **/ - function generateFixtureFile($model, $fixture) { + function generateFixtureFile($model, $otherVars) { + $defaults = array('table' => null, 'schema' => null, 'records' => null, 'import' => null, 'fields' => null); + $vars = array_merge($defaults, $otherVars); + //@todo fix plugin pathing. $path = $this->path; if (isset($this->plugin)) { @@ -218,11 +218,16 @@ class FixtureTask extends Shell { $path = APP . $pluginPath . 'tests' . DS . 'fixtures' . DS; } $filename = Inflector::underscore($model) . '_fixture.php'; - $content = ""; + + $Generator = new CodeGenerator(); + $Generator->setPaths($this->Dispatch->shellPaths); + $Generator->set('model', $model); + $Generator->set($vars); + $content = $Generator->generate('objects', 'fixture'); + $this->out("\nBaking test fixture for $model..."); $this->createFile($path . $filename, $content); + return $content; } /** @@ -233,7 +238,7 @@ class FixtureTask extends Shell { **/ function _generateSchema($tableInfo) { $cols = array(); - $out = "\n\tvar \$fields = array(\n"; + $out = "array(\n"; foreach ($tableInfo as $field => $fieldInfo) { if (is_array($fieldInfo)) { if ($field != 'indexes') { @@ -252,7 +257,7 @@ class FixtureTask extends Shell { } } $out .= join(",\n", $cols); - $out .= "\n\t);\n\n"; + $out .= "\n\t)"; return $out; } @@ -263,7 +268,7 @@ class FixtureTask extends Shell { * @return string **/ function _generateRecords($tableInfo, $recordCount = 1) { - $out = "\tvar \$records = array(\n"; + $out = "array(\n"; for ($i = 0; $i < $recordCount; $i++) { $records = array(); @@ -317,7 +322,7 @@ class FixtureTask extends Shell { $out .= implode(",\n", $records); $out .= "\n\t\t),\n"; } - $out .= "\t);\n"; + $out .= "\t)"; return $out; } @@ -342,99 +347,4 @@ class FixtureTask extends Shell { $this->_stop(); } } - -/** - * Similar to View but has no dependancy on controller - * - **/ -class CodeGenerator { -/** - * variables to add to template scope - * - * @var array - **/ - var $templateVars = array(); -/** - * set the paths for the code generator to search for templates - * - * @param array $paths Array of paths to look in - * @access public - * @return void - **/ - function setPaths($paths) { - $this->_paths = $paths; - } - -/** - * Find a template - * - * @param string $directory Subdirectory to look for ie. 'views', 'objects' - * @param string $filename lower_case_underscored filename you want. - * @access public - * @return string filename or false if scan failed. - **/ - function _findTemplate($directory, $filename) { - foreach ($this->_paths as $path) { - $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; - if (file_exists($templatePath) && is_file($templatePath)) { - return $templatePath; - } - } - return false; - } - -/** - * Set variable values to the template scope - * - * @param mixed $one A string or an array of data. - * @param mixed $two Value in case $one is a string (which then works as the key). - * Unused if $one is an associative array, otherwise serves as the values to $one's keys. - * @return void - */ - function set($one, $two = null) { - $data = null; - if (is_array($one)) { - if (is_array($two)) { - $data = array_combine($one, $two); - } else { - $data = $one; - } - } else { - $data = array($one => $two); - } - - if ($data == null) { - return false; - } - - foreach ($data as $name => $value) { - $this->viewVars[$name] = $value; - } - } - -/** - * Runs the template - * - * @param string $directory directory / type of thing you want - * @param string $filename template name - * @param string $vars Additional vars to set to template scope. - * @access public - * @return contents of generated code template - **/ - function generate($directory, $filename, $vars = null) { - if ($vars !== null) { - $this->set($vars); - } - $templateFile = $this->_findTemplate($directory, $filename); - if ($templateFile) { - extract($this->templateVars); - ob_start(); - ob_implicit_flush(0); - include($templatePath); - $content = ob_get_clean(); - return $content; - } - return ''; - } -} ?> diff --git a/cake/console/libs/templates/objects/fixture.ctp b/cake/console/libs/templates/objects/fixture.ctp index 23484a3cd..34d84bf4a 100644 --- a/cake/console/libs/templates/objects/fixture.ctp +++ b/cake/console/libs/templates/objects/fixture.ctp @@ -20,19 +20,21 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ ?> - + /* Fixture generated on: */ class Fixture extends CakeTestFixture { var $name = ''; - - var $table = ''; + + var $table = ''; var $import = ; + var $fields = ; + var $records = ; diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 871efbbb2..10b3c862c 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -38,6 +38,7 @@ if (!class_exists('ShellDispatcher')) { } if (!class_exists('FixtureTask')) { + require CAKE . 'console' . DS . 'libs' . DS . 'bake.php'; require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php'; } @@ -79,6 +80,7 @@ class FixtureTaskTest extends CakeTestCase { $this->Task =& new MockFixtureTask(); $this->Task->Model =& new MockFixtureModelTask(); $this->Task->Dispatch = new $this->Dispatcher; + $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); } /** * tearDown method @@ -216,11 +218,11 @@ class FixtureTaskTest extends CakeTestCase { $this->Task->path = '/my/path/'; $filename = '/my/path/article_fixture.php'; - $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/my fixture/'))); - $result = $this->Task->generateFixtureFile('Article', 'my fixture'); + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/Article/'))); + $result = $this->Task->generateFixtureFile('Article', array()); $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/\<\?php(.*)\?\>/ms'))); - $result = $this->Task->generateFixtureFile('Article', 'my fixture'); + $result = $this->Task->generateFixtureFile('Article', array()); } } ?> \ No newline at end of file From dff90e892ed0890def6f405f9a464b81b16301a4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 12 May 2009 21:19:15 -0400 Subject: [PATCH 040/207] Adding Template Task, removing CodeGenerator. --- cake/console/libs/bake.php | 95 --------------------- cake/console/libs/tasks/template.php | 120 +++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 95 deletions(-) create mode 100644 cake/console/libs/tasks/template.php diff --git a/cake/console/libs/bake.php b/cake/console/libs/bake.php index bce32a767..6277342d5 100644 --- a/cake/console/libs/bake.php +++ b/cake/console/libs/bake.php @@ -218,99 +218,4 @@ class BakeShell extends Shell { } } - -/** - * Similar to View but has no dependancy on controller - * - **/ -class CodeGenerator { -/** - * variables to add to template scope - * - * @var array - **/ - var $templateVars = array(); -/** - * set the paths for the code generator to search for templates - * - * @param array $paths Array of paths to look in - * @access public - * @return void - **/ - function setPaths($paths) { - $this->_paths = $paths; - } - -/** - * Find a template - * - * @param string $directory Subdirectory to look for ie. 'views', 'objects' - * @param string $filename lower_case_underscored filename you want. - * @access public - * @return string filename or false if scan failed. - **/ - function _findTemplate($directory, $filename) { - foreach ($this->_paths as $path) { - $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; - if (file_exists($templatePath) && is_file($templatePath)) { - return $templatePath; - } - } - return false; - } - -/** - * Set variable values to the template scope - * - * @param mixed $one A string or an array of data. - * @param mixed $two Value in case $one is a string (which then works as the key). - * Unused if $one is an associative array, otherwise serves as the values to $one's keys. - * @return void - */ - function set($one, $two = null) { - $data = null; - if (is_array($one)) { - if (is_array($two)) { - $data = array_combine($one, $two); - } else { - $data = $one; - } - } else { - $data = array($one => $two); - } - - if ($data == null) { - return false; - } - - foreach ($data as $name => $value) { - $this->templateVars[$name] = $value; - } - } - -/** - * Runs the template - * - * @param string $directory directory / type of thing you want - * @param string $filename template name - * @param string $vars Additional vars to set to template scope. - * @access public - * @return contents of generated code template - **/ - function generate($directory, $filename, $vars = null) { - if ($vars !== null) { - $this->set($vars); - } - $templateFile = $this->_findTemplate($directory, $filename); - if ($templateFile) { - extract($this->templateVars); - ob_start(); - ob_implicit_flush(0); - include($templateFile); - $content = ob_get_clean(); - return $content; - } - return ''; - } -} ?> \ No newline at end of file diff --git a/cake/console/libs/tasks/template.php b/cake/console/libs/tasks/template.php new file mode 100644 index 000000000..ab4c607c9 --- /dev/null +++ b/cake/console/libs/tasks/template.php @@ -0,0 +1,120 @@ +_paths = $this->Dispatch->shellPaths; + } +/** + * set the paths for the code generator to search for templates + * + * @param array $paths Array of paths to look in + * @access public + * @return void + **/ + function setPaths($paths) { + $this->_paths = $paths; + } + +/** + * Find a template + * + * @param string $directory Subdirectory to look for ie. 'views', 'objects' + * @param string $filename lower_case_underscored filename you want. + * @access public + * @return string filename or false if scan failed. + **/ + function _findTemplate($directory, $filename) { + foreach ($this->_paths as $path) { + $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; + if (file_exists($templatePath) && is_file($templatePath)) { + return $templatePath; + } + } + return false; + } + +/** + * Set variable values to the template scope + * + * @param mixed $one A string or an array of data. + * @param mixed $two Value in case $one is a string (which then works as the key). + * Unused if $one is an associative array, otherwise serves as the values to $one's keys. + * @return void + */ + function set($one, $two = null) { + $data = null; + if (is_array($one)) { + if (is_array($two)) { + $data = array_combine($one, $two); + } else { + $data = $one; + } + } else { + $data = array($one => $two); + } + + if ($data == null) { + return false; + } + + foreach ($data as $name => $value) { + $this->templateVars[$name] = $value; + } + } + +/** + * Runs the template + * + * @param string $directory directory / type of thing you want + * @param string $filename template name + * @param string $vars Additional vars to set to template scope. + * @access public + * @return contents of generated code template + **/ + function generate($directory, $filename, $vars = null) { + if ($vars !== null) { + $this->set($vars); + } + $templateFile = $this->_findTemplate($directory, $filename); + if ($templateFile) { + extract($this->templateVars); + ob_start(); + ob_implicit_flush(0); + include($templateFile); + $content = ob_get_clean(); + return $content; + } + return ''; + } +} \ No newline at end of file From a38233e75d10b2884b9e6d8fc0e0f72d0085d19f Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 12 May 2009 21:26:37 -0400 Subject: [PATCH 041/207] Updating FixtureTask and FixtureTask test to use TemplateTask --- cake/console/libs/tasks/fixture.php | 10 ++++------ cake/tests/cases/console/libs/tasks/fixture.test.php | 4 +++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index e5e8541b6..ec1bc7240 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -42,7 +42,7 @@ class FixtureTask extends Shell { * @var array * @access public */ - var $tasks = array('DbConfig', 'Model'); + var $tasks = array('DbConfig', 'Model', 'Template'); /** * path to fixtures directory * @@ -219,11 +219,9 @@ class FixtureTask extends Shell { } $filename = Inflector::underscore($model) . '_fixture.php'; - $Generator = new CodeGenerator(); - $Generator->setPaths($this->Dispatch->shellPaths); - $Generator->set('model', $model); - $Generator->set($vars); - $content = $Generator->generate('objects', 'fixture'); + $this->Template->set('model', $model); + $this->Template->set($vars); + $content = $this->Template->generate('objects', 'fixture'); $this->out("\nBaking test fixture for $model..."); $this->createFile($path . $filename, $content); diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 10b3c862c..2ec79fd49 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -38,7 +38,7 @@ if (!class_exists('ShellDispatcher')) { } if (!class_exists('FixtureTask')) { - require CAKE . 'console' . DS . 'libs' . DS . 'bake.php'; + require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'template.php'; require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php'; } @@ -80,7 +80,9 @@ class FixtureTaskTest extends CakeTestCase { $this->Task =& new MockFixtureTask(); $this->Task->Model =& new MockFixtureModelTask(); $this->Task->Dispatch = new $this->Dispatcher; + $this->Task->Template =& new TemplateTask($this->Task->Dispatch); $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); + $this->Task->Template->initialize(); } /** * tearDown method From 3a36979a210e5325662d9088a179abf51969fb40 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 12 May 2009 21:35:06 -0400 Subject: [PATCH 042/207] fixing doc block --- .../cases/console/libs/tasks/fixture.test.php | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/fixture.test.php b/cake/tests/cases/console/libs/tasks/fixture.test.php index 2ec79fd49..f5f41f059 100644 --- a/cake/tests/cases/console/libs/tasks/fixture.test.php +++ b/cake/tests/cases/console/libs/tasks/fixture.test.php @@ -1,28 +1,23 @@ Date: Tue, 12 May 2009 22:00:30 -0400 Subject: [PATCH 043/207] Updating TemplateTask adding test case and test object file. --- cake/console/libs/tasks/template.php | 14 +- .../console/libs/tasks/template.test.php | 124 ++++++++++++++++++ .../shells/templates/objects/test_object.ctp | 2 + 3 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 cake/tests/cases/console/libs/tasks/template.test.php create mode 100644 cake/tests/test_app/vendors/shells/templates/objects/test_object.ctp diff --git a/cake/console/libs/tasks/template.php b/cake/console/libs/tasks/template.php index ab4c607c9..6fe7ddfed 100644 --- a/cake/console/libs/tasks/template.php +++ b/cake/console/libs/tasks/template.php @@ -33,17 +33,7 @@ class TemplateTask extends Shell { * @return void **/ function initialize() { - $this->_paths = $this->Dispatch->shellPaths; - } -/** - * set the paths for the code generator to search for templates - * - * @param array $paths Array of paths to look in - * @access public - * @return void - **/ - function setPaths($paths) { - $this->_paths = $paths; + $this->templatePaths = $this->Dispatch->shellPaths; } /** @@ -55,7 +45,7 @@ class TemplateTask extends Shell { * @return string filename or false if scan failed. **/ function _findTemplate($directory, $filename) { - foreach ($this->_paths as $path) { + foreach ($this->templatePaths as $path) { $templatePath = $path . 'templates' . DS . $directory . DS . $filename . '.ctp'; if (file_exists($templatePath) && is_file($templatePath)) { return $templatePath; diff --git a/cake/tests/cases/console/libs/tasks/template.test.php b/cake/tests/cases/console/libs/tasks/template.test.php new file mode 100644 index 000000000..86baa4559 --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/template.test.php @@ -0,0 +1,124 @@ +Dispatcher =& new TestTemplateTaskMockShellDispatcher(); + $this->Task =& new MockTemplateTask($this->Dispatcher); + $this->Task->Dispatch = new $this->Dispatcher; + $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); + } + +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + unset($this->Task, $this->Dispatcher); + ClassRegistry::flush(); + } + +/** + * test that set sets variables + * + * @return void + **/ + function testSet() { + $this->Task->set('one', 'two'); + $this->assertTrue(isset($this->Task->templateVars['one'])); + $this->assertEqual($this->Task->templateVars['one'], 'two'); + + $this->Task->set(array('one' => 'three', 'four' => 'five')); + $this->assertTrue(isset($this->Task->templateVars['one'])); + $this->assertEqual($this->Task->templateVars['one'], 'three'); + $this->assertTrue(isset($this->Task->templateVars['four'])); + $this->assertEqual($this->Task->templateVars['four'], 'five'); + } + +/** + * test Initialize + * + * @return void + **/ + function testInitialize() { + $this->Task->initialize(); + $this->assertEqual($this->Task->templatePaths, $this->Task->Dispatch->shellPaths); + } + +/** + * test generate + * + * @return void + **/ + function testGenerate() { + $this->Task->templatePaths = array( + TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'vendors' . DS . 'shells' . DS + ); + $result = $this->Task->generate('objects', 'test_object', array('test' => 'foo')); + $expected = "I got rendered\nfoo"; + $this->assertEqual($result, $expected); + + + } +} +?> \ No newline at end of file diff --git a/cake/tests/test_app/vendors/shells/templates/objects/test_object.ctp b/cake/tests/test_app/vendors/shells/templates/objects/test_object.ctp new file mode 100644 index 000000000..c524b8231 --- /dev/null +++ b/cake/tests/test_app/vendors/shells/templates/objects/test_object.ctp @@ -0,0 +1,2 @@ +I got rendered + \ No newline at end of file From 333713e9783c113d6748f51ee27c3e7e4c80df31 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 12 May 2009 22:01:27 -0400 Subject: [PATCH 044/207] removing whitespace. --- cake/tests/cases/console/libs/tasks/template.test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/template.test.php b/cake/tests/cases/console/libs/tasks/template.test.php index 86baa4559..f12656436 100644 --- a/cake/tests/cases/console/libs/tasks/template.test.php +++ b/cake/tests/cases/console/libs/tasks/template.test.php @@ -117,8 +117,6 @@ class TemplateTaskTest extends CakeTestCase { $result = $this->Task->generate('objects', 'test_object', array('test' => 'foo')); $expected = "I got rendered\nfoo"; $this->assertEqual($result, $expected); - - } } ?> \ No newline at end of file From a7f0071c610e56e718c83028631fa3b44a72ffc4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 13 May 2009 23:35:41 -0400 Subject: [PATCH 045/207] Forcing templatePaths to exist. --- cake/console/libs/tasks/template.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cake/console/libs/tasks/template.php b/cake/console/libs/tasks/template.php index 6fe7ddfed..d68ba61fe 100644 --- a/cake/console/libs/tasks/template.php +++ b/cake/console/libs/tasks/template.php @@ -26,6 +26,13 @@ class TemplateTask extends Shell { * @var array **/ var $templateVars = array(); + +/** + * Paths to look for templates on. + * + * @var array + **/ + var $templatePaths = array(); /** * Initialize callback * @@ -96,6 +103,9 @@ class TemplateTask extends Shell { if ($vars !== null) { $this->set($vars); } + if (empty($this->templatePaths)) { + $this->initialize(); + } $templateFile = $this->_findTemplate($directory, $filename); if ($templateFile) { extract($this->templateVars); From 3c08369e3af7d260712868e5754fd77b30e23c92 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 13 May 2009 23:36:13 -0400 Subject: [PATCH 046/207] Adding bake model template. Adding tests for bake model. --- cake/console/libs/tasks/model.php | 13 +- cake/console/libs/templates/objects/model.ctp | 125 ++++++++++++++++++ .../cases/console/libs/tasks/model.test.php | 93 ++++++++++++- 3 files changed, 223 insertions(+), 8 deletions(-) create mode 100644 cake/console/libs/templates/objects/model.ctp diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 39307355b..c9f2920be 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -62,7 +62,7 @@ class ModelTask extends Shell { * @var array * @access public */ - var $tasks = array('DbConfig', 'Fixture', 'Test'); + var $tasks = array('DbConfig', 'Fixture', 'Test', 'Template'); /** * Holds tables found on connection. @@ -700,7 +700,12 @@ class ModelTask extends Shell { $useDbConfig = $name->useDbConfig; $name = $name->name; } - + + $this->Template->set(compact('name', 'useDbConfig', 'associations', 'validate', 'primaryKey', 'useTable')); + $this->Template->set('plugin', $this->plugin); + $out = $this->Template->generate('objects', 'model'); + + /* $out = "plugin}AppModel {\n\n"; $out .= "\tvar \$name = '{$name}';\n"; @@ -841,9 +846,11 @@ class ModelTask extends Shell { } $out .= "}\n"; $out .= "?>"; + */ $filename = $this->path . Inflector::underscore($name) . '.php'; $this->out("\nBaking model class for $name..."); - return $this->createFile($filename, $out); + $this->createFile($filename, $out); + return $out; } /** diff --git a/cake/console/libs/templates/objects/model.ctp b/cake/console/libs/templates/objects/model.ctp new file mode 100644 index 000000000..5cb28dc9c --- /dev/null +++ b/cake/console/libs/templates/objects/model.ctp @@ -0,0 +1,125 @@ + +class extends AppModel { + var $name = ''; + + var $useDbConfig = ''; + + + + var $primaryKey = ''; + + $validations): + echo "\t\t'$field' => array(\n"; + foreach ($validations as $key => $validator): + echo "\t\t\t'$key' => array('rule' => array('$validator')),\n"; + endforeach; + echo "\t\t),\n"; + endforeach; + echo "\t);\n"; +endif; + +foreach (array('hasOne', 'belongsTo') as $assocType): + if (!empty($associations[$assocType])): + $typeCount = count($associations[$assocType]); + echo "\n\tvar \$$assocType = array("; + foreach ($associations[$assocType] as $i => $relation): + $out = "\n\t\t'{$relation['alias']}' => array(\n"; + $out .= "\t\t\t'className' => '{$relation['className']}',\n"; + $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; + $out .= "\t\t\t'conditions' => '',\n"; + $out .= "\t\t\t'fields' => '',\n"; + $out .= "\t\t\t'order' => ''\n"; + $out .= "\t\t)"; + if ($i + 1 < $typeCount) { + $out .= ","; + } + echo $out; + endforeach; + echo "\n\t);\n"; + endif; +endforeach; + +if (!empty($associations['hasMany'])): + $belongsToCount = count($associations['hasMany']); + echo "\n\tvar \$hasMany = array("; + foreach ($associations['hasMany'] as $i => $relation): + $out = "\n\t\t'{$relation['alias']}' => array(\n"; + $out .= "\t\t\t'className' => '{$relation['className']}',\n"; + $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; + $out .= "\t\t\t'dependent' => false,\n"; + $out .= "\t\t\t'conditions' => '',\n"; + $out .= "\t\t\t'fields' => '',\n"; + $out .= "\t\t\t'order' => '',\n"; + $out .= "\t\t\t'limit' => '',\n"; + $out .= "\t\t\t'offset' => '',\n"; + $out .= "\t\t\t'exclusive' => '',\n"; + $out .= "\t\t\t'finderQuery' => '',\n"; + $out .= "\t\t\t'counterQuery' => ''\n"; + $out .= "\t\t)"; + if ($i + 1 < $belongsToCount) { + $out .= ","; + } + echo $out; + endforeach; + echo "\n\t);\n\n"; +endif; + +if (!empty($associations['hasAndBelongsToMany'])): + $habtmCount = count($associations['hasAndBelongsToMany']); + echo "\n\tvar \$hasAndBelongsToMany = array("; + foreach ($associations['hasAndBelongsToMany'] as $i => $relation): + $out = "\n\t\t'{$relation['alias']}' => array(\n"; + $out .= "\t\t\t'className' => '{$relation['className']}',\n"; + $out .= "\t\t\t'joinTable' => '{$relation['joinTable']}',\n"; + $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; + $out .= "\t\t\t'associationForeignKey' => '{$relation['associationForeignKey']}',\n"; + $out .= "\t\t\t'unique' => true,\n"; + $out .= "\t\t\t'conditions' => '',\n"; + $out .= "\t\t\t'fields' => '',\n"; + $out .= "\t\t\t'order' => '',\n"; + $out .= "\t\t\t'limit' => '',\n"; + $out .= "\t\t\t'offset' => '',\n"; + $out .= "\t\t\t'finderQuery' => '',\n"; + $out .= "\t\t\t'deleteQuery' => '',\n"; + $out .= "\t\t\t'insertQuery' => ''\n"; + $out .= "\t\t)"; + if ($i + 1 < $habtmCount) { + $out .= ","; + } + echo $out; + endforeach; + echo "\n\t);\n\n"; +endif; +?> +'; ?> diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 9c49bde37..d66a6c9d3 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -37,10 +37,10 @@ if (!class_exists('ShellDispatcher')) { ob_end_clean(); } -if (!class_exists('ModelTask')) { - require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'model.php'; - require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php'; -} +require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'model.php'; +require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'fixture.php'; +require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'template.php'; + Mock::generatePartial( 'ShellDispatcher', 'TestModelTaskMockShellDispatcher', @@ -82,7 +82,9 @@ class ModelTaskTest extends CakeTestCase { function startTest() { $this->Dispatcher =& new TestModelTaskMockShellDispatcher(); $this->Task =& new MockModelTask($this->Dispatcher); - $this->Task->Dispatch = new $this->Dispatcher; + $this->Task->Dispatch =& new $this->Dispatcher; + $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); + $this->Task->Template =& new TemplateTask($this->Task->Dispatch); } /** @@ -517,5 +519,86 @@ class ModelTaskTest extends CakeTestCase { $result = $this->Task->inOptions($options, 'Pick a number'); $this->assertEqual($result, 1); } + +/** + * test baking validation + * + * @return void + **/ + function testBakeValidation() { + $validate = array( + 'name' => array( + 'notempty' => 'notempty' + ), + 'email' => array( + 'email' => 'email', + ), + 'some_date' => array( + 'date' => 'date' + ), + 'some_time' => array( + 'time' => 'time' + ) + ); + $result = $this->Task->bake('Article', array(), $validate); + $this->assertPattern('/class Article extends AppModel \{/', $result); + $this->assertPattern('/\$name \= \'Article\'/', $result); + $this->assertPattern('/\$validate \= array\(/', $result); + $pattern = '/' . preg_quote("'notempty' => array('rule' => array('notempty')),", '/') . '/'; + $this->assertPattern($pattern, $result); + } +/** + * test baking relations + * + * @return void + **/ + function testBakeRelations() { + $associations = array( + 'belongsTo' => array( + array( + 'alias' => 'SomethingElse', + 'className' => 'SomethingElse', + 'foreignKey' => 'something_else_id', + ), + array( + 'alias' => 'User', + 'className' => 'User', + 'foreignKey' => 'user_id', + ), + ), + 'hasOne' => array( + array( + 'alias' => 'OtherModel', + 'className' => 'OtherModel', + 'foreignKey' => 'other_model_id', + ), + ), + 'hasMany' => array( + array( + 'alias' => 'Comment', + 'className' => 'Comment', + 'foreignKey' => 'parent_id', + ), + ), + 'hasAndBelongsToMany' => array( + array( + 'alias' => 'Tag', + 'className' => 'Tag', + 'foreignKey' => 'article_id', + 'joinTable' => 'articles_tags', + 'associationForeignKey' => 'tag_id', + ), + ) + ); + $result = $this->Task->bake('Article', $associations, array()); + $this->assertPattern('/\$hasAndBelongsToMany \= array\(/', $result); + $this->assertPattern('/\$hasMany \= array\(/', $result); + $this->assertPattern('/\$belongsTo \= array\(/', $result); + $this->assertPattern('/\$hasOne \= array\(/', $result); + $this->assertPattern('/Tag/', $result); + $this->assertPattern('/OtherModel/', $result); + $this->assertPattern('/SomethingElse/', $result); + $this->assertPattern('/Comment/', $result); + } } ?> \ No newline at end of file From 4a9a5bce69741debb3ad29afcf40d8910b6c16b2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 13 May 2009 23:37:21 -0400 Subject: [PATCH 047/207] Removing template code. --- cake/console/libs/tasks/model.php | 145 +----------------------------- 1 file changed, 2 insertions(+), 143 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index c9f2920be..1fb2e0c6f 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -700,153 +700,12 @@ class ModelTask extends Shell { $useDbConfig = $name->useDbConfig; $name = $name->name; } - + $this->Template->set(compact('name', 'useDbConfig', 'associations', 'validate', 'primaryKey', 'useTable')); $this->Template->set('plugin', $this->plugin); $out = $this->Template->generate('objects', 'model'); - /* - $out = "plugin}AppModel {\n\n"; - $out .= "\tvar \$name = '{$name}';\n"; - - if ($useDbConfig !== 'default') { - $out .= "\tvar \$useDbConfig = '$useDbConfig';\n"; - } - - if (($useTable && $useTable !== Inflector::tableize($name)) || $useTable === false) { - $table = "'$useTable'"; - if (!$useTable) { - $table = 'false'; - } - $out .= "\tvar \$useTable = $table;\n"; - } - - if ($primaryKey !== 'id') { - $out .= "\tvar \$primaryKey = '$primaryKey';\n"; - } - - $validateCount = count($validate); - if (is_array($validate) && $validateCount > 0) { - $out .= "\tvar \$validate = array(\n"; - $keys = array_keys($validate); - for ($i = 0; $i < $validateCount; $i++) { - $val = "'" . $validate[$keys[$i]] . "'"; - $out .= "\t\t'" . $keys[$i] . "' => array({$val})"; - if ($i + 1 < $validateCount) { - $out .= ","; - } - $out .= "\n"; - } - $out .= "\t);\n"; - } - $out .= "\n"; - - if (!empty($associations)) { - if (!empty($associations['belongsTo']) || !empty($associations['hasOne']) || !empty($associations['hasMany']) || !empty($associations['hasAndBelongsToMany'])) { - $out.= "\t//The Associations below have been created with all possible keys, those that are not needed can be removed\n"; - } - - if (!empty($associations['belongsTo'])) { - $out .= "\tvar \$belongsTo = array(\n"; - $belongsToCount = count($associations['belongsTo']); - - for ($i = 0; $i < $belongsToCount; $i++) { - $out .= "\t\t'{$associations['belongsTo'][$i]['alias']}' => array(\n"; - $out .= "\t\t\t'className' => '{$associations['belongsTo'][$i]['className']}',\n"; - $out .= "\t\t\t'foreignKey' => '{$associations['belongsTo'][$i]['foreignKey']}',\n"; - $out .= "\t\t\t'conditions' => '',\n"; - $out .= "\t\t\t'fields' => '',\n"; - $out .= "\t\t\t'order' => ''\n"; - $out .= "\t\t)"; - if ($i + 1 < $belongsToCount) { - $out .= ","; - } - $out .= "\n"; - - } - $out .= "\t);\n\n"; - } - - if (!empty($associations['hasOne'])) { - $out .= "\tvar \$hasOne = array(\n"; - $hasOneCount = count($associations['hasOne']); - - for ($i = 0; $i < $hasOneCount; $i++) { - $out .= "\t\t'{$associations['hasOne'][$i]['alias']}' => array(\n"; - $out .= "\t\t\t'className' => '{$associations['hasOne'][$i]['className']}',\n"; - $out .= "\t\t\t'foreignKey' => '{$associations['hasOne'][$i]['foreignKey']}',\n"; - $out .= "\t\t\t'dependent' => false,\n"; - $out .= "\t\t\t'conditions' => '',\n"; - $out .= "\t\t\t'fields' => '',\n"; - $out .= "\t\t\t'order' => ''\n"; - $out .= "\t\t)"; - if ($i + 1 < $hasOneCount) { - $out .= ","; - } - $out .= "\n"; - - } - $out .= "\t);\n\n"; - } - - if (!empty($associations['hasMany'])) { - $out .= "\tvar \$hasMany = array(\n"; - $hasManyCount = count($associations['hasMany']); - - for ($i = 0; $i < $hasManyCount; $i++) { - $out .= "\t\t'{$associations['hasMany'][$i]['alias']}' => array(\n"; - $out .= "\t\t\t'className' => '{$associations['hasMany'][$i]['className']}',\n"; - $out .= "\t\t\t'foreignKey' => '{$associations['hasMany'][$i]['foreignKey']}',\n"; - $out .= "\t\t\t'dependent' => false,\n"; - $out .= "\t\t\t'conditions' => '',\n"; - $out .= "\t\t\t'fields' => '',\n"; - $out .= "\t\t\t'order' => '',\n"; - $out .= "\t\t\t'limit' => '',\n"; - $out .= "\t\t\t'offset' => '',\n"; - $out .= "\t\t\t'exclusive' => '',\n"; - $out .= "\t\t\t'finderQuery' => '',\n"; - $out .= "\t\t\t'counterQuery' => ''\n"; - $out .= "\t\t)"; - if ($i + 1 < $hasManyCount) { - $out .= ","; - } - $out .= "\n"; - } - $out .= "\t);\n\n"; - } - - if (!empty($associations['hasAndBelongsToMany'])) { - $out .= "\tvar \$hasAndBelongsToMany = array(\n"; - $hasAndBelongsToManyCount = count($associations['hasAndBelongsToMany']); - - for ($i = 0; $i < $hasAndBelongsToManyCount; $i++) { - $out .= "\t\t'{$associations['hasAndBelongsToMany'][$i]['alias']}' => array(\n"; - $out .= "\t\t\t'className' => '{$associations['hasAndBelongsToMany'][$i]['className']}',\n"; - $out .= "\t\t\t'joinTable' => '{$associations['hasAndBelongsToMany'][$i]['joinTable']}',\n"; - $out .= "\t\t\t'foreignKey' => '{$associations['hasAndBelongsToMany'][$i]['foreignKey']}',\n"; - $out .= "\t\t\t'associationForeignKey' => '{$associations['hasAndBelongsToMany'][$i]['associationForeignKey']}',\n"; - $out .= "\t\t\t'unique' => true,\n"; - $out .= "\t\t\t'conditions' => '',\n"; - $out .= "\t\t\t'fields' => '',\n"; - $out .= "\t\t\t'order' => '',\n"; - $out .= "\t\t\t'limit' => '',\n"; - $out .= "\t\t\t'offset' => '',\n"; - $out .= "\t\t\t'finderQuery' => '',\n"; - $out .= "\t\t\t'deleteQuery' => '',\n"; - $out .= "\t\t\t'insertQuery' => ''\n"; - $out .= "\t\t)"; - if ($i + 1 < $hasAndBelongsToManyCount) { - $out .= ","; - } - $out .= "\n"; - } - $out .= "\t);\n\n"; - } - } - $out .= "}\n"; - $out .= "?>"; - */ + //@todo solve plugin model paths. $filename = $this->path . Inflector::underscore($name) . '.php'; $this->out("\nBaking model class for $name..."); $this->createFile($filename, $out); From a85bf16560740c424198d9e29c3fc735a2dcd7bc Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 13 May 2009 23:50:46 -0400 Subject: [PATCH 048/207] Cleaning up model template. --- cake/console/libs/templates/objects/model.ctp | 16 +++++++++++----- .../cases/console/libs/tasks/model.test.php | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/cake/console/libs/templates/objects/model.ctp b/cake/console/libs/templates/objects/model.ctp index 5cb28dc9c..06b2ca22e 100644 --- a/cake/console/libs/templates/objects/model.ctp +++ b/cake/console/libs/templates/objects/model.ctp @@ -21,6 +21,7 @@ */ echo " + class extends AppModel { var $name = ''; @@ -32,11 +33,11 @@ class extends AppModel { $table = 'false'; endif; echo "\tvar \$useTable = $table;\n"; -endif; ?> - +endif; +if ($primaryKey !== 'id'): ?> var $primaryKey = ''; - - $validations): @@ -47,7 +48,11 @@ if (!empty($validate)): echo "\t\t),\n"; endforeach; echo "\t);\n"; -endif; +endif; + +?> + //The Associations below have been created with all possible keys, those that are not needed can be removed + +} '; ?> diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index d66a6c9d3..7ae9b592e 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -547,6 +547,7 @@ class ModelTaskTest extends CakeTestCase { $pattern = '/' . preg_quote("'notempty' => array('rule' => array('notempty')),", '/') . '/'; $this->assertPattern($pattern, $result); } + /** * test baking relations * From 3f7821c258477ad91b49a6be20a152f0b121c3b2 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 21:42:07 -0400 Subject: [PATCH 049/207] Adding test cases for bake model all Adding test cases for bake model MyModel Fixing all() Starting refactor into Test task --- cake/console/libs/tasks/model.php | 11 ++-- .../cases/console/libs/tasks/model.test.php | 54 +++++++++++++++++-- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 1fb2e0c6f..d83f4e9ab 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -121,12 +121,12 @@ class ModelTask extends Shell { * @return void **/ function all() { - $this->listAll($ds, false); + $this->listAll($this->connection, false); foreach ($this->__tables as $table) { $modelClass = Inflector::classify($table); $this->out(sprintf(__('Baking %s', true), $modelClass)); - $this->_getModelObject($modelClass); + $object = $this->_getModelObject($modelClass); $this->bake($object, false); } } @@ -242,6 +242,7 @@ class ModelTask extends Shell { if (strtolower($looksGood) == 'y') { if ($this->bake($currentModelName, $associations, $validate, $primaryKey, $useTable, $this->connection)) { if ($this->_checkUnitTest()) { + $this->bakeFixture($currentModelName, $useTable); $this->bakeTest($currentModelName, $useTable, $associations); } } @@ -719,7 +720,9 @@ class ModelTask extends Shell { * @access private */ function bakeTest($className, $useTable = null, $associations = array()) { - $this->fixture($className, $useTable); + $this->Test->plugin = $this->plugin; + $this->Test->connection = $this->connection; + return $this->Test->bake('Model', $className); $fixtureInc = 'app'; if ($this->plugin) { @@ -898,7 +901,7 @@ class ModelTask extends Shell { * * @return null. **/ - function fixture($className, $useTable = null) { + function bakeFixture($className, $useTable = null) { $this->Fixture->connection = $this->connection; $this->Fixture->bake($className, $useTable); } diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 7ae9b592e..b4821a03d 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -49,7 +49,7 @@ Mock::generatePartial( Mock::generatePartial( 'ModelTask', 'MockModelTask', - array('in', 'out', 'err', 'createFile', '_stop') + array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest') ); Mock::generate( @@ -85,6 +85,8 @@ class ModelTaskTest extends CakeTestCase { $this->Task->Dispatch =& new $this->Dispatcher; $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); $this->Task->Template =& new TemplateTask($this->Task->Dispatch); + $this->Task->Fixture =& new MockModelTaskFixtureTask(); + $this->Task->Test =& new MockModelTaskFixtureTask(); } /** @@ -453,10 +455,9 @@ class ModelTaskTest extends CakeTestCase { * * @return void **/ - function testFixture() { - $this->Task->Fixture =& new MockModelTaskFixtureTask(); + function testBakeFixture() { $this->Task->Fixture->expectAt(0, 'bake', array('Article', 'articles')); - $this->Task->fixture('Article', 'articles'); + $this->Task->bakeFixture('Article', 'articles'); } /** @@ -601,5 +602,50 @@ class ModelTaskTest extends CakeTestCase { $this->assertPattern('/SomethingElse/', $result); $this->assertPattern('/Comment/', $result); } + +/** + * test that execute passes runs bake depending with named model. + * + * @return void + **/ + function testExecuteWithNamedModel() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('article'); + $filename = '/my/path/article.php'; + $this->Task->setReturnValue('_checkUnitTest', 1); + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class Article extends AppModel/'))); + $this->Task->execute(); + } + +/** + * test that execute runs all() when args[0] = all + * + * @return void + **/ + function testExecuteIntoAll() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('all'); +//core.article', 'core.comment', 'core.articles_tag', 'core.tag', 'core.category_thread + + $filename = '/my/path/article.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class Article/'))); + $this->Task->execute(); + + $filename = '/my/path/articles_tag.php'; + $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/class ArticlesTag/'))); + + $filename = '/my/path/category_thread.php'; + $this->Task->expectAt(2, 'createFile', array($filename, new PatternExpectation('/class CategoryThread/'))); + + $filename = '/my/path/comment.php'; + $this->Task->expectAt(3, 'createFile', array($filename, new PatternExpectation('/class Comment/'))); + + $filename = '/my/path/tag.php'; + $this->Task->expectAt(4, 'createFile', array($filename, new PatternExpectation('/class Tag/'))); + + $this->Task->execute(); + } } ?> \ No newline at end of file From 8a5d6cae773d65c7356b1dcb8171d144095b1a13 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 22:19:43 -0400 Subject: [PATCH 050/207] Removing junk --- cake/tests/cases/console/libs/tasks/model.test.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index b4821a03d..0cdaca828 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -627,8 +627,7 @@ class ModelTaskTest extends CakeTestCase { $this->Task->connection = 'test_suite'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); -//core.article', 'core.comment', 'core.articles_tag', 'core.tag', 'core.category_thread - + $filename = '/my/path/article.php'; $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class Article/'))); $this->Task->execute(); From ad930f277d0eb1966f634f63b07df99d20e9bf26 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 22:23:36 -0400 Subject: [PATCH 051/207] Moving test generation to a temporary home --- cake/console/libs/tasks/model.php | 54 --------------------------- cake/console/libs/tasks/test.php | 61 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 54 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index d83f4e9ab..0985deca0 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -723,60 +723,6 @@ class ModelTask extends Shell { $this->Test->plugin = $this->plugin; $this->Test->connection = $this->connection; return $this->Test->bake('Model', $className); - - $fixtureInc = 'app'; - if ($this->plugin) { - $fixtureInc = 'plugin.'.Inflector::underscore($this->plugin); - } - - $fixture[] = "'{$fixtureInc}." . Inflector::underscore($className) ."'"; - - if (!empty($associations)) { - $assoc[] = Set::extract($associations, 'belongsTo.{n}.className'); - $assoc[] = Set::extract($associations, 'hasOne.{n}.className'); - $assoc[] = Set::extract($associations, 'hasMany.{n}.className'); - foreach ($assoc as $key => $value) { - if (is_array($value)) { - foreach ($value as $class) { - $fixture[] = "'{$fixtureInc}." . Inflector::underscore($class) ."'"; - } - } - } - } - $fixture = join(", ", $fixture); - - $import = $className; - if (isset($this->plugin)) { - $import = $this->plugin . '.' . $className; - } - - $out = "App::import('Model', '$import');\n\n"; - $out .= "class {$className}TestCase extends CakeTestCase {\n"; - $out .= "\tvar \${$className} = null;\n"; - $out .= "\tvar \$fixtures = array($fixture);\n\n"; - $out .= "\tfunction startTest() {\n"; - $out .= "\t\t\$this->{$className} =& ClassRegistry::init('{$className}');\n"; - $out .= "\t}\n\n"; - $out .= "\tfunction endTest() {\n"; - $out .= "\t\tunset(\$this->{$className});\n"; - $out .= "\t}\n\n"; - $out .= "\tfunction test{$className}Instance() {\n"; - $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}'));\n"; - $out .= "\t}\n\n"; - $out .= "}\n"; - - $path = MODEL_TESTS; - if (isset($this->plugin)) { - $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; - $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'models' . DS; - } - - $filename = Inflector::underscore($className).'.test.php'; - $this->out("\nBaking unit test for $className..."); - - $header = '$Id'; - $content = ""; - return $this->createFile($path . $filename, $content); } /** diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 45b853448..5d35acba4 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -199,5 +199,66 @@ class TestTask extends Shell { } return $extras; } + +/** + * Create a test for a Model object. + * + * @return void + **/ + function bakeModelTest($className) { + $fixtureInc = 'app'; + if ($this->plugin) { + $fixtureInc = 'plugin.'.Inflector::underscore($this->plugin); + } + + $fixture[] = "'{$fixtureInc}." . Inflector::underscore($className) ."'"; + + if (!empty($associations)) { + $assoc[] = Set::extract($associations, 'belongsTo.{n}.className'); + $assoc[] = Set::extract($associations, 'hasOne.{n}.className'); + $assoc[] = Set::extract($associations, 'hasMany.{n}.className'); + foreach ($assoc as $key => $value) { + if (is_array($value)) { + foreach ($value as $class) { + $fixture[] = "'{$fixtureInc}." . Inflector::underscore($class) ."'"; + } + } + } + } + $fixture = join(", ", $fixture); + + $import = $className; + if (isset($this->plugin)) { + $import = $this->plugin . '.' . $className; + } + + $out = "App::import('Model', '$import');\n\n"; + $out .= "class {$className}TestCase extends CakeTestCase {\n"; + $out .= "\tvar \${$className} = null;\n"; + $out .= "\tvar \$fixtures = array($fixture);\n\n"; + $out .= "\tfunction startTest() {\n"; + $out .= "\t\t\$this->{$className} =& ClassRegistry::init('{$className}');\n"; + $out .= "\t}\n\n"; + $out .= "\tfunction endTest() {\n"; + $out .= "\t\tunset(\$this->{$className});\n"; + $out .= "\t}\n\n"; + $out .= "\tfunction test{$className}Instance() {\n"; + $out .= "\t\t\$this->assertTrue(is_a(\$this->{$className}, '{$className}'));\n"; + $out .= "\t}\n\n"; + $out .= "}\n"; + + $path = MODEL_TESTS; + if (isset($this->plugin)) { + $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; + $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'models' . DS; + } + + $filename = Inflector::underscore($className).'.test.php'; + $this->out("\nBaking unit test for $className..."); + + $header = '$Id'; + $content = ""; + return $this->createFile($path . $filename, $content); + } } ?> \ No newline at end of file From 305104140c5e3e265693ff8b99e17460eb906cfc Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 22:36:04 -0400 Subject: [PATCH 052/207] Adding tests for __interactive --- cake/console/libs/tasks/model.php | 2 +- .../cases/console/libs/tasks/model.test.php | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 0985deca0..2112c057b 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -217,7 +217,7 @@ class ModelTask extends Shell { $this->out("Name: " . $currentModelName); if ($this->connection !== 'default') { - $this->out(sprintf(__("DB Config: %s", true), $useDbConfig)); + $this->out(sprintf(__("DB Config: %s", true), $this->connection)); } if ($fullTableName !== Inflector::tableize($currentModelName)) { $this->out(sprintf(__("DB Table: %s", true), $fullTableName)); diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index 0cdaca828..c323a3ea3 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -646,5 +646,27 @@ class ModelTaskTest extends CakeTestCase { $this->Task->execute(); } + +/** + * test the interactive side of bake. + * + * @return void + **/ + function testExecuteIntoInteractive() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + + $this->Task->setReturnValueAt(0, 'in', '1'); //choose article + $this->Task->setReturnValueAt(1, 'in', 'n'); //no validation + $this->Task->setReturnValueAt(2, 'in', 'y'); //yes to associations + $this->Task->setReturnValueAt(3, 'in', 'y'); //yes to comment relation + $this->Task->setReturnValueAt(4, 'in', 'y'); //yes to user relation + $this->Task->setReturnValueAt(5, 'in', 'y'); //yes to tag relation + $this->Task->setReturnValueAt(6, 'in', 'n'); //no to looksGood? + + $filename = '/my/path/article.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class Article/'))); + $this->Task->execute(); + } } ?> \ No newline at end of file From e6881cced494d391e2d5f0e3d8f9054944bb91f1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 23:00:29 -0400 Subject: [PATCH 053/207] Extracted another method. --- cake/console/libs/tasks/model.php | 62 ++++++++++++++++++------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 2112c057b..28e62d050 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -689,7 +689,7 @@ class ModelTask extends Shell { * @param string $useDbConfig Database configuration setting to use * @access private */ - function bake($name, $associations = array(), $validate = array(), $primaryKey = 'id', $useTable = null, $useDbConfig = 'default') { + function bake($name, $associations = array(), $validate = array(), $primaryKey = 'id', $useTable = null, $useDbConfig = 'default') { if (is_object($name)) { if (!is_array($associations)) { @@ -731,35 +731,15 @@ class ModelTask extends Shell { * @param string $useDbConfig Database configuration name * @access public */ - function listAll($useDbConfig = null, $interactive = true) { - if (!isset($useDbConfig)) { - $useDbConfig = $this->connection; - } - $db =& ConnectionManager::getDataSource($useDbConfig); - $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; - if ($usePrefix) { - $tables = array(); - foreach ($db->listSources() as $table) { - if (!strncmp($table, $usePrefix, strlen($usePrefix))) { - $tables[] = substr($table, strlen($usePrefix)); - } - } - } else { - $tables = $db->listSources(); - } - if (empty($tables)) { - $this->err(__('Your database does not have any tables.', true)); - $this->_stop(); - } + function listAll($useDbConfig = null) { + $this->__tables = $this->getAllTables($useDbConfig); - $this->__tables = $tables; - - if ($interactive === true) { + if ($this->interactive === true) { $this->out(__('Possible Models based on your current database:', true)); $this->_modelNames = array(); - $count = count($tables); + $count = count($this->__tables); for ($i = 0; $i < $count; $i++) { - $this->_modelNames[] = $this->_modelName($tables[$i]); + $this->_modelNames[] = $this->_modelName($this->__tables[$i]); $this->out($i + 1 . ". " . $this->_modelNames[$i]); } } @@ -793,6 +773,36 @@ class ModelTask extends Shell { return $useTable; } +/** + * Get an Array of all the tables in the supplied connection + * will halt the script if no tables are found. + * + * @param string $useDbConfig Connection name to scan. + * @return array Array of tables in the database. + **/ + function getAllTables($useDbConfig = null) { + if (!isset($useDbConfig)) { + $useDbConfig = $this->connection; + } + $tables = array(); + $db =& ConnectionManager::getDataSource($useDbConfig); + $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; + if ($usePrefix) { + foreach ($db->listSources() as $table) { + if (!strncmp($table, $usePrefix, strlen($usePrefix))) { + $tables[] = substr($table, strlen($usePrefix)); + } + } + } else { + $tables = $db->listSources(); + } + if (empty($tables)) { + $this->err(__('Your database does not have any tables.', true)); + $this->_stop(); + } + return $tables; + } + /** * Forces the user to specify the model he wants to bake, and returns the selected model name. * From 03e231c05ddc7df17f915527b3093c76282c29f1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 23:17:42 -0400 Subject: [PATCH 054/207] Adding test case for controller task. Refactoring listAll() to use Model task which has the necessary code. --- cake/console/libs/tasks/controller.php | 39 ++---- .../console/libs/tasks/controller.test.php | 123 ++++++++++++++++++ 2 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 cake/tests/cases/console/libs/tasks/controller.test.php diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index ec69bb21f..3248351c2 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -44,7 +44,7 @@ class ControllerTask extends Shell { * @var array * @access public */ - var $tasks = array('Project'); + var $tasks = array('Model', 'Project', 'Template'); /** * path to CONTROLLERS directory * @@ -105,12 +105,8 @@ class ControllerTask extends Shell { * @return void **/ function all() { - $ds = 'default'; - if (isset($this->params['connection'])) { - $ds = $this->params['connection']; - } $this->interactive = false; - $this->listAll($ds, false); + $this->listAll($this->connection, false); foreach ($this->__tables as $table) { $model = $this->_modelName($table); $controller = $this->_controllerName($model); @@ -509,40 +505,27 @@ class ControllerTask extends Shell { $content = ""; return $this->createFile($path . $filename, $content); } + /** - * Outputs and gets the list of possible models or controllers from database + * Outputs and gets the list of possible controllers from database * * @param string $useDbConfig Database configuration name * @param boolean $interactive Whether you are using listAll interactively and want options output. * @return array Set of controllers * @access public */ - function listAll($useDbConfig = 'default', $interactive = true) { - $db =& ConnectionManager::getDataSource($useDbConfig); - $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; - if ($usePrefix) { - $tables = array(); - foreach ($db->listSources() as $table) { - if (!strncmp($table, $usePrefix, strlen($usePrefix))) { - $tables[] = substr($table, strlen($usePrefix)); - } - } - } else { - $tables = $db->listSources(); + function listAll($useDbConfig = null) { + if (is_null($useDbConfig)) { + $useDbConfig = $this->connection; } + $this->__tables = $this->Model->getAllTables($useDbConfig); - if (empty($tables)) { - $this->err(__('Your database does not have any tables.', true)); - $this->_stop(); - } - - $this->__tables = $tables; - if ($interactive == true) { + if ($this->interactive == true) { $this->out('Possible Controllers based on your current database:'); $this->_controllerNames = array(); - $count = count($tables); + $count = count($this->__tables); for ($i = 0; $i < $count; $i++) { - $this->_controllerNames[] = $this->_controllerName($this->_modelName($tables[$i])); + $this->_controllerNames[] = $this->_controllerName($this->_modelName($this->__tables[$i])); $this->out($i + 1 . ". " . $this->_controllerNames[$i]); } return $this->_controllerNames; diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php new file mode 100644 index 000000000..dccddc275 --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -0,0 +1,123 @@ +Dispatcher =& new TestControllerTaskMockShellDispatcher(); + $this->Task =& new MockControllerTask($this->Dispatcher); + $this->Task->Dispatch =& new $this->Dispatcher; + $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); + $this->Task->Template =& new TemplateTask($this->Task->Dispatch); + $this->Task->Model =& new ControllerMockModelTask($this->Task->Dispatch); + } + +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + unset($this->Task, $this->Dispatcher); + ClassRegistry::flush(); + } + +/** + * test ListAll + * + * @return void + **/ + function testListAll() { + $this->Task->connection = 'test_suite'; + $this->Task->interactive = true; + $this->Task->expectAt(1, 'out', array('1. Articles')); + $this->Task->expectAt(2, 'out', array('2. ArticlesTags')); + $this->Task->expectAt(3, 'out', array('3. Comments')); + $this->Task->expectAt(4, 'out', array('4. Tags')); + + $expected = array('Articles', 'ArticlesTags', 'Comments', 'Tags'); + $result = $this->Task->listAll('test_suite'); + $this->assertEqual($result, $expected); + + $this->Task->expectAt(6, 'out', array('1. Articles')); + $this->Task->expectAt(7, 'out', array('2. ArticlesTags')); + $this->Task->expectAt(8, 'out', array('4. Comments')); + $this->Task->expectAt(9, 'out', array('5. Tags')); + + $this->Task->interactive = false; + $result = $this->Task->listAll(); + + $expected = array('articles', 'articles_tags', 'comments', 'tags'); + $this->assertEqual($result, $expected); + } +} +?> \ No newline at end of file From 9b9b1fbf211b674e0b2f9c67b035b2a11db55098 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 23:25:52 -0400 Subject: [PATCH 055/207] Updating doc block --- cake/tests/cases/console/libs/tasks/model.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/cases/console/libs/tasks/model.test.php b/cake/tests/cases/console/libs/tasks/model.test.php index c323a3ea3..aec16157b 100644 --- a/cake/tests/cases/console/libs/tasks/model.test.php +++ b/cake/tests/cases/console/libs/tasks/model.test.php @@ -128,7 +128,7 @@ class ModelTaskTest extends CakeTestCase { } /** - * Test that listAll scans the database connection and lists all the tables in it.s + * Test that getName interacts with the user and returns the model name. * * @return void **/ From 68a858b39a310afb1b73b7a48af19461056cdc15 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 23:28:27 -0400 Subject: [PATCH 056/207] Adding test case for getName --- cake/console/libs/tasks/controller.php | 10 +++---- .../console/libs/tasks/controller.test.php | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 3248351c2..9ea0a81a4 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -536,16 +536,16 @@ class ControllerTask extends Shell { /** * Forces the user to specify the controller he wants to bake, and returns the selected controller name. * + * @param string $useDbConfig Connection name to get a controller name for. * @return string Controller name * @access public */ - function getName() { - $useDbConfig = 'default'; + function getName($useDbConfig = null) { $controllers = $this->listAll($useDbConfig); $enteredController = ''; while ($enteredController == '') { - $enteredController = $this->in(__("Enter a number from the list above, type in the name of another controller, or 'q' to exit", true), null, 'q'); + $enteredController = $this->in(__("Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit", true), null, 'q'); if ($enteredController === 'q') { $this->out(__("Exit", true)); @@ -553,8 +553,7 @@ class ControllerTask extends Shell { } if ($enteredController == '' || intval($enteredController) > count($controllers)) { - $this->out(__('Error:', true)); - $this->out(__("The Controller name you supplied was empty, or the number \nyou selected was not an option. Please try again.", true)); + $this->err(__("The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again.", true)); $enteredController = ''; } } @@ -564,7 +563,6 @@ class ControllerTask extends Shell { } else { $controllerName = Inflector::camelize($enteredController); } - return $controllerName; } /** diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index dccddc275..47fda0d66 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -119,5 +119,32 @@ class ControllerTaskTest extends CakeTestCase { $expected = array('articles', 'articles_tags', 'comments', 'tags'); $this->assertEqual($result, $expected); } + +/** + * Test that getName interacts with the user and returns the controller name. + * + * @return void + **/ + function testGetName() { + $this->Task->setReturnValue('in', 1); + + $this->Task->setReturnValueAt(0, 'in', 'q'); + $this->Task->expectOnce('_stop'); + $this->Task->getName('test_suite'); + + $this->Task->setReturnValueAt(1, 'in', 1); + $result = $this->Task->getName('test_suite'); + $expected = 'Articles'; + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(2, 'in', 3); + $result = $this->Task->getName('test_suite'); + $expected = 'Comments'; + $this->assertEqual($result, $expected); + + $this->Task->setReturnValueAt(3, 'in', 10); + $result = $this->Task->getName('test_suite'); + $this->Task->expectOnce('err'); + } } ?> \ No newline at end of file From b1de3166e948684b30acd3659f6a5801f5677bfc Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 14 May 2009 23:33:10 -0400 Subject: [PATCH 057/207] Removing dead options. --- cake/console/libs/tasks/controller.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 9ea0a81a4..0f11c7e84 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -149,29 +149,29 @@ class ControllerTask extends Shell { } $doItInteractive = $this->in(join("\n", $question), array('y','n'), 'y'); - if (low($doItInteractive) == 'y' || low($doItInteractive) == 'yes') { + if (strtolower($doItInteractive) == 'y') { $this->interactive = true; $wannaUseScaffold = $this->in(__("Would you like to use scaffolding?", true), array('y','n'), 'n'); - if (low($wannaUseScaffold) == 'n' || low($wannaUseScaffold) == 'no') { + if (strtolower($wannaUseScaffold) == 'n') { $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'n'); - if (low($wannaDoScaffolding) == 'y' || low($wannaDoScaffolding) == 'yes') { + if (strtolower($wannaDoScaffolding) == 'y') { $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'n'); } $wannaDoHelpers = $this->in(__("Would you like this controller to use other helpers besides HtmlHelper and FormHelper?", true), array('y','n'), 'n'); - if (low($wannaDoHelpers) == 'y' || low($wannaDoHelpers) == 'yes') { + if (strtolower($wannaDoHelpers) == 'y') { $helpersList = $this->in(__("Please provide a comma separated list of the other helper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true)); $helpersListTrimmed = str_replace(' ', '', $helpersList); $helpers = explode(',', $helpersListTrimmed); } $wannaDoComponents = $this->in(__("Would you like this controller to use any components?", true), array('y','n'), 'n'); - if (low($wannaDoComponents) == 'y' || low($wannaDoComponents) == 'yes') { + if (strtolower($wannaDoComponents) == 'y') { $componentsList = $this->in(__("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true)); $componentsListTrimmed = str_replace(' ', '', $componentsList); $components = explode(',', $componentsListTrimmed); @@ -184,17 +184,17 @@ class ControllerTask extends Shell { } else { $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'y'); - if (low($wannaDoScaffolding) == 'y' || low($wannaDoScaffolding) == 'yes') { + if (strtolower($wannaDoScaffolding) == 'y') { $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'y'); } } $admin = false; - if ((low($wannaDoAdmin) == 'y' || low($wannaDoAdmin) == 'yes')) { + if (strtolower($wannaDoAdmin) == 'y') { $admin = $this->getAdmin(); } - if (low($wannaDoScaffolding) == 'y' || low($wannaDoScaffolding) == 'yes') { + if (strtolower($wannaDoScaffolding) == 'y') { $actions = $this->bakeActions($controllerName, null, in_array(low($wannaUseSession), array('y', 'yes'))); if ($admin) { $actions .= $this->bakeActions($controllerName, $admin, in_array(low($wannaUseSession), array('y', 'yes'))); @@ -208,7 +208,7 @@ class ControllerTask extends Shell { $this->hr(); $this->out("Controller Name: $controllerName"); - if (low($wannaUseScaffold) == 'y' || low($wannaUseScaffold) == 'yes') { + if (strtolower($wannaUseScaffold) == 'y') { $this->out(" var \$scaffold;"); $actions = 'scaffold'; } @@ -239,7 +239,7 @@ class ControllerTask extends Shell { $this->hr(); $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); - if (low($looksGood) == 'y' || low($looksGood) == 'yes') { + if (strtolower($looksGood) == 'y') { $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses); if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); From d609a62dc58ca4ce6da8369286540e02a1c04aaf Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 15 May 2009 00:03:53 -0400 Subject: [PATCH 058/207] Adding welcome message back to model task --- cake/console/libs/tasks/model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index 28e62d050..c585d9394 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -85,6 +85,7 @@ class ModelTask extends Shell { **/ function startup() { App::import('Core', 'Model'); + parent::startup(); } /** From 9eb27f14d7e3b7ed33a051d3b7c72e317d03d88b Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 15 May 2009 00:04:57 -0400 Subject: [PATCH 059/207] Adding tests and starting clean up of __interactive. --- cake/console/libs/tasks/controller.php | 90 ++++++++++++------- .../console/libs/tasks/controller.test.php | 34 +++++++ 2 files changed, 90 insertions(+), 34 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 0f11c7e84..2469369dc 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -44,7 +44,7 @@ class ControllerTask extends Shell { * @var array * @access public */ - var $tasks = array('Model', 'Project', 'Template'); + var $tasks = array('Model', 'Project', 'Template', 'DbConfig'); /** * path to CONTROLLERS directory * @@ -70,6 +70,9 @@ class ControllerTask extends Shell { } if (isset($this->args[0])) { + if (!isset($this->connection)) { + $this->connection = 'default'; + } if (strtolower($this->args[0]) == 'all') { return $this->all(); } @@ -121,33 +124,34 @@ class ControllerTask extends Shell { * * @access private */ - function __interactive($controllerName = false) { - if (!$controllerName) { - $this->interactive = true; - $this->hr(); - $this->out(sprintf("Bake Controller\nPath: %s", $this->path)); - $this->hr(); - $actions = ''; - $uses = array(); - $helpers = array(); - $components = array(); - $wannaUseSession = 'y'; - $wannaDoAdmin = 'n'; - $wannaUseScaffold = 'n'; - $wannaDoScaffolding = 'y'; - $controllerName = $this->getName(); + function __interactive() { + $this->interactive = true; + $this->hr(); + $this->out(sprintf("Bake Controller\nPath: %s", $this->path)); + $this->hr(); + + if (empty($this->connection)) { + $this->connection = $this->DbConfig->getConfig(); } + + $controllerName = $this->getName(); $this->hr(); $this->out("Baking {$controllerName}Controller"); $this->hr(); + $actions = ''; + $wannaUseSession = 'y'; + $wannaDoAdmin = 'n'; + $wannaUseScaffold = 'n'; + $wannaDoScaffolding = 'y'; + $controllerFile = low(Inflector::underscore($controllerName)); $question[] = __("Would you like to build your controller interactively?", true); if (file_exists($this->path . $controllerFile .'_controller.php')) { $question[] = sprintf(__("Warning: Choosing no will overwrite the %sController.", true), $controllerName); } - $doItInteractive = $this->in(join("\n", $question), array('y','n'), 'y'); + $doItInteractive = $this->in(join("\n", $question), array('y', 'n'), 'y'); if (strtolower($doItInteractive) == 'y') { $this->interactive = true; @@ -161,21 +165,8 @@ class ControllerTask extends Shell { if (strtolower($wannaDoScaffolding) == 'y') { $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'n'); } - - $wannaDoHelpers = $this->in(__("Would you like this controller to use other helpers besides HtmlHelper and FormHelper?", true), array('y','n'), 'n'); - - if (strtolower($wannaDoHelpers) == 'y') { - $helpersList = $this->in(__("Please provide a comma separated list of the other helper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true)); - $helpersListTrimmed = str_replace(' ', '', $helpersList); - $helpers = explode(',', $helpersListTrimmed); - } - $wannaDoComponents = $this->in(__("Would you like this controller to use any components?", true), array('y','n'), 'n'); - - if (strtolower($wannaDoComponents) == 'y') { - $componentsList = $this->in(__("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true)); - $componentsListTrimmed = str_replace(' ', '', $componentsList); - $components = explode(',', $componentsListTrimmed); - } + $helpers = $this->doHelpers(); + $components = $this->doComponents(); $wannaUseSession = $this->in(__("Would you like to use Sessions?", true), array('y','n'), 'y'); } else { @@ -244,8 +235,6 @@ class ControllerTask extends Shell { if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); } - } else { - $this->__interactive($controllerName); } } else { $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses); @@ -506,6 +495,38 @@ class ControllerTask extends Shell { return $this->createFile($path . $filename, $content); } +/** + * Interact with the user and get a list of additional helpers + * + * @return array Helpers that the user wants to use. + **/ + function doHelpers() { + $wannaDoHelpers = $this->in(__("Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?", true), array('y','n'), 'n'); + $helpers = array(); + if (strtolower($wannaDoHelpers) == 'y') { + $helpersList = $this->in(__("Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true)); + $helpersListTrimmed = str_replace(' ', '', $helpersList); + $helpers = explode(',', $helpersListTrimmed); + } + return $helpers; + } + +/** + * Interact with the user and get a list of additional components + * + * @return array Components the user wants to use. + **/ + function doComponents() { + $wannaDoComponents = $this->in(__("Would you like this controller to use any components?", true), array('y','n'), 'n'); + $components = array(); + if (strtolower($wannaDoComponents) == 'y') { + $componentsList = $this->in(__("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true)); + $componentsListTrimmed = str_replace(' ', '', $componentsList); + $components = explode(',', $componentsListTrimmed); + } + return $components; + } + /** * Outputs and gets the list of possible controllers from database * @@ -565,6 +586,7 @@ class ControllerTask extends Shell { } return $controllerName; } + /** * Displays help contents * diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 47fda0d66..6b84f568a 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -146,5 +146,39 @@ class ControllerTaskTest extends CakeTestCase { $result = $this->Task->getName('test_suite'); $this->Task->expectOnce('err'); } + +/** + * test helper interactions + * + * @return void + **/ + function testDoHelpers() { + $this->Task->setReturnValueAt(0, 'in', 'n'); + $result = $this->Task->doHelpers(); + $this->assertEqual($result, array()); + + $this->Task->setReturnValueAt(1, 'in', 'y'); + $this->Task->setReturnValueAt(2, 'in', ' Javascript, Ajax, CustomOne '); + $result = $this->Task->doHelpers(); + $expected = array('Javascript', 'Ajax', 'CustomOne'); + $this->assertEqual($result, $expected); + } + +/** + * test component interactions + * + * @return void + **/ + function testDoComponents() { + $this->Task->setReturnValueAt(0, 'in', 'n'); + $result = $this->Task->doComponents(); + $this->assertEqual($result, array()); + + $this->Task->setReturnValueAt(1, 'in', 'y'); + $this->Task->setReturnValueAt(2, 'in', ' RequestHandler, Security '); + $result = $this->Task->doComponents(); + $expected = array('RequestHandler', 'Security'); + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file From 938ba849d2da28f3c9361923a40e592df67fd8d1 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 16 May 2009 22:41:38 -0400 Subject: [PATCH 060/207] Refactoring doXX methods Adding doUses seems to have gotten lost at one point. --- cake/console/libs/tasks/controller.php | 129 +++++++++++++++---------- 1 file changed, 80 insertions(+), 49 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 2469369dc..38185a99a 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -138,14 +138,15 @@ class ControllerTask extends Shell { $this->hr(); $this->out("Baking {$controllerName}Controller"); $this->hr(); - + + $helpers = $components = $uses = array(); $actions = ''; $wannaUseSession = 'y'; - $wannaDoAdmin = 'n'; - $wannaUseScaffold = 'n'; - $wannaDoScaffolding = 'y'; + $wannaBakeAdminCrud = 'n'; + $useDynamicScaffold = 'n'; + $wannaBakeCrud = 'y'; - $controllerFile = low(Inflector::underscore($controllerName)); + $controllerFile = strtolower(Inflector::underscore($controllerName)); $question[] = __("Would you like to build your controller interactively?", true); if (file_exists($this->path . $controllerFile .'_controller.php')) { @@ -155,41 +156,31 @@ class ControllerTask extends Shell { if (strtolower($doItInteractive) == 'y') { $this->interactive = true; + $useDynamicScaffold = $this->in( + __("Would you like to use dynamic scaffolding?", true), array('y','n'), 'n' + ); - $wannaUseScaffold = $this->in(__("Would you like to use scaffolding?", true), array('y','n'), 'n'); - - if (strtolower($wannaUseScaffold) == 'n') { - - $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'n'); - - if (strtolower($wannaDoScaffolding) == 'y') { - $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'n'); - } + if (strtolower($useDynamicScaffold) == 'n') { + list($wannaBakeCrud, $wannaBakeCrud) = $this->_askAboutMethods(); + $helpers = $this->doHelpers(); $components = $this->doComponents(); + $uses = $this->doUses(); $wannaUseSession = $this->in(__("Would you like to use Sessions?", true), array('y','n'), 'y'); } else { - $wannaDoScaffolding = 'n'; + $wannaBakeCrud = 'n'; } } else { - $wannaDoScaffolding = $this->in(__("Would you like to include some basic class methods (index(), add(), view(), edit())?", true), array('y','n'), 'y'); - - if (strtolower($wannaDoScaffolding) == 'y') { - $wannaDoAdmin = $this->in(__("Would you like to create the methods for admin routing?", true), array('y','n'), 'y'); - } + list($wannaBakeCrud, $wannaBakeCrud) = $this->_askAboutMethods(); } - $admin = false; - if (strtolower($wannaDoAdmin) == 'y') { + if (strtolower($wannaBakeCrud) == 'y') { + $actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) == 'y'); + } + if (strtolower($wannaBakeAdminCrud) == 'y') { $admin = $this->getAdmin(); - } - - if (strtolower($wannaDoScaffolding) == 'y') { - $actions = $this->bakeActions($controllerName, null, in_array(low($wannaUseSession), array('y', 'yes'))); - if ($admin) { - $actions .= $this->bakeActions($controllerName, $admin, in_array(low($wannaUseSession), array('y', 'yes'))); - } + $actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) == 'y'); } if ($this->interactive === true) { @@ -197,15 +188,15 @@ class ControllerTask extends Shell { $this->hr(); $this->out('The following controller will be created:'); $this->hr(); - $this->out("Controller Name: $controllerName"); + $this->out("Controller Name:\t$controllerName"); - if (strtolower($wannaUseScaffold) == 'y') { - $this->out(" var \$scaffold;"); + if (strtolower($useDynamicScaffold) == 'y') { + $this->out("\t\tvar \$scaffold;"); $actions = 'scaffold'; } if (count($helpers)) { - $this->out("Helpers: ", false); + $this->out("Helpers:", false); foreach ($helpers as $help) { if ($help != $helpers[count($helpers) - 1]) { @@ -217,7 +208,7 @@ class ControllerTask extends Shell { } if (count($components)) { - $this->out("Components: ", false); + $this->out("Components:", false); foreach ($components as $comp) { if ($comp != $components[count($components) - 1]) { @@ -243,6 +234,24 @@ class ControllerTask extends Shell { } } } + +/** + * Interact with the user and ask about which methods (admin or regular they want to bake) + * + * @return array Array containing (bakeRegular, bakeAdmin) answers + **/ + function _askAboutMethods() { + $wannaBakeCrud = $this->in( + __("Would you like to create some basic class methods \n(index(), add(), view(), edit())?", true), + array('y','n'), 'n' + ); + $wannaBakeAdminCrud = $this->in( + __("Would you like to create the basic class methods for admin routing?", true), + array('y','n'), 'n' + ); + return array($wannaBakeCrud, $wannaBakeAdminCrud); + } + /** * Bake scaffold actions * @@ -501,14 +510,10 @@ class ControllerTask extends Shell { * @return array Helpers that the user wants to use. **/ function doHelpers() { - $wannaDoHelpers = $this->in(__("Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?", true), array('y','n'), 'n'); - $helpers = array(); - if (strtolower($wannaDoHelpers) == 'y') { - $helpersList = $this->in(__("Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true)); - $helpersListTrimmed = str_replace(' ', '', $helpersList); - $helpers = explode(',', $helpersListTrimmed); - } - return $helpers; + return $this->_doPropertyChoices( + __("Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?", true), + __("Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'", true) + ); } /** @@ -517,14 +522,40 @@ class ControllerTask extends Shell { * @return array Components the user wants to use. **/ function doComponents() { - $wannaDoComponents = $this->in(__("Would you like this controller to use any components?", true), array('y','n'), 'n'); - $components = array(); - if (strtolower($wannaDoComponents) == 'y') { - $componentsList = $this->in(__("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true)); - $componentsListTrimmed = str_replace(' ', '', $componentsList); - $components = explode(',', $componentsListTrimmed); + return $this->_doPropertyChoices( + __("Would you like this controller to use any components?", true), + __("Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'", true) + ); + } + +/** + * Interact with the user and get a list of additional models to use + * + * @return array Models the user wants to use. + **/ + function doUses() { + return $this->_doPropertyChoices( + __("Would you like this controller to use any additional models?", true), + __("Please provide a comma separated list of the model names you'd like to use.\nExample: 'Post, Comment, User'", true) + ); + } + +/** + * Common code for property choice handling. + * + * @param string $prompt A yes/no question to precede the list + * @param sting $example A question for a comma separated list, with examples. + * @return array Array of values for property. + **/ + function _doPropertyChoices($prompt, $example) { + $proceed = $this->in($prompt, array('y','n'), 'n'); + $property = array(); + if (strtolower($proceed) == 'y') { + $propertyList = $this->in($example); + $propertyListTrimmed = str_replace(' ', '', $propertyList); + $property = explode(',', $propertyListTrimmed); } - return $components; + return $property; } /** From 08394629c9f474dd154f7d50551693df88cbf97c Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 16 May 2009 23:17:40 -0400 Subject: [PATCH 061/207] Creating confirmController and test case. --- cake/console/libs/tasks/controller.php | 80 ++++++++++--------- .../console/libs/tasks/controller.test.php | 21 ++++- 2 files changed, 64 insertions(+), 37 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 38185a99a..8764ad92c 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -167,7 +167,9 @@ class ControllerTask extends Shell { $components = $this->doComponents(); $uses = $this->doUses(); - $wannaUseSession = $this->in(__("Would you like to use Sessions?", true), array('y','n'), 'y'); + $wannaUseSession = $this->in( + __("Would you like to use Session flash messages?", true), array('y','n'), 'y' + ); } else { $wannaBakeCrud = 'n'; } @@ -184,41 +186,7 @@ class ControllerTask extends Shell { } if ($this->interactive === true) { - $this->out(''); - $this->hr(); - $this->out('The following controller will be created:'); - $this->hr(); - $this->out("Controller Name:\t$controllerName"); - - if (strtolower($useDynamicScaffold) == 'y') { - $this->out("\t\tvar \$scaffold;"); - $actions = 'scaffold'; - } - - if (count($helpers)) { - $this->out("Helpers:", false); - - foreach ($helpers as $help) { - if ($help != $helpers[count($helpers) - 1]) { - $this->out(ucfirst($help) . ", ", false); - } else { - $this->out(ucfirst($help)); - } - } - } - - if (count($components)) { - $this->out("Components:", false); - - foreach ($components as $comp) { - if ($comp != $components[count($components) - 1]) { - $this->out(ucfirst($comp) . ", ", false); - } else { - $this->out(ucfirst($comp)); - } - } - } - $this->hr(); + $this->confirmController($controllerName, $useDynamicScaffold, $uses, $helpers, $components); $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); if (strtolower($looksGood) == 'y') { @@ -235,6 +203,46 @@ class ControllerTask extends Shell { } } +/** + * Confirm a to be baked controller with the user + * + * @return void + **/ + function confirmController($controllerName, $useDynamicScaffold, $uses, $helpers, $components) { + $this->out(''); + $this->hr(); + $this->out('The following controller will be created:'); + $this->hr(); + $this->out("Controller Name:\n\t$controllerName"); + + if (strtolower($useDynamicScaffold) == 'y') { + $this->out("\t\tvar \$scaffold;"); + $actions = 'scaffold'; + } + + $properties = array( + 'helpers' => __("Helpers:", true), + 'components' => __('Components:', true), + 'uses' => __('Uses:', true) + ); + + foreach ($properties as $var => $title) { + if (count($$var)) { + $output = ''; + $length = count($$var); + foreach ($$var as $i => $propElement) { + if ($i != $length -1) { + $output .= ucfirst($propElement) . ', '; + } else { + $output .= ucfirst($propElement); + } + } + $this->out($title . "\n\t" . $output); + } + } + $this->hr(); + } + /** * Interact with the user and ask about which methods (admin or regular they want to bake) * diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 6b84f568a..2bdab3f88 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -43,7 +43,7 @@ Mock::generatePartial( Mock::generatePartial( 'ControllerTask', 'MockControllerTask', - array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest') + array('in', 'hr', 'out', 'err', 'createFile', '_stop', '_checkUnitTest') ); Mock::generatePartial( @@ -180,5 +180,24 @@ class ControllerTaskTest extends CakeTestCase { $expected = array('RequestHandler', 'Security'); $this->assertEqual($result, $expected); } + +/** + * test Confirming controller user interaction + * + * @return void + **/ + function testConfirmController() { + $controller = 'Posts'; + $scaffold = false; + $helpers = array('Ajax', 'Time'); + $components = array('Acl', 'Auth'); + $uses = array('Comment', 'User'); + + $this->Task->expectAt(2, 'out', array("Controller Name:\n\t$controller")); + $this->Task->expectAt(3, 'out', array("Helpers:\n\tAjax, Time")); + $this->Task->expectAt(4, 'out', array("Components:\n\tAcl, Auth")); + $this->Task->expectAt(5, 'out', array("Uses:\n\tComment, User")); + $this->Task->confirmController($controller, $scaffold, $uses, $helpers, $components); + } } ?> \ No newline at end of file From c0f06be65e0d54003f1d643224170c3d165ce4ce Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 17 May 2009 00:04:33 -0400 Subject: [PATCH 062/207] Adding test case for bake output. --- .../console/libs/tasks/controller.test.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 2bdab3f88..5bec03b8b 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -199,5 +199,31 @@ class ControllerTaskTest extends CakeTestCase { $this->Task->expectAt(5, 'out', array("Uses:\n\tComment, User")); $this->Task->confirmController($controller, $scaffold, $uses, $helpers, $components); } + +/** + * test the bake method + * + * @return void + **/ + function testBake() { + $helpers = array('Ajax', 'Time'); + $components = array('Acl', 'Auth'); + $uses = array('Comment', 'User'); + $this->Task->setReturnValue('createFile', true); + + $result = $this->Task->bake('Articles', '--actions--', $helpers, $components, $uses); + $this->assertPattern('/class ArticlesController extends AppController/', $result); + $this->assertPattern('/\$components \= array\(\'Acl\', \'Auth\'\)/', $result); + $this->assertPattern('/\$uses \= array\(\'Article\', \'Comment\', \'User\'\)/', $result); + $this->assertPattern('/\$helpers \= array\(\'Html\', \'Form\', \'Ajax\', \'Time\'\)/', $result); + $this->assertPattern('/\-\-actions\-\-/', $result); + + $result = $this->Task->bake('Articles', 'scaffold', $helpers, $components, $uses); + $this->assertPattern('/class ArticlesController extends AppController/', $result); + $this->assertPattern('/var \$scaffold/', $result); + $this->assertNoPattern('/helpers/', $result); + $this->assertNoPattern('/components/', $result); + $this->assertNoPattern('/uses/', $result); + } } ?> \ No newline at end of file From d31c43d40995ad29c4fa2d68029dad1628fde6b9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 17 May 2009 00:05:07 -0400 Subject: [PATCH 063/207] Refactoring code generation into controller.ctp --- cake/console/libs/tasks/controller.php | 61 ++++-------------- .../libs/templates/objects/controller.ctp | 64 +++++++++++++++++++ 2 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 cake/console/libs/templates/objects/controller.ctp diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 8764ad92c..088150239 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -160,7 +160,10 @@ class ControllerTask extends Shell { __("Would you like to use dynamic scaffolding?", true), array('y','n'), 'n' ); - if (strtolower($useDynamicScaffold) == 'n') { + if (strtolower($useDynamicScaffold) == 'y') { + $wannaBakeCrud = 'n'; + $actions = 'scaffold'; + } else { list($wannaBakeCrud, $wannaBakeCrud) = $this->_askAboutMethods(); $helpers = $this->doHelpers(); @@ -170,8 +173,6 @@ class ControllerTask extends Shell { $wannaUseSession = $this->in( __("Would you like to use Session flash messages?", true), array('y','n'), 'y' ); - } else { - $wannaBakeCrud = 'n'; } } else { list($wannaBakeCrud, $wannaBakeCrud) = $this->_askAboutMethods(); @@ -216,8 +217,7 @@ class ControllerTask extends Shell { $this->out("Controller Name:\n\t$controllerName"); if (strtolower($useDynamicScaffold) == 'y') { - $this->out("\t\tvar \$scaffold;"); - $actions = 'scaffold'; + $this->out("var \$scaffold;"); } $properties = array( @@ -428,52 +428,17 @@ class ControllerTask extends Shell { * @access private */ function bake($controllerName, $actions = '', $helpers = null, $components = null, $uses = null) { - $out = "plugin}AppController {\n\n"; - $out .= "\tvar \$name = '$controllerName';\n"; + $isScaffold = ($actions === 'scaffold') ? true : false; - if (low($actions) == 'scaffold') { - $out .= "\tvar \$scaffold;\n"; - } else { - if (count($uses)) { - $out .= "\tvar \$uses = array('" . $this->_modelName($controllerName) . "', "; + $this->Template->set('plugin', $this->plugin); + $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'uses', 'isScaffold')); + $contents = $this->Template->generate('objects', 'controller'); - foreach ($uses as $use) { - if ($use != $uses[count($uses) - 1]) { - $out .= "'" . $this->_modelName($use) . "', "; - } else { - $out .= "'" . $this->_modelName($use) . "'"; - } - } - $out .= ");\n"; - } - - $out .= "\tvar \$helpers = array('Html', 'Form'"; - if (count($helpers)) { - foreach ($helpers as $help) { - $out .= ", '" . Inflector::camelize($help) . "'"; - } - } - $out .= ");\n"; - - if (count($components)) { - $out .= "\tvar \$components = array("; - - foreach ($components as $comp) { - if ($comp != $components[count($components) - 1]) { - $out .= "'" . Inflector::camelize($comp) . "', "; - } else { - $out .= "'" . Inflector::camelize($comp) . "'"; - } - } - $out .= ");\n"; - } - $out .= $actions; - } - $out .= "}\n"; - $out .= "?>"; $filename = $this->path . $this->_controllerPath($controllerName) . '_controller.php'; - return $this->createFile($filename, $out); + if ($this->createFile($filename, $contents)) { + return $contents; + } + return false; } /** * Assembles and writes a unit test file diff --git a/cake/console/libs/templates/objects/controller.ctp b/cake/console/libs/templates/objects/controller.ctp new file mode 100644 index 000000000..61f104fe7 --- /dev/null +++ b/cake/console/libs/templates/objects/controller.ctp @@ -0,0 +1,64 @@ + +class Controller extends AppController { + + var $name = ''; + + var $scaffold; + +_modelName($controllerName) . "'"; + foreach ($uses as $use): + echo ", '" . $this->_modelName($use) . "'"; + endforeach; + echo ");\n"; +endif; + +echo "\tvar \$helpers = array('Html', 'Form'"; +if (count($helpers)): + foreach ($helpers as $help): + echo ", '" . Inflector::camelize($help) . "'"; + endforeach; +endif; +echo ");\n"; + +if (count($components)): + echo "\tvar \$components = array("; + for ($i = 0, $len = count($components); $i < $len; $i++): + if ($i != $len - 1): + echo "'" . Inflector::camelize($components[$i]) . "', "; + else: + echo "'" . Inflector::camelize($components[$i]) . "'"; + endif; + endfor; + echo ");\n"; +endif; + +echo $actions; + +endif; ?> +} +"; ?> \ No newline at end of file From 9d405faf8f74db15b273165df5e23b1b55d7f3eb Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 17 May 2009 00:31:37 -0400 Subject: [PATCH 064/207] Allowing controller bake all to use connections other than default. --- cake/console/libs/tasks/controller.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 088150239..fc49f0c73 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -59,6 +59,7 @@ class ControllerTask extends Shell { */ function initialize() { } + /** * Execution method always used for tasks * @@ -101,6 +102,7 @@ class ControllerTask extends Shell { } } } + /** * Bake All the controllers at once. Will only bake controllers for models that exist. * @@ -110,6 +112,7 @@ class ControllerTask extends Shell { function all() { $this->interactive = false; $this->listAll($this->connection, false); + ClassRegistry::config('Model', array('ds' => $this->connection)); foreach ($this->__tables as $table) { $model = $this->_modelName($table); $controller = $this->_controllerName($model); @@ -119,6 +122,7 @@ class ControllerTask extends Shell { } } } + /** * Interactive * @@ -272,16 +276,17 @@ class ControllerTask extends Shell { function bakeActions($controllerName, $admin = null, $wannaUseSession = true) { $currentModelName = $this->_modelName($controllerName); if (!App::import('Model', $currentModelName)) { - $this->err(__('You must have a model for this class to build scaffold methods. Please try again.', true)); - exit; + $this->err(__('You must have a model for this class to build basic methods. Please try again.', true)); + $this->_stop(); } $actions = null; - $modelObj =& new $currentModelName(); + $modelObj =& ClassRegistry::init($currentModelName); $controllerPath = $this->_controllerPath($controllerName); $pluralName = $this->_pluralName($currentModelName); $singularName = Inflector::variable($currentModelName); $singularHumanName = Inflector::humanize($currentModelName); $pluralHumanName = Inflector::humanize($controllerName); + $actions .= "\n"; $actions .= "\tfunction {$admin}index() {\n"; $actions .= "\t\t\$this->{$currentModelName}->recursive = 0;\n"; @@ -440,6 +445,7 @@ class ControllerTask extends Shell { } return false; } + /** * Assembles and writes a unit test file * From 0d7b86fc8b169e513e618c4fc0491ee668c39b8b Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 18 May 2009 22:26:16 -0400 Subject: [PATCH 065/207] Removing $uses as part of bake. --- cake/console/libs/tasks/controller.php | 26 ++++------------ .../libs/templates/objects/controller.ctp | 7 ----- .../console/libs/tasks/controller.test.php | 30 ++++++++++++++++--- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index fc49f0c73..2df4ef5bd 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -143,7 +143,7 @@ class ControllerTask extends Shell { $this->out("Baking {$controllerName}Controller"); $this->hr(); - $helpers = $components = $uses = array(); + $helpers = $components = array(); $actions = ''; $wannaUseSession = 'y'; $wannaBakeAdminCrud = 'n'; @@ -172,7 +172,6 @@ class ControllerTask extends Shell { $helpers = $this->doHelpers(); $components = $this->doComponents(); - $uses = $this->doUses(); $wannaUseSession = $this->in( __("Would you like to use Session flash messages?", true), array('y','n'), 'y' @@ -195,13 +194,13 @@ class ControllerTask extends Shell { $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); if (strtolower($looksGood) == 'y') { - $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses); + $baked = $this->bake($controllerName, $actions, $helpers, $components); if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); } } } else { - $baked = $this->bake($controllerName, $actions, $helpers, $components, $uses); + $baked = $this->bake($controllerName, $actions, $helpers, $components); if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); } @@ -213,7 +212,7 @@ class ControllerTask extends Shell { * * @return void **/ - function confirmController($controllerName, $useDynamicScaffold, $uses, $helpers, $components) { + function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) { $this->out(''); $this->hr(); $this->out('The following controller will be created:'); @@ -227,7 +226,6 @@ class ControllerTask extends Shell { $properties = array( 'helpers' => __("Helpers:", true), 'components' => __('Components:', true), - 'uses' => __('Uses:', true) ); foreach ($properties as $var => $title) { @@ -432,11 +430,11 @@ class ControllerTask extends Shell { * @return string Baked controller * @access private */ - function bake($controllerName, $actions = '', $helpers = null, $components = null, $uses = null) { + function bake($controllerName, $actions = '', $helpers = null, $components = null) { $isScaffold = ($actions === 'scaffold') ? true : false; $this->Template->set('plugin', $this->plugin); - $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'uses', 'isScaffold')); + $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'isScaffold')); $contents = $this->Template->generate('objects', 'controller'); $filename = $this->path . $this->_controllerPath($controllerName) . '_controller.php'; @@ -507,18 +505,6 @@ class ControllerTask extends Shell { ); } -/** - * Interact with the user and get a list of additional models to use - * - * @return array Models the user wants to use. - **/ - function doUses() { - return $this->_doPropertyChoices( - __("Would you like this controller to use any additional models?", true), - __("Please provide a comma separated list of the model names you'd like to use.\nExample: 'Post, Comment, User'", true) - ); - } - /** * Common code for property choice handling. * diff --git a/cake/console/libs/templates/objects/controller.ctp b/cake/console/libs/templates/objects/controller.ctp index 61f104fe7..539210d2e 100644 --- a/cake/console/libs/templates/objects/controller.ctp +++ b/cake/console/libs/templates/objects/controller.ctp @@ -29,13 +29,6 @@ class Controller extends App var $scaffold; _modelName($controllerName) . "'"; - foreach ($uses as $use): - echo ", '" . $this->_modelName($use) . "'"; - endforeach; - echo ");\n"; -endif; echo "\tvar \$helpers = array('Html', 'Form'"; if (count($helpers)): diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 5bec03b8b..a29a0e174 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -196,8 +196,7 @@ class ControllerTaskTest extends CakeTestCase { $this->Task->expectAt(2, 'out', array("Controller Name:\n\t$controller")); $this->Task->expectAt(3, 'out', array("Helpers:\n\tAjax, Time")); $this->Task->expectAt(4, 'out', array("Components:\n\tAcl, Auth")); - $this->Task->expectAt(5, 'out', array("Uses:\n\tComment, User")); - $this->Task->confirmController($controller, $scaffold, $uses, $helpers, $components); + $this->Task->confirmController($controller, $scaffold, $helpers, $components); } /** @@ -214,7 +213,6 @@ class ControllerTaskTest extends CakeTestCase { $result = $this->Task->bake('Articles', '--actions--', $helpers, $components, $uses); $this->assertPattern('/class ArticlesController extends AppController/', $result); $this->assertPattern('/\$components \= array\(\'Acl\', \'Auth\'\)/', $result); - $this->assertPattern('/\$uses \= array\(\'Article\', \'Comment\', \'User\'\)/', $result); $this->assertPattern('/\$helpers \= array\(\'Html\', \'Form\', \'Ajax\', \'Time\'\)/', $result); $this->assertPattern('/\-\-actions\-\-/', $result); @@ -223,7 +221,31 @@ class ControllerTaskTest extends CakeTestCase { $this->assertPattern('/var \$scaffold/', $result); $this->assertNoPattern('/helpers/', $result); $this->assertNoPattern('/components/', $result); - $this->assertNoPattern('/uses/', $result); + } + +/** + * test that execute runs all when the first arg == all + * + * @return void + **/ + function testExecuteIntoAll() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('all'); + + $filename = '/my/path/articles_controller.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticlesController/'))); + + $filename = '/my/path/articles_tags_contoller.php'; + $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/class ArticlesTagsController/'))); + + $filename = '/my/path/comments_controller.php'; + $this->Task->expectAt(2, 'createFile', array($filename, new PatternExpectation('/class CommentsController/'))); + + $filename = '/my/path/tags_controller.php'; + $this->Task->expectAt(4, 'createFile', array($filename, new PatternExpectation('/class TagsController/'))); + + $this->Task->execute(); } } ?> \ No newline at end of file From 4f6d3219efd42f390dbe349d87430ee7e01a36fd Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 18 May 2009 23:46:20 -0400 Subject: [PATCH 066/207] Adding test cases for bakeActions --- .../console/libs/tasks/controller.test.php | 90 +++++++++++++++++-- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index a29a0e174..7394bb1c3 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -51,6 +51,18 @@ Mock::generatePartial( array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest') ); +if (!class_exists('Article')) { + define('ARTICLE_MODEL_CREATED', true); + App::import('Core', 'Model'); + + class Article extends Model { + var $name = 'Article'; + var $hasMany = array('Comment'); + var $hasAndBelongToMany = array('Tag'); + } + +} + /** * ControllerTaskTest class * @@ -223,12 +235,81 @@ class ControllerTaskTest extends CakeTestCase { $this->assertNoPattern('/components/', $result); } +/** + * test that bakeActions is creating the correct controller Code. (Using sessions) + * + * @return void + **/ + function testBakeActionsUsingSessions() { + $result = $this->Task->bakeActions('Articles', null, true); + + $this->assertTrue(strpos($result, 'function index() {') !== false); + $this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false); + $this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false); + + $this->assertTrue(strpos($result, 'function view($id = null)') !== false); + $this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Invalid Article', true))") !== false); + $this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false); + + $this->assertTrue(strpos($result, 'function add()') !== false); + $this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false); + $this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false); + $this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The Article has been saved', true))") !== false); + + $this->assertTrue(strpos($result, 'function edit($id = null)') !== false); + $this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The Article could not be saved. Please, try again.', true));") !== false); + + $this->assertTrue(strpos($result, 'function delete($id = null)') !== false); + $this->assertTrue(strpos($result, 'if ($this->Article->del($id))') !== false); + $this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Article deleted', true))") !== false); + + + $result = $this->Task->bakeActions('Articles', 'admin_', true); + + $this->assertTrue(strpos($result, 'function admin_index() {') !== false); + $this->assertTrue(strpos($result, 'function admin_add()') !== false); + $this->assertTrue(strpos($result, 'function admin_view($id = null)') !== false); + $this->assertTrue(strpos($result, 'function admin_edit($id = null)') !== false); + $this->assertTrue(strpos($result, 'function admin_delete($id = null)') !== false); + } + +/** + * Test baking with Controller::flash() or no sessions. + * + * @return void + **/ + function testBakeActionsWithNoSessions() { + $result = $this->Task->bakeActions('Articles', null, false); + + $this->assertTrue(strpos($result, 'function index() {') !== false); + $this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false); + $this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false); + + $this->assertTrue(strpos($result, 'function view($id = null)') !== false); + $this->assertTrue(strpos($result, "\$this->flash(__('Invalid Article', true), array('action'=>'index'))") !== false); + $this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false); + + $this->assertTrue(strpos($result, 'function add()') !== false); + $this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false); + $this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false); + $this->assertTrue(strpos($result, "\$this->flash(__('The Article has been saved.', true), array('action'=>'index'))") !== false); + + $this->assertTrue(strpos($result, 'function edit($id = null)') !== false); + + $this->assertTrue(strpos($result, 'function delete($id = null)') !== false); + $this->assertTrue(strpos($result, 'if ($this->Article->del($id))') !== false); + $this->assertTrue(strpos($result, "\$this->flash(__('Article deleted', true), array('action'=>'index'))") !== false); + } /** * test that execute runs all when the first arg == all * * @return void **/ function testExecuteIntoAll() { + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute into all could not be run as an Article model was already loaded'); + if ($skip) { + return; + } $this->Task->connection = 'test_suite'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); @@ -236,15 +317,6 @@ class ControllerTaskTest extends CakeTestCase { $filename = '/my/path/articles_controller.php'; $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticlesController/'))); - $filename = '/my/path/articles_tags_contoller.php'; - $this->Task->expectAt(1, 'createFile', array($filename, new PatternExpectation('/class ArticlesTagsController/'))); - - $filename = '/my/path/comments_controller.php'; - $this->Task->expectAt(2, 'createFile', array($filename, new PatternExpectation('/class CommentsController/'))); - - $filename = '/my/path/tags_controller.php'; - $this->Task->expectAt(4, 'createFile', array($filename, new PatternExpectation('/class TagsController/'))); - $this->Task->execute(); } } From 8bcd8ff890e8c3ef72495c658be29e8317bd3585 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 18 May 2009 23:49:44 -0400 Subject: [PATCH 067/207] Adding skipIf's Fixing typo, adding assertions. --- .../cases/console/libs/tasks/controller.test.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 7394bb1c3..b5b2c2cb5 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -58,7 +58,7 @@ if (!class_exists('Article')) { class Article extends Model { var $name = 'Article'; var $hasMany = array('Comment'); - var $hasAndBelongToMany = array('Tag'); + var $hasAndBelongsToMany = array('Tag'); } } @@ -241,6 +241,10 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testBakeActionsUsingSessions() { + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article Model to be undefined. %s'); + if ($skip) { + return; + } $result = $this->Task->bakeActions('Articles', null, true); $this->assertTrue(strpos($result, 'function index() {') !== false); @@ -279,6 +283,10 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testBakeActionsWithNoSessions() { + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article Model to be undefined. %s'); + if ($skip) { + return; + } $result = $this->Task->bakeActions('Articles', null, false); $this->assertTrue(strpos($result, 'function index() {') !== false); @@ -295,18 +303,20 @@ class ControllerTaskTest extends CakeTestCase { $this->assertTrue(strpos($result, "\$this->flash(__('The Article has been saved.', true), array('action'=>'index'))") !== false); $this->assertTrue(strpos($result, 'function edit($id = null)') !== false); + $this->assertTrue(strpos($result, "\$this->Article->Tag->find('list')") !== false); $this->assertTrue(strpos($result, 'function delete($id = null)') !== false); $this->assertTrue(strpos($result, 'if ($this->Article->del($id))') !== false); $this->assertTrue(strpos($result, "\$this->flash(__('Article deleted', true), array('action'=>'index'))") !== false); } + /** * test that execute runs all when the first arg == all * * @return void **/ function testExecuteIntoAll() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute into all could not be run as an Article model was already loaded'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute into all could not be run as an Article model was already loaded. %s'); if ($skip) { return; } From 2cae04308cc0e7ec69e909d81bd27bed1ae4cdcc Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 19 May 2009 00:18:59 -0400 Subject: [PATCH 068/207] Adding tests for interactive mode. Fixing notice error. --- cake/console/libs/tasks/controller.php | 2 +- .../console/libs/tasks/controller.test.php | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 2df4ef5bd..873dc640d 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -190,7 +190,7 @@ class ControllerTask extends Shell { } if ($this->interactive === true) { - $this->confirmController($controllerName, $useDynamicScaffold, $uses, $helpers, $components); + $this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components); $looksGood = $this->in(__('Look okay?', true), array('y','n'), 'y'); if (strtolower($looksGood) == 'y') { diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index b5b2c2cb5..928eecafc 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -304,12 +304,36 @@ class ControllerTaskTest extends CakeTestCase { $this->assertTrue(strpos($result, 'function edit($id = null)') !== false); $this->assertTrue(strpos($result, "\$this->Article->Tag->find('list')") !== false); + $this->assertTrue(strpos($result, "\$this->set(compact('tags'))") !== false); $this->assertTrue(strpos($result, 'function delete($id = null)') !== false); $this->assertTrue(strpos($result, 'if ($this->Article->del($id))') !== false); $this->assertTrue(strpos($result, "\$this->flash(__('Article deleted', true), array('action'=>'index'))") !== false); } +/** + * test Interactive mode. + * + * @return void + **/ + function testInteractive() { + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path'; + $this->Task->setReturnValueAt(0, 'in', '1'); + $this->Task->setReturnValueAt(1, 'in', 'y'); // build interactive + $this->Task->setReturnValueAt(2, 'in', 'n'); // build no scaffolds + $this->Task->setReturnValueAt(3, 'in', 'y'); // build normal methods + $this->Task->setReturnValueAt(4, 'in', 'n'); // build admin methods + $this->Task->setReturnValueAt(5, 'in', 'n'); // helpers? + $this->Task->setReturnValueAt(6, 'in', 'n'); // components? + $this->Task->setReturnValueAt(7, 'in', 'y'); // use sessions + $this->Task->setReturnValueAt(8, 'in', 'y'); // looks good + + $this->Task->execute(); + + $filename = '/my/path/articles_controller.php'; + $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticlesController/'))); + } /** * test that execute runs all when the first arg == all * From a4f6fdc3b955e9bf61bfdcae1740b27aa527c55b Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 19 May 2009 23:53:41 -0400 Subject: [PATCH 069/207] Refactoring bake action generation into a template file. Adding template file for controller actions. --- cake/console/libs/tasks/controller.php | 134 +---------------- .../templates/objects/controller_actions.ctp | 138 ++++++++++++++++++ 2 files changed, 142 insertions(+), 130 deletions(-) create mode 100644 cake/console/libs/templates/objects/controller_actions.ctp diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 873dc640d..2b538b83b 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -277,7 +277,7 @@ class ControllerTask extends Shell { $this->err(__('You must have a model for this class to build basic methods. Please try again.', true)); $this->_stop(); } - $actions = null; + $modelObj =& ClassRegistry::init($currentModelName); $controllerPath = $this->_controllerPath($controllerName); $pluralName = $this->_pluralName($currentModelName); @@ -285,136 +285,10 @@ class ControllerTask extends Shell { $singularHumanName = Inflector::humanize($currentModelName); $pluralHumanName = Inflector::humanize($controllerName); - $actions .= "\n"; - $actions .= "\tfunction {$admin}index() {\n"; - $actions .= "\t\t\$this->{$currentModelName}->recursive = 0;\n"; - $actions .= "\t\t\$this->set('{$pluralName}', \$this->paginate());\n"; - $actions .= "\t}\n"; - $actions .= "\n"; - $actions .= "\tfunction {$admin}view(\$id = null) {\n"; - $actions .= "\t\tif (!\$id) {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid {$singularHumanName}.', true));\n"; - $actions .= "\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action'=>'index'));\n"; - } - $actions .= "\t\t}\n"; - $actions .= "\t\t\$this->set('".$singularName."', \$this->{$currentModelName}->read(null, \$id));\n"; - $actions .= "\t}\n"; - $actions .= "\n"; + $this->Template->set(compact('admin', 'controllerPath', 'pluralName', 'singularName', 'singularHumanName', + 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName')); + $actions = $this->Template->generate('objects', 'controller_actions'); - /* ADD ACTION */ - $compact = array(); - $actions .= "\tfunction {$admin}add() {\n"; - $actions .= "\t\tif (!empty(\$this->data)) {\n"; - $actions .= "\t\t\t\$this->{$currentModelName}->create();\n"; - $actions .= "\t\t\tif (\$this->{$currentModelName}->save(\$this->data)) {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\t\$this->Session->setFlash(__('The ".$singularHumanName." has been saved', true));\n"; - $actions .= "\t\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $actions .= "\t\t\t\t\$this->flash(__('{$currentModelName} saved.', true), array('action'=>'index'));\n"; - } - $actions .= "\t\t\t} else {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\t\$this->Session->setFlash(__('The {$singularHumanName} could not be saved. Please, try again.', true));\n"; - } - $actions .= "\t\t\t}\n"; - $actions .= "\t\t}\n"; - foreach ($modelObj->hasAndBelongsToMany as $associationName => $relation) { - if (!empty($associationName)) { - $habtmModelName = $this->_modelName($associationName); - $habtmSingularName = $this->_singularName($associationName); - $habtmPluralName = $this->_pluralName($associationName); - $actions .= "\t\t\${$habtmPluralName} = \$this->{$currentModelName}->{$habtmModelName}->find('list');\n"; - $compact[] = "'{$habtmPluralName}'"; - } - } - foreach ($modelObj->belongsTo as $associationName => $relation) { - if (!empty($associationName)) { - $belongsToModelName = $this->_modelName($associationName); - $belongsToPluralName = $this->_pluralName($associationName); - $actions .= "\t\t\${$belongsToPluralName} = \$this->{$currentModelName}->{$belongsToModelName}->find('list');\n"; - $compact[] = "'{$belongsToPluralName}'"; - } - } - if (!empty($compact)) { - $actions .= "\t\t\$this->set(compact(".join(', ', $compact)."));\n"; - } - $actions .= "\t}\n"; - $actions .= "\n"; - - /* EDIT ACTION */ - $compact = array(); - $actions .= "\tfunction {$admin}edit(\$id = null) {\n"; - $actions .= "\t\tif (!\$id && empty(\$this->data)) {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid {$singularHumanName}', true));\n"; - $actions .= "\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $actions .= "\t\t\t\$this->flash(__('Invalid {$singularHumanName}', true), array('action'=>'index'));\n"; - } - $actions .= "\t\t}\n"; - $actions .= "\t\tif (!empty(\$this->data)) {\n"; - $actions .= "\t\t\tif (\$this->{$currentModelName}->save(\$this->data)) {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\t\$this->Session->setFlash(__('The ".$singularHumanName." has been saved', true));\n"; - $actions .= "\t\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $actions .= "\t\t\t\t\$this->flash(__('The ".$singularHumanName." has been saved.', true), array('action'=>'index'));\n"; - } - $actions .= "\t\t\t} else {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\t\$this->Session->setFlash(__('The {$singularHumanName} could not be saved. Please, try again.', true));\n"; - } - $actions .= "\t\t\t}\n"; - $actions .= "\t\t}\n"; - $actions .= "\t\tif (empty(\$this->data)) {\n"; - $actions .= "\t\t\t\$this->data = \$this->{$currentModelName}->read(null, \$id);\n"; - $actions .= "\t\t}\n"; - - foreach ($modelObj->hasAndBelongsToMany as $associationName => $relation) { - if (!empty($associationName)) { - $habtmModelName = $this->_modelName($associationName); - $habtmSingularName = $this->_singularName($associationName); - $habtmPluralName = $this->_pluralName($associationName); - $actions .= "\t\t\${$habtmPluralName} = \$this->{$currentModelName}->{$habtmModelName}->find('list');\n"; - $compact[] = "'{$habtmPluralName}'"; - } - } - foreach ($modelObj->belongsTo as $associationName => $relation) { - if (!empty($associationName)) { - $belongsToModelName = $this->_modelName($associationName); - $belongsToPluralName = $this->_pluralName($associationName); - $actions .= "\t\t\${$belongsToPluralName} = \$this->{$currentModelName}->{$belongsToModelName}->find('list');\n"; - $compact[] = "'{$belongsToPluralName}'"; - } - } - if (!empty($compact)) { - $actions .= "\t\t\$this->set(compact(".join(',', $compact)."));\n"; - } - $actions .= "\t}\n"; - $actions .= "\n"; - $actions .= "\tfunction {$admin}delete(\$id = null) {\n"; - $actions .= "\t\tif (!\$id) {\n"; - if ($wannaUseSession) { - $actions .= "\t\t\t\$this->Session->setFlash(__('Invalid id for {$singularHumanName}', true));\n"; - $actions .= "\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $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"; - if ($wannaUseSession) { - $actions .= "\t\t\t\$this->Session->setFlash(__('{$singularHumanName} deleted', true));\n"; - $actions .= "\t\t\t\$this->redirect(array('action'=>'index'));\n"; - } else { - $actions .= "\t\t\t\$this->flash(__('{$singularHumanName} deleted', true), array('action'=>'index'));\n"; - } - $actions .= "\t\t}\n"; - $actions .= "\t}\n"; - $actions .= "\n"; return $actions; } diff --git a/cake/console/libs/templates/objects/controller_actions.ctp b/cake/console/libs/templates/objects/controller_actions.ctp new file mode 100644 index 000000000..90c4a02c3 --- /dev/null +++ b/cake/console/libs/templates/objects/controller_actions.ctp @@ -0,0 +1,138 @@ + + + function index() { + $this->->recursive = 0; + $this->set('', $this->paginate()); + } + + + function view($id = null) { + if (!$id) { + + $this->Session->setFlash(__('Invalid ', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__('Invalid ', true), array('action'=>'index')); + + } + $this->set('', $this->->read(null, $id)); + } + + + + function add() { + if (!empty($this->data)) { + $this->->create(); + if ($this->->save($this->data)) { + + $this->Session->setFlash(__('The has been saved', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__(' saved.', true), array('action'=>'index')); + + } else { + + $this->Session->setFlash(__('The could not be saved. Please, try again.', true)); + + } + } +{$assoc} as $associationName => $relation): + if (!empty($associationName)): + $otherModelName = $this->_modelName($associationName); + $otherPluralName = $this->_pluralName($associationName); + echo "\t\t\${$otherPluralName} = \$this->{$currentModelName}->{$otherModelName}->find('list');\n"; + $compact[] = "'{$otherPluralName}'"; + endif; + endforeach; + endforeach; + if (!empty($compact)): + echo "\t\t\$this->set(compact(".join(', ', $compact)."));\n"; + endif; +?> + } + + + function edit($id = null) { + if (!$id && empty($this->data)) { + + $this->Session->setFlash(__('Invalid ', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__('Invalid ', true), array('action'=>'index')); + + } + if (!empty($this->data)) { + if ($this->->save($this->data)) { + + $this->Session->setFlash(__('The has been saved', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__('The has been saved.', true), array('action'=>'index')); + + } else { + + $this->Session->setFlash(__('The could not be saved. Please, try again.', true)); + + } + } + if (empty($this->data)) { + $this->data = $this->->read(null, $id); + } +{$assoc} as $associationName => $relation): + if (!empty($associationName)): + $otherModelName = $this->_modelName($associationName); + $otherPluralName = $this->_pluralName($associationName); + echo "\t\t\${$otherPluralName} = \$this->{$currentModelName}->{$otherModelName}->find('list');\n"; + $compact[] = "'{$otherPluralName}'"; + endif; + endforeach; + endforeach; + if (!empty($compact)): + echo "\t\t\$this->set(compact(".join(', ', $compact)."));\n"; + endif; + ?> + } + + function delete($id = null) { + if (!$id) { + + $this->Session->setFlash(__('Invalid id for ', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__('Invalid ', true), array('action'=>'index')); + + } + if ($this->->del($id)) { + + $this->Session->setFlash(__(' deleted', true)); + $this->redirect(array('action'=>'index')); + + $this->flash(__(' deleted', true), array('action'=>'index')); + + } + } From 6eada280cf09c7c631adc462d59060457547ad7a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 00:00:36 -0400 Subject: [PATCH 070/207] Fixing typo. Removing newlines --- cake/console/libs/tasks/controller.php | 3 +-- cake/console/libs/templates/objects/controller_actions.ctp | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 2b538b83b..5e42a53d8 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -168,7 +168,7 @@ class ControllerTask extends Shell { $wannaBakeCrud = 'n'; $actions = 'scaffold'; } else { - list($wannaBakeCrud, $wannaBakeCrud) = $this->_askAboutMethods(); + list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods(); $helpers = $this->doHelpers(); $components = $this->doComponents(); @@ -288,7 +288,6 @@ class ControllerTask extends Shell { $this->Template->set(compact('admin', 'controllerPath', 'pluralName', 'singularName', 'singularHumanName', 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName')); $actions = $this->Template->generate('objects', 'controller_actions'); - return $actions; } diff --git a/cake/console/libs/templates/objects/controller_actions.ctp b/cake/console/libs/templates/objects/controller_actions.ctp index 90c4a02c3..c4b1ce935 100644 --- a/cake/console/libs/templates/objects/controller_actions.ctp +++ b/cake/console/libs/templates/objects/controller_actions.ctp @@ -26,7 +26,6 @@ $this->set('', $this->paginate()); } - function view($id = null) { if (!$id) { @@ -40,7 +39,6 @@ } - function add() { if (!empty($this->data)) { $this->->create(); From e8eaf97dcfc04789bbc1ead574df3a0ac5ac1f46 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 00:31:59 -0400 Subject: [PATCH 071/207] Additional tests for execute --- .../console/libs/tasks/controller.test.php | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 928eecafc..3f7b017d5 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -334,6 +334,7 @@ class ControllerTaskTest extends CakeTestCase { $filename = '/my/path/articles_controller.php'; $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticlesController/'))); } + /** * test that execute runs all when the first arg == all * @@ -351,6 +352,50 @@ class ControllerTaskTest extends CakeTestCase { $filename = '/my/path/articles_controller.php'; $this->Task->expectAt(0, 'createFile', array($filename, new PatternExpectation('/class ArticlesController/'))); + $this->Task->execute(); + } + +/** + * test that `cake bake controller foo scaffold` works. + * + * @return void + **/ + function testExecuteWithScaffoldParam() { + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute with scaffold param requires no Article model to be defined. %s'); + if ($skip) { + return; + } + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('Articles', 'scaffold'); + + $filename = '/my/path/articles_controller.php'; + $this->Task->expectAt(0, 'createFile', array( + $filename, new NoPatternExpectation('/admin_index/') + )); + + $this->Task->execute(); + } + +/** + * test that `cake bake controller foo scaffold admin` works + * + * @return void + **/ + function testExecuteWithAdminScaffoldParams() { + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute with scaffold admin param requires no Article model to be defined. %s'); + if ($skip) { + return; + } + $this->Task->connection = 'test_suite'; + $this->Task->path = '/my/path/'; + $this->Task->args = array('Articles', 'scaffold', 'admin'); + + $filename = '/my/path/articles_controller.php'; + $this->Task->expectAt(0, 'createFile', array( + $filename, new PatternExpectation('/admin_index/') + )); + $this->Task->execute(); } } From de1b495afbab6fddb2176a87f9f3d3c02ad0b9b6 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 00:46:09 -0400 Subject: [PATCH 072/207] Adding some i18n strings. Moving test creation to TestTask. --- cake/console/libs/tasks/controller.php | 34 ++++--------------------- cake/console/libs/tasks/test.php | 35 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 5e42a53d8..2cf5ad343 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -215,9 +215,9 @@ class ControllerTask extends Shell { function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) { $this->out(''); $this->hr(); - $this->out('The following controller will be created:'); + $this->out(__('The following controller will be created:', true)); $this->hr(); - $this->out("Controller Name:\n\t$controllerName"); + $this->out(sprintf(__("Controller Name:\n\t%s", true), $controllerName)); if (strtolower($useDynamicScaffold) == 'y') { $this->out("var \$scaffold;"); @@ -325,33 +325,9 @@ class ControllerTask extends Shell { * @access private */ function bakeTest($className) { - $import = $className; - if ($this->plugin) { - $import = $this->plugin . '.' . $className; - } - $out = "App::import('Controller', '$import');\n\n"; - $out .= "class Test{$className} extends {$className}Controller {\n"; - $out .= "\tvar \$autoRender = false;\n}\n\n"; - $out .= "class {$className}ControllerTest extends CakeTestCase {\n"; - $out .= "\tvar \${$className} = null;\n\n"; - $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 endTest() {\n\t\tunset(\$this->{$className});\n\t}\n}\n"; - - $path = CONTROLLER_TESTS; - if (isset($this->plugin)) { - $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; - $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'controllers' . DS; - } - - $filename = Inflector::underscore($className).'_controller.test.php'; - $this->out("\nBaking unit test for $className..."); - - $header = '$Id'; - $content = ""; - return $this->createFile($path . $filename, $content); + $this->Test->plugin = $this->plugin; + $this->Test->connection = $this->connection; + return $this->Test->bake('Controller', $className); } /** diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 5d35acba4..879e80349 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -260,5 +260,40 @@ class TestTask extends Shell { $content = ""; return $this->createFile($path . $filename, $content); } + +/** + * Create a test case for a controller. + * + * @return void + **/ + function bakeControllerTest() { + $import = $className; + if ($this->plugin) { + $import = $this->plugin . '.' . $className; + } + $out = "App::import('Controller', '$import');\n\n"; + $out .= "class Test{$className} extends {$className}Controller {\n"; + $out .= "\tvar \$autoRender = false;\n}\n\n"; + $out .= "class {$className}ControllerTest extends CakeTestCase {\n"; + $out .= "\tvar \${$className} = null;\n\n"; + $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 endTest() {\n\t\tunset(\$this->{$className});\n\t}\n}\n"; + + $path = CONTROLLER_TESTS; + if (isset($this->plugin)) { + $pluginPath = 'plugins' . DS . Inflector::underscore($this->plugin) . DS; + $path = APP . $pluginPath . 'tests' . DS . 'cases' . DS . 'controllers' . DS; + } + + $filename = Inflector::underscore($className).'_controller.test.php'; + $this->out("\nBaking unit test for $className..."); + + $header = '$Id'; + $content = ""; + return $this->createFile($path . $filename, $content); + } } ?> \ No newline at end of file From dc016735030860b645f1fe1179a9a59712c3e874 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 22:28:15 -0400 Subject: [PATCH 073/207] More i18n strings. --- cake/console/libs/tasks/controller.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cake/console/libs/tasks/controller.php b/cake/console/libs/tasks/controller.php index 2cf5ad343..33320b4f9 100644 --- a/cake/console/libs/tasks/controller.php +++ b/cake/console/libs/tasks/controller.php @@ -44,7 +44,7 @@ class ControllerTask extends Shell { * @var array * @access public */ - var $tasks = array('Model', 'Project', 'Template', 'DbConfig'); + var $tasks = array('Model', 'Test', 'Template', 'DbConfig'); /** * path to CONTROLLERS directory * @@ -80,7 +80,7 @@ class ControllerTask extends Shell { $controller = Inflector::camelize($this->args[0]); $actions = null; if (isset($this->args[1]) && $this->args[1] == 'scaffold') { - $this->out('Baking scaffold for ' . $controller); + $this->out(__('Baking scaffold for ', true) . $controller); $actions = $this->bakeActions($controller); } else { $actions = 'scaffold'; @@ -131,7 +131,7 @@ class ControllerTask extends Shell { function __interactive() { $this->interactive = true; $this->hr(); - $this->out(sprintf("Bake Controller\nPath: %s", $this->path)); + $this->out(sprintf(__("Bake Controller\nPath: %s", true), $this->path)); $this->hr(); if (empty($this->connection)) { @@ -140,7 +140,7 @@ class ControllerTask extends Shell { $controllerName = $this->getName(); $this->hr(); - $this->out("Baking {$controllerName}Controller"); + $this->out(sprintf(__('Baking %sController', true), $controllerName)); $this->hr(); $helpers = $components = array(); @@ -387,7 +387,7 @@ class ControllerTask extends Shell { $this->__tables = $this->Model->getAllTables($useDbConfig); if ($this->interactive == true) { - $this->out('Possible Controllers based on your current database:'); + $this->out(__('Possible Controllers based on your current database:', true)); $this->_controllerNames = array(); $count = count($this->__tables); for ($i = 0; $i < $count; $i++) { From 5843d5e40a50f331901855b917f994f7c5513f41 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 23:15:31 -0400 Subject: [PATCH 074/207] Adding test case for DbConfig task making DbConfigTask testable. --- cake/console/libs/tasks/db_config.php | 22 ++- .../console/libs/tasks/db_config.test.php | 155 ++++++++++++++++++ 2 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 cake/tests/cases/console/libs/tasks/db_config.test.php diff --git a/cake/console/libs/tasks/db_config.php b/cake/console/libs/tasks/db_config.php index 856b1226c..283bba162 100644 --- a/cake/console/libs/tasks/db_config.php +++ b/cake/console/libs/tasks/db_config.php @@ -24,9 +24,6 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -if (!class_exists('File')) { - uses('file'); -} /** * Task class for creating and updating the database configuration file. * @@ -52,6 +49,13 @@ class DbConfigTask extends Shell { 'login'=> 'root', 'password'=> 'password', 'database'=> 'project_name', 'schema'=> null, 'prefix'=> null, 'encoding' => null, 'port' => null ); +/** + * String name of the database config class name. + * Used for testing. + * + * @var string + **/ + var $databaseClassName = 'DATABASE_CONFIG'; /** * initialization callback * @@ -92,8 +96,7 @@ class DbConfigTask extends Shell { if (preg_match('/[^a-z0-9_]/i', $name)) { $name = ''; $this->out('The name may only contain unaccented latin characters, numbers or underscores'); - } - else if (preg_match('/^[^a-z_]/i', $name)) { + } else if (preg_match('/^[^a-z_]/i', $name)) { $name = ''; $this->out('The name must start with an unaccented latin character or an underscore'); } @@ -240,7 +243,7 @@ class DbConfigTask extends Shell { $this->hr(); $looksGood = $this->in('Look okay?', array('y', 'n'), 'y'); - if (low($looksGood) == 'y' || low($looksGood) == 'yes') { + if (strtolower($looksGood) == 'y') { return $config; } return false; @@ -262,7 +265,7 @@ class DbConfigTask extends Shell { $oldConfigs = array(); if (file_exists($filename)) { - $db = new DATABASE_CONFIG; + $db = new $this->databaseClassName; $temp = get_class_vars(get_class($db)); foreach ($temp as $configName => $info) { @@ -346,7 +349,7 @@ class DbConfigTask extends Shell { $out .= "}\n"; $out .= "?>"; - $filename = $this->path.'database.php'; + $filename = $this->path . 'database.php'; return $this->createFile($filename, $out); } @@ -357,7 +360,7 @@ class DbConfigTask extends Shell { **/ function getConfig() { $useDbConfig = 'default'; - $configs = get_class_vars('DATABASE_CONFIG'); + $configs = get_class_vars($this->databaseClassName); if (!is_array($configs)) { return $this->execute(); @@ -369,5 +372,6 @@ class DbConfigTask extends Shell { } return $useDbConfig; } + } ?> \ No newline at end of file diff --git a/cake/tests/cases/console/libs/tasks/db_config.test.php b/cake/tests/cases/console/libs/tasks/db_config.test.php new file mode 100644 index 000000000..27a4f820e --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/db_config.test.php @@ -0,0 +1,155 @@ + 'mysql', + 'persistent' => false, + 'host' => 'localhost', + 'login' => 'user', + 'password' => 'password', + 'database' => 'database_name', + 'prefix' => '', + ); + + var $otherOne = array( + 'driver' => 'mysql', + 'persistent' => false, + 'host' => 'localhost', + 'login' => 'user', + 'password' => 'password', + 'database' => 'other_one', + 'prefix' => '', + ); +} + +/** + * DbConfigTest class + * + * @package cake + * @subpackage cake.tests.cases.console.libs.tasks + */ +class DbConfigTaskTest extends CakeTestCase { + +/** + * setUp method + * + * @return void + * @access public + */ + function startTest() { + $this->Dispatcher =& new TestDbConfigTaskMockShellDispatcher(); + $this->Task =& new MockDbConfigTask($this->Dispatcher); + $this->Task->Dispatch =& new $this->Dispatcher; + $this->Task->Dispatch->shellPaths = Configure::read('shellPaths'); + //$this->Task->Template =& new TemplateTask($this->Task->Dispatch); + + $this->Task->params['working'] = rtrim(APP, '/'); + $this->Task->databaseClassName = 'TEST_DATABASE_CONFIG'; + } + +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + unset($this->Task, $this->Dispatcher); + ClassRegistry::flush(); + } + +/** + * Test the getConfig method. + * + * @return void + **/ + function testGetConfig() { + $this->Task->setReturnValueAt(0, 'in', 'otherOne'); + $result = $this->Task->getConfig(); + $this->assertEqual($result, 'otherOne'); + } + +/** + * test that initialize sets the path up. + * + * @return void + **/ + function testInitialize() { + $this->assertTrue(empty($this->Task->path)); + $this->Task->initialize(); + $this->assertFalse(empty($this->Task->path)); + $this->assertEqual($this->Task->path, APP . 'config' . DS); + + } +/** + * test execute and by extension __interactive + * + * @return void + **/ + function testExecuteIntoInteractive() { + $this->Task->initialize(); + + $this->Task->expectOnce('_stop'); + $this->Task->setReturnValue('in', 'y'); + $this->Task->setReturnValueAt(0, 'in', 'default'); + $this->Task->setReturnValueAt(1, 'in', 'n'); + $this->Task->setReturnValueAt(2, 'in', 'localhost'); + $this->Task->setReturnValueAt(3, 'in', 'n'); + $this->Task->setReturnValueAt(4, 'in', 'root'); + $this->Task->setReturnValueAt(5, 'in', 'password'); + $this->Task->setReturnValueAt(6, 'in', 'cake_test'); + $this->Task->setReturnValueAt(7, 'in', 'n'); + $this->Task->setReturnValueAt(8, 'in', 'y'); + $this->Task->setReturnValueAt(9, 'in', 'y'); + $this->Task->setReturnValueAt(10, 'in', 'y'); + $this->Task->setReturnValueAt(11, 'in', 'n'); + + $result = $this->Task->execute(); + } +} +?> \ No newline at end of file From fe2e3d82fd1e2185680c64d89967d00b2864d915 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 20 May 2009 23:21:36 -0400 Subject: [PATCH 075/207] Removing while() loops wrapping in() with concrete options. --- cake/console/libs/tasks/db_config.php | 31 +++++++++------------------ 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/cake/console/libs/tasks/db_config.php b/cake/console/libs/tasks/db_config.php index 283bba162..da2d8bf97 100644 --- a/cake/console/libs/tasks/db_config.php +++ b/cake/console/libs/tasks/db_config.php @@ -101,29 +101,22 @@ class DbConfigTask extends Shell { $this->out('The name must start with an unaccented latin character or an underscore'); } } - $driver = ''; - while ($driver == '') { - $driver = $this->in('Driver:', array('db2', 'firebird', 'mssql', 'mysql', 'mysqli', 'odbc', 'oracle', 'postgres', 'sqlite', 'sybase'), 'mysql'); - } - $persistent = ''; - - while ($persistent == '') { - $persistent = $this->in('Persistent Connection?', array('y', 'n'), 'n'); - } + $driver = $this->in('Driver:', array('db2', 'firebird', 'mssql', 'mysql', 'mysqli', 'odbc', 'oracle', 'postgres', 'sqlite', 'sybase'), 'mysql'); + $persistent = $this->in('Persistent Connection?', array('y', 'n'), 'n'); if (low($persistent) == 'n') { $persistent = 'false'; } else { $persistent = 'true'; } - $host = ''; + $host = ''; while ($host == '') { $host = $this->in('Database Host:', null, 'localhost'); } - $port = ''; + $port = ''; while ($port == '') { $port = $this->in('Port?', null, 'n'); } @@ -131,8 +124,8 @@ class DbConfigTask extends Shell { if (low($port) == 'n') { $port = null; } - $login = ''; + $login = ''; while ($login == '') { $login = $this->in('User:', null, 'root'); } @@ -144,43 +137,39 @@ class DbConfigTask extends Shell { if ($password == '') { $blank = $this->in('The password you supplied was empty. Use an empty password?', array('y', 'n'), 'n'); - if ($blank == 'y') - { + if ($blank == 'y') { $blankPassword = true; } } } - $database = ''; + $database = ''; while ($database == '') { $database = $this->in('Database Name:', null, 'cake'); } - $prefix = ''; + $prefix = ''; while ($prefix == '') { $prefix = $this->in('Table Prefix?', null, 'n'); } - if (low($prefix) == 'n') { $prefix = null; } - $encoding = ''; + $encoding = ''; while ($encoding == '') { $encoding = $this->in('Table encoding?', null, 'n'); } - if (low($encoding) == 'n') { $encoding = null; } - $schema = ''; + $schema = ''; if ($driver == 'postgres') { while ($schema == '') { $schema = $this->in('Table schema?', null, 'n'); } } - if (low($schema) == 'n') { $schema = null; } From 838af5862e97f773f72fabd8849429868a255be7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 May 2009 22:56:54 -0400 Subject: [PATCH 076/207] Making test bail if any of the required models exist. --- .../console/libs/tasks/controller.test.php | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cake/tests/cases/console/libs/tasks/controller.test.php b/cake/tests/cases/console/libs/tasks/controller.test.php index 3f7b017d5..cc7927952 100644 --- a/cake/tests/cases/console/libs/tasks/controller.test.php +++ b/cake/tests/cases/console/libs/tasks/controller.test.php @@ -51,7 +51,11 @@ Mock::generatePartial( array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest') ); -if (!class_exists('Article')) { +$imported = App::import('Model', 'Article'); +$imported = $imported || App::import('Model', 'Comment'); +$imported = $imported || App::import('Model', 'Tag'); + +if (!$imported) { define('ARTICLE_MODEL_CREATED', true); App::import('Core', 'Model'); @@ -241,7 +245,8 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testBakeActionsUsingSessions() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article Model to be undefined. %s'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), + 'Testing bakeActions requires Article, Comment & Tag Model to be undefined. %s'); if ($skip) { return; } @@ -283,7 +288,8 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testBakeActionsWithNoSessions() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article Model to be undefined. %s'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), + 'Testing bakeActions requires Article, Tag, Comment Models to be undefined. %s'); if ($skip) { return; } @@ -341,7 +347,8 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testExecuteIntoAll() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute into all could not be run as an Article model was already loaded. %s'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), + 'Execute into all could not be run as an Article, Tag or Comment model was already loaded. %s'); if ($skip) { return; } @@ -361,7 +368,8 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testExecuteWithScaffoldParam() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute with scaffold param requires no Article model to be defined. %s'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), + 'Execute with scaffold param requires no Article, Tag or Comment model to be defined. %s'); if ($skip) { return; } @@ -383,7 +391,8 @@ class ControllerTaskTest extends CakeTestCase { * @return void **/ function testExecuteWithAdminScaffoldParams() { - $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Execute with scaffold admin param requires no Article model to be defined. %s'); + $skip = $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), + 'Execute with scaffold admin param requires no Article, Tag or Comment model to be defined. %s'); if ($skip) { return; } From 4fe3c2efe1f2216f93c570b3d6f187a1653f394f Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 May 2009 23:25:14 -0400 Subject: [PATCH 077/207] Removing ability to bake $useTable = false models. --- cake/console/libs/tasks/model.php | 2 +- cake/console/libs/templates/objects/model.ctp | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/cake/console/libs/tasks/model.php b/cake/console/libs/tasks/model.php index c585d9394..3e67d6e9a 100644 --- a/cake/console/libs/tasks/model.php +++ b/cake/console/libs/tasks/model.php @@ -769,7 +769,7 @@ class ModelTask extends Shell { $tableIsGood = $this->in(__('Do you want to use this table?', true), array('y','n'), 'y'); } if (strtolower($tableIsGood) == 'n') { - $useTable = $this->in(__('What is the name of the table (enter "null" to use NO table)?', true)); + $useTable = $this->in(__('What is the name of the table?', true)); } return $useTable; } diff --git a/cake/console/libs/templates/objects/model.ctp b/cake/console/libs/templates/objects/model.ctp index 06b2ca22e..dadf31f76 100644 --- a/cake/console/libs/templates/objects/model.ctp +++ b/cake/console/libs/templates/objects/model.ctp @@ -27,11 +27,8 @@ class extends AppModel { var $useDbConfig = ''; - From dee9b6370b3df63b6e1d897f495ccff444445e08 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 May 2009 23:30:41 -0400 Subject: [PATCH 078/207] Adding test template. --- cake/console/libs/templates/objects/test.ctp | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 cake/console/libs/templates/objects/test.ctp diff --git a/cake/console/libs/templates/objects/test.ctp b/cake/console/libs/templates/objects/test.ctp new file mode 100644 index 000000000..09c161e5b --- /dev/null +++ b/cake/console/libs/templates/objects/test.ctp @@ -0,0 +1,26 @@ + +class TestCase extends CakeTestCase { + +} +'; ?> \ No newline at end of file From f20a7e4f611cc304a9550ea6767fa7f0d47bd497 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 23 May 2009 23:48:25 -0400 Subject: [PATCH 079/207] Adding method extraction and test case. --- cake/console/libs/tasks/test.php | 20 ++++++++++ .../cases/console/libs/tasks/test.test.php | 37 ++++++++++++++++--- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 879e80349..c45f75fde 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -200,6 +200,26 @@ class TestTask extends Shell { return $extras; } +/** + * Get methods declared in the class given. + * No parent methods will be returned + * + * @param string $className Name of class to look at. + * @return array Array of method names. + **/ + function getTestableMethods($className) { + $classMethods = get_class_methods($className); + $parentMethods = get_class_methods(get_parent_class($className)); + $thisMethods = array_diff($classMethods, $parentMethods); + $out = array(); + foreach ($thisMethods as $method) { + if (substr($method, 0, 1) != '_') { + $out[] = $method; + } + } + return $out; + } + /** * Create a test for a Model object. * diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index c8835cfcb..b131a604b 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -42,13 +42,25 @@ if (!class_exists('TestTask')) { } Mock::generatePartial( - 'ShellDispatcher', 'TestTestTaskMockShellDispatcher', - array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment') - ); + 'ShellDispatcher', 'TestTestTaskMockShellDispatcher', + array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment') +); Mock::generatePartial( - 'TestTask', 'MockTestTask', - array('in', 'out', 'createFile') - ); + 'TestTask', 'MockTestTask', + array('in', 'out', 'createFile') +); + +class TestTaskSubjectClass extends Object { + function methodOne() { + + } + function methodTwo() { + + } + function _noTest() { + + } +} /** * TestTaskTest class * @@ -96,5 +108,18 @@ class TestTaskTest extends CakeTestCase { $this->Task->expectAt(1, 'createFile', array($file, '*')); $this->Task->bake('Model', 'MyClass'); } + +/** + * Test that method introspection pulls all relevant non parent class + * methods into the test case. + * + * @return void + **/ + function testMethodIntrospection() { + $result = $this->Task->getTestableMethods('TestTaskSubjectClass'); + $expected = array('methodOne', 'methodTwo'); + $this->assertEqual($result, $expected); + + } } ?> \ No newline at end of file From 61191d88cd46fc0c3afdbb42aecdfac422bddab3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 May 2009 01:15:31 -0400 Subject: [PATCH 080/207] Adding test cases and ability to pull all fixtures for a model. --- cake/console/libs/tasks/test.php | 57 ++++++++++++ .../cases/console/libs/tasks/test.test.php | 86 ++++++++++++++++--- 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index c45f75fde..3039dec9b 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -220,6 +220,63 @@ class TestTask extends Shell { return $out; } +/** + * Generate the list of fixtures that will be required to run this test based on + * loaded models. + * + * @param object The object you want to generate fixtures for. + * @return array Array of fixtures to be included in the test. + **/ + function generateFixtureList(&$subject) { + $this->_fixtures = array(); + if (is_a($subject, 'Model')) { + $this->_processModel($subject); + } elseif (is_a($subject, 'Controller')) { + $this->_processController($subject); + } + return array_values($this->_fixtures); + } + +/** + * Process a model recursively and pull out all the + * model names converting them to fixture names. + * + * @return void + **/ + function _processModel(&$subject) { + $this->_addFixture($subject->name); + $associated = $subject->getAssociated(); + foreach ($associated as $alias => $type) { + $className = $subject->{$alias}->name; + if (!isset($this->_fixtures[$className])) { + $this->_processModel($subject->{$alias}); + } + if ($type == 'hasAndBelongsToMany') { + $joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']); + if (!isset($this->_fixtures[$joinModel])) { + $this->_processModel($subject->{$joinModel}); + } + } + } + } + +/** + * Add classname to the fixture list. + * Sets the app. or plugin.plugin_name. prefix. + * + * @return void + **/ + function _addFixture($name) { + $parent = get_parent_class($name); + $prefix = 'app.'; + if (strtolower($parent) != 'appmodel' && strtolower(substr($parent, -8)) == 'appmodel') { + $pluginName = substr($parent, 0, strlen($parent) -8); + $prefix = 'plugin.' . Inflector::underscore($pluginName) . '.'; + } + $fixture = $prefix . Inflector::underscore($name); + $this->_fixtures[$name] = $fixture; + } + /** * Create a test for a Model object. * diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index b131a604b..d1a3f0e38 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -49,18 +49,66 @@ Mock::generatePartial( 'TestTask', 'MockTestTask', array('in', 'out', 'createFile') ); - +/** + * Test subject for method extraction + * + **/ class TestTaskSubjectClass extends Object { - function methodOne() { - - } - function methodTwo() { - - } - function _noTest() { - - } + function methodOne() { } + function methodTwo() { } + function _noTest() { } } + +/** + * Test subject models for fixture generation + **/ +class TestTaskArticle extends Model { + var $name = 'TestTaskArticle'; + var $useTable = 'articles'; + var $hasMany = array( + 'Comment' => array( + 'className' => 'TestTask.TestTaskComment', + 'foreignKey' => 'article_id', + ) + ); + var $hasAndBelongsToMany = array( + 'Tag' => array( + 'className' => 'TestTaskTag', + 'joinTable' => 'articles_tags', + 'foreignKey' => 'article_id', + 'associationForeignKey' => 'tag_id' + ) + ); +} +class TestTaskTag extends Model { + var $name = 'TestTaskTag'; + var $useTable = 'tags'; + var $hasAndBelongsToMany = array( + 'Article' => array( + 'className' => 'TestTaskArticle', + 'joinTable' => 'articles_tags', + 'foreignKey' => 'tag_id', + 'associationForeignKey' => 'article_id' + ) + ); +} +/** + * Simulated Plugin + **/ +class TestTaskAppModel extends Model { + +} +class TestTaskComment extends TestTaskAppModel { + var $name = 'TestTaskComment'; + var $useTable = 'comments'; + var $belongsTo = array( + 'Article' => array( + 'className' => 'TestTaskArticle', + 'foreignKey' => 'article_id', + ) + ); +} + /** * TestTaskTest class * @@ -68,6 +116,8 @@ class TestTaskSubjectClass extends Object { * @subpackage cake.tests.cases.console.libs.tasks */ class TestTaskTest extends CakeTestCase { + + var $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); /** * setUp method * @@ -79,6 +129,7 @@ class TestTaskTest extends CakeTestCase { $this->Task =& new MockTestTask($this->Dispatcher); $this->Task->Dispatch = new $this->Dispatcher; } + /** * tearDown method * @@ -88,6 +139,7 @@ class TestTaskTest extends CakeTestCase { function tearDown() { ClassRegistry::flush(); } + /** * Test that file path generation doesn't continuously append paths. * @@ -119,6 +171,20 @@ class TestTaskTest extends CakeTestCase { $result = $this->Task->getTestableMethods('TestTaskSubjectClass'); $expected = array('methodOne', 'methodTwo'); $this->assertEqual($result, $expected); + } + +/** + * test that the generation of fixtures works correctly. + * + * @return void + **/ + function testFixtureArrayGeneration() { + $subject = ClassRegistry::init('TestTaskArticle'); + $result = $this->Task->generateFixtureList($subject); + $expected = array('plugin.test_task.test_task_comment', 'app.articles_tags', + 'app.test_task_article', 'app.test_task_tag'); + + $this->assertEqual(sort($result), sort($expected)); } } From 1d6ceffb926898e780ff3702469cb32641c93a6c Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 May 2009 01:30:04 -0400 Subject: [PATCH 081/207] Adding test case and function for generating fixture lists from controller objects. --- cake/console/libs/tasks/test.php | 20 ++++++++++++++-- .../cases/console/libs/tasks/test.test.php | 24 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 3039dec9b..81609be98 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -221,7 +221,7 @@ class TestTask extends Shell { } /** - * Generate the list of fixtures that will be required to run this test based on + * Generate the list of fixtures that will be required to run this test based on * loaded models. * * @param object The object you want to generate fixtures for. @@ -238,7 +238,7 @@ class TestTask extends Shell { } /** - * Process a model recursively and pull out all the + * Process a model recursively and pull out all the * model names converting them to fixture names. * * @return void @@ -260,6 +260,22 @@ class TestTask extends Shell { } } +/** + * Process all the models attached to a controller + * and generate a fixture list. + * + * @return void + **/ + function _processController(&$subject) { + $subject->constructClasses(); + $models = array(Inflector::classify($subject->name)); + if (!empty($subject->uses)) { + $models = $subject->uses; + } + foreach ($models as $model) { + $this->_processModel($subject->{$model}); + } + } /** * Add classname to the fixture list. * Sets the app. or plugin.plugin_name. prefix. diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index d1a3f0e38..774312756 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -25,6 +25,7 @@ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ App::import('Core', 'Shell'); +App::import('Core', array('Controller', 'Model')); if (!defined('DISABLE_AUTO_DISPATCH')) { define('DISABLE_AUTO_DISPATCH', true); @@ -49,6 +50,7 @@ Mock::generatePartial( 'TestTask', 'MockTestTask', array('in', 'out', 'createFile') ); + /** * Test subject for method extraction * @@ -109,6 +111,11 @@ class TestTaskComment extends TestTaskAppModel { ); } +class TestTaskCommentsController extends Controller { + var $name = 'TestTaskComments'; + var $uses = array('TestTaskComment', 'TestTaskTag'); +} + /** * TestTaskTest class * @@ -178,7 +185,7 @@ class TestTaskTest extends CakeTestCase { * * @return void **/ - function testFixtureArrayGeneration() { + function testFixtureArrayGenerationFromModel() { $subject = ClassRegistry::init('TestTaskArticle'); $result = $this->Task->generateFixtureList($subject); $expected = array('plugin.test_task.test_task_comment', 'app.articles_tags', @@ -187,5 +194,20 @@ class TestTaskTest extends CakeTestCase { $this->assertEqual(sort($result), sort($expected)); } + +/** + * test that the generation of fixtures works correctly. + * + * @return void + **/ + function testFixtureArrayGenerationFromController() { + $subject = new TestTaskCommentsController(); + $result = $this->Task->generateFixtureList($subject); + $expected = array('plugin.test_task.test_task_comment', 'app.articles_tags', + 'app.test_task_article', 'app.test_task_tag'); + + $this->assertEqual(sort($result), sort($expected)); + + } } ?> \ No newline at end of file From eb9f40c6f4faea75522b291f8e9c2085112d9535 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 May 2009 20:12:17 -0400 Subject: [PATCH 082/207] extracting out object type interaction. test case added. --- cake/console/libs/tasks/test.php | 71 +++++++++++++------ .../cases/console/libs/tasks/test.test.php | 17 ++++- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 81609be98..2c530f2b6 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -45,6 +45,14 @@ class TestTask extends Shell { * @access public */ var $path = TESTS; + +/** + * class types that methods can be generated for + * + * @var array + **/ + var $classTypes = array('Model', 'Controller', 'Component', 'Behavior', 'Helper'); + /** * Execution method always used for tasks * @@ -66,40 +74,31 @@ class TestTask extends Shell { } } } + /** * Handles interactive baking * * @access private */ - function __interactive($class = null) { + function __interactive($type = null) { $this->hr(); - $this->out(sprintf("Bake Tests\nPath: %s", $this->path)); + $this->out(__('Bake Tests', true)); + $this->out(sprintf(__("Path: %s", true), $this->path)); $this->hr(); - $key = null; - $options = array('Behavior', 'Helper', 'Component', 'Model', 'Controller'); - - if ($class !== null) { - $class = Inflector::camelize($class); - if (in_array($class, $options)) { - $key = array_search($class); + $selection = null; + if ($type) { + $type = Inflector::camelize($type); + if (in_array($type, $this->classTypes)) { + $selection = array_search($type); } } + if (!$selection) { + $selection = $this->getObjectType(); + } + /* - while ($class == null) { - $cases = array(); - $this->hr(); - $this->out("Select a class:"); - $this->hr(); - - $keys = array(); - foreach ($options as $key => $option) { - $this->out(++$key . '. ' . $option); - $keys[] = $key; - } - $keys[] = 'q'; - - $key = $this->in(__("Enter the class to test or (q)uit", true), $keys, 'q'); + $key = $this->in(__("Enter the class to bake a test for or (q)uit", true), $keys, 'q'); if ($key != 'q') { if (isset($options[--$key])) { @@ -127,7 +126,32 @@ class TestTask extends Shell { $this->_stop(); } } + */ } + +/** + * Interact with the user and get their chosen type. Can exit the script. + * + * @return int Index of users chosen object type. + **/ + function getObjectType() { + $this->hr(); + $this->out(__("Select an object type:", true)); + $this->hr(); + + $keys = array(); + foreach ($this->classTypes as $key => $option) { + $this->out(++$key . '. ' . $option); + $keys[] = $key; + } + $keys[] = 'q'; + $selection = $this->in(__("Enter the type of object to bake a test for or (q)uit", true), $keys, 'q'); + if ($selection == 'q') { + $this->_stop(); + } + return $selection; + } + /** * Writes File * @@ -276,6 +300,7 @@ class TestTask extends Shell { $this->_processModel($subject->{$model}); } } + /** * Add classname to the fixture list. * Sets the app. or plugin.plugin_name. prefix. diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 774312756..2124c54bb 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -48,7 +48,7 @@ Mock::generatePartial( ); Mock::generatePartial( 'TestTask', 'MockTestTask', - array('in', 'out', 'createFile') + array('in', '_stop', 'err', 'out', 'createFile') ); /** @@ -192,7 +192,6 @@ class TestTaskTest extends CakeTestCase { 'app.test_task_article', 'app.test_task_tag'); $this->assertEqual(sort($result), sort($expected)); - } /** @@ -207,7 +206,21 @@ class TestTaskTest extends CakeTestCase { 'app.test_task_article', 'app.test_task_tag'); $this->assertEqual(sort($result), sort($expected)); + } +/** + * test user interaction to get object type + * + * @return void + **/ + function testGetObjectType() { + $this->Task->expectOnce('_stop'); + $this->Task->setReturnValueAt(0, 'in', 'q'); + $this->Task->getObjectType(); + + $this->Task->setReturnValueAt(1, 'in', 2); + $result = $this->Task->getObjectType(); + $this->assertEqual($result, 2); } } ?> \ No newline at end of file From 587b0ca07d3e6fe0e71a25eff4abdd750d2e7831 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 24 May 2009 23:50:21 -0400 Subject: [PATCH 083/207] Test generation for models is partially complete. fixtures and introspected methods work. --- cake/console/libs/tasks/test.php | 263 +++++++++++++----- cake/console/libs/templates/objects/test.ctp | 15 +- .../cases/console/libs/tasks/test.test.php | 109 ++++++-- 3 files changed, 294 insertions(+), 93 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 2c530f2b6..a52020968 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -46,6 +46,13 @@ class TestTask extends Shell { */ var $path = TESTS; +/** + * Tasks used. + * + * @var array + **/ + var $tasks = array('Template'); + /** * class types that methods can be generated for * @@ -53,6 +60,20 @@ class TestTask extends Shell { **/ var $classTypes = array('Model', 'Controller', 'Component', 'Behavior', 'Helper'); +/** + * Internal list of fixtures that have been added so far. + * + * @var string + **/ + var $_fixtures = array(); + +/** + * Flag for interactive mode + * + * @var boolean + **/ + var $interactive = false; + /** * Execution method always used for tasks * @@ -68,8 +89,8 @@ class TestTask extends Shell { } if (count($this->args) > 1) { - $class = Inflector::underscore($this->args[0]); - if ($this->bake($class, $this->args[1])) { + $type = Inflector::underscore($this->args[0]); + if ($this->bake($type, $this->args[1])) { $this->out('done'); } } @@ -81,6 +102,7 @@ class TestTask extends Shell { * @access private */ function __interactive($type = null) { + $this->interactive = true; $this->hr(); $this->out(__('Bake Tests', true)); $this->out(sprintf(__("Path: %s", true), $this->path)); @@ -89,75 +111,54 @@ class TestTask extends Shell { $selection = null; if ($type) { $type = Inflector::camelize($type); - if (in_array($type, $this->classTypes)) { - $selection = array_search($type); + if (!in_array($type, $this->classTypes)) { + unset($type); } } - if (!$selection) { - $selection = $this->getObjectType(); + if (!$type) { + $type = $this->getObjectType(); } - /* - - $key = $this->in(__("Enter the class to bake a test for or (q)uit", true), $keys, 'q'); - - if ($key != 'q') { - if (isset($options[--$key])) { - $class = $options[$key]; - } - - if ($class) { - $name = $this->in(__("Enter the name for the test or (q)uit", true), null, 'q'); - if ($name !== 'q') { - $case = null; - while ($case !== 'q') { - $case = $this->in(__("Enter a test case or (q)uit", true), null, 'q'); - if ($case !== 'q') { - $cases[] = $case; - } - } - if ($this->bake($class, $name, $cases)) { - $this->out(__("Test baked\n", true)); - $type = null; - } - $class = null; - } - } - } else { - $this->_stop(); - } - } - */ + $className = $this->getClassName($type); + return $this->bake($type, $className); } /** - * Interact with the user and get their chosen type. Can exit the script. - * - * @return int Index of users chosen object type. - **/ - function getObjectType() { - $this->hr(); - $this->out(__("Select an object type:", true)); - $this->hr(); - - $keys = array(); - foreach ($this->classTypes as $key => $option) { - $this->out(++$key . '. ' . $option); - $keys[] = $key; - } - $keys[] = 'q'; - $selection = $this->in(__("Enter the type of object to bake a test for or (q)uit", true), $keys, 'q'); - if ($selection == 'q') { - $this->_stop(); - } - return $selection; - } - -/** - * Writes File + * Completes final steps for generating data to create test case. * + * @param string $type Type of object to bake test case for ie. Model, Controller + * @param string $className the 'cake name' for the class ie. Posts for the PostsController * @access public */ - function bake($class, $name = null, $cases = array()) { + function bake($type, $className) { + if ($this->typeCanDetectFixtures($type) && $this->isLoadableClass($type, $className)) { + $this->out(__('Bake is detecting possible fixtures..', true)); + $testSubject =& $this->buildTestSubject($type, $className); + $this->generateFixtureList($testSubject); + } elseif ($this->interactive) { + $this->getUserFixtures(); + } + $fullClassName = $this->getRealClassName($type, $className); + + $methods = array(); + if (class_exists($fullClassName)) { + $methods = $this->getTestableMethods($fullClassName); + } + + $this->Template->set('fixtures', $this->_fixtures); + $this->Template->set('plugin', $this->plugin); + $this->Template->set(compact('className', 'methods', 'type', 'fullClassName')); + $out = $this->Template->generate('objects', 'test'); + + if (strpos($this->path, $type) === false) { + $this->filePath = $this->path . 'cases' . DS . Inflector::tableize($type) . DS; + } + $made = $this->createFile($this->filePath . Inflector::underscore($className) . '.test.php', $out); + if ($made) { + return $out; + } + return false; + + /* if (!$name) { return false; } @@ -205,23 +206,102 @@ class TestTask extends Shell { } $header = '$Id'; - $content = ""; + $content = ""; return $this->createFile($this->filePath . Inflector::underscore($name) . '.test.php', $content); + */ } + /** - * Handles the extra stuff needed + * Interact with the user and get their chosen type. Can exit the script. * - * @access private - */ - function __extras($class) { - $extras = null; - switch ($class) { - case 'Model': - $extras = "\n\tvar \$cacheSources = false;"; - $extras .= "\n\tvar \$useDbConfig = 'test_suite';\n"; - break; + * @return string Users chosen type. + **/ + function getObjectType() { + $this->hr(); + $this->out(__("Select an object type:", true)); + $this->hr(); + + $keys = array(); + foreach ($this->classTypes as $key => $option) { + $this->out(++$key . '. ' . $option); + $keys[] = $key; } - return $extras; + $keys[] = 'q'; + $selection = $this->in(__("Enter the type of object to bake a test for or (q)uit", true), $keys, 'q'); + if ($selection == 'q') { + return $this->_stop(); + } + return $this->classTypes[$selection - 1]; + } + +/** + * Get the user chosen Class name for the chosen type + * + * @param string $objectType Type of object to list classes for i.e. Model, Controller. + * @return string Class name the user chose. + **/ + function getClassName($objectType) { + $options = Configure::listObjects(strtolower($objectType)); + $this->out(sprintf(__('Choose a %s class', true), $objectType)); + $keys = array(); + foreach ($options as $key => $option) { + $this->out(++$key . '. ' . $option); + $keys[] = $key; + } + $selection = $this->in(__('Choose an existing class, or enter the name of a class that does not exist', true)); + if (isset($options[$selection - 1])) { + return $options[$selection - 1]; + } + return $selection; + } + +/** + * Checks whether the chosen type can find its own fixtures. + * Currently only model, and controller are supported + * + * @return boolean + **/ + function typeCanDetectFixtures($type) { + $type = strtolower($type); + return ($type == 'controller' || $type == 'model'); + } + +/** + * Check if a class with the given type is loaded or can be loaded. + * + * @return boolean + **/ + function isLoadableClass($type, $class) { + return App::import($type, $class); + } + +/** + * Construct an instance of the class to be tested. + * So that fixtures and methods can be detected + * + * @return object + **/ + function &buildTestSubject($type, $class) { + App::import($type, $class); + $class = $this->getRealClassName($type, $class); + if (strtolower($type) == 'model') { + $instance =& ClassRegistry::init($class); + } else { + $instance =& new $class(); + } + return $instance; + } + +/** + * Gets the real class name from the cake short form. + * + * @return string Real classname + **/ + function getRealClassName($type, $class) { + if (strtolower($type) == 'model') { + return $class; + } + return $class . $type; } /** @@ -266,6 +346,7 @@ class TestTask extends Shell { * model names converting them to fixture names. * * @return void + * @access protected **/ function _processModel(&$subject) { $this->_addFixture($subject->name); @@ -289,6 +370,7 @@ class TestTask extends Shell { * and generate a fixture list. * * @return void + * @access protected **/ function _processController(&$subject) { $subject->constructClasses(); @@ -306,6 +388,7 @@ class TestTask extends Shell { * Sets the app. or plugin.plugin_name. prefix. * * @return void + * @access protected **/ function _addFixture($name) { $parent = get_parent_class($name); @@ -318,6 +401,38 @@ class TestTask extends Shell { $this->_fixtures[$name] = $fixture; } +/** + * Interact with the user to get additional fixtures they want to use. + * + * @return void + **/ + function getUserFixtures() { + $proceed = $this->in(__('Bake could not detect fixtures, would you like to add some?', true), array('y','n'), 'n'); + $fixtures = array(); + if (strtolower($proceed) == 'y') { + $fixtureList = $this->in(__("Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'", true)); + $fixtureListTrimmed = str_replace(' ', '', $fixtureList); + $fixtures = explode(',', $fixtureListTrimmed); + } + $this->_fixtures = array_merge($this->_fixtures, $fixtures); + return $fixtures; + } + +/** + * Handles the extra stuff needed + * + * @access private + */ + function __extras($class) { + $extras = null; + switch ($class) { + case 'Model': + $extras = "\n\tvar \$cacheSources = false;"; + $extras .= "\n\tvar \$useDbConfig = 'test_suite';\n"; + break; + } + return $extras; + } /** * Create a test for a Model object. * diff --git a/cake/console/libs/templates/objects/test.ctp b/cake/console/libs/templates/objects/test.ctp index 09c161e5b..8300c5356 100644 --- a/cake/console/libs/templates/objects/test.ctp +++ b/cake/console/libs/templates/objects/test.ctp @@ -20,7 +20,18 @@ */ echo " -class TestCase extends CakeTestCase { - +App::import('', ''); + +class TestCase extends CakeTestCase { + + var $fixtures = array(''); + + + + function test() { + + } + + } '; ?> \ No newline at end of file diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 2124c54bb..59e947805 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -40,6 +40,7 @@ if (!class_exists('ShellDispatcher')) { if (!class_exists('TestTask')) { require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'test.php'; + require CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'template.php'; } Mock::generatePartial( @@ -48,19 +49,9 @@ Mock::generatePartial( ); Mock::generatePartial( 'TestTask', 'MockTestTask', - array('in', '_stop', 'err', 'out', 'createFile') + array('in', '_stop', 'err', 'out', 'createFile', 'isLoadableClass') ); -/** - * Test subject for method extraction - * - **/ -class TestTaskSubjectClass extends Object { - function methodOne() { } - function methodTwo() { } - function _noTest() { } -} - /** * Test subject models for fixture generation **/ @@ -81,6 +72,15 @@ class TestTaskArticle extends Model { 'associationForeignKey' => 'tag_id' ) ); + function doSomething() { + + } + function doSomethingElse() { + + } + function _innerMethod() { + + } } class TestTaskTag extends Model { var $name = 'TestTaskTag'; @@ -131,10 +131,12 @@ class TestTaskTest extends CakeTestCase { * @return void * @access public */ - function setUp() { + function startTest() { $this->Dispatcher =& new TestTestTaskMockShellDispatcher(); + $this->Dispatcher->shellPaths = Configure::read('shellPaths'); $this->Task =& new MockTestTask($this->Dispatcher); - $this->Task->Dispatch = new $this->Dispatcher; + $this->Task->Dispatch =& $this->Dispatcher; + $this->Task->Template =& new TemplateTask($this->Dispatcher); } /** @@ -143,7 +145,7 @@ class TestTaskTest extends CakeTestCase { * @return void * @access public */ - function tearDown() { + function endTest() { ClassRegistry::flush(); } @@ -175,8 +177,8 @@ class TestTaskTest extends CakeTestCase { * @return void **/ function testMethodIntrospection() { - $result = $this->Task->getTestableMethods('TestTaskSubjectClass'); - $expected = array('methodOne', 'methodTwo'); + $result = $this->Task->getTestableMethods('TestTaskArticle'); + $expected = array('doSomething', 'doSomethingElse'); $this->assertEqual($result, $expected); } @@ -220,7 +222,80 @@ class TestTaskTest extends CakeTestCase { $this->Task->setReturnValueAt(1, 'in', 2); $result = $this->Task->getObjectType(); - $this->assertEqual($result, 2); + $this->assertEqual($result, $this->Task->classTypes[1]); + } + +/** + * test that getClassName returns the user choice as a classname. + * + * @return void + **/ + function testGetClassName() { + $this->Task->setReturnValueAt(0, 'in', 'MyCustomClass'); + $result = $this->Task->getClassName('Model'); + $this->assertEqual($result, 'MyCustomClass'); + + $this->Task->setReturnValueAt(1, 'in', 1); + $result = $this->Task->getClassName('Model'); + $options = Configure::listObjects('model'); + $this->assertEqual($result, $options[0]); + } + +/** + * Test the user interaction for defining additional fixtures. + * + * @return void + **/ + function testGetUserFixtures() { + $this->Task->setReturnValueAt(0, 'in', 'y'); + $this->Task->setReturnValueAt(1, 'in', 'app.pizza, app.topping, app.side_dish'); + $result = $this->Task->getUserFixtures(); + $expected = array('app.pizza', 'app.topping', 'app.side_dish'); + $this->assertEqual($result, $expected); + } + +/** + * test that resolving classnames works + * + * @return void + **/ + function testGetRealClassname() { + $result = $this->Task->getRealClassname('Model', 'Post'); + $this->assertEqual($result, 'Post'); + + $result = $this->Task->getRealClassname('Controller', 'Posts'); + $this->assertEqual($result, 'PostsController'); + + $result = $this->Task->getRealClassname('Helper', 'Form'); + $this->assertEqual($result, 'FormHelper'); + + $result = $this->Task->getRealClassname('Behavior', 'Containable'); + $this->assertEqual($result, 'ContainableBehavior'); + + $result = $this->Task->getRealClassname('Component', 'Auth'); + $this->assertEqual($result, 'AuthComponent'); + } + +/** + * test baking files. + * + * @return void + **/ + function testBake() { + $this->Task->setReturnValue('createFile', true); + $this->Task->setReturnValue('isLoadableClass', true); + + $result = $this->Task->bake('Model', 'TestTaskArticle'); + + $this->assertPattern('/App::import\(\'Model\', \'TestTaskArticle\'\)/', $result); + $this->assertPattern('/class TestTaskArticleTestCase extends CakeTestCase/', $result); + $this->assertPattern('/function testDoSomething\(\)/', $result); + $this->assertPattern('/function testDoSomethingElse\(\)/', $result); + + $this->assertPattern("/'app\.test_task_article'/", $result); + $this->assertPattern("/'plugin\.test_task\.test_task_comment'/", $result); + $this->assertPattern("/'app\.test_task_tag'/", $result); + $this->assertPattern("/'app\.articles_tag'/", $result); } } ?> \ No newline at end of file From 975aab8009d0f2bf63a17ae837b40c3d37607296 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 25 May 2009 00:54:23 -0400 Subject: [PATCH 084/207] Fixing plugin imports Adding contstructor generation. and test case for controller construction. --- cake/console/libs/tasks/test.php | 91 ++++++++----------- cake/console/libs/templates/objects/test.ctp | 16 +++- .../cases/console/libs/tasks/test.test.php | 18 ++++ 3 files changed, 68 insertions(+), 57 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index a52020968..ae50b9da7 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -143,10 +143,17 @@ class TestTask extends Shell { if (class_exists($fullClassName)) { $methods = $this->getTestableMethods($fullClassName); } + $mock = $this->generateMockClass($type, $fullClassName); + $construction = $this->generateConstructor($type, $fullClassName); + + $plugin = null; + if ($this->plugin) { + $plugin = $this->plugin . '.'; + } $this->Template->set('fixtures', $this->_fixtures); - $this->Template->set('plugin', $this->plugin); - $this->Template->set(compact('className', 'methods', 'type', 'fullClassName')); + $this->Template->set('plugin', $plugin); + $this->Template->set(compact('className', 'methods', 'type', 'fullClassName', 'mock', 'construction')); $out = $this->Template->generate('objects', 'test'); if (strpos($this->path, $type) === false) { @@ -157,58 +164,6 @@ class TestTask extends Shell { return $out; } return false; - - /* - if (!$name) { - return false; - } - - if (!is_array($cases)) { - $cases = array($cases); - } - - if (strpos($this->path, $class) === false) { - $this->filePath = $this->path . 'cases' . DS . Inflector::tableize($class) . DS; - } - - $class = Inflector::classify($class); - $name = Inflector::classify($name); - - $import = $name; - if (isset($this->plugin)) { - $import = $this->plugin . '.' . $name; - } - $extras = $this->__extras($class); - $out = "App::import('$class', '$import');\n"; - if ($class == 'Model') { - $class = null; - } - $out .= "class Test{$name} extends {$name}{$class} {\n"; - $out .= "{$extras}"; - $out .= "}\n\n"; - $out .= "class {$name}{$class}Test extends CakeTestCase {\n"; - $out .= "\n\tfunction startTest() {"; - $out .= "\n\t\t\$this->{$name} = new Test{$name}();"; - $out .= "\n\t}\n"; - $out .= "\n\tfunction test{$name}Instance() {\n"; - $out .= "\t\t\$this->assertTrue(is_a(\$this->{$name}, '{$name}{$class}'));\n\t}\n"; - foreach ($cases as $case) { - $case = Inflector::classify($case); - $out .= "\n\tfunction test{$case}() {\n\n\t}\n"; - } - $out .= "}\n"; - - $this->out("Baking unit test for $name..."); - $this->out($out); - $ok = $this->in(__('Is this correct?', true), array('y', 'n'), 'y'); - if ($ok == 'n') { - return false; - } - - $header = '$Id'; - $content = ""; - return $this->createFile($this->filePath . Inflector::underscore($name) . '.test.php', $content); - */ } /** @@ -277,7 +232,7 @@ class TestTask extends Shell { /** * Construct an instance of the class to be tested. - * So that fixtures and methods can be detected + * So that fixtures can be detected * * @return object **/ @@ -418,6 +373,31 @@ class TestTask extends Shell { return $fixtures; } +/** + * Generate a stub class or mock as needed. + * + * @return void + **/ + function generateMockClass($type, $class) { + return ''; + } + +/** + * Generate a constructor code snippet for the type and classname + * + * @return string Constructor snippet for the thing you are building. + **/ + function generateConstructor($type, $fullClassName) { + $type = strtolower($type); + if ($type == 'model') { + return "ClassRegistry::init('$fullClassName');"; + } + if ($type == 'controller') { + return "new Test$fullClassName();\n\t\t\$this->{$fullClassName}->constructClasses();"; + } + return "new $fullClassName"; + } + /** * Handles the extra stuff needed * @@ -433,6 +413,7 @@ class TestTask extends Shell { } return $extras; } + /** * Create a test for a Model object. * diff --git a/cake/console/libs/templates/objects/test.ctp b/cake/console/libs/templates/objects/test.ctp index 8300c5356..c1b3cc76d 100644 --- a/cake/console/libs/templates/objects/test.ctp +++ b/cake/console/libs/templates/objects/test.ctp @@ -19,14 +19,26 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ echo " -App::import('', ''); +App::import('', ''); -class TestCase extends CakeTestCase { + + +class TestCase extends CakeTestCase { var $fixtures = array(''); + function startTest() { + $this-> + } + + function endTest() { + unset($this->); + ClassRegistry::flush(); + } + function test() { diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 59e947805..3a86100cc 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -289,6 +289,13 @@ class TestTaskTest extends CakeTestCase { $this->assertPattern('/App::import\(\'Model\', \'TestTaskArticle\'\)/', $result); $this->assertPattern('/class TestTaskArticleTestCase extends CakeTestCase/', $result); + + $this->assertPattern('/function startTest\(\)/', $result); + $this->assertPattern("/\\\$this->TestTaskArticle \=\& ClassRegistry::init\('TestTaskArticle'\)/", $result); + + $this->assertPattern('/function endTest\(\)/', $result); + $this->assertPattern('/unset\(\$this->TestTaskArticle\)/', $result); + $this->assertPattern('/function testDoSomething\(\)/', $result); $this->assertPattern('/function testDoSomethingElse\(\)/', $result); @@ -297,5 +304,16 @@ class TestTaskTest extends CakeTestCase { $this->assertPattern("/'app\.test_task_tag'/", $result); $this->assertPattern("/'app\.articles_tag'/", $result); } + +/** + * test Constructor generation ensure that constructClasses is called for controllers + * + * @return void + **/ + function testGenerateContsructor() { + $result = $this->Task->generateConstructor('controller', 'PostsController'); + $expected = "new TestPostsController();\n\t\t\$this->PostsController->constructClasses();"; + $this->assertEqual($result, $expected); + } } ?> \ No newline at end of file From 66b36ba3b8ebb8d329c84ebf08eccdf1d12f3444 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 25 May 2009 01:02:59 -0400 Subject: [PATCH 085/207] Adding tests for other object types. --- cake/console/libs/tasks/test.php | 6 +++--- cake/tests/cases/console/libs/tasks/test.test.php | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index ae50b9da7..f00ac01b5 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -390,12 +390,12 @@ class TestTask extends Shell { function generateConstructor($type, $fullClassName) { $type = strtolower($type); if ($type == 'model') { - return "ClassRegistry::init('$fullClassName');"; + return "ClassRegistry::init('$fullClassName');\n"; } if ($type == 'controller') { - return "new Test$fullClassName();\n\t\t\$this->{$fullClassName}->constructClasses();"; + return "new Test$fullClassName();\n\t\t\$this->{$fullClassName}->constructClasses();\n"; } - return "new $fullClassName"; + return "new $fullClassName()\n"; } /** diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 3a86100cc..e5e513289 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -312,7 +312,15 @@ class TestTaskTest extends CakeTestCase { **/ function testGenerateContsructor() { $result = $this->Task->generateConstructor('controller', 'PostsController'); - $expected = "new TestPostsController();\n\t\t\$this->PostsController->constructClasses();"; + $expected = "new TestPostsController();\n\t\t\$this->PostsController->constructClasses();\n"; + $this->assertEqual($result, $expected); + + $result = $this->Task->generateConstructor('model', 'Post'); + $expected = "ClassRegistry::init('Post');\n"; + $this->assertEqual($result, $expected); + + $result = $this->Task->generateConstructor('helper', 'FormHelper'); + $expected = "new FormHelper()\n"; $this->assertEqual($result, $expected); } } From 877616ad9b229c66381bb5645954e866f520479e Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 25 May 2009 01:19:54 -0400 Subject: [PATCH 086/207] Fixing broken comment. --- cake/console/libs/templates/objects/test.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/console/libs/templates/objects/test.ctp b/cake/console/libs/templates/objects/test.ctp index c1b3cc76d..e06a44eaf 100644 --- a/cake/console/libs/templates/objects/test.ctp +++ b/cake/console/libs/templates/objects/test.ctp @@ -19,7 +19,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ echo " App::import('', ''); From 518c318887485291c54e9c1de9f33dcc22c48321 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 25 May 2009 23:48:41 -0400 Subject: [PATCH 087/207] Adding tests and code for controller stub generation. --- cake/console/libs/tasks/test.php | 12 +++--- cake/console/libs/templates/objects/test.ctp | 10 ++++- .../cases/console/libs/tasks/test.test.php | 42 ++++++++++++++++++- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index f00ac01b5..718eff603 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -143,7 +143,7 @@ class TestTask extends Shell { if (class_exists($fullClassName)) { $methods = $this->getTestableMethods($fullClassName); } - $mock = $this->generateMockClass($type, $fullClassName); + $mock = $this->hasMockClass($type, $fullClassName); $construction = $this->generateConstructor($type, $fullClassName); $plugin = null; @@ -374,12 +374,14 @@ class TestTask extends Shell { } /** - * Generate a stub class or mock as needed. + * Is a mock class required for this type of test? + * Controllers require a mock class. * - * @return void + * @return boolean **/ - function generateMockClass($type, $class) { - return ''; + function hasMockClass($type) { + $type = strtolower($type); + return $type == 'controller'; } /** diff --git a/cake/console/libs/templates/objects/test.ctp b/cake/console/libs/templates/objects/test.ctp index e06a44eaf..b19b89793 100644 --- a/cake/console/libs/templates/objects/test.ctp +++ b/cake/console/libs/templates/objects/test.ctp @@ -23,8 +23,16 @@ echo "/* ". $className ." Test cases generated on: " . date('Y-m-d H:m:s') . " : ?> App::import('', ''); - + +class Test extends { + var $autoRender = false; + function redirect($url, $status = null, $exit = true) { + $this->redirectUrl = $url; + } +} + + class TestCase extends CakeTestCase { var $fixtures = array(''); diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index e5e513289..735cb7082 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -281,7 +281,7 @@ class TestTaskTest extends CakeTestCase { * * @return void **/ - function testBake() { + function testBakeModelTest() { $this->Task->setReturnValue('createFile', true); $this->Task->setReturnValue('isLoadableClass', true); @@ -305,6 +305,36 @@ class TestTaskTest extends CakeTestCase { $this->assertPattern("/'app\.articles_tag'/", $result); } +/** + * test baking controller test files, ensure that the stub class is generated. + * + * @return void + **/ + function testBakeControllerTest() { + $this->Task->setReturnValue('createFile', true); + $this->Task->setReturnValue('isLoadableClass', true); + + $result = $this->Task->bake('Controller', 'TestTaskComments'); + + $this->assertPattern('/App::import\(\'Controller\', \'TestTaskComments\'\)/', $result); + $this->assertPattern('/class TestTaskCommentsControllerTestCase extends CakeTestCase/', $result); + + $this->assertPattern('/class TestTestTaskCommentsController extends TestTaskCommentsController/', $result); + $this->assertPattern('/var \$autoRender = false/', $result); + $this->assertPattern('/function redirect\(\$url, \$status = null, \$exit = true\)/', $result); + + $this->assertPattern('/function startTest\(\)/', $result); + $this->assertPattern("/\\\$this->TestTaskComments \=\& new TestTestTaskCommentsController()/", $result); + + $this->assertPattern('/function endTest\(\)/', $result); + $this->assertPattern('/unset\(\$this->TestTaskComments\)/', $result); + + $this->assertPattern("/'app\.test_task_article'/", $result); + $this->assertPattern("/'plugin\.test_task\.test_task_comment'/", $result); + $this->assertPattern("/'app\.test_task_tag'/", $result); + $this->assertPattern("/'app\.articles_tag'/", $result); + } + /** * test Constructor generation ensure that constructClasses is called for controllers * @@ -323,5 +353,15 @@ class TestTaskTest extends CakeTestCase { $expected = "new FormHelper()\n"; $this->assertEqual($result, $expected); } + +/** + * Test that mock class generation works for the appropriate classes + * + * @return void + **/ + function testMockClassGeneration() { + $result = $this->Task->hasMockClass('controller'); + $this->assertTrue($result); + } } ?> \ No newline at end of file From 79568cc74212d35a4b10d9e7d53a15c8a0cabb7d Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 25 May 2009 23:57:15 -0400 Subject: [PATCH 088/207] Fixing controller test file generation --- cake/console/libs/tasks/test.php | 2 +- cake/tests/cases/console/libs/tasks/test.test.php | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 718eff603..431073986 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -159,7 +159,7 @@ class TestTask extends Shell { if (strpos($this->path, $type) === false) { $this->filePath = $this->path . 'cases' . DS . Inflector::tableize($type) . DS; } - $made = $this->createFile($this->filePath . Inflector::underscore($className) . '.test.php', $out); + $made = $this->createFile($this->filePath . Inflector::underscore($fullClassName) . '.test.php', $out); if ($made) { return $out; } diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 735cb7082..d2f122a94 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -161,13 +161,16 @@ class TestTaskTest extends CakeTestCase { $this->Task->Dispatch->expectNever('stderr'); $this->Task->Dispatch->expectNever('_stop'); - $this->Task->setReturnValueAt(0, 'in', 'y'); + $this->Task->setReturnValue('in', 'y'); $this->Task->expectAt(0, 'createFile', array($file, '*')); $this->Task->bake('Model', 'MyClass'); - $this->Task->setReturnValueAt(1, 'in', 'y'); $this->Task->expectAt(1, 'createFile', array($file, '*')); $this->Task->bake('Model', 'MyClass'); + + $file = TESTS . 'cases' . DS . 'controllers' . DS . 'comments_controller.test.php'; + $this->Task->expectAt(2, 'createFile', array($file, '*')); + $this->Task->bake('Controller', 'Comments'); } /** From fe235f4e943b1adf693e20db91b7fe1d4e1ab325 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 26 May 2009 00:20:17 -0400 Subject: [PATCH 089/207] Tweaking template. --- cake/console/libs/templates/objects/model.ctp | 1 - 1 file changed, 1 deletion(-) diff --git a/cake/console/libs/templates/objects/model.ctp b/cake/console/libs/templates/objects/model.ctp index dadf31f76..849be35b3 100644 --- a/cake/console/libs/templates/objects/model.ctp +++ b/cake/console/libs/templates/objects/model.ctp @@ -21,7 +21,6 @@ */ echo " - class extends AppModel { var $name = ''; From 2b6ea8748c330b059de849f64c613dca3ffb1996 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 26 May 2009 00:36:25 -0400 Subject: [PATCH 090/207] Adding flush so models in registry are always fresh fixes issues baking model + test --- cake/console/libs/tasks/test.php | 1 + .../cases/console/libs/tasks/test.test.php | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/cake/console/libs/tasks/test.php b/cake/console/libs/tasks/test.php index 431073986..fd0efbb12 100644 --- a/cake/console/libs/tasks/test.php +++ b/cake/console/libs/tasks/test.php @@ -237,6 +237,7 @@ class TestTask extends Shell { * @return object **/ function &buildTestSubject($type, $class) { + ClassRegistry::flush(); App::import($type, $class); $class = $this->getRealClassName($type, $class); if (strtolower($type) == 'model') { diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index d2f122a94..6646d6605 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -228,6 +228,30 @@ class TestTaskTest extends CakeTestCase { $this->assertEqual($result, $this->Task->classTypes[1]); } +/** + * creating test subjects should clear the registry so the registry is always fresh + * + * @return void + **/ + function testRegistryClearWhenBuildingTestObjects() { + ClassRegistry::flush(); + $model = ClassRegistry::init('TestTaskComment'); + $model->bindModel(array( + 'belongsTo' => array( + 'Random' => array( + 'className' => 'TestTaskArticle', + 'foreignKey' => 'article_id', + ) + ) + )); + $keys = ClassRegistry::keys(); + $this->assertTrue(in_array('random', $keys)); + $object =& $this->Task->buildTestSubject('Model', 'TestTaskComment'); + + $keys = ClassRegistry::keys(); + $this->assertFalse(in_array('random', $keys)); + } + /** * test that getClassName returns the user choice as a classname. * From b301654b968448865b78da422a4afeadd9d9be16 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 30 May 2009 00:14:57 -0400 Subject: [PATCH 091/207] Adding test cases for execute() --- .../cases/console/libs/tasks/test.test.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cake/tests/cases/console/libs/tasks/test.test.php b/cake/tests/cases/console/libs/tasks/test.test.php index 6646d6605..9dec56987 100644 --- a/cake/tests/cases/console/libs/tasks/test.test.php +++ b/cake/tests/cases/console/libs/tasks/test.test.php @@ -390,5 +390,31 @@ class TestTaskTest extends CakeTestCase { $result = $this->Task->hasMockClass('controller'); $this->assertTrue($result); } + +/** + * test execute with a type defined + * + * @return void + **/ + function testExecuteWithOneArg() { + $this->Task->args[0] = 'Model'; + $this->Task->setReturnValueAt(0, 'in', 'TestTaskTag'); + $this->Task->setReturnValue('isLoadableClass', true); + $this->Task->expectAt(0, 'createFile', array('*', new PatternExpectation('/class TestTaskTagTestCase extends CakeTestCase/'))); + $this->Task->execute(); + } + +/** + * test execute with type and class name defined + * + * @return void + **/ + function testExecuteWithTwoArgs() { + $this->Task->args = array('Model', 'TestTaskTag'); + $this->Task->setReturnValueAt(0, 'in', 'TestTaskTag'); + $this->Task->setReturnValue('isLoadableClass', true); + $this->Task->expectAt(0, 'createFile', array('*', new PatternExpectation('/class TestTaskTagTestCase extends CakeTestCase/'))); + $this->Task->execute(); + } } ?> \ No newline at end of file From f1821f563144d4351beb9708cac72ed4707da246 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 30 May 2009 00:28:18 -0400 Subject: [PATCH 092/207] Adding test case for ViewTask --- .../cases/console/libs/tasks/view.test.php | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 cake/tests/cases/console/libs/tasks/view.test.php diff --git a/cake/tests/cases/console/libs/tasks/view.test.php b/cake/tests/cases/console/libs/tasks/view.test.php new file mode 100644 index 000000000..5acf40f6e --- /dev/null +++ b/cake/tests/cases/console/libs/tasks/view.test.php @@ -0,0 +1,118 @@ +Dispatcher =& new TestTestTaskMockShellDispatcher(); + $this->Dispatcher->shellPaths = Configure::read('shellPaths'); + $this->Task =& new MockViewTask($this->Dispatcher); + $this->Task->Dispatch =& $this->Dispatcher; + $this->Task->Template =& new TemplateTask($this->Dispatcher); + } + +/** + * tearDown method + * + * @return void + * @access public + */ + function endTest() { + ClassRegistry::flush(); + } + +/** + * Test getContent and parsing of Templates. + * + * @return void + **/ + function testGetContent() { + $vars = array( + 'modelClass' => 'TestViewModel', + 'schema' => array(), + 'primaryKey' => 'id', + 'displayField' => 'name', + 'singularVar' => 'testViewModel', + 'pluralVar' => 'testViewModels', + 'singularHumanName' => 'Test View Model', + 'pluralHumanName' => 'Test View Models', + 'fields' => array('id', 'name', 'body'), + 'associations' => array() + ); + $result = $this->Task->getContent('view', $vars); + + $this->assertPattern('/Delete Test View Model/', $result); + $this->assertPattern('/Edit Test View Model/', $result); + $this->assertPattern('/List Test View Models/', $result); + $this->assertPattern('/New Test View Model/', $result); + + $this->assertPattern('/testViewModel\[\'TestViewModel\'\]\[\'id\'\]/', $result); + $this->assertPattern('/testViewModel\[\'TestViewModel\'\]\[\'name\'\]/', $result); + $this->assertPattern('/testViewModel\[\'TestViewModel\'\]\[\'body\'\]/', $result); + } +} +?> \ No newline at end of file From fb2be781f2f513db8594e621597966a88164a198 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 30 May 2009 00:32:57 -0400 Subject: [PATCH 093/207] Refactoring to use TemplateTask --- cake/console/libs/tasks/view.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index b85dac809..054dd978b 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -45,7 +45,7 @@ class ViewTask extends Shell { * @var array * @access public */ - var $tasks = array('Project', 'Controller'); + var $tasks = array('Project', 'Controller', 'Template'); /** * path to VIEWS directory * @@ -175,6 +175,7 @@ class ViewTask extends Shell { } } } + /** * Handles interactive baking * @@ -353,29 +354,21 @@ class ViewTask extends Shell { $action = $template; $template = 'form'; } - $loaded = false; - foreach ($this->Dispatch->shellPaths as $path) { - $templatePath = $path . 'templates' . DS . 'views' . DS .Inflector::underscore($template).'.ctp'; - if (file_exists($templatePath) && is_file($templatePath)) { - $loaded = true; - break; - } - } if (!$vars) { $vars = $this->__loadController(); } - if ($loaded) { - extract($vars); - ob_start(); - ob_implicit_flush(0); - include($templatePath); - $content = ob_get_clean(); - return $content; + + $this->Template->set($vars); + $output = $this->Template->generate('views', $template); + + if (!empty($output)) { + return $output; } $this->hr(); $this->err(sprintf(__('Template for %s could not be found', true), $template)); return false; } + /** * Displays help contents * From 9967b10b58cb9bfb6cb7cd0c046ca45231eecd2a Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 30 May 2009 00:34:45 -0400 Subject: [PATCH 094/207] Removing dead options. --- cake/console/libs/tasks/view.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index 054dd978b..8c5564697 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -191,25 +191,25 @@ class ViewTask extends Shell { $this->controllerName = $this->Controller->getName(); - $this->controllerPath = low(Inflector::underscore($this->controllerName)); + $this->controllerPath = strtolower(Inflector::underscore($this->controllerName)); $interactive = $this->in("Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite {$this->controllerName} views if it exist.", array('y','n'), 'y'); - if (low($interactive) == 'y' || low($interactive) == 'yes') { + if (strtolower($interactive) == 'y') { $this->interactive = true; $wannaDoScaffold = $this->in("Would you like to create some scaffolded views (index, add, view, edit) for this controller?\nNOTE: Before doing so, you'll need to create your controller and model classes (including associated models).", array('y','n'), 'n'); } - if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') { + if (strtolower($wannaDoScaffold) == 'y') { $wannaDoAdmin = $this->in("Would you like to create the views for admin routing?", array('y','n'), 'y'); } $admin = false; - if ((low($wannaDoAdmin) == 'y' || low($wannaDoAdmin) == 'yes')) { + if (strtolower($wannaDoAdmin) == 'y') { $admin = $this->getAdmin(); } - if (low($wannaDoScaffold) == 'y' || low($wannaDoScaffold) == 'yes') { + if (strtolower($wannaDoScaffold) == 'y') { $actions = $this->scaffoldActions; if ($admin) { foreach ($actions as $action) { From 03e7ca71b6ed8ffd019ee37f7d1f31097b63f159 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 30 May 2009 00:46:25 -0400 Subject: [PATCH 095/207] Reformatting help() --- cake/console/libs/tasks/fixture.php | 6 +++--- cake/console/libs/tasks/view.php | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/cake/console/libs/tasks/fixture.php b/cake/console/libs/tasks/fixture.php index ec1bc7240..056297041 100644 --- a/cake/console/libs/tasks/fixture.php +++ b/cake/console/libs/tasks/fixture.php @@ -338,9 +338,9 @@ class FixtureTask extends Shell { $this->out("\nfixture all\n\tbakes all fixtures."); $this->out(""); $this->out('Parameters:'); - $this->out("\t-count The number of records to include in the fixture(s)."); - $this->out("\t-connection Which database configuration to use for baking."); - $this->out("\t-plugin lowercased_underscored name of plugin to bake fixtures for."); + $this->out("\t-count The number of records to include in the fixture(s)."); + $this->out("\t-connection Which database configuration to use for baking."); + $this->out("\t-plugin lowercased_underscored name of plugin to bake fixtures for."); $this->out(""); $this->_stop(); } diff --git a/cake/console/libs/tasks/view.php b/cake/console/libs/tasks/view.php index 8c5564697..438818885 100644 --- a/cake/console/libs/tasks/view.php +++ b/cake/console/libs/tasks/view.php @@ -379,9 +379,19 @@ class ViewTask extends Shell { $this->out("Usage: cake bake view ..."); $this->hr(); $this->out('Commands:'); - $this->out("\n\tview \n\t\twill read the given controller for methods\n\t\tand bake corresponding views.\n\t\tIf var scaffold is found it will bake the scaffolded actions\n\t\t(index,view,add,edit)"); - $this->out("\n\tview \n\t\twill bake a template. core templates: (index, add, edit, view)"); - $this->out("\n\tview