Merge branch '2.0' of github.com:cakephp/cakephp into 2.0

This commit is contained in:
Jose Lorenzo Rodriguez 2011-08-11 13:17:19 -04:30
commit 9b6ea7dc45
45 changed files with 685 additions and 204 deletions

View file

@ -247,7 +247,6 @@
* 'serialize' => true, [optional]
* ));
*
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
@ -263,12 +262,11 @@
* 'engine' => 'Xcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
*
* Memcache (http://www.danga.com/memcached/)
*
* Cache::config('default', array(
@ -281,9 +279,16 @@
* ), //[optional]
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* ));
*
* Wincache (http://php.net/wincache)
*
* Cache::config('default', array(
* 'engine' => 'Wincache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*/
/**
@ -315,7 +320,7 @@ Cache::config('_cake_core_', array(
));
/**
* Configure the cache for model, and datasource caches. This cache configuration
* Configure the cache for model and datasource caches. This cache configuration
* is used to store schema descriptions, and table listings in connections.
*/
Cache::config('_cake_model_', array(

View file

@ -3,8 +3,6 @@
/**
* Command-line code generation utility to automate programmer chores.
*
* Shell dispatcher class
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
@ -15,10 +13,29 @@
*
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.console
* @since CakePHP(tm) v 1.2.0.5012
* @package app.Console
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require_once(dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'lib'. DIRECTORY_SEPARATOR . 'Cake' . DIRECTORY_SEPARATOR . 'Console' . DIRECTORY_SEPARATOR . 'ShellDispatcher.php');
$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';
$found = false;
$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($paths as $path) {
if (file_exists($path . $ds . $dispatcher)) {
$found = $path;
}
}
if (!$found && function_exists('ini_set')) {
$root = dirname(dirname(dirname(__FILE__)));
ini_set('include_path', $root . $ds. 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include($dispatcher)) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $found, $dispatcher, $root, $ds);
return ShellDispatcher::run($argv);

View file

@ -44,13 +44,19 @@
if (!defined('APP_DIR')) {
define('APP_DIR', basename(dirname(dirname(__FILE__))));
}
/**
* The absolute path to the "cake" directory, WITHOUT a trailing DS.
*
* Un-comment this line to specify a fixed path to CakePHP.
* This should point at the directory containg `Cake`.
*
* For ease of development CakePHP uses PHP's include_path. If you
* cannot modify your include_path set this value.
*
* Leaving this constant undefined will result in it being defined in Cake/bootstrap.php
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
}
//define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
/**
* Editing below this line should NOT be necessary.
@ -63,11 +69,20 @@
if (!defined('WWW_ROOT')) {
define('WWW_ROOT', dirname(__FILE__) . DS);
}
if (!defined('CORE_PATH')) {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
} else {
if (!include(CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
}
if (!include(CORE_PATH . 'Cake' . DS . 'bootstrap.php')) {
if (!empty($failed)) {
trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
}

View file

@ -44,13 +44,16 @@ ini_set('display_errors', 1);
if (!defined('APP_DIR')) {
define('APP_DIR', basename(dirname(dirname(__FILE__))));
}
/**
* The absolute path to the "Cake" directory, WITHOUT a trailing DS.
*
* For ease of development CakePHP uses PHP's include_path. If you
* need to cannot modify your include_path, you can set this path.
*
* Leaving this constant undefined will result in it being defined in Cake/bootstrap.php
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
}
//define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
/**
* Editing below this line should not be necessary.
@ -63,11 +66,20 @@ if (!defined('WEBROOT_DIR')) {
if (!defined('WWW_ROOT')) {
define('WWW_ROOT', dirname(__FILE__) . DS);
}
if (!defined('CORE_PATH')) {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
} else {
if (!include(CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
}
if (!include(CORE_PATH . 'Cake' . DS . 'bootstrap.php')) {
if (!empty($failed)) {
trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
}

View file

@ -37,10 +37,4 @@
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
}
/**
* Set the include path or define app and core path
*/
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
require APP_DIR . DS . WEBROOT_DIR . DS . 'index.php';

View file

@ -82,7 +82,7 @@ class Cache {
*
* `Cache::config('default');`
*
* There are 4 built-in caching engines:
* There are 5 built-in caching engines:
*
* - `FileEngine` - Uses simple files to store content. Poor performance, but good for
* storing large objects, or things that are not IO sensitive.
@ -90,6 +90,7 @@ class Cache {
* - `MemcacheEngine` - Uses the PECL::Memcache extension and Memcached for storage.
* Fast reads/writes, and benefits from memcache being distributed.
* - `XcacheEngine` - Uses the Xcache extension, an alternative to APC.
* - `WincacheEngine` - Uses Windows Cache Extension for PHP. Supports wincache 1.1.0 and higher.
*
* The following keys are used in core cache engines:
*

View file

@ -45,7 +45,7 @@ class CommandListShell extends Shell {
if (empty($this->params['xml'])) {
$this->out(__d('cake_console', "<info>Current Paths:</info>"), 2);
$this->out(" -app: ". APP_DIR);
$this->out(" -working: " . rtrim(APP_PATH, DS));
$this->out(" -working: " . rtrim(APP, DS));
$this->out(" -root: " . rtrim(ROOT, DS));
$this->out(" -core: " . rtrim(CORE_PATH, DS));
$this->out("");

View file

@ -50,8 +50,9 @@ class ProjectTask extends Shell {
while (!$project) {
$prompt = __d('cake_console', "What is the path to the project you want to bake?");
$project = $this->in($prompt, null, APP_PATH . 'myapp');
$project = $this->in($prompt, null, APP . 'myapp');
}
if ($project && !Folder::isAbsolute($project) && isset($_SERVER['PWD'])) {
$project = $_SERVER['PWD'] . DS . $project;
@ -97,20 +98,24 @@ class ProjectTask extends Shell {
$success = false;
}
$this->out(__d('cake_console', 'The value for CAKE_CORE_INCLUDE_PATH can be hardcoded set to %s in webroot/index.php', CAKE_CORE_INCLUDE_PATH));
$this->out(__d('cake_console', '<warning>If you hard code it, the project will possibly run only in your computer.</warning>'));
$setConstants = $this->in(__d('cake_console', 'Do you want to set CAKE_CORE_INCLUDE_PATH in webroot/index.php?'), array('y', 'n'), 'n');
if (strtolower($setConstants) === 'y') {
if ($this->corePath($path) === true) {
$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', ' * <warning>Remember to check these values after moving to production server</warning>'));
} 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;
}
$hardCode = false;
if ($this->cakeOnIncludePath()) {
$this->out(__d('cake_console', '<info>CakePHP is on your `include_path`. CAKE_CORE_INCLUDE_PATH will be set, but commented out.</info>'));
} else {
$this->out(__d('cake_console', '<warning>Please make sure your cake core is accessible, if you have problems edit CAKE_CORE_INCLUDE_PATH in webroot/index.php</warning>'));
$this->out(__d('cake_console', '<warning>CakePHP is not on your `include_path`, CAKE_CORE_INCLUDE_PATH will be hard coded.</warning>'));
$this->out(__d('cake_console', 'You can fix this by adding CakePHP to your `include_path`.'));
$hardCode = true;
}
$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));
} 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;
}
if ($success && $hardCode) {
$this->out(__d('cake_console', ' * <warning>Remember to check these values after moving to production server</warning>'));
}
$Folder = new Folder($path);
@ -128,6 +133,21 @@ class ProjectTask extends Shell {
}
}
/**
* Checks PHP's include_path for CakePHP.
*
* @return bool Indicates whether or not CakePHP exists on include_path
*/
public function cakeOnIncludePath() {
$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($paths as $path) {
if (file_exists($path . DS . 'Cake' . DS . 'bootstrap.php')) {
return true;
}
}
return false;
}
/**
* Looks for a skeleton template of a Cake application,
* and if not found asks the user for a path. When there is a path
@ -225,8 +245,8 @@ class ProjectTask extends Shell {
$File = new File($path . 'Console' . DS . 'cake.php');
$contents = $File->read();
if (preg_match('/(__CAKE_PATH__)/', $contents, $match)) {
$path = CAKE . 'Console' . DS;
$replacement = "'" . str_replace(DS, "' . DIRECTORY_SEPARATOR . '", $path) . "'";
$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;
@ -283,36 +303,49 @@ class ProjectTask extends Shell {
* Generates and writes CAKE_CORE_INCLUDE_PATH
*
* @param string $path Project path
* @param bool $hardCode Wether or not define calls should be hardcoded.
* @return boolean Success
*/
public function corePath($path) {
public function corePath($path, $hardCode = true) {
if (dirname($path) !== CAKE_CORE_INCLUDE_PATH) {
$File = new File($path . 'webroot' . DS . 'index.php');
$contents = $File->read();
if (preg_match('/([\s]*define\(\'CAKE_CORE_INCLUDE_PATH\',[\s\'A-z0-9\.]*\);)/', $contents, $match)) {
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
$result = str_replace($match[0], "\n\t\tdefine('CAKE_CORE_INCLUDE_PATH', " . $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "');", $contents);
if (!$File->write($result)) {
return false;
}
} else {
$filename = $path . 'webroot' . DS . 'index.php';
if (!$this->_replaceCorePath($filename, $hardCode)) {
return false;
}
$File = new File($path . 'webroot' . DS . 'test.php');
$contents = $File->read();
if (preg_match('/([\s]*define\(\'CAKE_CORE_INCLUDE_PATH\',[\s\'A-z0-9\.]*\);)/', $contents, $match)) {
$result = str_replace($match[0], "\n\t\tdefine('CAKE_CORE_INCLUDE_PATH', " . $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "');", $contents);
if (!$File->write($result)) {
return false;
}
} else {
$filename = $path . 'webroot' . DS . 'test.php';
if (!$this->_replaceCorePath($filename, $hardCode)) {
return false;
}
return true;
}
}
/**
* 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.
* @retun bool Success
*/
protected function _replaceCorePath($filename, $hardCode) {
$contents = file_get_contents($filename);
$root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'";
$corePath = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'";
$result = str_replace('__CAKE_PATH__', $corePath, $contents, $count);
if ($hardCode) {
$result = str_replace('//define(\'CAKE_CORE', 'define(\'CAKE_CORE', $result);
}
if (!file_put_contents($filename, $result)) {
return false;
}
if ($count == 0) {
return false;
}
return true;
}
/**
* Enables Configure::read('Routing.prefixes') in /app/Config/core.php
*

View file

@ -71,6 +71,10 @@ class UpgradeShell extends Shell {
public function locations() {
$cwd = getcwd();
if (!empty($this->params['plugin'])) {
chdir(App::pluginPath($this->params['plugin']));
}
if (is_dir('plugins')) {
$Folder = new Folder('plugins');

View file

@ -89,6 +89,11 @@ class ConsoleInputOption {
$this->_default = $default;
$this->_choices = $choices;
}
if (strlen($this->_short) > 1) {
throw new ConsoleException(
__d('cake_console', 'Short options must be one letter.')
);
}
}
/**

View file

@ -41,7 +41,8 @@ App::uses('HelpFormatter', 'Console');
*
* Options can be defined with both long and short forms. By using `$parser->addOption()`
* you can define new options. The name of the option is used as its long form, and you
* can supply an additional short form, with the `short` option.
* can supply an additional short form, with the `short` option. Short options should
* only be one letter long. Using more than one letter for a short option will raise an exception.
*
* Calling options can be done using syntax similar to most *nix command line tools. Long options
* cane either include an `=` or leave it out.
@ -52,6 +53,15 @@ App::uses('HelpFormatter', 'Console');
*
* `cake myshell command -cn`
*
* Short options can be combined into groups as seen above. Each letter in a group
* will be treated as a separate option. The previous example is equivalent to:
*
* `cake myshell command -c -n`
*
* Short options can also accept values:
*
* `cake myshell command -c default`
*
* ### Positional arguments
*
* If no positional arguments are defined, all of them will be parsed. If you define positional
@ -116,6 +126,13 @@ class ConsoleOptionParser {
*/
protected $_subcommands = array();
/**
* Command name.
*
* @var string
*/
protected $_command = '';
/**
* Construct an OptionParser so you can define its behavior
*
@ -124,7 +141,7 @@ class ConsoleOptionParser {
* this to false will prevent the addition of `--verbose` & `--quiet` options.
*/
public function __construct($command = null, $defaultOptions = true) {
$this->_command = $command;
$this->command($command);
$this->addOption('help', array(
'short' => 'h',
@ -206,7 +223,7 @@ class ConsoleOptionParser {
*/
public function command($text = null) {
if ($text !== null) {
$this->_command = $text;
$this->_command = Inflector::underscore($text);
return $this;
}
return $this->_command;
@ -562,7 +579,7 @@ class ConsoleOptionParser {
$option = $this->_options[$name];
$isBoolean = $option->isBoolean();
$nextValue = $this->_nextToken();
if (!$isBoolean && !empty($nextValue) && $nextValue{0} != '-') {
if (!$isBoolean && !empty($nextValue) && !$this->_optionExists($nextValue)) {
array_shift($this->_tokens);
$value = $nextValue;
} elseif ($isBoolean) {
@ -576,6 +593,23 @@ class ConsoleOptionParser {
}
}
/**
* Check to see if $name has an option (short/long) defined for it.
*
* @param string $name The name of the option.
* @return boolean
*/
protected function _optionExists($name) {
if (substr($name, 0, 2) === '--') {
return isset($this->_options[substr($name, 2)]);
}
if ($name{0} === '-' && $name{1} !== '-') {
return isset($this->_shortOptions[$name{1}]);
}
return false;
}
/**
* Parse an argument, and ensure that the argument doesn't exceed the number of arguments
* and that the argument is a valid choice.

View file

@ -29,6 +29,20 @@ App::uses('String', 'Utility');
* @since CakePHP(tm) v 2.0
*/
class HelpFormatter {
/**
* The maximum number of arguments shown when generating usage.
*
* @var integer
*/
protected $_maxArgs = 6;
/**
* The maximum number of options shown when generating usage.
*
* @var integer
*/
protected $_maxOptions = 6;
/**
* Build the help formatter for a an OptionParser
*
@ -122,12 +136,22 @@ class HelpFormatter {
if (!empty($subcommands)) {
$usage[] = '[subcommand]';
}
$options = array();
foreach ($this->_parser->options() as $option) {
$usage[] = $option->usage();
$options[] = $option->usage();
}
if (count($options) > $this->_maxOptions){
$options = array('[options]');
}
$usage = array_merge($usage, $options);
$args = array();
foreach ($this->_parser->arguments() as $argument) {
$usage[] = $argument->usage();
$args[] = $argument->usage();
}
if (count($args) > $this->_maxArgs) {
$args = array('[arguments]');
}
$usage = array_merge($usage, $args);
return implode(' ', $usage);
}

View file

@ -206,7 +206,7 @@ class Shell extends Object {
$this->out(__d('cake_console', '<info>Welcome to CakePHP %s Console</info>', 'v' . Configure::version()));
$this->hr();
$this->out(__d('cake_console', 'App : %s', APP_DIR));
$this->out(__d('cake_console', 'Path: %s', APP_PATH));
$this->out(__d('cake_console', 'Path: %s', APP));
$this->hr();
}
@ -389,7 +389,7 @@ class Shell extends Object {
$format = 'text';
if (!empty($this->args[0]) && $this->args[0] == 'xml') {
$format = 'xml';
$this->output->outputAs(ConsoleOutput::RAW);
$this->stdout->outputAs(ConsoleOutput::RAW);
} else {
$this->_welcome();
}

View file

@ -122,15 +122,15 @@ class ShellDispatcher {
private function __bootstrap() {
define('ROOT', $this->params['root']);
define('APP_DIR', $this->params['app']);
define('APP_PATH', $this->params['working'] . DS);
define('WWW_ROOT', APP_PATH . $this->params['webroot'] . DS);
define('APP', $this->params['working'] . DS);
define('WWW_ROOT', APP . $this->params['webroot'] . DS);
if (!is_dir(ROOT . DS . APP_DIR . DS . 'tmp')) {
define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS);
}
$boot = file_exists(ROOT . DS . APP_DIR . DS . 'Config' . DS . 'bootstrap.php');
require CORE_PATH . 'Cake' . DS . 'bootstrap.php';
if (!file_exists(APP_PATH . 'Config' . DS . 'core.php')) {
if (!file_exists(APP . 'Config' . DS . 'core.php')) {
include_once CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'Config' . DS . 'core.php';
App::build();
}

View file

@ -247,7 +247,6 @@
* 'serialize' => true, [optional]
* ));
*
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
@ -263,12 +262,11 @@
* 'engine' => 'Xcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
*
* Memcache (http://www.danga.com/memcached/)
*
* Cache::config('default', array(
@ -281,9 +279,16 @@
* ), //[optional]
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* ));
*
* Wincache (http://php.net/wincache)
*
* Cache::config('default', array(
* 'engine' => 'Wincache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*/
/**
@ -315,7 +320,7 @@ Cache::config('_cake_core_', array(
));
/**
* Configure the cache for model, and datasource caches. This cache configuration
* Configure the cache for model and datasource caches. This cache configuration
* is used to store schema descriptions, and table listings in connections.
*/
Cache::config('_cake_model_', array(

View file

@ -3,8 +3,6 @@
/**
* Command-line code generation utility to automate programmer chores.
*
* Shell dispatcher class
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
@ -16,9 +14,28 @@
* @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Console
* @since CakePHP(tm) v 1.2.0.5012
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require_once(__CAKE_PATH__ . 'ShellDispatcher.php');
$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';
$found = false;
$paths = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($paths as $path) {
if (file_exists($path . $ds . $dispatcher)) {
$found = $path;
}
}
if (!$found && function_exists('ini_set')) {
$root = dirname(dirname(dirname(__FILE__)));
ini_set('include_path', __CAKE_PATH__ . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include($dispatcher)) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $found, $dispatcher, $root, $ds);
return ShellDispatcher::run($argv);

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

Before

Width:  |  Height:  |  Size: 496 B

After

Width:  |  Height:  |  Size: 496 B

View file

Before

Width:  |  Height:  |  Size: 783 B

After

Width:  |  Height:  |  Size: 783 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -44,13 +44,19 @@
if (!defined('APP_DIR')) {
define('APP_DIR', basename(dirname(dirname(__FILE__))));
}
/**
* The absolute path to the "cake" directory, WITHOUT a trailing DS.
*
* Un-comment this line to specify a fixed path to CakePHP.
* This should point at the directory containg `Cake`.
*
* For ease of development CakePHP uses PHP's include_path. If you
* need to squeeze a bit more performance you can set this path.
*
* Leaving this constant undefined will result in it being defined in Cake/bootstrap.php
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
}
//define('CAKE_CORE_INCLUDE_PATH', __CAKE_PATH__);
/**
* Editing below this line should NOT be necessary.
@ -63,11 +69,17 @@
if (!defined('WWW_ROOT')) {
define('WWW_ROOT', dirname(__FILE__) . DS);
}
if (!defined('CORE_PATH')) {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
} else {
if (!include(CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
}
if (!include(CORE_PATH . 'Cake' . DS . 'bootstrap.php')) {
if (!empty($failed)) {
trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
}
@ -76,5 +88,6 @@
}
App::uses('Dispatcher', 'Routing');
$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse(array('charset' => Configure::read('App.encoding'))));

View file

@ -44,13 +44,16 @@ ini_set('display_errors', 1);
if (!defined('APP_DIR')) {
define('APP_DIR', basename(dirname(dirname(__FILE__))));
}
/**
* The absolute path to the "Cake" directory, WITHOUT a trailing DS.
*
* For ease of development CakePHP uses PHP's include_path. If you
* need to cannot modify your include_path, you can set this path.
*
* Leaving this constant undefined will result in it being defined in Cake/bootstrap.php
*/
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib');
}
//define('CAKE_CORE_INCLUDE_PATH', __CAKE_PATH__);
/**
* Editing below this line should not be necessary.
@ -63,11 +66,17 @@ if (!defined('WEBROOT_DIR')) {
if (!defined('WWW_ROOT')) {
define('WWW_ROOT', dirname(__FILE__) . DS);
}
if (!defined('CORE_PATH')) {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
} else {
if (!include(CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php')) {
$failed = true;
}
}
if (!include(CORE_PATH . 'Cake' . DS . 'bootstrap.php')) {
if (!empty($failed)) {
trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR);
}

View file

@ -19,6 +19,6 @@
* @since CakePHP(tm) v 1.2.0.5012
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR. 'ShellDispatcher.php');
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ShellDispatcher.php');
return ShellDispatcher::run($argv);

View file

@ -491,7 +491,7 @@ class Controller extends Object {
if (!$privateAction && !empty($prefixes)) {
if (empty($request->params['prefix']) && strpos($request->params['action'], '_') > 0) {
list($prefix, $action) = explode('_', $request->params['action']);
list($prefix) = explode('_', $request->params['action']);
$privateAction = in_array($prefix, $prefixes);
}
}
@ -877,7 +877,7 @@ class Controller extends Object {
$currentObject = ClassRegistry::getObject($currentModel);
if (is_a($currentObject, 'Model')) {
$className = get_class($currentObject);
list($plugin, $package) = pluginSplit(App::location($className));
list($plugin) = pluginSplit(App::location($className));
$this->request->params['models'][$currentObject->alias] = compact('plugin', 'className');
$View->validationErrors[$currentObject->alias] =& $currentObject->validationErrors;
}

View file

@ -320,7 +320,7 @@ class Configure {
*/
public static function version() {
if (!isset(self::$_values['Cake']['version'])) {
require(CAKE . 'Config' . DS . 'config.php');
require CAKE . 'Config' . DS . 'config.php';
self::write($config);
}
return self::$_values['Cake']['version'];

View file

@ -42,6 +42,19 @@
* using CakeLogs's methods. If you don't configure any adapters, and write to the logs
* a default FileLog will be autoconfigured for you.
*
* ### Configuring Log adapters
*
* You can configure log adapters in your applications `bootstrap.php` file. A sample configuration
* would look like:
*
* `CakeLog::config('my_log', array('engine' => 'FileLog'));`
*
* See the documentation on CakeLog::config() for more detail.
*
* ### Writing to the log
*
* You write to the logs using CakeLog::write(). See its documentation for more information.
*
* @package Cake.Log
*/
class CakeLog {
@ -69,11 +82,7 @@ class CakeLog {
*
* Will configure a FileLog instance to use the specified path. All options that are not `engine`
* are passed onto the logging adapter, and handled there. Any class can be configured as a logging
* adapter as long as it implements a `write` method with the following signature.
*
* `write($type, $message)`
*
* For an explaination of these parameters, see CakeLog::write()
* adapter as long as it implements the methods in CakeLogInterface.
*
* @param string $key The keyname for this logger, used to remove the logger later.
* @param array $config Array of configuration information for the logger
@ -190,7 +199,7 @@ class CakeLog {
if (empty(self::$_streams)) {
self::_autoConfig();
}
foreach (self::$_streams as $key => $logger) {
foreach (self::$_streams as $logger) {
$logger->write($type, $message);
}
return true;

View file

@ -73,7 +73,7 @@ class AclBehavior extends ModelBehavior {
if (empty($type)) {
$type = $this->__typeMaps[$this->settings[$model->name]['type']];
if (is_array($type)) {
trigger_error(__('AclBehavior is setup with more then one type, please specify type parameter for node()', true), E_USER_WARNING);
trigger_error(__d('cake_dev', 'AclBehavior is setup with more then one type, please specify type parameter for node()'), E_USER_WARNING);
return null;
}
}

View file

@ -219,7 +219,7 @@ class TreeBehavior extends ModelBehavior {
if ($id === null) {
return $Model->find('count', array('conditions' => $scope));
} elseif (isset($Model->data[$Model->alias][$left]) && isset($Model->data[$Model->alias][$right])) {
} elseif ($Model->id === $id && isset($Model->data[$Model->alias][$left]) && isset($Model->data[$Model->alias][$right])) {
$data = $Model->data[$Model->alias];
} else {
$data = $Model->find('first', array('conditions' => array($scope, $Model->escapeField() => $id), 'recursive' => $recursive));

View file

@ -613,7 +613,7 @@ class CakeRequest implements ArrayAccess {
$acceptTypes = explode(',', $this->header('accept'));
foreach ($acceptTypes as $i => $accepted) {
if (strpos($accepted, ';') !== false) {
list($accepted, $prefValue) = explode(';', $accepted);
list($accepted) = explode(';', $accepted);
$acceptTypes[$i] = $accepted;
}
}

View file

@ -572,7 +572,6 @@ class CakeResponse {
if (is_array($ctype)) {
return array_map(array($this, 'mapType'), $ctype);
}
$keys = array_keys($this->_mimeTypes);
foreach ($this->_mimeTypes as $alias => $types) {
if (is_array($types) && in_array($ctype, $types)) {

View file

@ -156,7 +156,7 @@ class CakeRoute {
}
$names[] = $name;
}
if (preg_match('#\/\*$#', $route, $m)) {
if (preg_match('#\/\*$#', $route)) {
$parsed = preg_replace('#/\\\\\*$#', '(?:/(?P<_args_>.*))?', $parsed);
$this->_greedy = true;
}
@ -281,7 +281,7 @@ class CakeRoute {
if ((!isset($this->options['named']) || !empty($this->options['named'])) && $separatorIsPresent) {
list($key, $val) = explode($namedConfig['separator'], $param, 2);
$hasRule = isset($rules[$key]);
$passIt = (!$hasRule && !$greedy) || ($hasRule && !$this->_matchNamed($key, $val, $rules[$key], $context));
$passIt = (!$hasRule && !$greedy) || ($hasRule && !$this->_matchNamed($val, $rules[$key], $context));
if ($passIt) {
$pass[] = $param;
} else {
@ -314,13 +314,12 @@ class CakeRoute {
* Return true if a given named $param's $val matches a given $rule depending on $context. Currently implemented
* rule types are controller, action and match that can be combined with each other.
*
* @param string $param The name of the named parameter
* @param string $val The value of the named parameter
* @param array $rule The rule(s) to apply, can also be a match string
* @param string $context An array with additional context information (controller / action)
* @return boolean
*/
protected function _matchNamed($param, $val, $rule, $context) {
protected function _matchNamed($val, $rule, $context) {
if ($rule === true || $rule === false) {
return $rule;
}
@ -512,4 +511,4 @@ class CakeRoute {
return $out;
}
}
}

View file

@ -118,37 +118,42 @@ class ProjectTaskTest extends CakeTestCase {
$path = $this->Task->args[0] = TMP . 'tests' . DS . 'bake_test_app';
$this->Task->params['skel'] = CAKE . 'Console' . DS . 'Templates' . DS . 'skel';
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
$this->Task->expects($this->at(3))->method('in')->will($this->returnValue('n'));
$this->Task->execute();
$this->assertTrue(is_dir($this->Task->args[0]), 'No project dir');
$file = new File($path . DS . 'webroot' . DS . 'index.php');
$contents = $file->read();
$this->assertPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
$this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents);
$file = new File($path . DS . 'webroot' . DS . 'test.php');
$contents = $file->read();
$this->assertPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
$this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents);
}
/**
* test bake with setting CAKE_CORE_INCLUDE_PATH in webroot/index.php
* test bake with CakePHP on the include path. The constants should remain commented out.
*
* @return void
*/
public function testExecuteWithSettingIncludePath() {
public function testExecuteWithCakeOnIncludePath() {
if (!function_exists('ini_set')) {
$this->markTestAsSkipped('Not access to ini_set, cannot proceed.');
}
$restore = ini_get('include_path');
ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . $restore);
$path = $this->Task->args[0] = TMP . 'tests' . DS . 'bake_test_app';
$this->Task->params['skel'] = CAKE . 'Console' . DS . 'Templates' . DS . 'skel';
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
$this->Task->expects($this->at(3))->method('in')->will($this->returnValue('y'));
$this->Task->execute();
$this->assertTrue(is_dir($this->Task->args[0]), 'No project dir');
$file = new File($path . DS . 'webroot' . DS . 'index.php');
$contents = $file->read();
$this->assertNoPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
$file = new File($path . DS . 'webroot' . DS . 'test.php');
$contents = $file->read();
$this->assertNoPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
$contents = file_get_contents($path . DS . 'webroot' . DS . 'index.php');
$this->assertRegExp('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents);
$contents = file_get_contents($path . DS . 'webroot' . DS . 'test.php');
$this->assertRegExp('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents);
ini_set('include_path', $restore);
}
/**

View file

@ -139,6 +139,18 @@ class ConsoleOptionParserTest extends CakeTestCase {
$this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Short parameter did not parse out');
}
/**
* Test that adding an option using a two letter short value causes an exception.
* As they will not parse correctly.
*
* @expectedException ConsoleException
* @return void
*/
public function testAddOptionShortOneLetter() {
$parser = new ConsoleOptionParser('test', false);
$parser->addOption('test', array('short' => 'te'));
}
/**
* test adding and using boolean options.
*
@ -255,6 +267,21 @@ class ConsoleOptionParserTest extends CakeTestCase {
$result = $parser->parse(array('--name', 'jimmy'));
}
/**
* Ensure that option values can start with -
*
* @return void
*/
public function testOptionWithValueStartingWithMinus() {
$parser = new ConsoleOptionParser('test', false);
$parser->addOption('name')
->addOption('age');
$result = $parser->parse(array('--name', '-foo', '--age', 'old'));
$expected = array('name' => '-foo', 'age' => 'old', 'help' => false);
$this->assertEquals($expected, $result[0], 'Option values starting with "-" are broken.');
}
/**
* test positional argument parsing.
*
@ -496,6 +523,16 @@ TEXT;
$this->assertEquals('factory', $parser->command());
}
/**
* test that command() inflects the command name.
*
* @return void
*/
public function testCommandInflection() {
$parser = new ConsoleOptionParser('CommandLine');
$this->assertEquals('command_line', $parser->command());
}
/**
* test that parse() takes a subcommand argument, and that the subcommand parser
* is used.
@ -529,4 +566,4 @@ TEXT;
$this->assertEquals($expected, $result, 'Sub parser did not parse request.');
}
}
}

View file

@ -210,6 +210,54 @@ TEXT;
$this->assertEquals($expected, $result, 'Help does not match');
}
/**
* Test that a long set of options doesn't make useless output.
*
* @return void
*/
public function testHelpWithLotsOfOptions() {
$parser = new ConsoleOptionParser('mycommand', false);
$parser
->addOption('test', array('help' => 'A test option.'))
->addOption('test2', array('help' => 'A test option.'))
->addOption('test3', array('help' => 'A test option.'))
->addOption('test4', array('help' => 'A test option.'))
->addOption('test5', array('help' => 'A test option.'))
->addOption('test6', array('help' => 'A test option.'))
->addOption('test7', array('help' => 'A test option.'))
->addArgument('model', array('help' => 'The model to make.', 'required' => true))
->addArgument('other_longer', array('help' => 'Another argument.'));
$formatter = new HelpFormatter($parser);
$result = $formatter->text();
$expected = 'cake mycommand [options] <model> [<other_longer>]';
$this->assertContains($expected, $result);
}
/**
* Test that a long set of arguments doesn't make useless output.
*
* @return void
*/
public function testHelpWithLotsOfArguments() {
$parser = new ConsoleOptionParser('mycommand', false);
$parser
->addArgument('test', array('help' => 'A test option.'))
->addArgument('test2', array('help' => 'A test option.'))
->addArgument('test3', array('help' => 'A test option.'))
->addArgument('test4', array('help' => 'A test option.'))
->addArgument('test5', array('help' => 'A test option.'))
->addArgument('test6', array('help' => 'A test option.'))
->addArgument('test7', array('help' => 'A test option.'))
->addArgument('model', array('help' => 'The model to make.', 'required' => true))
->addArgument('other_longer', array('help' => 'Another argument.'));
$formatter = new HelpFormatter($parser);
$result = $formatter->text();
$expected = 'cake mycommand [-h] [arguments]';
$this->assertContains($expected, $result);
}
/**
* test help() with options and arguments that have choices.
*
@ -437,4 +485,4 @@ TEXT;
$result = $formatter->xml(false);
$this->assertInstanceOf('SimpleXmlElement', $result);
}
}
}

View file

@ -1118,6 +1118,11 @@ class TreeBehaviorNumberTest extends CakeTestCase {
$total = $this->Tree->childCount();
$this->assertEqual($total, 6);
$this->Tree->read(null, $data[$modelClass]['id']);
$id = $this->Tree->field('id', array($modelClass . '.name' => '1.2'));
$total = $this->Tree->childCount($id);
$this->assertEqual($total, 2);
}
/**

View file

@ -97,7 +97,8 @@ class Contact extends CakeTestModel {
'password' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
'published' => array('type' => 'date', 'null' => true, 'default' => null, 'length' => null),
'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''),
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null),
'age' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => null)
);
/**
@ -886,6 +887,36 @@ class FormHelperTest extends CakeTestCase {
'/div'
);
}
/**
* Tests correct generation of text fields for double and float fields
*
* @access public
* @return void
*/
public function testTextFieldTypeNumberGenerationForIntegers() {
$model = ClassRegistry::getObject('Contact');
$model->setSchema(array('foo' => array(
'type' => 'integer',
'null' => false,
'default' => null,
'length' => null
)));
$this->Form->create('Contact');
$result = $this->Form->input('foo');
$expected = array(
'div' => array('class' => 'input text'),
'label' => array('for' => 'ContactFoo'),
'Foo',
'/label',
array('input' => array(
'type' => 'number', 'name' => 'data[Contact][foo]',
'id' => 'ContactFoo'
)),
'/div'
);
}
/**
* testFormSecurityMultipleFields method
@ -1672,7 +1703,7 @@ class FormHelperTest extends CakeTestCase {
'label' => array('for'),
'Balance',
'/label',
'input' => array('name', 'type' => 'text', 'maxlength' => 8, 'id'),
'input' => array('name', 'type' => 'number', 'maxlength' => 8, 'id'),
'/div',
);
$this->assertTags($result, $expected);
@ -2477,6 +2508,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
);
@ -2500,6 +2533,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
);
@ -2524,6 +2559,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
'/fieldset'
@ -2548,6 +2585,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
);
@ -2575,6 +2614,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
'/fieldset'
@ -2603,6 +2644,8 @@ class FormHelperTest extends CakeTestCase {
'*/div',
array('div' => array('class' => 'input datetime')),
'*/div',
array('div' => array('class' => 'input number')),
'*/div',
array('div' => array('class' => 'input select')),
'*/div',
'/fieldset'
@ -5658,6 +5701,35 @@ class FormHelperTest extends CakeTestCase {
$this->assertTrue(strpos($result, '<input type="hidden" name="data[extra]" value="value"/>') !== false);
}
/**
* Test that postButton adds _Token fields.
*
* @return void
*/
public function testSecurePostButton() {
$this->Form->request->params['_Token'] = array('key' => 'testkey');
$result = $this->Form->postButton('Delete', '/posts/delete/1');
$expected = array(
'form' => array(
'method' => 'post', 'action' => '/posts/delete/1', 'accept-charset' => 'utf-8',
'style' => 'display:none;'
),
array('div' => array('style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/')),
'/div',
'button' => array('type' => 'submit'),
'Delete',
'/button',
array('div' => array('style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/')),
'/div',
'/form',
);
$this->assertTags($result, $expected);
}
/**
* testPostLink method
*
@ -5670,9 +5742,7 @@ class FormHelperTest extends CakeTestCase {
'method' => 'post', 'action' => '/posts/delete/1',
'name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;'
),
'div' => array('style' => 'display:none;'),
'input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST'),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\); event\.returnValue = false; return false;/'),
'Delete',
@ -5685,9 +5755,7 @@ class FormHelperTest extends CakeTestCase {
'method' => 'post', 'action' => '/posts/delete/1',
'name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;'
),
'div' => array('style' => 'display:none;'),
'input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST'),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/if \(confirm\(&#039;Confirm\?&#039;\)\) \{ document\.post_\w+\.submit\(\); \} event\.returnValue = false; return false;/'),
'Delete',
@ -5695,7 +5763,35 @@ class FormHelperTest extends CakeTestCase {
));
$result = $this->Form->postLink('Delete', '/posts/delete', array('data' => array('id' => 1)));
$this->assertTrue(strpos($result, '<input type="hidden" name="data[id]" value="1"/>') !== false);
$this->assertContains('<input type="hidden" name="data[id]" value="1"/>', $result);
}
/**
* Test that postLink adds _Token fields.
*
* @return void
*/
public function testSecurePostLink() {
$this->Form->request->params['_Token'] = array('key' => 'testkey');
$result = $this->Form->postLink('Delete', '/posts/delete/1');
$expected = array(
'form' => array(
'method' => 'post', 'action' => '/posts/delete/1',
'name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;'
),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][key]', 'value' => 'testkey', 'id' => 'preg:/Token\d+/')),
'div' => array('style' => 'display:none;'),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][fields]', 'value' => 'preg:/[\w\d%]+/', 'id' => 'preg:/TokenFields\d+/')),
array('input' => array('type' => 'hidden', 'name' => 'data[_Token][unlocked]', 'value' => '', 'id' => 'preg:/TokenUnlocked\d+/')),
'/div',
'/form',
'a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\); event\.returnValue = false; return false;/'),
'Delete',
'/a'
);
$this->assertTags($result, $expected);
}
/**
@ -7287,6 +7383,12 @@ class FormHelperTest extends CakeTestCase {
'input' => array('type' => 'text', 'name' => 'data[User][query]', 'id' => 'UserQuery', 'value' => 'test')
);
$this->assertTags($result, $expected);
$result = $this->Form->input('User.website', array('type' => 'url', 'value' => 'http://domain.tld', 'div' => false, 'label' => false));
$expected = array(
'input' => array('type' => 'url', 'name' => 'data[User][website]', 'id' => 'UserWebsite', 'value' => 'http://domain.tld')
);
$this->assertTags($result, $expected);
}
/**

View file

@ -16,7 +16,7 @@
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require_once dirname(__FILE__) . '/base_coverage_report.php';
App::uses('BaseCoverageReport', 'TestSuite/Coverage');
PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__FILE__, 'DEFAULT');
@ -56,4 +56,4 @@ class TextCoverageReport extends BaseCoverageReport {
return "$filename : $percentCovered%\n";
}
}
}

View file

@ -17,7 +17,8 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
include_once dirname(__FILE__) . DS . 'cake_base_reporter.php';
App::uses('CakeBaseReporter', 'TestSuite/Reporter');
App::uses('TextCoverageReport', 'TestSuite/Coverage');
PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__FILE__, 'DEFAULT');
@ -91,7 +92,7 @@ class CakeTextReporter extends CakeBaseReporter {
echo 'Peak memory: ' . number_format(memory_get_peak_usage()) . " bytes\n";
if (isset($this->params['codeCoverage']) && $this->params['codeCoverage']) {
$coverage = $result->getCodeCoverageInformation();
$coverage = $result->getCodeCoverage()->getSummary();
echo $this->paintCoverage($coverage);
}
}
@ -184,8 +185,6 @@ class CakeTextReporter extends CakeBaseReporter {
* @return string
*/
public function paintCoverage($coverage) {
$file = dirname(dirname(__FILE__)) . '/coverage/text_coverage_report.php';
include $file;
$reporter = new TextCoverageReport($coverage, $this);
echo $reporter->report();
}

View file

@ -191,14 +191,15 @@ class Debugger {
}
/**
* Formats and outputs the contents of the supplied variable.
* Recursively formats and outputs the contents of the supplied variable.
*
*
* @param $var mixed the variable to dump
* @return void
* @see Debugger::exportVar()
* @static
* @link http://book.cakephp.org/view/1191/Using-the-Debugger-Class
*/
*/
public static function dump($var) {
pr(self::exportVar($var));
}
@ -405,12 +406,22 @@ class Debugger {
}
/**
* Grabs an excerpt from a file and highlights a given line of code
* Grabs an excerpt from a file and highlights a given line of code.
*
* Usage:
*
* `Debugger::excerpt('/path/to/file', 100, 4);`
*
* The above would return an array of 8 items. The 4th item would be the provided line,
* and would be wrapped in `<span class="code-highlight"></span>`. All of the lines
* are processed with highlight_string() as well, so they have basic PHP syntax highlighting
* applied.
*
* @param string $file Absolute path to a PHP file
* @param integer $line Line number to highlight
* @param integer $context Number of lines of context to extract above and below $line
* @return array Set of lines highlighted
* @see http://php.net/highlight_string
* @static
* @link http://book.cakephp.org/view/1191/Using-the-Debugger-Class
*/
@ -441,6 +452,20 @@ class Debugger {
/**
* Converts a variable to a string for debug output.
*
* *Note:* The following keys will have their contents replaced with
* `*****`:
*
* - password
* - login
* - host
* - database
* - port
* - prefix
* - schema
*
* This is done to protect database credentials, which could be accidentally
* shown in an error message if CakePHP is deployed in development mode.
*
* @param string $var Variable to convert
* @return string Variable as a formatted string
* @static

View file

@ -368,7 +368,7 @@ class Folder {
if (@chmod($fullpath, intval($mode, 8))) {
$this->__messages[] = __d('cake_dev', '%s changed to %s', $fullpath, $mode);
} else {
$this->__errors[] = __d('cake_deverloper', '%s NOT changed to %s', $fullpath, $mode);
$this->__errors[] = __d('cake_dev', '%s NOT changed to %s', $fullpath, $mode);
}
}
}

View file

@ -130,27 +130,6 @@ class Set {
return Set::__map($val, $class);
}
/**
* Get the array value of $array. If $array is null, it will return
* the current array Set holds. If it is an object of type Set, it
* will return its value. If it is another object, its object variables.
* If it is anything else but an array, it will return an array whose first
* element is $array.
*
* @param mixed $array Data from where to get the array.
* @return array Array from $array.
*/
private function __array($array) {
if (empty($array)) {
$array = array();
} elseif (is_object($array)) {
$array = get_object_vars($array);
} elseif (!is_array($array)) {
$array = array($array);
}
return $array;
}
/**
* Maps the given value as an object. If $value is an object,
* it returns $value. Otherwise it maps $value as an object of

View file

@ -439,18 +439,7 @@ class FormHelper extends AppHelper {
$htmlAttributes = array_merge($options, $htmlAttributes);
$this->fields = array();
if (!empty($this->request->params['_Token'])) {
$append .= $this->hidden('_Token.key', array(
'value' => $this->request->params['_Token']['key'], 'id' => 'Token' . mt_rand(),
'secure' => self::SECURE_SKIP
));
if (!empty($this->request['_Token']['unlockedFields'])) {
foreach ((array)$this->request['_Token']['unlockedFields'] as $unlocked) {
$this->_unlockedFields[] = $unlocked;
}
}
}
$append .= $this->_csrfField();
if (!empty($append)) {
$append = $this->Html->useTag('block', ' style="display:none;"', $append);
@ -462,6 +451,27 @@ class FormHelper extends AppHelper {
return $this->Html->useTag('form', $action, $htmlAttributes) . $append;
}
/**
* Return a CSRF input if the _Token is present.
* Used to secure forms in conjunction with SecurityComponent
*
* @return string
*/
protected function _csrfField() {
if (empty($this->request->params['_Token'])) {
return '';
}
if (!empty($this->request['_Token']['unlockedFields'])) {
foreach ((array)$this->request['_Token']['unlockedFields'] as $unlocked) {
$this->_unlockedFields[] = $unlocked;
}
}
return $this->hidden('_Token.key', array(
'value' => $this->request->params['_Token']['key'], 'id' => 'Token' . mt_rand(),
'secure' => self::SECURE_SKIP
));
}
/**
* Closes an HTML form, cleans up values set by FormHelper::create(), and writes hidden
* input fields where appropriate.
@ -917,7 +927,8 @@ class FormHelper extends AppHelper {
'string' => 'text', 'datetime' => 'datetime',
'boolean' => 'checkbox', 'timestamp' => 'datetime',
'text' => 'textarea', 'time' => 'time',
'date' => 'date', 'float' => 'text'
'date' => 'date', 'float' => 'number',
'integer' => 'number'
);
if (isset($this->map[$type])) {
@ -1071,6 +1082,9 @@ class FormHelper extends AppHelper {
case 'textarea':
$input = $this->textarea($fieldName, $options + array('cols' => '30', 'rows' => '6'));
break;
case 'url':
$input = $this->text($fieldName, array('type' => 'url') + $options);
break;
default:
$input = $this->{$type}($fieldName, $options);
}
@ -1507,13 +1521,18 @@ class FormHelper extends AppHelper {
$formName = uniqid('post_');
$formUrl = $this->url($url);
$out = $this->Html->useTag('form', $formUrl, array('name' => $formName, 'id' => $formName, 'style' => 'display:none;', 'method' => 'post'));
$out .= $this->Html->useTag('block', ' style="display:none;"', $this->Html->useTag('hidden', '_method', ' value="POST"'));
$out .= $this->Html->useTag('hidden', '_method', ' value="POST"');
$out .= $this->_csrfField();
$fields = array();
if (isset($options['data']) && is_array($options['data'])) {
foreach ($options['data'] as $key => $value) {
$fields[$key] = $value;
$out .= $this->hidden($key, array('value' => $value, 'id' => false));
}
unset($options['data']);
}
$out .= $this->secure($fields);
$out .= $this->Html->useTag('formend');
$url = '#';

View file

@ -156,7 +156,16 @@ class HtmlHelper extends AppHelper {
);
/**
* Default Constructor
* Constructor
*
* ### Settings
*
* - `configFile` A file containing an array of tags you wish to redefine.
*
* ### Customizing tag sets
*
* Using the `configFile` option you can redefine the tag HtmlHelper will use.
* The file named should be compatible with HtmlHelper::loadConfig().
*
* @param View $View The View this helper is being attached to.
* @param array $settings Configuration settings for the helper.
@ -357,6 +366,20 @@ class HtmlHelper extends AppHelper {
/**
* Creates a link element for CSS stylesheets.
*
* ### Usage
*
* Include one CSS file:
*
* `echo $this->Html->css('styles.css');`
*
* Include multiple CSS files:
*
* `echo $this->Html->css(array('one.css', 'two.css'));`
*
* Add the stylesheet to the `$scripts_for_layout` layout var:
*
* `$this->Html->css('styles.css', null, array('inline' => false));`
*
* ### Options
*
* - `inline` If set to false, the generated tag appears in the head tag of the layout. Defaults to true
@ -427,7 +450,20 @@ class HtmlHelper extends AppHelper {
* If the filename is prefixed with "/", the path will be relative to the base path of your
* application. Otherwise, the path will be relative to your JavaScript path, usually webroot/js.
*
* Can include one or many Javascript files.
*
* ### Usage
*
* Include one script file:
*
* `echo $this->Html->script('styles.js');`
*
* Include multiple script files:
*
* `echo $this->Html->script(array('one.js', 'two.js'));`
*
* Add the script file to the `$scripts_for_layout` layout var:
*
* `$this->Html->script('styles.js', null, array('inline' => false));`
*
* ### Options
*
@ -922,7 +958,39 @@ class HtmlHelper extends AppHelper {
}
/**
* Load Html configs
* Load Html tag configuration.
*
* Loads a file from APP/Config that contains tag data. By default the file is expected
* to be compatible with PhpReader:
*
* `$this->Html->loadConfig('tags.php');`
*
* tags.php could look like:
*
* {{{
* $tags = array(
* 'meta' => '<meta %s>'
* );
* }}}
*
* If you wish to store tag definitions in another format you can give an array
* containing the file name, and reader class name:
*
* `$this->Html->loadConfig(array('tags.ini', 'ini'));`
*
* Its expected that the `tags` index will exist from any configuration file that is read.
* You can also specify the path to read the configuration file from, if APP/Config is not
* where the file is.
*
* `$this->Html->loadConfig('tags.php', APP . 'Lib' . DS);`
*
* Configuration files can define the following sections:
*
* - `tags` The tags to replace.
* - `minimizedAttributes` The attributes that are represented like `disabled="disabled"`
* - `docTypes` Additional doctypes to use.
* - `attributeFormat` Format for long attributes e.g. `'%s="%s"'`
* - `minimizedAttributeFormat` Format for minimized attributes e.g. `'%s="%s"'`
*
* @param mixed $configFile String with the config file (load using PhpReader) or an array with file and reader name
* @param string $path Path with config file

View file

@ -187,7 +187,7 @@ class RssHelper extends AppHelper {
/**
* Converts an array into an `<item />` element and its contents
*
* @param array $attrib The attributes of the `<item />` element
* @param array $att The attributes of the `<item />` element
* @param array $elements The list of elements contained in this `<item />`
* @return string An RSS `<item />` element
*/

View file

@ -23,18 +23,17 @@ if (!defined('E_DEPRECATED')) {
}
error_reporting(E_ALL & ~E_DEPRECATED);
/**
* If the index.php file is used instead of an .htaccess file
* or if the user can not set the web root to use the public
* directory we will define ROOT there, otherwise we set it
* here.
*/
if (!defined('ROOT')) {
define('ROOT', '../');
}
if (!defined('WEBROOT_DIR')) {
define('WEBROOT_DIR', 'webroot');
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(__FILE__)));
}
if (!defined('CORE_PATH')) {
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
if (!defined('WEBROOT_DIR')) {
define('WEBROOT_DIR', 'webroot');
}
/**
* Path to the cake directory.