Upgrade CakePHP from 2.2.5 to 2.9.5

This commit is contained in:
Brm Ko 2017-02-26 15:29:44 +01:00
parent 5a580df460
commit 235a541597
793 changed files with 60746 additions and 23753 deletions

View file

@ -2,18 +2,17 @@
/**
* Base class for Bake Tasks.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc.
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.3
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -42,7 +41,7 @@ class BakeTask extends AppShell {
/**
* Flag for interactive mode
*
* @var boolean
* @var bool
*/
public $interactive = false;
@ -59,7 +58,7 @@ class BakeTask extends AppShell {
}
/**
* Gets the path for output. Checks the plugin property
* Gets the path for output. Checks the plugin property
* and returns the correct path.
*
* @return string Path to output.

View file

@ -0,0 +1,183 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 2.5
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
/**
* Base class for Shell Command reflection.
*
* @package Cake.Console.Command.Task
*/
class CommandTask extends AppShell {
/**
* Gets the shell command listing.
*
* @return array
*/
public function getShellList() {
$skipFiles = array('AppShell');
$plugins = CakePlugin::loaded();
$shellList = array_fill_keys($plugins, null) + array('CORE' => null, 'app' => null);
$corePath = App::core('Console/Command');
$shells = App::objects('file', $corePath[0]);
$shells = array_diff($shells, $skipFiles);
$this->_appendShells('CORE', $shells, $shellList);
$appShells = App::objects('Console/Command', null, false);
$appShells = array_diff($appShells, $shells, $skipFiles);
$this->_appendShells('app', $appShells, $shellList);
foreach ($plugins as $plugin) {
$pluginShells = App::objects($plugin . '.Console/Command');
$this->_appendShells($plugin, $pluginShells, $shellList);
}
return array_filter($shellList);
}
/**
* Scan the provided paths for shells, and append them into $shellList
*
* @param string $type The type of object.
* @param array $shells The shell name.
* @param array &$shellList List of shells.
* @return void
*/
protected function _appendShells($type, $shells, &$shellList) {
foreach ($shells as $shell) {
$shellList[$type][] = Inflector::underscore(str_replace('Shell', '', $shell));
}
}
/**
* Return a list of all commands
*
* @return array
*/
public function commands() {
$shellList = $this->getShellList();
$options = array();
foreach ($shellList as $type => $commands) {
$prefix = '';
if (!in_array(strtolower($type), array('app', 'core'))) {
$prefix = $type . '.';
}
foreach ($commands as $shell) {
$options[] = $prefix . $shell;
}
}
return $options;
}
/**
* Return a list of subcommands for a given command
*
* @param string $commandName The command you want subcommands from.
* @return array
*/
public function subCommands($commandName) {
$Shell = $this->getShell($commandName);
if (!$Shell) {
return array();
}
$taskMap = TaskCollection::normalizeObjectArray((array)$Shell->tasks);
$return = array_keys($taskMap);
$return = array_map('Inflector::underscore', $return);
$ShellReflection = new ReflectionClass('AppShell');
$shellMethods = $ShellReflection->getMethods(ReflectionMethod::IS_PUBLIC);
$shellMethodNames = array('main', 'help');
foreach ($shellMethods as $method) {
$shellMethodNames[] = $method->getName();
}
$Reflection = new ReflectionClass($Shell);
$methods = $Reflection->getMethods(ReflectionMethod::IS_PUBLIC);
$methodNames = array();
foreach ($methods as $method) {
$methodNames[] = $method->getName();
}
$return += array_diff($methodNames, $shellMethodNames);
sort($return);
return $return;
}
/**
* Get Shell instance for the given command
*
* @param mixed $commandName The command you want.
* @return mixed
*/
public function getShell($commandName) {
list($pluginDot, $name) = pluginSplit($commandName, true);
if (in_array(strtolower($pluginDot), array('app.', 'core.'))) {
$commandName = $name;
$pluginDot = '';
}
if (!in_array($commandName, $this->commands())) {
return false;
}
$name = Inflector::camelize($name);
$pluginDot = Inflector::camelize($pluginDot);
$class = $name . 'Shell';
App::uses($class, $pluginDot . 'Console/Command');
$Shell = new $class();
$Shell->plugin = trim($pluginDot, '.');
$Shell->initialize();
return $Shell;
}
/**
* Get Shell instance for the given command
*
* @param mixed $commandName The command to get options for.
* @return array
*/
public function options($commandName) {
$Shell = $this->getShell($commandName);
if (!$Shell) {
$parser = new ConsoleOptionParser();
} else {
$parser = $Shell->getOptionParser();
}
$options = array();
$array = $parser->options();
foreach ($array as $name => $obj) {
$options[] = "--$name";
$short = $obj->short();
if ($short) {
$options[] = "-$short";
}
}
return $options;
}
}

View file

@ -2,18 +2,17 @@
/**
* The ControllerTask handles creating and updating controller files.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc.
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -65,7 +64,7 @@ class ControllerTask extends BakeTask {
if (!isset($this->connection)) {
$this->connection = 'default';
}
if (strtolower($this->args[0]) == 'all') {
if (strtolower($this->args[0]) === 'all') {
return $this->all();
}
@ -96,7 +95,7 @@ class ControllerTask extends BakeTask {
}
/**
* Bake All the controllers at once. Will only bake controllers for models that exist.
* Bake All the controllers at once. Will only bake controllers for models that exist.
*
* @return void
*/
@ -105,17 +104,33 @@ class ControllerTask extends BakeTask {
$this->listAll($this->connection, false);
ClassRegistry::config('Model', array('ds' => $this->connection));
$unitTestExists = $this->_checkUnitTest();
$admin = false;
if (!empty($this->params['admin'])) {
$admin = $this->Project->getPrefix();
}
$controllersCreated = 0;
foreach ($this->__tables as $table) {
$model = $this->_modelName($table);
$controller = $this->_controllerName($model);
App::uses($model, 'Model');
if (class_exists($model)) {
$actions = $this->bakeActions($controller);
if ($admin) {
$this->out(__d('cake_console', 'Adding %s methods', $admin));
$actions .= "\n" . $this->bakeActions($controller, $admin);
}
if ($this->bake($controller, $actions) && $unitTestExists) {
$this->bakeTest($controller);
}
$controllersCreated++;
}
}
if (!$controllersCreated) {
$this->out(__d('cake_console', 'No Controllers were baked, Models need to exist before Controllers can be baked.'));
}
}
/**
@ -151,13 +166,13 @@ class ControllerTask extends BakeTask {
}
$doItInteractive = $this->in(implode("\n", $question), array('y', 'n'), 'y');
if (strtolower($doItInteractive) == 'y') {
if (strtolower($doItInteractive) === 'y') {
$this->interactive = true;
$useDynamicScaffold = $this->in(
__d('cake_console', "Would you like to use dynamic scaffolding?"), array('y', 'n'), 'n'
);
if (strtolower($useDynamicScaffold) == 'y') {
if (strtolower($useDynamicScaffold) === 'y') {
$wannaBakeCrud = 'n';
$actions = 'scaffold';
} else {
@ -167,27 +182,32 @@ class ControllerTask extends BakeTask {
$components = $this->doComponents();
$wannaUseSession = $this->in(
__d('cake_console', "Would you like to use Session flash messages?"), array('y','n'), 'y'
__d('cake_console', "Would you like to use the FlashComponent to display flash messages?"), array('y', 'n'), 'y'
);
if (strtolower($wannaUseSession) === 'y') {
array_push($components, 'Session', 'Flash');
}
array_unique($components);
}
} else {
list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods();
}
if (strtolower($wannaBakeCrud) == 'y') {
$actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) == 'y');
if (strtolower($wannaBakeCrud) === 'y') {
$actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) === 'y');
}
if (strtolower($wannaBakeAdminCrud) == 'y') {
if (strtolower($wannaBakeAdminCrud) === 'y') {
$admin = $this->Project->getPrefix();
$actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) == 'y');
$actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) === 'y');
}
$baked = false;
if ($this->interactive === true) {
$this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components);
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y','n'), 'y');
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
if (strtolower($looksGood) == 'y') {
if (strtolower($looksGood) === 'y') {
$baked = $this->bake($controllerName, $actions, $helpers, $components);
if ($baked && $this->_checkUnitTest()) {
$this->bakeTest($controllerName);
@ -205,10 +225,10 @@ class ControllerTask extends BakeTask {
/**
* Confirm a to be baked controller with the user
*
* @param string $controllerName
* @param string $useDynamicScaffold
* @param array $helpers
* @param array $components
* @param string $controllerName The name of the controller.
* @param string $useDynamicScaffold Whether or not to use dynamic scaffolds.
* @param array $helpers The list of helpers to include.
* @param array $components The list of components to include.
* @return void
*/
public function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) {
@ -218,7 +238,7 @@ class ControllerTask extends BakeTask {
$this->hr();
$this->out(__d('cake_console', "Controller Name:\n\t%s", $controllerName));
if (strtolower($useDynamicScaffold) == 'y') {
if (strtolower($useDynamicScaffold) === 'y') {
$this->out("public \$scaffold;");
}
@ -228,10 +248,10 @@ class ControllerTask extends BakeTask {
);
foreach ($properties as $var => $title) {
if (count($$var)) {
if (count(${$var})) {
$output = '';
$length = count($$var);
foreach ($$var as $i => $propElement) {
$length = count(${$var});
foreach (${$var} as $i => $propElement) {
if ($i != $length - 1) {
$output .= ucfirst($propElement) . ', ';
} else {
@ -252,11 +272,11 @@ class ControllerTask extends BakeTask {
protected function _askAboutMethods() {
$wannaBakeCrud = $this->in(
__d('cake_console', "Would you like to create some basic class methods \n(index(), add(), view(), edit())?"),
array('y','n'), 'n'
array('y', 'n'), 'n'
);
$wannaBakeAdminCrud = $this->in(
__d('cake_console', "Would you like to create the basic class methods for admin routing?"),
array('y','n'), 'n'
array('y', 'n'), 'n'
);
return array($wannaBakeCrud, $wannaBakeAdminCrud);
}
@ -266,7 +286,7 @@ class ControllerTask extends BakeTask {
*
* @param string $controllerName Controller name
* @param string $admin Admin route to use
* @param boolean $wannaUseSession Set to true to use sessions, false otherwise
* @param bool $wannaUseSession Set to true to use sessions, false otherwise
* @return string Baked actions
*/
public function bakeActions($controllerName, $admin = null, $wannaUseSession = true) {
@ -278,7 +298,7 @@ class ControllerTask extends BakeTask {
App::uses($modelImport, $plugin . 'Model');
if (!class_exists($modelImport)) {
$this->err(__d('cake_console', 'You must have a model for this class to build basic methods. Please try again.'));
$this->_stop();
return $this->_stop();
}
$modelObj = ClassRegistry::init($currentModelName);
@ -317,6 +337,11 @@ class ControllerTask extends BakeTask {
'plugin' => $this->plugin,
'pluginPath' => empty($this->plugin) ? '' : $this->plugin . '.'
));
if (!in_array('Paginator', (array)$components)) {
$components[] = 'Paginator';
}
$this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'isScaffold'));
$contents = $this->Template->generate('classes', 'controller');
@ -349,7 +374,7 @@ class ControllerTask extends BakeTask {
public function doHelpers() {
return $this->_doPropertyChoices(
__d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"),
__d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'")
__d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Text, Js, Time'")
);
}
@ -359,10 +384,11 @@ class ControllerTask extends BakeTask {
* @return array Components the user wants to use.
*/
public function doComponents() {
return $this->_doPropertyChoices(
__d('cake_console', "Would you like this controller to use any components?"),
$components = array('Paginator');
return array_merge($components, $this->_doPropertyChoices(
__d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent?"),
__d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
);
));
}
/**
@ -373,9 +399,9 @@ class ControllerTask extends BakeTask {
* @return array Array of values for property.
*/
protected function _doPropertyChoices($prompt, $example) {
$proceed = $this->in($prompt, array('y','n'), 'n');
$proceed = $this->in($prompt, array('y', 'n'), 'n');
$property = array();
if (strtolower($proceed) == 'y') {
if (strtolower($proceed) === 'y') {
$propertyList = $this->in($example);
$propertyListTrimmed = str_replace(' ', '', $propertyList);
$property = explode(',', $propertyListTrimmed);
@ -390,12 +416,12 @@ class ControllerTask extends BakeTask {
* @return array Set of controllers
*/
public function listAll($useDbConfig = null) {
if (is_null($useDbConfig)) {
if ($useDbConfig === null) {
$useDbConfig = $this->connection;
}
$this->__tables = $this->Model->getAllTables($useDbConfig);
if ($this->interactive == true) {
if ($this->interactive) {
$this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
$this->hr();
$this->_controllerNames = array();
@ -419,21 +445,21 @@ class ControllerTask extends BakeTask {
$controllers = $this->listAll($useDbConfig);
$enteredController = '';
while ($enteredController == '') {
while (!$enteredController) {
$enteredController = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit"), null, 'q');
if ($enteredController === 'q') {
$this->out(__d('cake_console', 'Exit'));
return $this->_stop();
}
if ($enteredController == '' || intval($enteredController) > count($controllers)) {
if (!$enteredController || (int)$enteredController > count($controllers)) {
$this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
$enteredController = '';
}
}
if (intval($enteredController) > 0 && intval($enteredController) <= count($controllers) ) {
$controllerName = $controllers[intval($enteredController) - 1];
if ((int)$enteredController > 0 && (int)$enteredController <= count($controllers)) {
$controllerName = $controllers[(int)$enteredController - 1];
} else {
$controllerName = Inflector::camelize($enteredController);
}
@ -441,31 +467,42 @@ class ControllerTask extends BakeTask {
}
/**
* get the option parser.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
__d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.')
))->addOption('public', array(
'help' => __d('cake_console', 'Bake a controller with basic crud actions (index, view, add, edit, delete).'),
'boolean' => true
))->addOption('admin', array(
'help' => __d('cake_console', 'Bake a controller with crud actions for one of the Routing.prefixes.'),
'boolean' => true
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'Plugin to bake the controller into.')
))->addOption('connection', array(
'short' => 'c',
'help' => __d('cake_console', 'The connection the controller\'s model is on.')
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake all controllers with CRUD methods.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
$parser->description(
__d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.'
))->addArgument('name', array(
'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.')
))->addOption('public', array(
'help' => __d('cake_console', 'Bake a controller with basic crud actions (index, view, add, edit, delete).'),
'boolean' => true
))->addOption('admin', array(
'help' => __d('cake_console', 'Bake a controller with crud actions for one of the Routing.prefixes.'),
'boolean' => true
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'Plugin to bake the controller into.')
))->addOption('connection', array(
'short' => 'c',
'help' => __d('cake_console', 'The connection the controller\'s model is on.')
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('force', array(
'short' => 'f',
'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake all controllers with CRUD methods.')
))->epilog(
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
);
return $parser;
}
}

View file

@ -2,18 +2,17 @@
/**
* The DbConfig Task handles creating and updating the database.php
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -76,7 +75,7 @@ class DbConfigTask extends AppShell {
public function execute() {
if (empty($this->args)) {
$this->_interactive();
$this->_stop();
return $this->_stop();
}
}
@ -92,10 +91,10 @@ class DbConfigTask extends AppShell {
$done = false;
$dbConfigs = array();
while ($done == false) {
while (!$done) {
$name = '';
while ($name == '') {
while (!$name) {
$name = $this->in(__d('cake_console', "Name:"), null, 'default');
if (preg_match('/[^a-z0-9_]/i', $name)) {
$name = '';
@ -109,85 +108,85 @@ class DbConfigTask extends AppShell {
$datasource = $this->in(__d('cake_console', 'Datasource:'), array('Mysql', 'Postgres', 'Sqlite', 'Sqlserver'), 'Mysql');
$persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n');
if (strtolower($persistent) == 'n') {
if (strtolower($persistent) === 'n') {
$persistent = 'false';
} else {
$persistent = 'true';
}
$host = '';
while ($host == '') {
while (!$host) {
$host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost');
}
$port = '';
while ($port == '') {
while (!$port) {
$port = $this->in(__d('cake_console', 'Port?'), null, 'n');
}
if (strtolower($port) == 'n') {
if (strtolower($port) === 'n') {
$port = null;
}
$login = '';
while ($login == '') {
while (!$login) {
$login = $this->in(__d('cake_console', 'User:'), null, 'root');
}
$password = '';
$blankPassword = false;
while ($password == '' && $blankPassword == false) {
while (!$password && !$blankPassword) {
$password = $this->in(__d('cake_console', 'Password:'));
if ($password == '') {
if (!$password) {
$blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n');
if ($blank == 'y') {
if ($blank === 'y') {
$blankPassword = true;
}
}
}
$database = '';
while ($database == '') {
while (!$database) {
$database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake');
}
$prefix = '';
while ($prefix == '') {
while (!$prefix) {
$prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n');
}
if (strtolower($prefix) == 'n') {
if (strtolower($prefix) === 'n') {
$prefix = null;
}
$encoding = '';
while ($encoding == '') {
while (!$encoding) {
$encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n');
}
if (strtolower($encoding) == 'n') {
if (strtolower($encoding) === 'n') {
$encoding = null;
}
$schema = '';
if ($datasource == 'postgres') {
while ($schema == '') {
if ($datasource === 'postgres') {
while (!$schema) {
$schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n');
}
}
if (strtolower($schema) == 'n') {
if (strtolower($schema) === 'n') {
$schema = null;
}
$config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema');
while ($this->_verify($config) == false) {
while (!$this->_verify($config)) {
$this->_interactive();
}
$dbConfigs[] = $config;
$doneYet = $this->in(__d('cake_console', 'Do you wish to add another database configuration?'), null, 'n');
if (strtolower($doneYet == 'n')) {
if (strtolower($doneYet === 'n')) {
$done = true;
}
}
@ -200,18 +199,18 @@ class DbConfigTask extends AppShell {
/**
* Output verification message and bake if it looks good
*
* @param array $config
* @return boolean True if user says it looks good, false otherwise
* @param array $config The config data.
* @return bool True if user says it looks good, false otherwise
*/
protected function _verify($config) {
$config = array_merge($this->_defaultConfig, $config);
$config += $this->_defaultConfig;
extract($config);
$this->out();
$this->hr();
$this->out(__d('cake_console', 'The following database configuration will be created:'));
$this->hr();
$this->out(__d('cake_console', "Name: %s", $name));
$this->out(__d('cake_console', "Datasource: %s", $datasource));
$this->out(__d('cake_console', "Datasource: %s", $datasource));
$this->out(__d('cake_console', "Persistent: %s", $persistent));
$this->out(__d('cake_console', "Host: %s", $host));
@ -238,7 +237,7 @@ class DbConfigTask extends AppShell {
$this->hr();
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
if (strtolower($looksGood) == 'y') {
if (strtolower($looksGood) === 'y') {
return $config;
}
return false;
@ -248,7 +247,7 @@ class DbConfigTask extends AppShell {
* Assembles and writes database.php
*
* @param array $configs Configuration settings to use
* @return boolean Success
* @return bool Success
*/
public function bake($configs) {
if (!is_dir($this->path)) {
@ -265,7 +264,7 @@ class DbConfigTask extends AppShell {
$temp = get_class_vars(get_class($db));
foreach ($temp as $configName => $info) {
$info = array_merge($this->_defaultConfig, $info);
$info += $this->_defaultConfig;
if (!isset($info['schema'])) {
$info['schema'] = null;
@ -277,11 +276,7 @@ class DbConfigTask extends AppShell {
$info['port'] = null;
}
if ($info['persistent'] === false) {
$info['persistent'] = 'false';
} else {
$info['persistent'] = ($info['persistent'] == true) ? 'true' : 'false';
}
$info['persistent'] = var_export((bool)$info['persistent'], true);
$oldConfigs[] = array(
'name' => $configName,
@ -300,8 +295,8 @@ class DbConfigTask extends AppShell {
}
foreach ($oldConfigs as $key => $oldConfig) {
foreach ($configs as $k => $config) {
if ($oldConfig['name'] == $config['name']) {
foreach ($configs as $config) {
if ($oldConfig['name'] === $config['name']) {
unset($oldConfigs[$key]);
}
}
@ -312,7 +307,7 @@ class DbConfigTask extends AppShell {
$out .= "class DATABASE_CONFIG {\n\n";
foreach ($configs as $config) {
$config = array_merge($this->_defaultConfig, $config);
$config += $this->_defaultConfig;
extract($config);
if (strpos($datasource, 'Database/') === false) {
@ -373,15 +368,18 @@ class DbConfigTask extends AppShell {
}
/**
* get the option parser
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
__d('cake_console', 'Bake new database configuration settings.')
);
$parser->description(
__d('cake_console', 'Bake new database configuration settings.')
);
return $parser;
}
}

View file

@ -2,18 +2,17 @@
/**
* Language string extractor
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2.0.5012
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -43,9 +42,9 @@ class ExtractTask extends AppShell {
protected $_files = array();
/**
* Merge all domains string into the default.pot file
* Merge all domain and category strings into the default.pot file
*
* @var boolean
* @var bool
*/
protected $_merge = false;
@ -71,7 +70,7 @@ class ExtractTask extends AppShell {
protected $_tokens = array();
/**
* Extracted strings indexed by domain.
* Extracted strings indexed by category, domain, msgid and context.
*
* @var array
*/
@ -94,21 +93,21 @@ class ExtractTask extends AppShell {
/**
* Holds whether this call should extract model validation messages
*
* @var boolean
* @var bool
*/
protected $_extractValidation = true;
/**
* Holds the validation string domain to use for validation messages when extracting
*
* @var boolean
* @var bool
*/
protected $_validationDomain = 'default';
/**
* Holds whether this call should extract the CakePHP Lib messages
*
* @var boolean
* @var bool
*/
protected $_extractCore = false;
@ -128,7 +127,7 @@ class ExtractTask extends AppShell {
);
$response = $this->in($message, null, $defaultPath);
if (strtoupper($response) === 'Q') {
$this->out(__d('cake_console', 'Extract Aborted'));
$this->err(__d('cake_console', 'Extract Aborted'));
return $this->_stop();
} elseif (strtoupper($response) === 'D' && count($this->_paths)) {
$this->out();
@ -152,7 +151,7 @@ class ExtractTask extends AppShell {
*/
public function execute() {
if (!empty($this->params['exclude'])) {
$this->_exclude = explode(',', $this->params['exclude']);
$this->_exclude = explode(',', str_replace('/', DS, $this->params['exclude']));
}
if (isset($this->params['files']) && !is_array($this->params['files'])) {
$this->_files = explode(',', $this->params['files']);
@ -177,14 +176,6 @@ class ExtractTask extends AppShell {
$this->_extractCore = strtolower($response) === 'y';
}
if ($this->_extractCore) {
$this->_paths[] = CAKE;
$this->_exclude = array_merge($this->_exclude, array(
CAKE . 'Test',
CAKE . 'Console' . DS . 'Templates'
));
}
if (!empty($this->params['exclude-plugins']) && $this->_isExtractingApp()) {
$this->_exclude = array_merge($this->_exclude, App::path('plugins'));
}
@ -196,6 +187,14 @@ class ExtractTask extends AppShell {
$this->_validationDomain = $this->params['validation-domain'];
}
if ($this->_extractCore) {
$this->_paths[] = CAKE;
$this->_exclude = array_merge($this->_exclude, array(
CAKE . 'Test',
CAKE . 'Console' . DS . 'Templates'
));
}
if (isset($this->params['output'])) {
$this->_output = $this->params['output'];
} elseif (isset($this->params['plugin'])) {
@ -205,9 +204,9 @@ class ExtractTask extends AppShell {
while (true) {
$response = $this->in($message, null, rtrim($this->_paths[0], DS) . DS . 'Locale');
if (strtoupper($response) === 'Q') {
$this->out(__d('cake_console', 'Extract Aborted'));
$this->_stop();
} elseif (is_dir($response)) {
$this->err(__d('cake_console', 'Extract Aborted'));
return $this->_stop();
} elseif ($this->_isPathUsable($response)) {
$this->_output = $response . DS;
break;
} else {
@ -221,14 +220,20 @@ class ExtractTask extends AppShell {
$this->_merge = !(strtolower($this->params['merge']) === 'no');
} else {
$this->out();
$response = $this->in(__d('cake_console', 'Would you like to merge all domains strings into the default.pot file?'), array('y', 'n'), 'n');
$response = $this->in(__d('cake_console', 'Would you like to merge all domain and category strings into the default.pot file?'), array('y', 'n'), 'n');
$this->_merge = strtolower($response) === 'y';
}
if (empty($this->_files)) {
$this->_searchFiles();
}
$this->_output = rtrim($this->_output, DS) . DS;
if (!$this->_isPathUsable($this->_output)) {
$this->err(__d('cake_console', 'The output directory %s was not found or writable.', $this->_output));
return $this->_stop();
}
$this->_extract();
}
@ -237,27 +242,33 @@ class ExtractTask extends AppShell {
*
* Takes care of duplicate translations
*
* @param string $domain
* @param string $msgid
* @param array $details
* @param string $category The category
* @param string $domain The domain
* @param string $msgid The message string
* @param array $details The file and line references
* @return void
*/
protected function _addTranslation($domain, $msgid, $details = array()) {
if (empty($this->_translations[$domain][$msgid])) {
$this->_translations[$domain][$msgid] = array(
'msgid_plural' => false
);
protected function _addTranslation($category, $domain, $msgid, $details = array()) {
$context = '';
if (isset($details['msgctxt'])) {
$context = $details['msgctxt'];
}
if (empty($this->_translations[$category][$domain][$msgid][$context])) {
$this->_translations[$category][$domain][$msgid][$context] = array(
'msgid_plural' => false,
);
}
if (isset($details['msgid_plural'])) {
$this->_translations[$domain][$msgid]['msgid_plural'] = $details['msgid_plural'];
$this->_translations[$category][$domain][$msgid][$context]['msgid_plural'] = $details['msgid_plural'];
}
if (isset($details['file'])) {
$line = 0;
if (isset($details['line'])) {
$line = $details['line'];
}
$this->_translations[$domain][$msgid]['references'][$details['file']][] = $line;
$this->_translations[$category][$domain][$msgid][$context]['references'][$details['file']][] = $line;
}
}
@ -289,52 +300,59 @@ class ExtractTask extends AppShell {
}
/**
* Get & configure the option parser
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(__d('cake_console', 'CakePHP Language String Extraction:'))
->addOption('app', array('help' => __d('cake_console', 'Directory where your application is located.')))
->addOption('paths', array('help' => __d('cake_console', 'Comma separated list of paths.')))
->addOption('merge', array(
'help' => __d('cake_console', 'Merge all domain strings into the default.po file.'),
'choices' => array('yes', 'no')
))
->addOption('output', array('help' => __d('cake_console', 'Full path to output directory.')))
->addOption('files', array('help' => __d('cake_console', 'Comma separated list of files.')))
->addOption('exclude-plugins', array(
'boolean' => true,
'default' => true,
'help' => __d('cake_console', 'Ignores all files in plugins if this command is run inside from the same app directory.')
))
->addOption('plugin', array(
'help' => __d('cake_console', 'Extracts tokens only from the plugin specified and puts the result in the plugin\'s Locale directory.')
))
->addOption('ignore-model-validation', array(
'boolean' => true,
'default' => false,
'help' => __d('cake_console', 'Ignores validation messages in the $validate property.' .
' If this flag is not set and the command is run from the same app directory,' .
' all messages in model validation rules will be extracted as tokens.')
))
->addOption('validation-domain', array(
'help' => __d('cake_console', 'If set to a value, the localization domain to be used for model validation messages.')
))
->addOption('exclude', array(
'help' => __d('cake_console', 'Comma separated list of directories to exclude.' .
' Any path containing a path segment with the provided values will be skipped. E.g. test,vendors')
))
->addOption('overwrite', array(
'boolean' => true,
'default' => false,
'help' => __d('cake_console', 'Always overwrite existing .pot files.')
))
->addOption('extract-core', array(
'help' => __d('cake_console', 'Extract messages from the CakePHP core libs.'),
'choices' => array('yes', 'no')
));
$parser->description(
__d('cake_console', 'CakePHP Language String Extraction:')
)->addOption('app', array(
'help' => __d('cake_console', 'Directory where your application is located.')
))->addOption('paths', array(
'help' => __d('cake_console', 'Comma separated list of paths.')
))->addOption('merge', array(
'help' => __d('cake_console', 'Merge all domain and category strings into the default.po file.'),
'choices' => array('yes', 'no')
))->addOption('no-location', array(
'boolean' => true,
'default' => false,
'help' => __d('cake_console', 'Do not write lines with locations'),
))->addOption('output', array(
'help' => __d('cake_console', 'Full path to output directory.')
))->addOption('files', array(
'help' => __d('cake_console', 'Comma separated list of files.')
))->addOption('exclude-plugins', array(
'boolean' => true,
'default' => true,
'help' => __d('cake_console', 'Ignores all files in plugins if this command is run inside from the same app directory.')
))->addOption('plugin', array(
'help' => __d('cake_console', 'Extracts tokens only from the plugin specified and puts the result in the plugin\'s Locale directory.')
))->addOption('ignore-model-validation', array(
'boolean' => true,
'default' => false,
'help' => __d('cake_console', 'Ignores validation messages in the $validate property.' .
' If this flag is not set and the command is run from the same app directory,' .
' all messages in model validation rules will be extracted as tokens.'
)
))->addOption('validation-domain', array(
'help' => __d('cake_console', 'If set to a value, the localization domain to be used for model validation messages.')
))->addOption('exclude', array(
'help' => __d('cake_console', 'Comma separated list of directories to exclude.' .
' Any path containing a path segment with the provided values will be skipped. E.g. test,vendors'
)
))->addOption('overwrite', array(
'boolean' => true,
'default' => false,
'help' => __d('cake_console', 'Always overwrite existing .pot files.')
))->addOption('extract-core', array(
'help' => __d('cake_console', 'Extract messages from the CakePHP core libs.'),
'choices' => array('yes', 'no')
));
return $parser;
}
/**
@ -345,14 +363,14 @@ class ExtractTask extends AppShell {
protected function _extractTokens() {
foreach ($this->_files as $file) {
$this->_file = $file;
$this->out(__d('cake_console', 'Processing %s...', $file));
$this->out(__d('cake_console', 'Processing %s...', $file), 1, Shell::VERBOSE);
$code = file_get_contents($file);
$allTokens = token_get_all($code);
$this->_tokens = array();
foreach ($allTokens as $token) {
if (!is_array($token) || ($token[0] != T_WHITESPACE && $token[0] != T_INLINE_HTML)) {
if (!is_array($token) || ($token[0] !== T_WHITESPACE && $token[0] !== T_INLINE_HTML)) {
$this->_tokens[] = $token;
}
}
@ -360,10 +378,19 @@ class ExtractTask extends AppShell {
$this->_parse('__', array('singular'));
$this->_parse('__n', array('singular', 'plural'));
$this->_parse('__d', array('domain', 'singular'));
$this->_parse('__c', array('singular'));
$this->_parse('__dc', array('domain', 'singular'));
$this->_parse('__c', array('singular', 'category'));
$this->_parse('__dc', array('domain', 'singular', 'category'));
$this->_parse('__dn', array('domain', 'singular', 'plural'));
$this->_parse('__dcn', array('domain', 'singular', 'plural'));
$this->_parse('__dcn', array('domain', 'singular', 'plural', 'count', 'category'));
$this->_parse('__x', array('context', 'singular'));
$this->_parse('__xn', array('context', 'singular', 'plural'));
$this->_parse('__dx', array('domain', 'context', 'singular'));
$this->_parse('__dxc', array('domain', 'context', 'singular', 'category'));
$this->_parse('__dxn', array('domain', 'context', 'singular', 'plural'));
$this->_parse('__dxcn', array('domain', 'context', 'singular', 'plural', 'count', 'category'));
$this->_parse('__xc', array('context', 'singular', 'category'));
}
}
@ -371,11 +398,12 @@ class ExtractTask extends AppShell {
* Parse tokens
*
* @param string $functionName Function name that indicates translatable string (e.g: '__')
* @param array $map Array containing what variables it will find (e.g: domain, singular, plural)
* @param array $map Array containing what variables it will find (e.g: category, domain, singular, plural)
* @return void
*/
protected function _parse($functionName, $map) {
$count = 0;
$categories = array('LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME', 'LC_MESSAGES');
$tokenCount = count($this->_tokens);
while (($tokenCount - $count) > 1) {
@ -387,14 +415,14 @@ class ExtractTask extends AppShell {
}
list($type, $string, $line) = $countToken;
if (($type == T_STRING) && ($string == $functionName) && ($firstParenthesis == '(')) {
if (($type == T_STRING) && ($string === $functionName) && ($firstParenthesis === '(')) {
$position = $count;
$depth = 0;
while ($depth == 0) {
if ($this->_tokens[$position] == '(') {
while (!$depth) {
if ($this->_tokens[$position] === '(') {
$depth++;
} elseif ($this->_tokens[$position] == ')') {
} elseif ($this->_tokens[$position] === ')') {
$depth--;
}
$position++;
@ -403,8 +431,12 @@ class ExtractTask extends AppShell {
$mapCount = count($map);
$strings = $this->_getStrings($position, $mapCount);
if ($mapCount == count($strings)) {
if ($mapCount === count($strings)) {
extract(array_combine($map, $strings));
$category = isset($category) ? $category : 6;
$category = (int)$category;
$categoryName = $categories[$category];
$domain = isset($domain) ? $domain : 'default';
$details = array(
'file' => $this->_file,
@ -413,8 +445,14 @@ class ExtractTask extends AppShell {
if (isset($plural)) {
$details['msgid_plural'] = $plural;
}
$this->_addTranslation($domain, $singular, $details);
} else {
if (isset($context)) {
$details['msgctxt'] = $context;
}
// Skip LC_TIME files as we use a special file format for them.
if ($categoryName !== 'LC_TIME') {
$this->_addTranslation($categoryName, $domain, $singular, $details);
}
} elseif (!is_array($this->_tokens[$count - 1]) || $this->_tokens[$count - 1][0] != T_FUNCTION) {
$this->_markerError($this->_file, $line, $functionName, $count);
}
}
@ -433,11 +471,29 @@ class ExtractTask extends AppShell {
return;
}
$plugins = array(null);
if (empty($this->params['exclude-plugins'])) {
$plugins = array_merge($plugins, App::objects('plugin', null, false));
}
foreach ($plugins as $plugin) {
$this->_extractPluginValidationMessages($plugin);
}
}
/**
* Extract validation messages from application or plugin models
*
* @param string $plugin Plugin name or `null` to process application models
* @return void
*/
protected function _extractPluginValidationMessages($plugin = null) {
App::uses('AppModel', 'Model');
$plugin = null;
if (!empty($this->params['plugin'])) {
App::uses($this->params['plugin'] . 'AppModel', $this->params['plugin'] . '.Model');
$plugin = $this->params['plugin'] . '.';
if (!empty($plugin)) {
if (!CakePlugin::loaded($plugin)) {
return;
}
App::uses($plugin . 'AppModel', $plugin . '.Model');
$plugin = $plugin . '.';
}
$models = App::objects($plugin . 'Model', null, false);
@ -472,15 +528,16 @@ class ExtractTask extends AppShell {
* @param array $rules the set of validation rules for the field
* @param string $file the file name where this validation rule was found
* @param string $domain default domain to bind the validations to
* @param string $category the translation category
* @return void
*/
protected function _processValidationRules($field, $rules, $file, $domain) {
protected function _processValidationRules($field, $rules, $file, $domain, $category = 'LC_MESSAGES') {
if (!is_array($rules)) {
return;
}
$dims = Hash::dimensions($rules);
if ($dims == 1 || ($dims == 2 && isset($rules['message']))) {
if ($dims === 1 || ($dims === 2 && isset($rules['message']))) {
$rules = array($rules);
}
@ -496,11 +553,12 @@ class ExtractTask extends AppShell {
$msgid = $rule;
}
if ($msgid) {
$msgid = $this->_formatString(sprintf("'%s'", $msgid));
$details = array(
'file' => $file,
'line' => 'validation for field ' . $field
);
$this->_addTranslation($domain, $msgid, $details);
$this->_addTranslation($category, $domain, $msgid, $details);
}
}
}
@ -513,31 +571,47 @@ class ExtractTask extends AppShell {
protected function _buildFiles() {
$paths = $this->_paths;
$paths[] = realpath(APP) . DS;
foreach ($this->_translations as $domain => $translations) {
foreach ($translations as $msgid => $details) {
$plural = $details['msgid_plural'];
$files = $details['references'];
$occurrences = array();
foreach ($files as $file => $lines) {
$lines = array_unique($lines);
$occurrences[] = $file . ':' . implode(';', $lines);
}
$occurrences = implode("\n#: ", $occurrences);
$header = '#: ' . str_replace($paths, '', $occurrences) . "\n";
if ($plural === false) {
$sentence = "msgid \"{$msgid}\"\n";
$sentence .= "msgstr \"\"\n\n";
} else {
$sentence = "msgid \"{$msgid}\"\n";
$sentence .= "msgid_plural \"{$plural}\"\n";
$sentence .= "msgstr[0] \"\"\n";
$sentence .= "msgstr[1] \"\"\n\n";
}
usort($paths, function ($a, $b) {
return strlen($b) - strlen($a);
});
$this->_store($domain, $header, $sentence);
if ($domain != 'default' && $this->_merge) {
$this->_store('default', $header, $sentence);
foreach ($this->_translations as $category => $domains) {
foreach ($domains as $domain => $translations) {
foreach ($translations as $msgid => $contexts) {
foreach ($contexts as $context => $details) {
$plural = $details['msgid_plural'];
$header = '';
if (empty($this->params['no-location'])) {
$files = $details['references'];
$occurrences = array();
foreach ($files as $file => $lines) {
$lines = array_unique($lines);
$occurrences[] = $file . ':' . implode(';', $lines);
}
$occurrences = implode("\n#: ", $occurrences);
$header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n";
}
$sentence = '';
if ($context) {
$sentence .= "msgctxt \"{$context}\"\n";
}
if ($plural === false) {
$sentence .= "msgid \"{$msgid}\"\n";
$sentence .= "msgstr \"\"\n\n";
} else {
$sentence .= "msgid \"{$msgid}\"\n";
$sentence .= "msgid_plural \"{$plural}\"\n";
$sentence .= "msgstr[0] \"\"\n";
$sentence .= "msgstr[1] \"\"\n\n";
}
$this->_store($category, $domain, $header, $sentence);
if (($category !== 'LC_MESSAGES' || $domain !== 'default') && $this->_merge) {
$this->_store('LC_MESSAGES', 'default', $header, $sentence);
}
}
}
}
}
@ -546,19 +620,23 @@ class ExtractTask extends AppShell {
/**
* Prepare a file to be stored
*
* @param string $domain
* @param string $header
* @param string $sentence
* @param string $category The category
* @param string $domain The domain
* @param string $header The header content.
* @param string $sentence The sentence to store.
* @return void
*/
protected function _store($domain, $header, $sentence) {
if (!isset($this->_storage[$domain])) {
$this->_storage[$domain] = array();
protected function _store($category, $domain, $header, $sentence) {
if (!isset($this->_storage[$category])) {
$this->_storage[$category] = array();
}
if (!isset($this->_storage[$domain][$sentence])) {
$this->_storage[$domain][$sentence] = $header;
if (!isset($this->_storage[$category][$domain])) {
$this->_storage[$category][$domain] = array();
}
if (!isset($this->_storage[$category][$domain][$sentence])) {
$this->_storage[$category][$domain][$sentence] = $header;
} else {
$this->_storage[$domain][$sentence] .= $header;
$this->_storage[$category][$domain][$sentence] .= $header;
}
}
@ -572,36 +650,42 @@ class ExtractTask extends AppShell {
if (!empty($this->params['overwrite'])) {
$overwriteAll = true;
}
foreach ($this->_storage as $domain => $sentences) {
$output = $this->_writeHeader();
foreach ($sentences as $sentence => $header) {
$output .= $header . $sentence;
}
$filename = $domain . '.pot';
$File = new File($this->_output . $filename);
$response = '';
while ($overwriteAll === false && $File->exists() && strtoupper($response) !== 'Y') {
$this->out();
$response = $this->in(
__d('cake_console', 'Error: %s already exists in this location. Overwrite? [Y]es, [N]o, [A]ll', $filename),
array('y', 'n', 'a'),
'y'
);
if (strtoupper($response) === 'N') {
$response = '';
while ($response == '') {
$response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename);
$File = new File($this->_output . $response);
$filename = $response;
}
} elseif (strtoupper($response) === 'A') {
$overwriteAll = true;
foreach ($this->_storage as $category => $domains) {
foreach ($domains as $domain => $sentences) {
$output = $this->_writeHeader();
foreach ($sentences as $sentence => $header) {
$output .= $header . $sentence;
}
$filename = $domain . '.pot';
if ($category === 'LC_MESSAGES') {
$File = new File($this->_output . $filename);
} else {
new Folder($this->_output . $category, true);
$File = new File($this->_output . $category . DS . $filename);
}
$response = '';
while ($overwriteAll === false && $File->exists() && strtoupper($response) !== 'Y') {
$this->out();
$response = $this->in(
__d('cake_console', 'Error: %s already exists in this location. Overwrite? [Y]es, [N]o, [A]ll', $filename),
array('y', 'n', 'a'),
'y'
);
if (strtoupper($response) === 'N') {
$response = '';
while (!$response) {
$response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename);
$File = new File($this->_output . $response);
$filename = $response;
}
} elseif (strtoupper($response) === 'A') {
$overwriteAll = true;
}
}
$File->write($output);
$File->close();
}
$File->write($output);
$File->close();
}
}
@ -611,14 +695,13 @@ class ExtractTask extends AppShell {
* @return string Translation template header
*/
protected function _writeHeader() {
$output = "# LANGUAGE translation of CakePHP Application\n";
$output = "# LANGUAGE translation of CakePHP Application\n";
$output .= "# Copyright YEAR NAME <EMAIL@ADDRESS>\n";
$output .= "#\n";
$output .= "#, fuzzy\n";
$output .= "msgid \"\"\n";
$output .= "msgstr \"\"\n";
$output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
$output .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
$output .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
$output .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
$output .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
@ -632,18 +715,18 @@ class ExtractTask extends AppShell {
/**
* Get the strings from the position forward
*
* @param integer $position Actual position on tokens array
* @param integer $target Number of strings to extract
* @param int &$position Actual position on tokens array
* @param int $target Number of strings to extract
* @return array Strings extracted
*/
protected function _getStrings(&$position, $target) {
$strings = array();
$count = count($strings);
while ($count < $target && ($this->_tokens[$position] == ',' || $this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING)) {
while ($count < $target && ($this->_tokens[$position] === ',' || $this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position][0] == T_LNUMBER)) {
$count = count($strings);
if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING && $this->_tokens[$position + 1] == '.') {
if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING && $this->_tokens[$position + 1] === '.') {
$string = '';
while ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position] == '.') {
while ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position] === '.') {
if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) {
$string .= $this->_formatString($this->_tokens[$position][1]);
}
@ -652,6 +735,8 @@ class ExtractTask extends AppShell {
$strings[] = $string;
} elseif ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) {
$strings[] = $this->_formatString($this->_tokens[$position][1]);
} elseif ($this->_tokens[$position][0] == T_LNUMBER) {
$strings[] = $this->_tokens[$position][1];
}
$position++;
}
@ -667,7 +752,7 @@ class ExtractTask extends AppShell {
protected function _formatString($string) {
$quote = substr($string, 0, 1);
$string = substr($string, 1, -1);
if ($quote == '"') {
if ($quote === '"') {
$string = stripcslashes($string);
} else {
$string = strtr($string, array("\\'" => "'", "\\\\" => "\\"));
@ -680,33 +765,33 @@ class ExtractTask extends AppShell {
* Indicate an invalid marker on a processed file
*
* @param string $file File where invalid marker resides
* @param integer $line Line number
* @param int $line Line number
* @param string $marker Marker found
* @param integer $count Count
* @param int $count Count
* @return void
*/
protected function _markerError($file, $line, $marker, $count) {
$this->out(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker), true);
$this->err(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker));
$count += 2;
$tokenCount = count($this->_tokens);
$parenthesis = 1;
while ((($tokenCount - $count) > 0) && $parenthesis) {
if (is_array($this->_tokens[$count])) {
$this->out($this->_tokens[$count][1], false);
$this->err($this->_tokens[$count][1], false);
} else {
$this->out($this->_tokens[$count], false);
if ($this->_tokens[$count] == '(') {
$this->err($this->_tokens[$count], false);
if ($this->_tokens[$count] === '(') {
$parenthesis++;
}
if ($this->_tokens[$count] == ')') {
if ($this->_tokens[$count] === ')') {
$parenthesis--;
}
}
$count++;
}
$this->out("\n", true);
$this->err("\n", true);
}
/**
@ -726,29 +811,36 @@ class ExtractTask extends AppShell {
}
$pattern = '/' . implode('|', $exclude) . '/';
}
foreach ($this->_paths as $path) {
$Folder = new Folder($path);
foreach ($this->_paths as $i => $path) {
$this->_paths[$i] = realpath($path) . DS;
$Folder = new Folder($this->_paths[$i]);
$files = $Folder->findRecursive('.*\.(php|ctp|thtml|inc|tpl)', true);
if (!empty($pattern)) {
foreach ($files as $i => $file) {
if (preg_match($pattern, $file)) {
unset($files[$i]);
}
}
$files = preg_grep($pattern, $files, PREG_GREP_INVERT);
$files = array_values($files);
}
$this->_files = array_merge($this->_files, $files);
}
$this->_files = array_unique($this->_files);
}
/**
* Returns whether this execution is meant to extract string only from directories in folder represented by the
* APP constant, i.e. this task is extracting strings from same application.
*
* @return boolean
* @return bool
*/
protected function _isExtractingApp() {
return $this->_paths === array(APP);
}
/**
* Checks whether or not a given path is usable for writing.
*
* @param string $path Path to folder
* @return bool true if it exists and is writable, false otherwise
*/
protected function _isPathUsable($path) {
return is_dir($path) && is_writable($path);
}
}

View file

@ -2,18 +2,17 @@
/**
* The FixtureTask handles creating and updating fixture files.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc.
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.3
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -61,32 +60,48 @@ class FixtureTask extends BakeTask {
}
/**
* get the option parser.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
$parser->description(
__d('cake_console', 'Generate fixtures for use with the test suite. You can use `bake fixture all` to bake all fixtures.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Name of the fixture to bake. Can use Plugin.name to bake plugin fixtures.')
))->addOption('count', array(
'help' => __d('cake_console', 'When using generated data, the number of records to include in the fixture(s).'),
'short' => 'n',
'default' => 10
'default' => 1
))->addOption('connection', array(
'help' => __d('cake_console', 'Which database configuration to use for baking.'),
'short' => 'c',
'default' => 'default'
))->addOption('plugin', array(
'help' => __d('cake_console', 'CamelCased name of the plugin to bake fixtures for.'),
'short' => 'p',
'short' => 'p'
))->addOption('schema', array(
'help' => __d('cake_console', 'Importing schema for fixtures rather than hardcoding it.'),
'short' => 's',
'boolean' => true
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('force', array(
'short' => 'f',
'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
))->addOption('records', array(
'help' => __d('cake_console', 'Used with --count and <name>/all commands to pull [n] records from the live tables, where [n] is either --count or the default of 10'),
'help' => __d('cake_console', 'Used with --count and <name>/all commands to pull [n] records from the live tables, ' .
'where [n] is either --count or the default of 10.'),
'short' => 'r',
'boolean' => true
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
))->epilog(
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
);
return $parser;
}
/**
@ -106,16 +121,17 @@ class FixtureTask extends BakeTask {
if (!isset($this->connection)) {
$this->connection = 'default';
}
if (strtolower($this->args[0]) == 'all') {
if (strtolower($this->args[0]) === 'all') {
return $this->all();
}
$model = $this->_modelName($this->args[0]);
$this->bake($model);
$importOptions = $this->importOptions($model);
$this->bake($model, false, $importOptions);
}
}
/**
* Bake All the Fixtures at once. Will only bake fixtures for models that exist.
* Bake All the Fixtures at once. Will only bake fixtures for models that exist.
*
* @return void
*/
@ -123,9 +139,14 @@ class FixtureTask extends BakeTask {
$this->interactive = false;
$this->Model->interactive = false;
$tables = $this->Model->listAll($this->connection, false);
foreach ($tables as $table) {
$model = $this->_modelName($table);
$this->bake($model);
$importOptions = array();
if (!empty($this->params['schema'])) {
$importOptions['schema'] = $model;
}
$this->bake($model, false, $importOptions);
}
}
@ -157,18 +178,32 @@ class FixtureTask extends BakeTask {
*/
public function importOptions($modelName) {
$options = array();
$doSchema = $this->in(__d('cake_console', 'Would you like to import schema for this fixture?'), array('y', 'n'), 'n');
if ($doSchema == 'y') {
$options['schema'] = $modelName;
$plugin = '';
if (isset($this->params['plugin'])) {
$plugin = $this->params['plugin'] . '.';
}
$doRecords = $this->in(__d('cake_console', 'Would you like to use record importing for this fixture?'), array('y', 'n'), 'n');
if ($doRecords == 'y') {
$options['records'] = true;
if (!empty($this->params['schema'])) {
$options['schema'] = $plugin . $modelName;
} elseif ($this->interactive) {
$doSchema = $this->in(__d('cake_console', 'Would you like to import schema for this fixture?'), array('y', 'n'), 'n');
if ($doSchema === 'y') {
$options['schema'] = $modelName;
}
}
if ($doRecords == 'n') {
if (!empty($this->params['records'])) {
$options['fromTable'] = true;
} elseif ($this->interactive) {
$doRecords = $this->in(__d('cake_console', 'Would you like to use record importing for this fixture?'), array('y', 'n'), 'n');
if ($doRecords === 'y') {
$options['records'] = true;
}
}
if (!isset($options['records']) && $this->interactive) {
$prompt = __d('cake_console', "Would you like to build this fixture with data from %s's table?", $modelName);
$fromTable = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($fromTable) == 'y') {
if (strtolower($fromTable) === 'y') {
$options['fromTable'] = true;
}
}
@ -181,7 +216,7 @@ class FixtureTask extends BakeTask {
* @param string $model Name of model to bake.
* @param string $useTable Name of table to use.
* @param array $importOptions Options for public $import
* @return string Baked fixture content
* @return string|null Baked fixture content, otherwise null.
*/
public function bake($model, $useTable = false, $importOptions = array()) {
App::uses('CakeSchema', 'Model');
@ -202,7 +237,7 @@ class FixtureTask extends BakeTask {
if (isset($importOptions['records'])) {
$importBits[] = "'records' => true";
}
if ($this->connection != 'default') {
if ($this->connection !== 'default') {
$importBits[] .= "'connection' => '{$this->connection}'";
}
if (!empty($importBits)) {
@ -213,12 +248,12 @@ class FixtureTask extends BakeTask {
$this->_Schema = new CakeSchema();
$data = $this->_Schema->read(array('models' => false, 'connection' => $this->connection));
if (!isset($data['tables'][$useTable])) {
$this->err('Could not find your selected table ' . $useTable);
return false;
$this->err("<warning>Warning:</warning> Could not find the '${useTable}' table for ${model}.");
return null;
}
$tableInfo = $data['tables'][$useTable];
if (is_null($modelImport)) {
if ($modelImport === null) {
$schema = $this->_generateSchema($tableInfo);
}
@ -232,7 +267,7 @@ class FixtureTask extends BakeTask {
if (!empty($this->params['records']) || isset($importOptions['fromTable'])) {
$records = $this->_makeRecordString($this->_getRecordsFromTable($model, $useTable));
}
$out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import', 'fields'));
$out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import'));
return $out;
}
@ -279,15 +314,15 @@ class FixtureTask extends BakeTask {
* @return string fields definitions
*/
protected function _generateSchema($tableInfo) {
$schema = $this->_Schema->generateTable('f', $tableInfo);
return substr($schema, 13, -2);
$schema = trim($this->_Schema->generateTable('f', $tableInfo), "\n");
return substr($schema, 13, -1);
}
/**
* Generate String representation of Records
*
* @param array $tableInfo Table schema array
* @param integer $recordCount
* @param int $recordCount The number of records to generate.
* @return array Array of records to use in the fixture.
*/
protected function _generateRecords($tableInfo, $recordCount = 1) {
@ -298,41 +333,42 @@ class FixtureTask extends BakeTask {
if (empty($fieldInfo['type'])) {
continue;
}
$insert = '';
switch ($fieldInfo['type']) {
case 'integer':
case 'float':
$insert = $i + 1;
break;
break;
case 'string':
case 'binary':
$isPrimaryUuid = (
isset($fieldInfo['key']) && strtolower($fieldInfo['key']) == 'primary' &&
isset($fieldInfo['key']) && strtolower($fieldInfo['key']) === 'primary' &&
isset($fieldInfo['length']) && $fieldInfo['length'] == 36
);
if ($isPrimaryUuid) {
$insert = String::uuid();
$insert = CakeText::uuid();
} else {
$insert = "Lorem ipsum dolor sit amet";
if (!empty($fieldInfo['length'])) {
$insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
$insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
}
}
break;
break;
case 'timestamp':
$insert = time();
break;
break;
case 'datetime':
$insert = date('Y-m-d H:i:s');
break;
break;
case 'date':
$insert = date('Y-m-d');
break;
break;
case 'time':
$insert = date('H:i:s');
break;
break;
case 'boolean':
$insert = 1;
break;
break;
case 'text':
$insert = "Lorem ipsum dolor sit amet, aliquet feugiat.";
$insert .= " Convallis morbi fringilla gravida,";
@ -341,7 +377,7 @@ class FixtureTask extends BakeTask {
$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;
break;
}
$record[$field] = $insert;
}
@ -351,7 +387,7 @@ class FixtureTask extends BakeTask {
}
/**
* Convert a $records array into a a string.
* Convert a $records array into a string.
*
* @param array $records Array of records to be converted to string
* @return string A string value of the $records array.
@ -384,25 +420,32 @@ class FixtureTask extends BakeTask {
* @return array Array of records.
*/
protected function _getRecordsFromTable($modelName, $useTable = null) {
$modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
if ($this->interactive) {
$condition = null;
$prompt = __d('cake_console', "Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1");
while (!$condition) {
$condition = $this->in($prompt, null, 'WHERE 1=1');
}
$recordsFound = $modelObject->find('count', array(
'conditions' => $condition,
'recursive' => -1,
));
$prompt = __d('cake_console', "How many records do you want to import?");
$recordCount = $this->in($prompt, null, 10);
$recordCount = $this->in($prompt, null, ($recordsFound < 10 ) ? $recordsFound : 10);
} else {
$condition = 'WHERE 1=1';
$recordCount = (isset($this->params['count']) ? $this->params['count'] : 10);
}
$modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
$records = $modelObject->find('all', array(
'conditions' => $condition,
'recursive' => -1,
'limit' => $recordCount
));
$db = $modelObject->getDatasource();
$schema = $modelObject->schema(true);
$out = array();
foreach ($records as $record) {

View file

@ -2,18 +2,17 @@
/**
* The ModelTask handles creating and updating models files.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -97,7 +96,7 @@ class ModelTask extends BakeTask {
if (!isset($this->connection)) {
$this->connection = 'default';
}
if (strtolower($this->args[0]) == 'all') {
if (strtolower($this->args[0]) === 'all') {
return $this->all();
}
$model = $this->_modelName($this->args[0]);
@ -149,7 +148,7 @@ class ModelTask extends BakeTask {
$object = new Model(array('name' => $className, 'table' => $table, 'ds' => $this->connection));
$fields = $object->schema(true);
foreach ($fields as $name => $field) {
if (isset($field['key']) && $field['key'] == 'primary') {
if (isset($field['key']) && $field['key'] === 'primary') {
$object->primaryKey = $name;
break;
}
@ -162,8 +161,8 @@ class ModelTask extends BakeTask {
*
* @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 integer result of user choice.
* @param int $default The default option for the given prompt.
* @return int Result of user choice.
*/
public function inOptions($options, $prompt = null, $default = null) {
$valid = false;
@ -177,7 +176,7 @@ class ModelTask extends BakeTask {
$prompt = __d('cake_console', 'Make a selection from the choices above');
}
$choice = $this->in($prompt, null, $default);
if (intval($choice) > 0 && intval($choice) <= $max) {
if ((int)$choice > 0 && (int)$choice <= $max) {
$valid = true;
}
}
@ -187,7 +186,7 @@ class ModelTask extends BakeTask {
/**
* Handles interactive baking
*
* @return boolean
* @return bool
*/
protected function _interactive() {
$this->hr();
@ -208,7 +207,7 @@ class ModelTask extends BakeTask {
if (!in_array($useTable, $this->_tables)) {
$prompt = __d('cake_console', "The table %s doesn't exist or could not be automatically detected\ncontinue anyway?", $useTable);
$continue = $this->in($prompt, array('y', 'n'));
if (strtolower($continue) == 'n') {
if (strtolower($continue) === 'n') {
return false;
}
}
@ -233,14 +232,14 @@ class ModelTask extends BakeTask {
}
$prompt = __d('cake_console', "Would you like to supply validation criteria \nfor the fields in your model?");
$wannaDoValidation = $this->in($prompt, array('y','n'), 'y');
if (array_search($useTable, $this->_tables) !== false && strtolower($wannaDoValidation) == 'y') {
$wannaDoValidation = $this->in($prompt, array('y', 'n'), 'y');
if (array_search($useTable, $this->_tables) !== false && strtolower($wannaDoValidation) === 'y') {
$validate = $this->doValidation($tempModel);
}
$prompt = __d('cake_console', "Would you like to define model associations\n(hasMany, hasOne, belongsTo, etc.)?");
$wannaDoAssoc = $this->in($prompt, array('y','n'), 'y');
if (strtolower($wannaDoAssoc) == 'y') {
$wannaDoAssoc = $this->in($prompt, array('y', 'n'), 'y');
if (strtolower($wannaDoAssoc) === 'y') {
$associations = $this->doAssociations($tempModel);
}
}
@ -257,7 +256,7 @@ class ModelTask extends BakeTask {
if ($fullTableName !== Inflector::tableize($currentModelName)) {
$this->out(__d('cake_console', 'DB Table: %s', $fullTableName));
}
if ($primaryKey != 'id') {
if ($primaryKey !== 'id') {
$this->out(__d('cake_console', 'Primary Key: %s', $primaryKey));
}
if (!empty($validate)) {
@ -274,7 +273,7 @@ class ModelTask extends BakeTask {
$this->hr();
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
if (strtolower($looksGood) == 'y') {
if (strtolower($looksGood) === 'y') {
$vars = compact('associations', 'validate', 'primaryKey', 'useTable', 'displayField');
$vars['useDbConfig'] = $this->connection;
if ($this->bake($currentModelName, $vars)) {
@ -314,7 +313,7 @@ class ModelTask extends BakeTask {
public function findPrimaryKey($fields) {
$name = 'id';
foreach ($fields as $name => $field) {
if (isset($field['key']) && $field['key'] == 'primary') {
if (isset($field['key']) && $field['key'] === 'primary') {
break;
}
}
@ -331,7 +330,7 @@ class ModelTask extends BakeTask {
$fieldNames = array_keys($fields);
$prompt = __d('cake_console', "A displayField could not be automatically detected\nwould you like to choose one?");
$continue = $this->in($prompt, array('y', 'n'));
if (strtolower($continue) == 'n') {
if (strtolower($continue) === 'n') {
return false;
}
$prompt = __d('cake_console', 'Choose a field from the options above:');
@ -343,24 +342,33 @@ class ModelTask extends BakeTask {
* Handles Generation and user interaction for creating validation.
*
* @param Model $model Model to have validations generated for.
* @return array $validate Array of user selected validations.
* @return array validate Array of user selected validations.
*/
public function doValidation($model) {
if (!is_object($model)) {
if (!$model instanceof Model) {
return false;
}
$fields = $model->schema();
$fields = $model->schema();
if (empty($fields)) {
return false;
}
$skipFields = false;
$validate = array();
$this->initValidations();
foreach ($fields as $fieldName => $field) {
$validation = $this->fieldValidation($fieldName, $field, $model->primaryKey);
if (isset($validation['_skipFields'])) {
unset($validation['_skipFields']);
$skipFields = true;
}
if (!empty($validation)) {
$validate[$fieldName] = $validation;
}
if ($skipFields) {
return $validate;
}
}
return $validate;
}
@ -375,11 +383,13 @@ class ModelTask extends BakeTask {
if (class_exists('Validation')) {
$options = get_class_methods('Validation');
}
$deprecatedOptions = array('notEmpty', 'between', 'ssn');
$options = array_diff($options, $deprecatedOptions);
sort($options);
$default = 1;
foreach ($options as $key => $option) {
if ($option{0} != '_') {
$choices[$default] = strtolower($option);
foreach ($options as $option) {
if ($option{0} !== '_') {
$choices[$default] = $option;
$default++;
}
}
@ -393,15 +403,20 @@ class ModelTask extends BakeTask {
*
* @param string $fieldName Name of field to be validated.
* @param array $metaData metadata for field
* @param string $primaryKey
* @param string $primaryKey The primary key field.
* @return array Array of validation for the field.
*/
public function fieldValidation($fieldName, $metaData, $primaryKey = 'id') {
$defaultChoice = count($this->_validations);
$validate = $alreadyChosen = array();
$prompt = __d('cake_console',
"or enter in a valid regex validation string.\nAlternatively [s] skip the rest of the fields.\n"
);
$methods = array_flip($this->_validations);
$anotherValidator = 'y';
while ($anotherValidator == 'y') {
while ($anotherValidator === 'y') {
if ($this->interactive) {
$this->out();
$this->out(__d('cake_console', 'Field: <info>%s</info>', $fieldName));
@ -423,35 +438,41 @@ class ModelTask extends BakeTask {
$this->hr();
}
$prompt = __d('cake_console', "... or enter in a valid regex validation string.\n");
$methods = array_flip($this->_validations);
$guess = $defaultChoice;
if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) {
if ($fieldName == 'email') {
if ($fieldName === 'email') {
$guess = $methods['email'];
} elseif ($metaData['type'] == 'string' && $metaData['length'] == 36) {
} elseif ($metaData['type'] === 'string' && $metaData['length'] == 36) {
$guess = $methods['uuid'];
} elseif ($metaData['type'] == 'string') {
$guess = $methods['notempty'];
} elseif ($metaData['type'] == 'text') {
$guess = $methods['notempty'];
} elseif ($metaData['type'] == 'integer') {
} elseif ($metaData['type'] === 'string') {
$guess = $methods['notBlank'];
} elseif ($metaData['type'] === 'text') {
$guess = $methods['notBlank'];
} elseif ($metaData['type'] === 'integer') {
$guess = $methods['numeric'];
} elseif ($metaData['type'] == 'boolean') {
} elseif ($metaData['type'] === 'float') {
$guess = $methods['numeric'];
} elseif ($metaData['type'] === 'boolean') {
$guess = $methods['boolean'];
} elseif ($metaData['type'] == 'date') {
} elseif ($metaData['type'] === 'date') {
$guess = $methods['date'];
} elseif ($metaData['type'] == 'time') {
} elseif ($metaData['type'] === 'time') {
$guess = $methods['time'];
} elseif ($metaData['type'] == 'datetime') {
} elseif ($metaData['type'] === 'datetime') {
$guess = $methods['datetime'];
} elseif ($metaData['type'] == 'inet') {
} elseif ($metaData['type'] === 'inet') {
$guess = $methods['ip'];
} elseif ($metaData['type'] === 'decimal') {
$guess = $methods['decimal'];
}
}
if ($this->interactive === true) {
$choice = $this->in($prompt, null, $guess);
if ($choice === 's') {
$validate['_skipFields'] = true;
return $validate;
}
if (in_array($choice, $alreadyChosen)) {
$this->out(__d('cake_console', "You have already chosen that validation rule,\nplease choose again"));
continue;
@ -472,16 +493,19 @@ class ModelTask extends BakeTask {
}
if ($choice != $defaultChoice) {
$validate[$validatorName] = $choice;
if (is_numeric($choice) && isset($this->_validations[$choice])) {
$validate[$validatorName] = $this->_validations[$choice];
} else {
$validate[$validatorName] = $choice;
}
}
if ($this->interactive == true && $choice != $defaultChoice) {
$anotherValidator = $this->in(__d('cake_console', 'Would you like to add another validation rule?'), array('y', 'n'), 'n');
} else {
$anotherValidator = 'n';
$anotherValidator = 'n';
if ($this->interactive && $choice != $defaultChoice) {
$anotherValidator = $this->in(__d('cake_console', "Would you like to add another validation rule\n" .
"or skip the rest of the fields?"), array('y', 'n', 's'), 'n');
if ($anotherValidator === 's') {
$validate['_skipFields'] = true;
return $validate;
}
}
}
return $validate;
@ -490,11 +514,11 @@ class ModelTask extends BakeTask {
/**
* Handles associations
*
* @param Model $model
* @return array $associations
* @param Model $model The model object
* @return array Associations
*/
public function doAssociations($model) {
if (!is_object($model)) {
if (!$model instanceof Model) {
return false;
}
if ($this->interactive === true) {
@ -539,25 +563,49 @@ class ModelTask extends BakeTask {
return $associations;
}
/**
* Handles behaviors
*
* @param Model $model The model object.
* @return array Behaviors
*/
public function doActsAs($model) {
if (!$model instanceof Model) {
return false;
}
$behaviors = array();
$fields = $model->schema(true);
if (empty($fields)) {
return array();
}
if (isset($fields['lft']) && $fields['lft']['type'] === 'integer' &&
isset($fields['rght']) && $fields['rght']['type'] === 'integer' &&
isset($fields['parent_id'])) {
$behaviors[] = 'Tree';
}
return $behaviors;
}
/**
* Find belongsTo relations and add them to the associations list.
*
* @param Model $model Model instance of model being generated.
* @param array $associations Array of in progress associations
* @return array $associations with belongsTo added in.
* @return array Associations with belongsTo added in.
*/
public function findBelongsTo(Model $model, $associations) {
$fields = $model->schema(true);
foreach ($fields as $fieldName => $field) {
$offset = strpos($fieldName, '_id');
if ($fieldName != $model->primaryKey && $fieldName != 'parent_id' && $offset !== false) {
$fieldNames = array_keys($model->schema(true));
foreach ($fieldNames as $fieldName) {
$offset = substr($fieldName, -3) === '_id';
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') {
} elseif ($fieldName === 'parent_id') {
$associations['belongsTo'][] = array(
'alias' => 'Parent' . $model->name,
'className' => $model->name,
@ -569,32 +617,32 @@ class ModelTask extends BakeTask {
}
/**
* Find the hasOne and HasMany relations and add them to associations list
* Find the hasOne and hasMany relations and add them to associations list
*
* @param Model $model Model instance being generated
* @param array $associations Array of in progress associations
* @return array $associations with hasOne and hasMany added in.
* @return array Associations with hasOne and hasMany added in.
*/
public function findHasOneAndMany(Model $model, $associations) {
$foreignKey = $this->_modelKey($model->name);
foreach ($this->_tables as $otherTable) {
$tempOtherModel = $this->_getModelObject($this->_modelName($otherTable), $otherTable);
$modelFieldsTemp = $tempOtherModel->schema(true);
$tempFieldNames = array_keys($tempOtherModel->schema(true));
$pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/';
$possibleJoinTable = preg_match($pattern, $otherTable);
if ($possibleJoinTable == true) {
if ($possibleJoinTable) {
continue;
}
foreach ($modelFieldsTemp as $fieldName => $field) {
foreach ($tempFieldNames as $fieldName) {
$assoc = false;
if ($fieldName != $model->primaryKey && $fieldName == $foreignKey) {
if ($fieldName !== $model->primaryKey && $fieldName === $foreignKey) {
$assoc = array(
'alias' => $tempOtherModel->name,
'className' => $tempOtherModel->name,
'foreignKey' => $fieldName
);
} elseif ($otherTable == $model->table && $fieldName == 'parent_id') {
} elseif ($otherTable === $model->table && $fieldName === 'parent_id') {
$assoc = array(
'alias' => 'Child' . $model->name,
'className' => $model->name,
@ -616,29 +664,22 @@ class ModelTask extends BakeTask {
*
* @param Model $model Model instance being generated
* @param array $associations Array of in-progress associations
* @return array $associations with hasAndBelongsToMany added in.
* @return array Associations with hasAndBelongsToMany added in.
*/
public function findHasAndBelongsToMany(Model $model, $associations) {
$foreignKey = $this->_modelKey($model->name);
foreach ($this->_tables as $otherTable) {
$tempOtherModel = $this->_getModelObject($this->_modelName($otherTable), $otherTable);
$modelFieldsTemp = $tempOtherModel->schema(true);
$tableName = null;
$offset = strpos($otherTable, $model->table . '_');
$otherOffset = strpos($otherTable, '_' . $model->table);
if ($offset !== false) {
$offset = strlen($model->table . '_');
$habtmName = $this->_modelName(substr($otherTable, $offset));
$associations['hasAndBelongsToMany'][] = array(
'alias' => $habtmName,
'className' => $habtmName,
'foreignKey' => $foreignKey,
'associationForeignKey' => $this->_modelKey($habtmName),
'joinTable' => $otherTable
);
$tableName = substr($otherTable, strlen($model->table . '_'));
} elseif ($otherOffset !== false) {
$habtmName = $this->_modelName(substr($otherTable, 0, $otherOffset));
$tableName = substr($otherTable, 0, $otherOffset);
}
if ($tableName && in_array($tableName, $this->_tables)) {
$habtmName = $this->_modelName($tableName);
$associations['hasAndBelongsToMany'][] = array(
'alias' => $habtmName,
'className' => $habtmName,
@ -665,9 +706,9 @@ class ModelTask extends BakeTask {
$prompt = "{$model->name} {$type} {$assoc['alias']}?";
$response = $this->in($prompt, array('y', 'n'), 'y');
if ('n' == strtolower($response)) {
if (strtolower($response) === 'n') {
unset($associations[$type][$i]);
} elseif ($type == 'hasMany') {
} elseif ($type === 'hasMany') {
unset($associations['hasOne'][$i]);
}
}
@ -688,19 +729,19 @@ class ModelTask extends BakeTask {
$prompt = __d('cake_console', 'Would you like to define some additional model associations?');
$wannaDoMoreAssoc = $this->in($prompt, array('y', 'n'), 'n');
$possibleKeys = $this->_generatePossibleKeys();
while (strtolower($wannaDoMoreAssoc) == 'y') {
while (strtolower($wannaDoMoreAssoc) === 'y') {
$assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
$this->out(__d('cake_console', 'What is the association type?'));
$assocType = intval($this->inOptions($assocs, __d('cake_console', 'Enter a number')));
$assocType = (int)$this->inOptions($assocs, __d('cake_console', 'Enter a number'));
$this->out(__d('cake_console', "For the following options be very careful to match your setup exactly.\n" .
"Any spelling mistakes will cause errors."));
$this->hr();
$alias = $this->in(__d('cake_console', 'What is the alias for this association?'));
$className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias );
$className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias);
if ($assocType == 0) {
if ($assocType === 0) {
if (!empty($possibleKeys[$model->table])) {
$showKeys = $possibleKeys[$model->table];
} else {
@ -728,12 +769,12 @@ class ModelTask extends BakeTask {
if (!empty($showKeys)) {
$this->out(__d('cake_console', 'A helpful List of possible keys'));
$foreignKey = $this->inOptions($showKeys, __d('cake_console', 'What is the foreignKey?'));
$foreignKey = $showKeys[intval($foreignKey)];
$foreignKey = $showKeys[(int)$foreignKey];
}
if (!isset($foreignKey)) {
$foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey);
}
if ($assocType == 3) {
if ($assocType === 3) {
$associationForeignKey = $this->in(__d('cake_console', 'What is the associationForeignKey?'), null, $this->_modelKey($model->name));
$joinTable = $this->in(__d('cake_console', 'What is the joinTable?'));
}
@ -743,7 +784,7 @@ class ModelTask extends BakeTask {
$associations[$assocs[$assocType]][$i]['alias'] = $alias;
$associations[$assocs[$assocType]][$i]['className'] = $className;
$associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey;
if ($assocType == 3) {
if ($assocType === 3) {
$associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey;
$associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable;
}
@ -755,7 +796,7 @@ class ModelTask extends BakeTask {
/**
* Finds all possible keys to use on custom associations.
*
* @return array array of tables and possible keys
* @return array Array of tables and possible keys
*/
protected function _generatePossibleKeys() {
$possible = array();
@ -763,7 +804,7 @@ class ModelTask extends BakeTask {
$tempOtherModel = new Model(array('table' => $otherTable, 'ds' => $this->connection));
$modelFieldsTemp = $tempOtherModel->schema(true);
foreach ($modelFieldsTemp as $fieldName => $field) {
if ($field['type'] == 'integer' || $field['type'] == 'string') {
if ($field['type'] === 'integer' || $field['type'] === 'string') {
$possible[$otherTable][] = $fieldName;
}
}
@ -775,15 +816,16 @@ class ModelTask extends BakeTask {
* Assembles and writes a Model file.
*
* @param string|object $name Model name or object
* @param array|boolean $data if array and $name is not an object assume bake data, otherwise boolean.
* @param array|bool $data if array and $name is not an object assume bake data, otherwise boolean.
* @return string
*/
public function bake($name, $data = array()) {
if (is_object($name)) {
if ($data == false) {
if ($name instanceof Model) {
if (!$data) {
$data = array();
$data['associations'] = $this->doAssociations($name);
$data['validate'] = $this->doValidation($name);
$data['actsAs'] = $this->doActsAs($name);
}
$data['primaryKey'] = $name->primaryKey;
$data['useTable'] = $name->table;
@ -792,8 +834,10 @@ class ModelTask extends BakeTask {
} else {
$data['name'] = $name;
}
$defaults = array(
'associations' => array(),
'actsAs' => array(),
'validate' => array(),
'primaryKey' => 'id',
'useTable' => null,
@ -842,7 +886,7 @@ class ModelTask extends BakeTask {
* @return array
*/
public function listAll($useDbConfig = null) {
$this->_tables = (array)$this->getAllTables($useDbConfig);
$this->_tables = $this->getAllTables($useDbConfig);
$this->_modelNames = array();
$count = count($this->_tables);
@ -885,8 +929,8 @@ class ModelTask extends BakeTask {
$this->out(__d('cake_console', "Given your model named '%s',\nCake would expect a database table named '%s'", $modelName, $fullTableName));
$tableIsGood = $this->in(__d('cake_console', 'Do you want to use this table?'), array('y', 'n'), 'y');
}
if (strtolower($tableIsGood) == 'n') {
$useTable = $this->in(__d('cake_console', 'What is the name of the table?'));
if (strtolower($tableIsGood) === 'n') {
$useTable = $this->in(__d('cake_console', 'What is the name of the table (without prefix)?'));
}
}
return $useTable;
@ -919,8 +963,9 @@ class ModelTask extends BakeTask {
}
if (empty($tables)) {
$this->err(__d('cake_console', 'Your database does not have any tables.'));
$this->_stop();
return $this->_stop();
}
sort($tables);
return $tables;
}
@ -928,56 +973,66 @@ class ModelTask extends BakeTask {
* Forces the user to specify the model he wants to bake, and returns the selected model name.
*
* @param string $useDbConfig Database config name
* @return string the model name
* @return string The model name
*/
public function getName($useDbConfig = null) {
$this->listAll($useDbConfig);
$enteredModel = '';
while ($enteredModel == '') {
while (!$enteredModel) {
$enteredModel = $this->in(__d('cake_console', "Enter a number from the list above,\n" .
"type in the name of another model, or 'q' to exit"), null, 'q');
if ($enteredModel === 'q') {
$this->out(__d('cake_console', 'Exit'));
$this->_stop();
return $this->_stop();
}
if ($enteredModel == '' || intval($enteredModel) > count($this->_modelNames)) {
if (!$enteredModel || (int)$enteredModel > count($this->_modelNames)) {
$this->err(__d('cake_console', "The model name you supplied was empty,\n" .
"or the number you selected was not an option. Please try again."));
$enteredModel = '';
}
}
if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) {
$currentModelName = $this->_modelNames[intval($enteredModel) - 1];
} else {
$currentModelName = $enteredModel;
if ((int)$enteredModel > 0 && (int)$enteredModel <= count($this->_modelNames)) {
return $this->_modelNames[(int)$enteredModel - 1];
}
return $currentModelName;
return $enteredModel;
}
/**
* get the option parser.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
__d('cake_console', 'Bake models.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Name of the model to bake. Can use Plugin.name to bake plugin models.')
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake all model files with associations and validation.')
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'Plugin to bake the model into.')
))->addOption('connection', array(
'short' => 'c',
'help' => __d('cake_console', 'The connection the model table is on.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
$parser->description(
__d('cake_console', 'Bake models.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Name of the model to bake. Can use Plugin.name to bake plugin models.')
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake all model files with associations and validation.')
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'Plugin to bake the model into.')
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('connection', array(
'short' => 'c',
'help' => __d('cake_console', 'The connection the model table is on.')
))->addOption('force', array(
'short' => 'f',
'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
))->epilog(
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
);
return $parser;
}
/**

View file

@ -1,19 +1,16 @@
<?php
/**
* The Plugin Task handles creating an empty plugin, ready to be used
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -64,9 +61,8 @@ class PluginTask extends AppShell {
$this->out(__d('cake_console', 'Plugin: %s already exists, no action taken', $plugin));
$this->out(__d('cake_console', 'Path: %s', $pluginPath));
return false;
} else {
$this->_interactive($plugin);
}
$this->_interactive($plugin);
} else {
return $this->_interactive();
}
@ -75,7 +71,7 @@ class PluginTask extends AppShell {
/**
* Interactive interface
*
* @param string $plugin
* @param string $plugin The plugin name.
* @return void
*/
protected function _interactive($plugin = null) {
@ -92,7 +88,7 @@ class PluginTask extends AppShell {
* Bake the plugin, create directories and files
*
* @param string $plugin Name of the plugin in CamelCased format
* @return boolean
* @return bool
*/
public function bake($plugin) {
$pathOptions = App::path('plugins');
@ -106,28 +102,35 @@ class PluginTask extends AppShell {
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n', 'q'), 'y');
if (strtolower($looksGood) == 'y') {
if (strtolower($looksGood) === 'y') {
$Folder = new Folder($this->path . $plugin);
$directories = array(
'Config' . DS . 'Schema',
'Model' . DS . 'Behavior',
'Model' . DS . 'Datasource',
'Console' . DS . 'Command' . DS . 'Task',
'Console' . DS . 'Templates',
'Controller' . DS . 'Component',
'Lib',
'View' . DS . 'Helper',
'Locale' . DS . 'eng' . DS . 'LC_MESSAGES',
'Model' . DS . 'Behavior',
'Model' . DS . 'Datasource',
'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component',
'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper',
'Test' . DS . 'Case' . DS . 'Lib',
'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior',
'Test' . DS . 'Case' . DS . 'Model' . DS . 'Datasource',
'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper',
'Test' . DS . 'Fixture',
'Vendor',
'webroot'
'View' . DS . 'Elements',
'View' . DS . 'Helper',
'View' . DS . 'Layouts',
'webroot' . DS . 'css',
'webroot' . DS . 'js',
'webroot' . DS . 'img',
);
foreach ($directories as $directory) {
$dirPath = $this->path . $plugin . DS . $directory;
$Folder->create($dirPath);
$File = new File($dirPath . DS . 'empty', true);
new File($dirPath . DS . 'empty', true);
}
foreach ($Folder->messages() as $message) {
@ -145,15 +148,17 @@ class PluginTask extends AppShell {
$controllerFileName = $plugin . 'AppController.php';
$out = "<?php\n\n";
$out .= "App::uses('AppController', 'Controller');\n\n";
$out .= "class {$plugin}AppController extends AppController {\n\n";
$out .= "}\n\n";
$out .= "}\n";
$this->createFile($this->path . $plugin . DS . 'Controller' . DS . $controllerFileName, $out);
$modelFileName = $plugin . 'AppModel.php';
$out = "<?php\n\n";
$out .= "App::uses('AppModel', 'Model');\n\n";
$out .= "class {$plugin}AppModel extends AppModel {\n\n";
$out .= "}\n\n";
$out .= "}\n";
$this->createFile($this->path . $plugin . DS . 'Model' . DS . $modelFileName, $out);
$this->_modifyBootstrap($plugin);
@ -168,6 +173,7 @@ class PluginTask extends AppShell {
/**
* Update the app's bootstrap.php file.
*
* @param string $plugin Name of plugin
* @return void
*/
protected function _modifyBootstrap($plugin) {
@ -183,16 +189,18 @@ class PluginTask extends AppShell {
/**
* find and change $this->path to the user selection
*
* @param array $pathOptions
* @return string plugin path
* @param array $pathOptions The list of paths to look in.
* @return void
*/
public function findPath($pathOptions) {
$valid = false;
foreach ($pathOptions as $i => $path) {
if (!is_dir($path)) {
array_splice($pathOptions, $i, 1);
unset($pathOptions[$i]);
}
}
$pathOptions = array_values($pathOptions);
$max = count($pathOptions);
while (!$valid) {
foreach ($pathOptions as $i => $option) {
@ -200,7 +208,7 @@ class PluginTask extends AppShell {
}
$prompt = __d('cake_console', 'Choose a plugin path from the paths above.');
$choice = $this->in($prompt, null, 1);
if (intval($choice) > 0 && intval($choice) <= $max) {
if ((int)$choice > 0 && (int)$choice <= $max) {
$valid = true;
}
}
@ -208,18 +216,21 @@ class PluginTask extends AppShell {
}
/**
* get the option parser for the plugin task
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(__d('cake_console',
'Create the directory structure, AppModel and AppController classes for a new plugin. ' .
'Can create plugins in any of your bootstrapped plugin paths.'
))->addArgument('name', array(
$parser->description(
__d('cake_console', 'Create the directory structure, AppModel and AppController classes for a new plugin. ' .
'Can create plugins in any of your bootstrapped plugin paths.')
)->addArgument('name', array(
'help' => __d('cake_console', 'CamelCased name of the plugin to create.')
));
return $parser;
}
}

View file

@ -2,25 +2,23 @@
/**
* The Project Task handles creating the base application
*
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
App::uses('File', 'Utility');
App::uses('Folder', 'Utility');
App::uses('String', 'Utility');
App::uses('CakeText', 'Utility');
App::uses('Security', 'Utility');
/**
@ -66,7 +64,7 @@ class ProjectTask extends AppShell {
}
$response = false;
while ($response == false && is_dir($project) === true && file_exists($project . 'Config' . 'core.php')) {
while (!$response && is_dir($project) === true && file_exists($project . 'Config' . 'core.php')) {
$prompt = __d('cake_console', '<warning>A project already exists in this location:</warning> %s Overwrite?', $project);
$response = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($response) === 'n') {
@ -92,6 +90,13 @@ class ProjectTask extends AppShell {
$success = false;
}
if ($this->cachePrefix($path)) {
$this->out(__d('cake_console', ' * Cache prefix set'));
} else {
$this->err(__d('cake_console', 'The cache prefix was <error>NOT</error> set'));
$success = false;
}
if ($this->consolePath($path) === true) {
$this->out(__d('cake_console', ' * app/Console/cake.php path set.'));
} else {
@ -109,8 +114,8 @@ class ProjectTask extends AppShell {
}
$success = $this->corePath($path, $hardCode) === true;
if ($success) {
$this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in webroot/index.php', CAKE_CORE_INCLUDE_PATH));
$this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in webroot/test.php', CAKE_CORE_INCLUDE_PATH));
$this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in %s', CAKE_CORE_INCLUDE_PATH, 'webroot/index.php'));
$this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in %s', CAKE_CORE_INCLUDE_PATH, 'webroot/test.php'));
} else {
$this->err(__d('cake_console', 'Unable to set CAKE_CORE_INCLUDE_PATH, you should change it in %s', $path . 'webroot' . DS . 'index.php'));
$success = false;
@ -122,7 +127,7 @@ class ProjectTask extends AppShell {
$Folder = new Folder($path);
if (!$Folder->chmod($path . 'tmp', 0777)) {
$this->err(__d('cake_console', 'Could not set permissions on %s', $path . DS . 'tmp'));
$this->out(__d('cake_console', 'chmod -R 0777 %s', $path . DS . 'tmp'));
$this->out('chmod -R 0777 ' . $path . DS . 'tmp');
$success = false;
}
if ($success) {
@ -137,7 +142,7 @@ class ProjectTask extends AppShell {
/**
* Checks PHP's include_path for CakePHP.
*
* @return boolean Indicates whether or not CakePHP exists on include_path
* @return bool Indicates whether or not CakePHP exists on include_path
*/
public function cakeOnIncludePath() {
$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
@ -207,7 +212,7 @@ class ProjectTask extends AppShell {
}
foreach ($Folder->messages() as $message) {
$this->out(String::wrap(' * ' . $message), 1, Shell::VERBOSE);
$this->out(CakeText::wrap(' * ' . $message), 1, Shell::VERBOSE);
}
return true;
@ -226,14 +231,14 @@ class ProjectTask extends AppShell {
* and points app/console/cake.php to the right place
*
* @param string $path Project path.
* @return boolean success
* @return bool success
*/
public function consolePath($path) {
$File = new File($path . 'Console' . DS . 'cake.php');
$contents = $File->read();
if (preg_match('/(__CAKE_PATH__)/', $contents, $match)) {
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " \$ds . '" : "'";
$replacement = $root . str_replace(DS, "' . \$ds . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
$replacement = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
$result = str_replace($match[0], $replacement, $contents);
if ($File->write($result)) {
return true;
@ -247,7 +252,7 @@ class ProjectTask extends AppShell {
* Generates and writes 'Security.salt'
*
* @param string $path Project path
* @return boolean Success
* @return bool Success
*/
public function securitySalt($path) {
$File = new File($path . 'Config' . DS . 'core.php');
@ -267,7 +272,7 @@ class ProjectTask extends AppShell {
* Generates and writes 'Security.cipherSeed'
*
* @param string $path Project path
* @return boolean Success
* @return bool Success
*/
public function securityCipherSeed($path) {
$File = new File($path . 'Config' . DS . 'core.php');
@ -284,12 +289,29 @@ class ProjectTask extends AppShell {
return false;
}
/**
* Writes cache prefix using app's name
*
* @param string $dir Path to project
* @return bool Success
*/
public function cachePrefix($dir) {
$app = basename($dir);
$File = new File($dir . 'Config' . DS . 'core.php');
$contents = $File->read();
if (preg_match('/(\$prefix = \'myapp_\';)/', $contents, $match)) {
$result = str_replace($match[0], '$prefix = \'' . $app . '_\';', $contents);
return $File->write($result);
}
return false;
}
/**
* Generates and writes CAKE_CORE_INCLUDE_PATH
*
* @param string $path Project path
* @param boolean $hardCode Wether or not define calls should be hardcoded.
* @return boolean Success
* @param bool $hardCode Whether or not define calls should be hardcoded.
* @return bool Success
*/
public function corePath($path, $hardCode = true) {
if (dirname($path) !== CAKE_CORE_INCLUDE_PATH) {
@ -309,8 +331,8 @@ class ProjectTask extends AppShell {
* Replaces the __CAKE_PATH__ placeholder in the template files.
*
* @param string $filename The filename to operate on.
* @param boolean $hardCode Whether or not the define should be uncommented.
* @return boolean Success
* @param bool $hardCode Whether or not the define should be uncommented.
* @return bool Success
*/
protected function _replaceCorePath($filename, $hardCode) {
$contents = file_get_contents($filename);
@ -318,6 +340,11 @@ class ProjectTask extends AppShell {
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
$corePath = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
$composer = ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib';
if (file_exists($composer)) {
$corePath = " ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'";
}
$result = str_replace('__CAKE_PATH__', $corePath, $contents, $count);
if ($hardCode) {
$result = str_replace('//define(\'CAKE_CORE', 'define(\'CAKE_CORE', $result);
@ -325,17 +352,14 @@ class ProjectTask extends AppShell {
if (!file_put_contents($filename, $result)) {
return false;
}
if ($count == 0) {
return false;
}
return true;
return (bool)$count;
}
/**
* Enables Configure::read('Routing.prefixes') in /app/Config/core.php
*
* @param string $name Name to use as admin routing
* @return boolean Success
* @return bool Success
*/
public function cakeAdmin($name) {
$path = (empty($this->configPath)) ? APP . 'Config' . DS : $this->configPath;
@ -346,12 +370,9 @@ class ProjectTask extends AppShell {
if ($File->write($result)) {
Configure::write('Routing.prefixes', array($name));
return true;
} else {
return false;
}
} else {
return false;
}
return false;
}
/**
@ -363,7 +384,7 @@ class ProjectTask extends AppShell {
$admin = '';
$prefixes = Configure::read('Routing.prefixes');
if (!empty($prefixes)) {
if (count($prefixes) == 1) {
if (count($prefixes) === 1) {
return $prefixes[0] . '_';
}
if ($this->interactive) {
@ -382,16 +403,20 @@ class ProjectTask extends AppShell {
}
if ($this->interactive) {
$this->hr();
$this->out(__d('cake_console', 'You need to enable Configure::write(\'Routing.prefixes\',array(\'admin\')) in /app/Config/core.php to use prefix routing.'));
$this->out(__d('cake_console', 'You need to enable %s in %s to use prefix routing.',
'Configure::write(\'Routing.prefixes\', array(\'admin\'))',
'/app/Config/core.php'));
$this->out(__d('cake_console', 'What would you like the prefix route to be?'));
$this->out(__d('cake_console', 'Example: www.example.com/admin/controller'));
while ($admin == '') {
$this->out(__d('cake_console', 'Example: %s', 'www.example.com/admin/controller'));
while (!$admin) {
$admin = $this->in(__d('cake_console', 'Enter a routing prefix:'), null, 'admin');
}
if ($this->cakeAdmin($admin) !== true) {
$this->out(__d('cake_console', '<error>Unable to write to</error> /app/Config/core.php.'));
$this->out(__d('cake_console', 'You need to enable Configure::write(\'Routing.prefixes\',array(\'admin\')) in /app/Config/core.php to use prefix routing.'));
$this->_stop();
$this->out(__d('cake_console', '<error>Unable to write to</error> %s.', '/app/Config/core.php'));
$this->out(__d('cake_console', 'You need to enable %s in %s to use prefix routing.',
'Configure::write(\'Routing.prefixes\', array(\'admin\'))',
'/app/Config/core.php'));
return $this->_stop();
}
return $admin . '_';
}
@ -399,23 +424,30 @@ class ProjectTask extends AppShell {
}
/**
* get the option parser.
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
__d('cake_console', 'Generate a new CakePHP project skeleton.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Application directory to make, if it starts with "/" the path is absolute.')
))->addOption('empty', array(
'boolean' => true,
'help' => __d('cake_console', 'Create empty files in each of the directories. Good if you are using git')
))->addOption('skel', array(
'default' => current(App::core('Console')) . 'Templates' . DS . 'skel',
'help' => __d('cake_console', 'The directory layout to use for the new application skeleton. Defaults to cake/Console/Templates/skel of CakePHP used to create the project.')
));
$parser->description(
__d('cake_console', 'Generate a new CakePHP project skeleton.')
)->addArgument('name', array(
'help' => __d('cake_console', 'Application directory to make, if it starts with "/" the path is absolute.')
))->addOption('empty', array(
'boolean' => true,
'help' => __d('cake_console', 'Create empty files in each of the directories. Good if you are using git')
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('skel', array(
'default' => current(App::core('Console')) . 'Templates' . DS . 'skel',
'help' => __d('cake_console', 'The directory layout to use for the new application skeleton.' .
' Defaults to cake/Console/Templates/skel of CakePHP used to create the project.')
));
return $parser;
}
}

View file

@ -2,18 +2,17 @@
/**
* Template Task can generate templated output Used in other Tasks
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.3
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -43,7 +42,7 @@ class TemplateTask extends AppShell {
public $templatePaths = array();
/**
* Initialize callback. Setup paths for the template task.
* Initialize callback. Setup paths for the template task.
*
* @return void
*/
@ -122,7 +121,7 @@ class TemplateTask extends AppShell {
$data = array($one => $two);
}
if ($data == null) {
if (!$data) {
return false;
}
$this->templateVars = $data + $this->templateVars;
@ -165,7 +164,7 @@ class TemplateTask extends AppShell {
* @return string returns the path to the selected theme.
*/
public function getThemePath() {
if (count($this->templatePaths) == 1) {
if (count($this->templatePaths) === 1) {
$paths = array_values($this->templatePaths);
return $paths[0];
}

View file

@ -2,18 +2,17 @@
/**
* The TestTask handles creating and updating test files.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.3
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -83,15 +82,16 @@ class TestTask extends BakeTask {
*/
public function execute() {
parent::execute();
if (empty($this->args)) {
$count = count($this->args);
if (!$count) {
$this->_interactive();
}
if (count($this->args) == 1) {
if ($count === 1) {
$this->_interactive($this->args[0]);
}
if (count($this->args) > 1) {
if ($count > 1) {
$type = Inflector::classify($this->args[0]);
if ($this->bake($type, $this->args[1])) {
$this->out('<success>Done</success>');
@ -102,8 +102,8 @@ class TestTask extends BakeTask {
/**
* Handles interactive baking
*
* @param string $type
* @return string|boolean
* @param string $type The type of object to bake a test for.
* @return string|bool
*/
protected function _interactive($type = null) {
$this->interactive = true;
@ -129,7 +129,7 @@ class TestTask extends BakeTask {
*
* @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
* @return string|boolean
* @return string|bool
*/
public function bake($type, $className) {
$plugin = null;
@ -196,7 +196,7 @@ class TestTask extends BakeTask {
}
$keys[] = 'q';
$selection = $this->in(__d('cake_console', 'Enter the type of object to bake a test for or (q)uit'), $keys, 'q');
if ($selection == 'q') {
if ($selection === 'q') {
return $this->_stop();
}
$types = array_keys($this->classTypes);
@ -242,7 +242,7 @@ class TestTask extends BakeTask {
* Currently only model, and controller are supported
*
* @param string $type The Type of object you are generating tests for eg. controller
* @return boolean
* @return bool
*/
public function typeCanDetectFixtures($type) {
$type = strtolower($type);
@ -254,7 +254,7 @@ class TestTask extends BakeTask {
*
* @param string $package The package of object you are generating tests for eg. controller
* @param string $class the Classname of the class the test is being generated for.
* @return boolean
* @return bool
*/
public function isLoadableClass($package, $class) {
App::uses($class, $package);
@ -275,11 +275,11 @@ class TestTask extends BakeTask {
* @param string $class the Classname of the class the test is being generated for.
* @return object And instance of the class that is going to be tested.
*/
public function &buildTestSubject($type, $class) {
public function buildTestSubject($type, $class) {
ClassRegistry::flush();
App::import($type, $class);
App::uses($class, $type);
$class = $this->getRealClassName($type, $class);
if (strtolower($type) == 'model') {
if (strtolower($type) === 'model') {
$instance = ClassRegistry::init($class);
} else {
$instance = new $class();
@ -293,16 +293,16 @@ class TestTask extends BakeTask {
*
* @param string $type The Type of object you are generating tests for eg. controller
* @param string $class the Classname of the class the test is being generated for.
* @return string Real classname
* @return string Real class name
*/
public function getRealClassName($type, $class) {
if (strtolower($type) == 'model' || empty($this->classTypes[$type])) {
if (strtolower($type) === 'model' || empty($this->classTypes[$type])) {
return $class;
}
$position = strpos($class, $type);
if ($position !== false && strlen($class) - $position == strlen($type)) {
if ($position !== false && (strlen($class) - $position) === strlen($type)) {
return $class;
}
return $class . $type;
@ -334,7 +334,7 @@ class TestTask extends BakeTask {
* @param string $type The type the class having a test
* generated for is in.
* @return array Array of (class, type)
* @throws CakeException On invalid typename
* @throws CakeException on invalid types.
*/
public function getBaseType($type) {
if (empty($this->baseTypes[$type])) {
@ -356,7 +356,7 @@ class TestTask extends BakeTask {
$thisMethods = array_diff($classMethods, $parentMethods);
$out = array();
foreach ($thisMethods as $method) {
if (substr($method, 0, 1) != '_' && $method != strtolower($className)) {
if (substr($method, 0, 1) !== '_' && $method != strtolower($className)) {
$out[] = $method;
}
}
@ -367,14 +367,14 @@ class TestTask extends BakeTask {
* Generate the list of fixtures that will be required to run this test based on
* loaded models.
*
* @param object $subject The object you want to generate fixtures for.
* @param CakeObject $subject The object you want to generate fixtures for.
* @return array Array of fixtures to be included in the test.
*/
public function generateFixtureList($subject) {
$this->_fixtures = array();
if (is_a($subject, 'Model')) {
if ($subject instanceof Model) {
$this->_processModel($subject);
} elseif (is_a($subject, 'Controller')) {
} elseif ($subject instanceof Controller) {
$this->_processController($subject);
}
return array_values($this->_fixtures);
@ -395,9 +395,9 @@ class TestTask extends BakeTask {
if (!isset($this->_fixtures[$className])) {
$this->_processModel($subject->{$alias});
}
if ($type == 'hasAndBelongsToMany') {
if ($type === 'hasAndBelongsToMany') {
if (!empty($subject->hasAndBelongsToMany[$alias]['with'])) {
list($plugin, $joinModel) = pluginSplit($subject->hasAndBelongsToMany[$alias]['with']);
list(, $joinModel) = pluginSplit($subject->hasAndBelongsToMany[$alias]['with']);
} else {
$joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']);
}
@ -422,13 +422,13 @@ class TestTask extends BakeTask {
$models = $subject->uses;
}
foreach ($models as $model) {
list($plugin, $model) = pluginSplit($model);
list(, $model) = pluginSplit($model);
$this->_processModel($subject->{$model});
}
}
/**
* Add classname to the fixture list.
* Add class name to the fixture list.
* Sets the app. or plugin.plugin_name. prefix.
*
* @param string $name Name of the Model class that a fixture might be required for.
@ -452,7 +452,7 @@ class TestTask extends BakeTask {
public function getUserFixtures() {
$proceed = $this->in(__d('cake_console', 'Bake could not detect fixtures, would you like to add some?'), array('y', 'n'), 'n');
$fixtures = array();
if (strtolower($proceed) == 'y') {
if (strtolower($proceed) === 'y') {
$fixtureList = $this->in(__d('cake_console', "Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'"));
$fixtureListTrimmed = str_replace(' ', '', $fixtureList);
$fixtures = explode(',', $fixtureListTrimmed);
@ -466,15 +466,15 @@ class TestTask extends BakeTask {
* Controllers require a mock class.
*
* @param string $type The type of object tests are being generated for eg. controller.
* @return boolean
* @return bool
*/
public function hasMockClass($type) {
$type = strtolower($type);
return $type == 'controller';
return $type === 'controller';
}
/**
* Generate a constructor code snippet for the type and classname
* Generate a constructor code snippet for the type and class name
*
* @param string $type The Type of object you are generating tests for eg. controller
* @param string $fullClassName The Classname of the class the test is being generated for.
@ -484,17 +484,17 @@ class TestTask extends BakeTask {
public function generateConstructor($type, $fullClassName, $plugin) {
$type = strtolower($type);
$pre = $construct = $post = '';
if ($type == 'model') {
if ($type === 'model') {
$construct = "ClassRegistry::init('{$plugin}$fullClassName');\n";
}
if ($type == 'behavior') {
if ($type === 'behavior') {
$construct = "new $fullClassName();\n";
}
if ($type == 'helper') {
if ($type === 'helper') {
$pre = "\$View = new View();\n";
$construct = "new {$fullClassName}(\$View);\n";
}
if ($type == 'component') {
if ($type === 'component') {
$pre = "\$Collection = new ComponentCollection();\n";
$construct = "new {$fullClassName}(\$Collection);\n";
}
@ -502,7 +502,7 @@ class TestTask extends BakeTask {
}
/**
* Generate the uses() calls for a type & classname
* Generate the uses() calls for a type & class name
*
* @param string $type The Type of object you are generating tests for eg. controller
* @param string $realType The package name for the class.
@ -512,11 +512,11 @@ class TestTask extends BakeTask {
public function generateUses($type, $realType, $className) {
$uses = array();
$type = strtolower($type);
if ($type == 'component') {
if ($type === 'component') {
$uses[] = array('ComponentCollection', 'Controller');
$uses[] = array('Component', 'Controller');
}
if ($type == 'helper') {
if ($type === 'helper') {
$uses[] = array('View', 'View');
$uses[] = array('Helper', 'View');
}
@ -543,28 +543,40 @@ class TestTask extends BakeTask {
}
/**
* get the option parser.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(__d('cake_console', 'Bake test case skeletons for classes.'))
->addArgument('type', array(
'help' => __d('cake_console', 'Type of class to bake, can be any of the following: controller, model, helper, component or behavior.'),
'choices' => array(
'Controller', 'controller',
'Model', 'model',
'Helper', 'helper',
'Component', 'component',
'Behavior', 'behavior'
)
))->addArgument('name', array(
'help' => __d('cake_console', 'An existing class to bake tests for.')
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'CamelCased name of the plugin to bake tests for.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
$parser->description(
__d('cake_console', 'Bake test case skeletons for classes.')
)->addArgument('type', array(
'help' => __d('cake_console', 'Type of class to bake, can be any of the following: controller, model, helper, component or behavior.'),
'choices' => array(
'Controller', 'controller',
'Model', 'model',
'Helper', 'helper',
'Component', 'component',
'Behavior', 'behavior'
)
))->addArgument('name', array(
'help' => __d('cake_console', 'An existing class to bake tests for.')
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('plugin', array(
'short' => 'p',
'help' => __d('cake_console', 'CamelCased name of the plugin to bake tests for.')
))->addOption('force', array(
'short' => 'f',
'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
))->epilog(
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
);
return $parser;
}
}

View file

@ -2,18 +2,17 @@
/**
* The View Tasks handles creating and updating view files.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
@ -63,7 +62,7 @@ class ViewTask extends BakeTask {
public $scaffoldActions = array('index', 'view', 'add', 'edit');
/**
* An array of action names that don't require templates. These
* An array of action names that don't require templates. These
* actions will not emit errors when doing bakeActions()
*
* @var array
@ -90,7 +89,7 @@ class ViewTask extends BakeTask {
$this->_interactive();
}
if (empty($this->args[0])) {
return;
return null;
}
if (!isset($this->connection)) {
$this->connection = 'default';
@ -99,7 +98,7 @@ class ViewTask extends BakeTask {
$this->controllerName = $this->_controllerName($this->args[0]);
$this->Project->interactive = false;
if (strtolower($this->args[0]) == 'all') {
if (strtolower($this->args[0]) === 'all') {
return $this->all();
}
@ -152,7 +151,7 @@ class ViewTask extends BakeTask {
unset($methods[$i]);
}
}
if ($method[0] === '_' || $method == strtolower($this->controllerName . 'Controller')) {
if ($method[0] === '_' || $method === strtolower($this->controllerName . 'Controller')) {
unset($methods[$i]);
}
}
@ -207,10 +206,10 @@ class ViewTask extends BakeTask {
$this->Controller->connection = $this->connection;
$this->controllerName = $this->Controller->getName();
$prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if it exist.", $this->controllerName);
$prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if they exist.", $this->controllerName);
$interactive = $this->in($prompt, array('y', 'n'), 'n');
if (strtolower($interactive) == 'n') {
if (strtolower($interactive) === 'n') {
$this->interactive = false;
}
@ -219,13 +218,13 @@ class ViewTask extends BakeTask {
$wannaDoAdmin = $this->in(__d('cake_console', "Would you like to create the views for admin routing?"), array('y', 'n'), 'n');
if (strtolower($wannaDoScaffold) == 'y' || strtolower($wannaDoAdmin) == 'y') {
if (strtolower($wannaDoScaffold) === 'y' || strtolower($wannaDoAdmin) === 'y') {
$vars = $this->_loadController();
if (strtolower($wannaDoScaffold) == 'y') {
if (strtolower($wannaDoScaffold) === 'y') {
$actions = $this->scaffoldActions;
$this->bakeActions($actions, $vars);
}
if (strtolower($wannaDoAdmin) == 'y') {
if (strtolower($wannaDoAdmin) === 'y') {
$admin = $this->Project->getPrefix();
$regularActions = $this->scaffoldActions;
$adminActions = array();
@ -249,7 +248,7 @@ class ViewTask extends BakeTask {
* 'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys',
* 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
*
* @return array Returns an variables to be made available to a view template
* @return array Returns a variables to be made available to a view template
*/
protected function _loadController() {
if (!$this->controllerName) {
@ -266,7 +265,7 @@ class ViewTask extends BakeTask {
if (!class_exists($controllerClassName)) {
$file = $controllerClassName . '.php';
$this->err(__d('cake_console', "The file '%s' could not be found.\nIn order to bake a view, you'll need to first create the controller.", $file));
$this->_stop();
return $this->_stop();
}
$controllerObj = new $controllerClassName();
$controllerObj->plugin = $this->plugin;
@ -299,7 +298,7 @@ class ViewTask extends BakeTask {
* Bake a view file for each of the supplied actions
*
* @param array $actions Array of actions to make files for.
* @param array $vars
* @param array $vars The template variables.
* @return void
*/
public function bakeActions($actions, $vars) {
@ -316,9 +315,9 @@ class ViewTask extends BakeTask {
*/
public function customAction() {
$action = '';
while ($action == '') {
while (!$action) {
$action = $this->in(__d('cake_console', 'Action Name? (use lowercase_underscored function name)'));
if ($action == '') {
if (!$action) {
$this->out(__d('cake_console', 'The action name you supplied was empty. Please try again.'));
}
}
@ -331,12 +330,11 @@ class ViewTask extends BakeTask {
$this->out(__d('cake_console', 'Path: %s', $this->getPath() . $this->controllerName . DS . Inflector::underscore($action) . ".ctp"));
$this->hr();
$looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y');
if (strtolower($looksGood) == 'y') {
if (strtolower($looksGood) === 'y') {
$this->bake($action, ' ');
$this->_stop();
} else {
$this->out(__d('cake_console', 'Bake Aborted.'));
return $this->_stop();
}
$this->out(__d('cake_console', 'Bake Aborted.'));
}
/**
@ -344,7 +342,7 @@ class ViewTask extends BakeTask {
*
* @param string $action Action to bake
* @param string $content Content to write
* @return boolean Success
* @return bool Success
*/
public function bake($action, $content = '') {
if ($content === true) {
@ -414,16 +412,17 @@ class ViewTask extends BakeTask {
}
/**
* get the option parser for this task
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
$parser->description(
__d('cake_console', 'Bake views for a controller, using built-in or custom templates.')
)->addArgument('controller', array(
'help' => __d('cake_console', 'Name of the controller views to bake. Can be Plugin.name as a shortcut for plugin baking.')
'help' => __d('cake_console', 'Name of the controller views to bake. Can be Plugin.name as a shortcut for plugin baking.')
))->addArgument('action', array(
'help' => __d('cake_console', "Will bake a single action's file. core templates are (index, add, edit, view)")
))->addArgument('alias', array(
@ -434,27 +433,37 @@ class ViewTask extends BakeTask {
))->addOption('admin', array(
'help' => __d('cake_console', 'Set to only bake views for a prefix in Routing.prefixes'),
'boolean' => true
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
))->addOption('connection', array(
'short' => 'c',
'help' => __d('cake_console', 'The connection the connected model is on.')
))->addOption('force', array(
'short' => 'f',
'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake all CRUD action views for all controllers. Requires models and controllers to exist.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
))->epilog(
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
);
return $parser;
}
/**
* Returns associations for controllers models.
*
* @param Model $model
* @return array $associations
* @param Model $model The Model instance.
* @return array associations
*/
protected function _associations(Model $model) {
$keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
$associations = array();
foreach ($keys as $key => $type) {
foreach ($keys as $type) {
foreach ($model->{$type} as $assocKey => $assocData) {
list($plugin, $modelClass) = pluginSplit($assocData['className']);
list(, $modelClass) = pluginSplit($assocData['className']);
$associations[$type][$assocKey]['primaryKey'] = $model->{$assocKey}->primaryKey;
$associations[$type][$assocKey]['displayField'] = $model->{$assocKey}->displayField;
$associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];