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

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
app/Config/database.php
app/tmp
app/webroot/zaloha.txt

View file

@ -1,16 +1,17 @@
<?php
/**
* 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
* @package Cake.Cache
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Inflector', 'Utility');
@ -25,12 +26,12 @@ App::uses('CacheEngine', 'Cache');
* You can configure Cache engines in your application's `bootstrap.php` file. A sample configuration would
* be
*
* {{{
* ```
* Cache::config('shared', array(
* 'engine' => 'Apc',
* 'prefix' => 'my_app_'
* ));
* }}}
* ```
*
* This would configure an APC cache engine to the 'shared' alias. You could then read and write
* to that cache alias by using it for the `$config` parameter in the various Cache methods. In
@ -50,6 +51,13 @@ class Cache {
*/
protected static $_config = array();
/**
* Group to Config mapping
*
* @var array
*/
protected static $_groups = array();
/**
* Whether to reset the settings with the next call to Cache::set();
*
@ -103,13 +111,13 @@ class Cache {
* - `path` Used by FileCache. Path to where cachefiles should be saved.
* - `lock` Used by FileCache. Should files be locked before writing to them?
* - `user` Used by Xcache. Username for XCache
* - `password` Used by Xcache. Password for XCache
* - `password` Used by Xcache/Redis. Password for XCache/Redis
*
* @see app/Config/core.php for configuration settings
* @param string $name Name of the configuration
* @param array $settings Optional associative array of settings passed to the engine
* @return array(engine, settings) on success, false on failure
* @return array array(engine, settings) on success, false on failure
* @throws CacheException
* @see app/Config/core.php for configuration settings
*/
public static function config($name = null, $settings = array()) {
if (is_array($name)) {
@ -117,25 +125,33 @@ class Cache {
}
$current = array();
if (isset(self::$_config[$name])) {
$current = self::$_config[$name];
if (isset(static::$_config[$name])) {
$current = static::$_config[$name];
}
if (!empty($settings)) {
self::$_config[$name] = array_merge($current, $settings);
static::$_config[$name] = $settings + $current;
}
if (empty(self::$_config[$name]['engine'])) {
if (empty(static::$_config[$name]['engine'])) {
return false;
}
$engine = self::$_config[$name]['engine'];
if (!empty(static::$_config[$name]['groups'])) {
foreach (static::$_config[$name]['groups'] as $group) {
static::$_groups[$group][] = $name;
sort(static::$_groups[$group]);
static::$_groups[$group] = array_unique(static::$_groups[$group]);
}
}
if (!isset(self::$_engines[$name])) {
self::_buildEngine($name);
$settings = self::$_config[$name] = self::settings($name);
} elseif ($settings = self::set(self::$_config[$name], null, $name)) {
self::$_config[$name] = $settings;
$engine = static::$_config[$name]['engine'];
if (!isset(static::$_engines[$name])) {
static::_buildEngine($name);
$settings = static::$_config[$name] = static::settings($name);
} elseif ($settings = static::set(static::$_config[$name], null, $name)) {
static::$_config[$name] = $settings;
}
return compact('engine', 'settings');
}
@ -144,31 +160,36 @@ class Cache {
* Finds and builds the instance of the required engine class.
*
* @param string $name Name of the config array that needs an engine instance built
* @return boolean
* @return bool
* @throws CacheException
*/
protected static function _buildEngine($name) {
$config = self::$_config[$name];
$config = static::$_config[$name];
list($plugin, $class) = pluginSplit($config['engine'], true);
$cacheClass = $class . 'Engine';
App::uses($cacheClass, $plugin . 'Cache/Engine');
if (!class_exists($cacheClass)) {
return false;
throw new CacheException(__d('cake_dev', 'Cache engine %s is not available.', $name));
}
$cacheClass = $class . 'Engine';
if (!is_subclass_of($cacheClass, 'CacheEngine')) {
throw new CacheException(__d('cake_dev', 'Cache engines must use CacheEngine as a base class.'));
throw new CacheException(__d('cake_dev', 'Cache engines must use %s as a base class.', 'CacheEngine'));
}
self::$_engines[$name] = new $cacheClass();
if (self::$_engines[$name]->init($config)) {
if (self::$_engines[$name]->settings['probability'] && time() % self::$_engines[$name]->settings['probability'] === 0) {
self::$_engines[$name]->gc();
static::$_engines[$name] = new $cacheClass();
if (!static::$_engines[$name]->init($config)) {
$msg = __d(
'cake_dev',
'Cache engine "%s" is not properly configured. Ensure required extensions are installed, and credentials/permissions are correct',
$name
);
throw new CacheException($msg);
}
if (static::$_engines[$name]->settings['probability'] && time() % static::$_engines[$name]->settings['probability'] === 0) {
static::$_engines[$name]->gc();
}
return true;
}
return false;
}
/**
* Returns an array containing the currently configured Cache settings.
@ -176,22 +197,22 @@ class Cache {
* @return array Array of configured Cache config names.
*/
public static function configured() {
return array_keys(self::$_config);
return array_keys(static::$_config);
}
/**
* Drops a cache engine. Deletes the cache configuration information
* If the deleted configuration is the last configuration using an certain engine,
* If the deleted configuration is the last configuration using a certain engine,
* the Engine instance is also unset.
*
* @param string $name A currently configured cache config you wish to remove.
* @return boolean success of the removal, returns false when the config does not exist.
* @return bool success of the removal, returns false when the config does not exist.
*/
public static function drop($name) {
if (!isset(self::$_config[$name])) {
if (!isset(static::$_config[$name])) {
return false;
}
unset(self::$_config[$name], self::$_engines[$name]);
unset(static::$_config[$name], static::$_engines[$name]);
return true;
}
@ -222,29 +243,29 @@ class Cache {
if (is_array($settings) && $value !== null) {
$config = $value;
}
if (!isset(self::$_config[$config]) || !isset(self::$_engines[$config])) {
if (!isset(static::$_config[$config]) || !isset(static::$_engines[$config])) {
return false;
}
if (!empty($settings)) {
self::$_reset = true;
static::$_reset = true;
}
if (self::$_reset === true) {
if (static::$_reset === true) {
if (empty($settings)) {
self::$_reset = false;
$settings = self::$_config[$config];
static::$_reset = false;
$settings = static::$_config[$config];
} else {
if (is_string($settings) && $value !== null) {
$settings = array($settings => $value);
}
$settings = array_merge(self::$_config[$config], $settings);
$settings += static::$_config[$config];
if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
$settings['duration'] = strtotime($settings['duration']) - time();
}
}
self::$_engines[$config]->settings = $settings;
static::$_engines[$config]->settings = $settings;
}
return self::settings($config);
return static::settings($config);
}
/**
@ -253,17 +274,15 @@ class Cache {
* Permanently remove all expired and deleted data
*
* @param string $config [optional] The config name you wish to have garbage collected. Defaults to 'default'
* @param integer $expires [optional] An expires timestamp. Defaults to NULL
* @return void
* @param int $expires [optional] An expires timestamp. Defaults to NULL
* @return bool
*/
public static function gc($config = 'default', $expires = null) {
self::$_engines[$config]->gc($expires);
return static::$_engines[$config]->gc($expires);
}
/**
* Write data for key into cache. Will automatically use the currently
* active cache configuration. To set the currently active configuration use
* Cache::config()
* Write data for key into a cache engine.
*
* ### Usage:
*
@ -278,32 +297,32 @@ class Cache {
* @param string $key Identifier for the data
* @param mixed $value Data to be cached - anything except a resource
* @param string $config Optional string configuration name to write to. Defaults to 'default'
* @return boolean True if the data was successfully cached, false on failure
* @return bool True if the data was successfully cached, false on failure
*/
public static function write($key, $value, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || is_resource($value)) {
return false;
}
$success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
self::set(null, $config);
$success = static::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
static::set(null, $config);
if ($success === false && $value !== '') {
trigger_error(
__d('cake_dev',
"%s cache was unable to write '%s' to %s cache",
$config,
$key,
self::$_engines[$config]->settings['engine']
static::$_engines[$config]->settings['engine']
),
E_USER_WARNING
);
@ -312,9 +331,7 @@ class Cache {
}
/**
* Read a key from the cache. Will automatically use the currently
* active cache configuration. To set the currently active configuration use
* Cache::config()
* Read a key from a cache config.
*
* ### Usage:
*
@ -331,46 +348,46 @@ class Cache {
* @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
*/
public static function read($key, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
return self::$_engines[$config]->read($settings['prefix'] . $key);
return static::$_engines[$config]->read($settings['prefix'] . $key);
}
/**
* Increment a number under the key and return incremented value.
*
* @param string $key Identifier for the data
* @param integer $offset How much to add
* @param int $offset How much to add
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it.
*/
public static function increment($key, $offset = 1, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || !is_integer($offset) || $offset < 0) {
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
$success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
self::set(null, $config);
$success = static::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
static::set(null, $config);
return $success;
}
@ -378,27 +395,27 @@ class Cache {
* Decrement a number under the key and return decremented value.
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it
*/
public static function decrement($key, $offset = 1, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || !is_integer($offset) || $offset < 0) {
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
$success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
self::set(null, $config);
$success = static::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
static::set(null, $config);
return $success;
}
@ -417,40 +434,40 @@ class Cache {
*
* @param string $key Identifier for the data
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public static function delete($key, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
$success = self::$_engines[$config]->delete($settings['prefix'] . $key);
self::set(null, $config);
$success = static::$_engines[$config]->delete($settings['prefix'] . $key);
static::set(null, $config);
return $success;
}
/**
* Delete all keys from the cache.
*
* @param boolean $check if true will check expiration, otherwise delete all
* @param bool $check if true will check expiration, otherwise delete all
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the cache was successfully cleared, false otherwise
* @return bool True if the cache was successfully cleared, false otherwise
*/
public static function clear($check = false, $config = 'default') {
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$success = self::$_engines[$config]->clear($check);
self::set(null, $config);
$success = static::$_engines[$config]->clear($check);
static::set(null, $config);
return $success;
}
@ -459,14 +476,14 @@ class Cache {
*
* @param string $group name of the group to be cleared
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the cache group was successfully cleared, false otherwise
* @return bool True if the cache group was successfully cleared, false otherwise
*/
public static function clearGroup($group, $config = 'default') {
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$success = self::$_engines[$config]->clearGroup($group);
self::set(null, $config);
$success = static::$_engines[$config]->clearGroup($group);
static::set(null, $config);
return $success;
}
@ -474,13 +491,13 @@ class Cache {
* Check if Cache has initialized a working config for the given name.
*
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean Whether or not the config name has been initialized.
* @return bool Whether or not the config name has been initialized.
*/
public static function isInitialized($config = 'default') {
if (Configure::read('Cache.disable')) {
return false;
}
return isset(self::$_engines[$config]);
return isset(static::$_engines[$config]);
}
/**
@ -491,11 +508,126 @@ class Cache {
* @see Cache::config()
*/
public static function settings($name = 'default') {
if (!empty(self::$_engines[$name])) {
return self::$_engines[$name]->settings();
if (!empty(static::$_engines[$name])) {
return static::$_engines[$name]->settings();
}
return array();
}
/**
* Retrieve group names to config mapping.
*
* ```
* Cache::config('daily', array(
* 'duration' => '1 day', 'groups' => array('posts')
* ));
* Cache::config('weekly', array(
* 'duration' => '1 week', 'groups' => array('posts', 'archive')
* ));
* $configs = Cache::groupConfigs('posts');
* ```
*
* $config will equal to `array('posts' => array('daily', 'weekly'))`
*
* @param string $group group name or null to retrieve all group mappings
* @return array map of group and all configuration that has the same group
* @throws CacheException
*/
public static function groupConfigs($group = null) {
if ($group === null) {
return static::$_groups;
}
if (isset(static::$_groups[$group])) {
return array($group => static::$_groups[$group]);
}
throw new CacheException(__d('cake_dev', 'Invalid cache group %s', $group));
}
/**
* Provides the ability to easily do read-through caching.
*
* When called if the $key is not set in $config, the $callable function
* will be invoked. The results will then be stored into the cache config
* at key.
*
* Examples:
*
* Using a Closure to provide data, assume $this is a Model:
*
* ```
* $model = $this;
* $results = Cache::remember('all_articles', function() use ($model) {
* return $model->find('all');
* });
* ```
*
* @param string $key The cache key to read/store data at.
* @param callable $callable The callable that provides data in the case when
* the cache key is empty. Can be any callable type supported by your PHP.
* @param string $config The cache configuration to use for this operation.
* Defaults to default.
* @return mixed The results of the callable or unserialized results.
*/
public static function remember($key, $callable, $config = 'default') {
$existing = static::read($key, $config);
if ($existing !== false) {
return $existing;
}
$results = call_user_func($callable);
static::write($key, $results, $config);
return $results;
}
/**
* Write data for key into a cache engine if it doesn't exist already.
*
* ### Usage:
*
* Writing to the active cache config:
*
* `Cache::add('cached_data', $data);`
*
* Writing to a specific cache config:
*
* `Cache::add('cached_data', $data, 'long_term');`
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached - anything except a resource.
* @param string $config Optional string configuration name to write to. Defaults to 'default'.
* @return bool True if the data was successfully cached, false on failure.
* Or if the key existed already.
*/
public static function add($key, $value, $config = 'default') {
$settings = self::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
if (!$key || is_resource($value)) {
return false;
}
$success = self::$_engines[$config]->add($settings['prefix'] . $key, $value, $settings['duration']);
self::set(null, $config);
return $success;
}
/**
* Fetch the engine attached to a specific configuration name.
*
* @param string $config Optional string configuration name to get an engine for. Defaults to 'default'.
* @return null|CacheEngine Null if the engine has not been initialized or the engine.
*/
public static function engine($config = 'default') {
if (self::isInitialized($config)) {
return self::$_engines[$config];
}
return null;
}
}

View file

@ -1,16 +1,17 @@
<?php
/**
* 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
* @package Cake.Cache
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -29,10 +30,10 @@ abstract class CacheEngine {
/**
* Contains the compiled string with all groups
* prefixes to be prepeded to every key in this cache engine
* prefixes to be prepended to every key in this cache engine
*
* @var string
**/
*/
protected $_groupPrefix = null;
/**
@ -41,7 +42,7 @@ abstract class CacheEngine {
* Called automatically by the cache frontend
*
* @param array $settings Associative array of parameters for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += $this->settings + array(
@ -66,7 +67,7 @@ abstract class CacheEngine {
*
* Permanently remove all expired and deleted data
*
* @param integer $expires [optional] An expires timestamp, invalidataing all data before.
* @param int $expires [optional] An expires timestamp, invalidating all data before.
* @return void
*/
public function gc($expires = null) {
@ -77,11 +78,22 @@ abstract class CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache for.
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache for.
* @return bool True if the data was successfully cached, false on failure
*/
abstract public function write($key, $value, $duration);
/**
* Write value for a key into cache if it doesn't already exist
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param int $duration How long to cache for.
* @return bool True if the data was successfully cached, false on failure
*/
public function add($key, $value, $duration) {
}
/**
* Read a key from the cache
*
@ -94,7 +106,7 @@ abstract class CacheEngine {
* Increment a number under the key and return incremented value
*
* @param string $key Identifier for the data
* @param integer $offset How much to add
* @param int $offset How much to add
* @return New incremented value, false otherwise
*/
abstract public function increment($key, $offset = 1);
@ -103,7 +115,7 @@ abstract class CacheEngine {
* Decrement a number under the key and return decremented value
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New incremented value, false otherwise
*/
abstract public function decrement($key, $offset = 1);
@ -112,25 +124,25 @@ abstract class CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
abstract public function delete($key);
/**
* Delete all keys from the cache
*
* @param boolean $check if true will check expiration, otherwise delete all
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check if true will check expiration, otherwise delete all
* @return bool True if the cache was successfully cleared, false otherwise
*/
abstract public function clear($check);
/**
* Clears all values belonging to a group. Is upt to the implementing engine
* to decide whether actually deete the keys or just simulate it to acheive
* Clears all values belonging to a group. Is up to the implementing engine
* to decide whether actually delete the keys or just simulate it to achieve
* the same result.
*
* @param string $groups name of the group to be cleared
* @return boolean
* @param string $group name of the group to be cleared
* @return bool
*/
public function clearGroup($group) {
return false;
@ -175,5 +187,4 @@ abstract class CacheEngine {
$key = preg_replace('/[\s]+/', '_', strtolower(trim(str_replace(array(DS, '/', '.'), '_', strval($key)))));
return $prefix . $key;
}
}

View file

@ -2,20 +2,18 @@
/**
* APC storage engine for cache.
*
*
* 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
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -27,12 +25,19 @@ class ApcEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
* APC or APCu extension
*
* @var string
*/
protected $_apcExtension = 'apc';
/**
* Initialize the Cache Engine
*
@ -40,7 +45,7 @@ class ApcEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@ -49,6 +54,10 @@ class ApcEngine extends CacheEngine {
}
$settings += array('engine' => 'Apc');
parent::init($settings);
if (function_exists('apcu_dec')) {
$this->_apcExtension = 'apcu';
return true;
}
return function_exists('apc_dec');
}
@ -57,17 +66,17 @@ class ApcEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
if ($duration == 0) {
$expires = 0;
} else {
if ($duration) {
$expires = time() + $duration;
}
apc_store($key . '_expires', $expires, $duration);
return apc_store($key, $value, $duration);
$func = $this->_apcExtension . '_store';
$func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
}
/**
@ -78,62 +87,74 @@ class ApcEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
$cachetime = intval(apc_fetch($key . '_expires'));
$func = $this->_apcExtension . '_fetch';
$cachetime = (int)$func($key . '_expires');
if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
return false;
}
return apc_fetch($key);
return $func($key);
}
/**
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
return apc_inc($key, $offset);
$func = $this->_apcExtension . '_inc';
return $func($key, $offset);
}
/**
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
return apc_dec($key, $offset);
$func = $this->_apcExtension . '_dec';
return $func($key, $offset);
}
/**
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return apc_delete($key);
$func = $this->_apcExtension . '_delete';
return $func($key);
}
/**
* Delete all keys from the cache. This will clear every cache config using APC.
*
* @param boolean $check If true, nothing will be cleared, as entries are removed
* @param bool $check If true, nothing will be cleared, as entries are removed
* from APC as they expired. This flag is really only used by FileEngine.
* @return boolean True Returns true.
* @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
return true;
}
$info = apc_cache_info('user');
$cacheKeys = $info['cache_list'];
unset($info);
foreach ($cacheKeys as $key) {
$func = $this->_apcExtension . '_delete';
if (class_exists('APCIterator', false)) {
$iterator = new APCIterator(
'user',
'/^' . preg_quote($this->settings['prefix'], '/') . '/',
APC_ITER_NONE
);
$func($iterator);
return true;
}
$cache = $this->_apcExtension === 'apc' ? apc_cache_info('user') : apcu_cache_info();
foreach ($cache['cache_list'] as $key) {
if (strpos($key['info'], $this->settings['prefix']) === 0) {
apc_delete($key['info']);
$func($key['info']);
}
}
return true;
@ -145,7 +166,7 @@ class ApcEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -153,11 +174,13 @@ class ApcEngine extends CacheEngine {
}
}
$groups = apc_fetch($this->_compiledGroupNames);
$fetchFunc = $this->_apcExtension . '_fetch';
$storeFunc = $this->_apcExtension . '_store';
$groups = $fetchFunc($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
apc_store($group, 1);
$storeFunc($group, 1);
$groups[$group] = 1;
}
}
@ -176,11 +199,32 @@ class ApcEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success);
$func = $this->_apcExtension . '_inc';
$func($this->settings['prefix'] . $group, 1, $success);
return $success;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/function.apc-add.php
*/
public function add($key, $value, $duration) {
$expires = 0;
if ($duration) {
$expires = time() + $duration;
}
$func = $this->_apcExtension . '_add';
$func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
}
}

View file

@ -6,18 +6,17 @@
*
* You can configure a FileEngine cache, using Cache::config()
*
* 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.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -43,7 +42,7 @@ class FileEngine extends CacheEngine {
*
* - path = absolute path to cache directory, default => CACHE
* - prefix = string prefix for filename, default => cake_
* - lock = enable file locking on write, default => false
* - lock = enable file locking on write, default => true
* - serialize = serialize the data, default => true
*
* @var array
@ -54,7 +53,7 @@ class FileEngine extends CacheEngine {
/**
* True unless FileEngine::__active(); fails
*
* @var boolean
* @var bool
*/
protected $_init = true;
@ -65,7 +64,7 @@ class FileEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += array(
@ -94,8 +93,8 @@ class FileEngine extends CacheEngine {
/**
* Garbage collection. Permanently remove all expired and deleted data
*
* @param integer $expires [optional] An expires timestamp, invalidataing all data before.
* @return boolean True if garbage collection was successful, false on failure
* @param int $expires [optional] An expires timestamp, invalidating all data before.
* @return bool True if garbage collection was successful, false on failure
*/
public function gc($expires = null) {
return $this->clear(true);
@ -106,11 +105,11 @@ class FileEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $data Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $data, $duration) {
if ($data === '' || !$this->_init) {
if (!$this->_init) {
return false;
}
@ -133,7 +132,7 @@ class FileEngine extends CacheEngine {
}
$expires = time() + $duration;
$contents = $expires . $lineBreak . $data . $lineBreak;
$contents = implode(array($expires, $lineBreak, $data, $lineBreak));
if ($this->settings['lock']) {
$this->_File->flock(LOCK_EX);
@ -166,7 +165,7 @@ class FileEngine extends CacheEngine {
$this->_File->rewind();
$time = time();
$cachetime = intval($this->_File->current());
$cachetime = (int)$this->_File->current();
if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
if ($this->settings['lock']) {
@ -201,7 +200,7 @@ class FileEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
if ($this->_setKey($key) === false || !$this->_init) {
@ -209,60 +208,104 @@ class FileEngine extends CacheEngine {
}
$path = $this->_File->getRealPath();
$this->_File = null;
return unlink($path);
//@codingStandardsIgnoreStart
return @unlink($path);
//@codingStandardsIgnoreEnd
}
/**
* Delete all values from the cache
*
* @param boolean $check Optional - only delete expired cache items
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check Optional - only delete expired cache items
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if (!$this->_init) {
return false;
}
$dir = dir($this->settings['path']);
$this->_File = null;
$threshold = $now = false;
if ($check) {
$now = time();
$threshold = $now - $this->settings['duration'];
}
$this->_clearDirectory($this->settings['path'], $now, $threshold);
$directory = new RecursiveDirectoryIterator($this->settings['path']);
$contents = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
$cleared = array();
foreach ($contents as $path) {
if ($path->isFile()) {
continue;
}
$path = $path->getRealPath() . DS;
if (!in_array($path, $cleared)) {
$this->_clearDirectory($path, $now, $threshold);
$cleared[] = $path;
}
}
return true;
}
/**
* Used to clear a directory of matching files.
*
* @param string $path The path to search.
* @param int $now The current timestamp
* @param int $threshold Any file not modified after this value will be deleted.
* @return void
*/
protected function _clearDirectory($path, $now, $threshold) {
$prefixLength = strlen($this->settings['prefix']);
if (!is_dir($path)) {
return;
}
$dir = dir($path);
while (($entry = $dir->read()) !== false) {
if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
continue;
}
if ($this->_setKey($entry) === false) {
try {
$file = new SplFileObject($path . $entry, 'r');
} catch (Exception $e) {
continue;
}
if ($check) {
$mtime = $this->_File->getMTime();
if ($threshold) {
$mtime = $file->getMTime();
if ($mtime > $threshold) {
continue;
}
$expires = (int)$this->_File->current();
$expires = (int)$file->current();
if ($expires > $now) {
continue;
}
}
$path = $this->_File->getRealPath();
$this->_File = null;
if (file_exists($path)) {
unlink($path);
if ($file->isFile()) {
$filePath = $file->getRealPath();
$file = null;
//@codingStandardsIgnoreStart
@unlink($filePath);
//@codingStandardsIgnoreEnd
}
}
$dir->close();
return true;
}
/**
* Not implemented
*
* @param string $key
* @param integer $offset
* @param string $key The key to decrement
* @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@ -273,8 +316,8 @@ class FileEngine extends CacheEngine {
/**
* Not implemented
*
* @param string $key
* @param integer $offset
* @param string $key The key to decrement
* @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@ -287,8 +330,8 @@ class FileEngine extends CacheEngine {
* for the cache file the key is referring to.
*
* @param string $key The key
* @param boolean $createKey Whether the key should be created if it doesn't exists, or not
* @return boolean true if the cache key could be set, false otherwise
* @param bool $createKey Whether the key should be created if it doesn't exists, or not
* @return bool true if the cache key could be set, false otherwise
*/
protected function _setKey($key, $createKey = false) {
$groups = null;
@ -298,7 +341,7 @@ class FileEngine extends CacheEngine {
$dir = $this->settings['path'] . $groups;
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
mkdir($dir, 0775, true);
}
$path = new SplFileInfo($dir . $key);
@ -327,10 +370,16 @@ class FileEngine extends CacheEngine {
/**
* Determine is cache directory is writable
*
* @return boolean
* @return bool
*/
protected function _active() {
$dir = new SplFileInfo($this->settings['path']);
if (Configure::read('debug')) {
$path = $dir->getPathname();
if (!is_dir($path)) {
mkdir($path, 0775, true);
}
}
if ($this->_init && !($dir->isDir() && $dir->isWritable())) {
$this->_init = false;
trigger_error(__d('cake_dev', '%s is not writable', $this->settings['path']), E_USER_WARNING);
@ -350,24 +399,51 @@ class FileEngine extends CacheEngine {
return false;
}
$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
$key = Inflector::underscore(str_replace(array(DS, '/', '.', '<', '>', '?', ':', '|', '*', '"'), '_', strval($key)));
return $key;
}
/**
* Recursively deletes all files under any directory named as $group
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
$this->_File = null;
$directoryIterator = new RecursiveDirectoryIterator($this->settings['path']);
$contents = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($contents as $object) {
$containsGroup = strpos($object->getPathName(), DS . $group . DS) !== false;
if ($object->isFile() && $containsGroup) {
unlink($object->getPathName());
$hasPrefix = true;
if (strlen($this->settings['prefix']) !== 0) {
$hasPrefix = strpos($object->getBaseName(), $this->settings['prefix']) === 0;
}
if ($object->isFile() && $containsGroup && $hasPrefix) {
$path = $object->getPathName();
$object = null;
//@codingStandardsIgnoreStart
@unlink($path);
//@codingStandardsIgnoreEnd
}
}
return true;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}

View file

@ -2,20 +2,18 @@
/**
* Memcache storage engine for cache
*
*
* 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
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -24,15 +22,16 @@
* more information.
*
* @package Cake.Cache.Engine
* @deprecated 3.0.0 You should use the Memcached adapter instead.
*/
class MemcacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
@ -60,7 +59,7 @@ class MemcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Memcache')) {
@ -105,10 +104,10 @@ class MemcacheEngine extends CacheEngine {
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
if ($server[0] == 'u') {
if (strpos($server, 'unix://') === 0) {
return array($server, 0);
}
if (substr($server, 0, 1) == '[') {
if (substr($server, 0, 1) === '[') {
$position = strpos($server, ']:');
if ($position !== false) {
$position++;
@ -132,8 +131,8 @@ class MemcacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
@ -157,14 +156,14 @@ class MemcacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
public function increment($key, $offset = 1) {
if ($this->settings['compress']) {
throw new CacheException(
__d('cake_dev', 'Method increment() not implemented for compressed cache in %s', __CLASS__)
__d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'increment()', __CLASS__)
);
}
return $this->_Memcache->increment($key, $offset);
@ -174,14 +173,14 @@ class MemcacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
public function decrement($key, $offset = 1) {
if ($this->settings['compress']) {
throw new CacheException(
__d('cake_dev', 'Method decrement() not implemented for compressed cache in %s', __CLASS__)
__d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'decrement()', __CLASS__)
);
}
return $this->_Memcache->decrement($key, $offset);
@ -191,7 +190,7 @@ class MemcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcache->delete($key);
@ -200,20 +199,21 @@ class MemcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
return true;
}
foreach ($this->_Memcache->getExtendedStats('slabs') as $slabs) {
foreach ($this->_Memcache->getExtendedStats('slabs', 0) as $slabs) {
foreach (array_keys($slabs) as $slabId) {
if (!is_numeric($slabId)) {
continue;
}
foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId) as $stats) {
foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId, 0) as $stats) {
if (!is_array($stats)) {
continue;
}
@ -232,8 +232,8 @@ class MemcacheEngine extends CacheEngine {
* Connects to a server in connection pool
*
* @param string $host host ip address or name
* @param integer $port Server port
* @return boolean True if memcache server was connected
* @param int $port Server port
* @return bool True if memcache server was connected
*/
public function connect($host, $port = 11211) {
if ($this->_Memcache->getServerStatus($host, $port) === 0) {
@ -251,7 +251,7 @@ class MemcacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -283,9 +283,30 @@ class MemcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcache->increment($this->settings['prefix'] . $group);
}
/**
* Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
* remember that the Memcached PECL extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/memcache.add.php
*/
public function add($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcache->add($key, $value, $this->settings['compress'], $duration);
}
}

View file

@ -0,0 +1,365 @@
<?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.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Memcached storage engine for cache. Memcached has some limitations in the amount of
* control you have over expire times far in the future. See MemcachedEngine::write() for
* more information.
*
* Main advantage of this Memcached engine over the memcached engine is
* support of binary protocol, and igbibnary serialization
* (if memcached extension compiled with --enable-igbinary)
* Compressed keys can also be incremented/decremented
*
* This cache engine requires at least ext/memcached version 2.0
*
* @package Cake.Cache.Engine
*/
class MemcachedEngine extends CacheEngine {
/**
* memcached wrapper.
*
* @var Memcache
*/
protected $_Memcached = null;
/**
* Settings
*
* - servers = string or array of memcached servers, default => 127.0.0.1. If an
* array MemcacheEngine will use them as a pool.
* - compress = boolean, default => false
* - persistent = string The name of the persistent connection. All configurations using
* the same persistent value will share a single underlying connection.
* - serialize = string, default => php. The serializer engine used to serialize data.
* Available engines are php, igbinary and json. Beside php, the memcached extension
* must be compiled with the appropriate serializer support.
* - options - Additional options for the memcached client. Should be an array of option => value.
* Use the Memcached::OPT_* constants as keys.
*
* @var array
*/
public $settings = array();
/**
* List of available serializer engines
*
* Memcached must be compiled with json and igbinary support to use these engines
*
* @var array
*/
protected $_serializers = array(
'igbinary' => Memcached::SERIALIZER_IGBINARY,
'json' => Memcached::SERIALIZER_JSON,
'php' => Memcached::SERIALIZER_PHP
);
/**
* Initialize the Cache Engine
*
* Called automatically by the cache frontend
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return bool True if the engine has been successfully initialized, false if not
* @throws CacheException when you try use authentication without Memcached compiled with SASL support
*/
public function init($settings = array()) {
if (!class_exists('Memcached')) {
return false;
}
if (!isset($settings['prefix'])) {
$settings['prefix'] = Inflector::slug(APP_DIR) . '_';
}
if (defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK) {
$this->_serializers['msgpack'] = Memcached::SERIALIZER_MSGPACK;
}
$settings += array(
'engine' => 'Memcached',
'servers' => array('127.0.0.1'),
'compress' => false,
'persistent' => false,
'login' => null,
'password' => null,
'serialize' => 'php',
'options' => array()
);
parent::init($settings);
if (!is_array($this->settings['servers'])) {
$this->settings['servers'] = array($this->settings['servers']);
}
if (isset($this->_Memcached)) {
return true;
}
if (!$this->settings['persistent']) {
$this->_Memcached = new Memcached();
} else {
$this->_Memcached = new Memcached((string)$this->settings['persistent']);
}
$this->_setOptions();
if (count($this->_Memcached->getServerList())) {
return true;
}
$servers = array();
foreach ($this->settings['servers'] as $server) {
$servers[] = $this->_parseServerString($server);
}
if (!$this->_Memcached->addServers($servers)) {
return false;
}
if ($this->settings['login'] !== null && $this->settings['password'] !== null) {
if (!method_exists($this->_Memcached, 'setSaslAuthData')) {
throw new CacheException(
__d('cake_dev', 'Memcached extension is not build with SASL support')
);
}
$this->_Memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$this->_Memcached->setSaslAuthData($this->settings['login'], $this->settings['password']);
}
if (is_array($this->settings['options'])) {
foreach ($this->settings['options'] as $opt => $value) {
$this->_Memcached->setOption($opt, $value);
}
}
return true;
}
/**
* Settings the memcached instance
*
* @throws CacheException when the Memcached extension is not built with the desired serializer engine
* @return void
*/
protected function _setOptions() {
$this->_Memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$serializer = strtolower($this->settings['serialize']);
if (!isset($this->_serializers[$serializer])) {
throw new CacheException(
__d('cake_dev', '%s is not a valid serializer engine for Memcached', $serializer)
);
}
if ($serializer !== 'php' && !constant('Memcached::HAVE_' . strtoupper($serializer))) {
throw new CacheException(
__d('cake_dev', 'Memcached extension is not compiled with %s support', $serializer)
);
}
$this->_Memcached->setOption(Memcached::OPT_SERIALIZER, $this->_serializers[$serializer]);
// Check for Amazon ElastiCache instance
if (defined('Memcached::OPT_CLIENT_MODE') && defined('Memcached::DYNAMIC_CLIENT_MODE')) {
$this->_Memcached->setOption(Memcached::OPT_CLIENT_MODE, Memcached::DYNAMIC_CLIENT_MODE);
}
$this->_Memcached->setOption(Memcached::OPT_COMPRESSION, (bool)$this->settings['compress']);
}
/**
* Parses the server address into the host/port. Handles both IPv6 and IPv4
* addresses and Unix sockets
*
* @param string $server The server address string.
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
$socketTransport = 'unix://';
if (strpos($server, $socketTransport) === 0) {
return array(substr($server, strlen($socketTransport)), 0);
}
if (substr($server, 0, 1) === '[') {
$position = strpos($server, ']:');
if ($position !== false) {
$position++;
}
} else {
$position = strpos($server, ':');
}
$port = 11211;
$host = $server;
if ($position !== false) {
$host = substr($server, 0, $position);
$port = substr($server, $position + 1);
}
return array($host, (int)$port);
}
/**
* Write data for key into cache. When using memcached as your cache engine
* remember that the Memcached PECL extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcached->set($key, $value, $duration);
}
/**
* Read a key from the cache
*
* @param string $key Identifier for the data
* @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
*/
public function read($key) {
return $this->_Memcached->get($key);
}
/**
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
public function increment($key, $offset = 1) {
return $this->_Memcached->increment($key, $offset);
}
/**
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
public function decrement($key, $offset = 1) {
return $this->_Memcached->decrement($key, $offset);
}
/**
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcached->delete($key);
}
/**
* Delete all keys from the cache
*
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise. Will
* also return false if you are using a binary protocol.
*/
public function clear($check) {
if ($check) {
return true;
}
$keys = $this->_Memcached->getAllKeys();
if ($keys === false) {
return false;
}
foreach ($keys as $key) {
if (strpos($key, $this->settings['prefix']) === 0) {
$this->_Memcached->delete($key);
}
}
return true;
}
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
}
}
$groups = $this->_Memcached->getMulti($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
$this->_Memcached->set($group, 1, 0);
$groups[$group] = 1;
}
}
ksort($groups);
}
$result = array();
$groups = array_values($groups);
foreach ($this->settings['groups'] as $i => $group) {
$result[] = $group . $groups[$i];
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group);
}
/**
* Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
* remember that the Memcached pecl extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/memcached.add.php
*/
public function add($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcached->add($key, $value, $duration);
}
}

View file

@ -2,20 +2,18 @@
/**
* Redis storage engine for cache
*
*
* 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
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 2.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -35,10 +33,12 @@ class RedisEngine extends CacheEngine {
/**
* Settings
*
* - server = string url or ip to the Redis server host
* - server = string URL or ip to the Redis server host
* - database = integer database number to use for connection
* - port = integer port number to the Redis server (default: 6379)
* - timeout = float timeout in seconds (default: 0)
* - persistent = bool Connects to the Redis server with a persistent connection (default: true)
* - persistent = boolean Connects to the Redis server with a persistent connection (default: true)
* - unix_socket = path to the unix socket file (default: false)
*
* @var array
*/
@ -51,7 +51,7 @@ class RedisEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Redis')) {
@ -59,11 +59,14 @@ class RedisEngine extends CacheEngine {
}
parent::init(array_merge(array(
'engine' => 'Redis',
'prefix' => null,
'prefix' => Inflector::slug(APP_DIR) . '_',
'server' => '127.0.0.1',
'database' => 0,
'port' => 6379,
'password' => false,
'timeout' => 0,
'persistent' => true
'persistent' => true,
'unix_socket' => false
), $settings)
);
@ -73,21 +76,29 @@ class RedisEngine extends CacheEngine {
/**
* Connects to a Redis server
*
* @return boolean True if Redis server was connected
* @return bool True if Redis server was connected
*/
protected function _connect() {
$return = false;
try {
$this->_Redis = new Redis();
if (empty($this->settings['persistent'])) {
if (!empty($this->settings['unix_socket'])) {
$return = $this->_Redis->connect($this->settings['unix_socket']);
} elseif (empty($this->settings['persistent'])) {
$return = $this->_Redis->connect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
} else {
$return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
$persistentId = $this->settings['port'] . $this->settings['timeout'] . $this->settings['database'];
$return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout'], $persistentId);
}
} catch (RedisException $e) {
$return = false;
}
if (!$return) {
return false;
}
return $return;
if ($this->settings['password'] && !$this->_Redis->auth($this->settings['password'])) {
return false;
}
return $this->_Redis->select($this->settings['database']);
}
/**
@ -95,13 +106,18 @@ class RedisEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
if (!is_int($value)) {
$value = serialize($value);
}
if (!$this->_Redis->isConnected()) {
$this->_connect();
}
if ($duration === 0) {
return $this->_Redis->set($key, $value);
}
@ -117,11 +133,11 @@ class RedisEngine extends CacheEngine {
*/
public function read($key) {
$value = $this->_Redis->get($key);
if (ctype_digit($value)) {
$value = (int)$value;
if (preg_match('/^[-]?\d+$/', $value)) {
return (int)$value;
}
if ($value !== false && is_string($value)) {
$value = unserialize($value);
return unserialize($value);
}
return $value;
}
@ -130,7 +146,7 @@ class RedisEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
@ -142,7 +158,7 @@ class RedisEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
@ -154,7 +170,7 @@ class RedisEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Redis->delete($key) > 0;
@ -163,8 +179,9 @@ class RedisEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check Whether or not expiration keys should be checked. If
* true, no keys will be removed as cache will rely on redis TTL's.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
@ -182,7 +199,7 @@ class RedisEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
$result = array();
foreach ($this->settings['groups'] as $group) {
@ -200,20 +217,42 @@ class RedisEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group name to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Redis->incr($this->settings['prefix'] . $group);
}
/**
* Disconnects from the redis server
*
* @return voind
**/
*/
public function __destruct() {
if (!$this->settings['persistent']) {
$this->_Redis->close();
}
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link https://github.com/phpredis/phpredis#setnx
*/
public function add($key, $value, $duration) {
if (!is_int($value)) {
$value = serialize($value);
}
$result = $this->_Redis->setnx($key, $value);
// setnx() doesn't have an expiry option, so overwrite the key with one
if ($result) {
return $this->_Redis->setex($key, $duration, $value);
}
return false;
}
}

View file

@ -4,19 +4,18 @@
*
* Supports wincache 1.1.0 and higher.
*
* 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
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -28,10 +27,10 @@ class WincacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
@ -41,7 +40,7 @@ class WincacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@ -58,8 +57,8 @@ class WincacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@ -81,7 +80,7 @@ class WincacheEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
$cachetime = intval(wincache_ucache_get($key . '_expires'));
$cachetime = (int)wincache_ucache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@ -92,7 +91,7 @@ class WincacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@ -103,7 +102,7 @@ class WincacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@ -114,7 +113,7 @@ class WincacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return wincache_ucache_delete($key);
@ -124,9 +123,9 @@ class WincacheEngine extends CacheEngine {
* Delete all keys from the cache. This will clear every
* item in the cache matching the cache config prefix.
*
* @param boolean $check If true, nothing will be cleared, as entries will
* @param bool $check If true, nothing will be cleared, as entries will
* naturally expire in wincache..
* @return boolean True Returns true.
* @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
@ -149,7 +148,7 @@ class WincacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -180,12 +179,29 @@ class WincacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
$success = null;
wincache_ucache_inc($this->settings['prefix'] . $group, 1, $success);
return $success;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}

View file

@ -2,19 +2,18 @@
/**
* Xcache storage engine for cache.
*
* 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
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4947
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -42,10 +41,10 @@ class XcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
parent::init(array_merge(array(
'engine' => 'Xcache',
'prefix' => Inflector::slug(APP_DIR) . '_',
@ -63,8 +62,8 @@ class XcacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@ -81,7 +80,7 @@ class XcacheEngine extends CacheEngine {
public function read($key) {
if (xcache_isset($key)) {
$time = time();
$cachetime = intval(xcache_get($key . '_expires'));
$cachetime = (int)xcache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@ -95,7 +94,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@ -107,7 +106,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@ -118,7 +117,7 @@ class XcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return xcache_unset($key);
@ -127,8 +126,9 @@ class XcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
$this->_auth();
@ -146,7 +146,7 @@ class XcacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
$result = array();
foreach ($this->settings['groups'] as $group) {
@ -164,8 +164,9 @@ class XcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)xcache_inc($this->settings['prefix'] . $group, 1);
}
@ -177,7 +178,7 @@ class XcacheEngine extends CacheEngine {
* This has to be done because xcache_clear_cache() needs to pass Basic Http Auth
* (see xcache.admin configuration settings)
*
* @param boolean $reverse Revert changes
* @param bool $reverse Revert changes
* @return void
*/
protected function _auth($reverse = false) {
@ -206,4 +207,21 @@ class XcacheEngine extends CacheEngine {
}
}
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}

3916
lib/Cake/Config/cacert.pem Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,20 +2,20 @@
/**
* Core Configurations.
*
* 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
* @package Cake.Config
* @since CakePHP(tm) v 1.1.11.4062
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
$versionFile = file(CAKE . 'VERSION.txt');
$config['Cake.version'] = trim(array_pop($versionFile));
return $config;

View file

@ -1,20 +1,17 @@
<?php
/**
* Default routes that CakePHP provides as catch all routes.
*
* 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
* @package Cake.Config
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -25,7 +22,6 @@
* created when your application has one or more plugins.
*
* - `/:prefix/:plugin` a plugin shortcut route.
* - `/:prefix/:plugin/:action/*` a plugin shortcut route.
* - `/:prefix/:plugin/:controller`
* - `/:prefix/:plugin/:controller/:action/*`
* - `/:prefix/:controller`
@ -34,7 +30,6 @@
* If plugins are found in your application the following routes are created:
*
* - `/:plugin` a plugin shortcut route.
* - `/:plugin/:action/*` a plugin shortcut route.
* - `/:plugin/:controller`
* - `/:plugin/:controller/:action/*`
*
@ -53,8 +48,8 @@ if ($plugins = CakePlugin::loaded()) {
$plugins[$key] = Inflector::underscore($value);
}
$pluginPattern = implode('|', $plugins);
$match = array('plugin' => $pluginPattern);
$shortParams = array('routeClass' => 'PluginShortRoute', 'plugin' => $pluginPattern);
$match = array('plugin' => $pluginPattern, 'defaultRoute' => true);
$shortParams = array('routeClass' => 'PluginShortRoute', 'plugin' => $pluginPattern, 'defaultRoute' => true);
foreach ($prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
@ -71,11 +66,11 @@ if ($plugins = CakePlugin::loaded()) {
foreach ($prefixes as $prefix) {
$params = array('prefix' => $prefix, $prefix => true);
$indexParams = $params + array('action' => 'index');
Router::connect("/{$prefix}/:controller", $indexParams);
Router::connect("/{$prefix}/:controller/:action/*", $params);
Router::connect("/{$prefix}/:controller", $indexParams, array('defaultRoute' => true));
Router::connect("/{$prefix}/:controller/:action/*", $params, array('defaultRoute' => true));
}
Router::connect('/:controller', array('action' => 'index'));
Router::connect('/:controller/:action/*');
Router::connect('/:controller', array('action' => 'index'), array('defaultRoute' => true));
Router::connect('/:controller/:action/*', array(), array('defaultRoute' => true));
$namedConfig = Router::namedConfig();
if ($namedConfig['rules'] === false) {
@ -84,3 +79,4 @@ if ($namedConfig['rules'] === false) {
unset($namedConfig, $params, $indexParams, $prefix, $prefixes, $shortParams, $match,
$pluginPattern, $plugins, $key, $value);

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.6833
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -8,19 +8,18 @@
* @see http://www.unicode.org/Public/UNIDATA/CaseFolding.txt
* @see http://www.unicode.org/reports/tr21/tr21-5.html
*
* 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
* @package Cake.Config.unicode.casefolding
* @since CakePHP(tm) v 1.2.0.5691
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**

View file

@ -1,16 +1,17 @@
<?php
/**
* 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
* @package Cake.Core
* @since CakePHP(tm) v 1.0.0.2363
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -25,9 +26,18 @@ interface ConfigReaderInterface {
* These sources can either be static resources like files, or dynamic ones like
* a database, or other datasource.
*
* @param string $key
* @param string $key Key to read.
* @return array An array of data to merge into the runtime configuration
*/
public function read($key);
/**
* Dumps the configure data into source.
*
* @param string $key The identifier to write to.
* @param array $data The data to dump.
* @return bool True on success or false on failure.
*/
public function dump($key, $data);
}

View file

@ -2,21 +2,22 @@
/**
* IniReader
*
* 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
* @package Cake.Configure
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Hash', 'Utility');
App::uses('CakePlugin', 'Core');
/**
* Ini file configuration engine.
@ -33,10 +34,10 @@ App::uses('Hash', 'Utility');
* You can nest properties as deeply as needed using `.`'s. In addition to using `.` you
* can use standard ini section notation to create nested structures:
*
* {{{
* ```
* [section]
* key = value
* }}}
* ```
*
* Once loaded into Configure, the above would be accessed using:
*
@ -94,30 +95,14 @@ class IniReader implements ConfigReaderInterface {
* @return array Parsed configuration values.
* @throws ConfigureException when files don't exist.
* Or when files contain '..' as this could lead to abusive reads.
* @throws ConfigureException
*/
public function read($key) {
if (strpos($key, '..') !== false) {
throw new ConfigureException(__d('cake_dev', 'Cannot load configuration files with ../ in them.'));
}
if (substr($key, -8) === '.ini.php') {
$key = substr($key, 0, -8);
list($plugin, $key) = pluginSplit($key);
$key .= '.ini.php';
} else {
if (substr($key, -4) === '.ini') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
$key .= '.ini';
}
if ($plugin) {
$file = App::pluginPath($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
if (!is_file($file)) {
$file = $this->_getFilePath($key);
if (!is_file(realpath($file))) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file));
}
@ -165,36 +150,39 @@ class IniReader implements ConfigReaderInterface {
/**
* Dumps the state of Configure data into an ini formatted string.
*
* @param string $filename The filename on $this->_path to save into.
* Extension ".ini" will be automatically appended if not included in filename.
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @param array $data The data to convert to ini file.
* @return int Bytes saved.
*/
public function dump($filename, $data) {
public function dump($key, $data) {
$result = array();
foreach ($data as $key => $value) {
if ($key[0] != '[') {
$result[] = "[$key]";
foreach ($data as $k => $value) {
$isSection = false;
if ($k[0] !== '[') {
$result[] = "[$k]";
$isSection = true;
}
if (is_array($value)) {
$keyValues = Hash::flatten($value, '.');
foreach ($keyValues as $k => $v) {
$result[] = "$k = " . $this->_value($v);
$kValues = Hash::flatten($value, '.');
foreach ($kValues as $k2 => $v) {
$result[] = "$k2 = " . $this->_value($v);
}
}
if ($isSection) {
$result[] = '';
}
$contents = join("\n", $result);
}
$contents = trim(implode("\n", $result));
if (substr($filename, -4) !== '.ini') {
$filename .= '.ini';
}
return file_put_contents($this->_path . $filename, $contents);
$filename = $this->_getFilePath($key);
return file_put_contents($filename, $contents);
}
/**
* Converts a value into the ini equivalent
*
* @param mixed $value to export.
* @param mixed $val Value to export.
* @return string String value for ini file.
*/
protected function _value($val) {
@ -210,4 +198,33 @@ class IniReader implements ConfigReaderInterface {
return (string)$val;
}
/**
* Get file path
*
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @return string Full file path
*/
protected function _getFilePath($key) {
if (substr($key, -8) === '.ini.php') {
$key = substr($key, 0, -8);
list($plugin, $key) = pluginSplit($key);
$key .= '.ini.php';
} else {
if (substr($key, -4) === '.ini') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
$key .= '.ini';
}
if ($plugin) {
$file = CakePlugin::path($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
return $file;
}
}

View file

@ -2,20 +2,21 @@
/**
* PhpReader file
*
* PHP 5
*
* 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://book.cakephp.org/2.0/en/development/configuration.html#loading-configuration-files CakePHP(tm) Configuration
* @package Cake.Configure
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('CakePlugin', 'Core');
/**
* PHP Reader allows Configure to load configuration values from
* files containing simple PHP arrays.
@ -50,7 +51,7 @@ class PhpReader implements ConfigReaderInterface {
* Read a config file and return its contents.
*
* Files with `.` in the name will be treated as values in plugins. Instead of reading from
* the initialized path, plugin keys will be located using App::pluginPath().
* the initialized path, plugin keys will be located using CakePlugin::path().
*
* @param string $key The identifier to read from. If the key has a . it will be treated
* as a plugin prefix.
@ -62,26 +63,15 @@ class PhpReader implements ConfigReaderInterface {
if (strpos($key, '..') !== false) {
throw new ConfigureException(__d('cake_dev', 'Cannot load configuration files with ../ in them.'));
}
if (substr($key, -4) === '.php') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
$key .= '.php';
if ($plugin) {
$file = App::pluginPath($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
if (!is_file($file)) {
$file = $this->_getFilePath($key);
if (!is_file(realpath($file))) {
throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file));
}
include $file;
if (!isset($config)) {
throw new ConfigureException(
sprintf(__d('cake_dev', 'No variable $config found in %s'), $file)
);
throw new ConfigureException(__d('cake_dev', 'No variable %s found in %s', '$config', $file));
}
return $config;
}
@ -90,18 +80,39 @@ class PhpReader implements ConfigReaderInterface {
* Converts the provided $data into a string of PHP code that can
* be used saved into a file and loaded later.
*
* @param string $filename The filename to create on $this->_path.
* Extension ".php" will be automatically appended if not included in filename.
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @param array $data Data to dump.
* @return int Bytes saved.
*/
public function dump($filename, $data) {
public function dump($key, $data) {
$contents = '<?php' . "\n" . '$config = ' . var_export($data, true) . ';';
if (substr($filename, -4) !== '.php') {
$filename .= '.php';
$filename = $this->_getFilePath($key);
return file_put_contents($filename, $contents);
}
return file_put_contents($this->_path . $filename, $contents);
/**
* Get file path
*
* @param string $key The identifier to write to. If the key has a . it will be treated
* as a plugin prefix.
* @return string Full file path
*/
protected function _getFilePath($key) {
if (substr($key, -4) === '.php') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
$key .= '.php';
if ($plugin) {
$file = CakePlugin::path($plugin) . 'Config' . DS . $key;
} else {
$file = $this->_path . $key;
}
return $file;
}
}

View file

@ -2,18 +2,17 @@
/**
* Acl Shell provides Acl access in the CLI environment
*
* 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');
@ -75,22 +74,22 @@ class AclShell extends AppShell {
App::uses($class, $plugin . 'Controller/Component/Acl');
if (!in_array($class, array('DbAcl', 'DB_ACL')) && !is_subclass_of($class, 'DbAcl')) {
$out = "--------------------------------------------------\n";
$out .= __d('cake_console', 'Error: Your current Cake configuration is set to an ACL implementation other than DB.') . "\n";
$out .= __d('cake_console', 'Error: Your current CakePHP configuration is set to an ACL implementation other than DB.') . "\n";
$out .= __d('cake_console', 'Please change your core config to reflect your decision to use DbAcl before attempting to use this script') . "\n";
$out .= "--------------------------------------------------\n";
$out .= __d('cake_console', 'Current ACL Classname: %s', $class) . "\n";
$out .= "--------------------------------------------------\n";
$this->err($out);
$this->_stop();
return $this->_stop();
}
if ($this->command) {
if (!config('database')) {
$this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.'), true);
$this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.'));
$this->args = null;
return $this->DbConfig->execute();
}
require_once (APP . 'Config' . DS . 'database.php');
require_once APP . 'Config' . DS . 'database.php';
if (!in_array($this->command, array('initdb'))) {
$collection = new ComponentCollection();
@ -121,14 +120,14 @@ class AclShell extends AppShell {
$class = ucfirst($this->args[0]);
$parent = $this->parseIdentifier($this->args[1]);
if (!empty($parent) && $parent != '/' && $parent != 'root') {
if (!empty($parent) && $parent !== '/' && $parent !== 'root') {
$parent = $this->_getNodeId($class, $parent);
} else {
$parent = null;
}
$data = $this->parseIdentifier($this->args[2]);
if (is_string($data) && $data != '/') {
if (is_string($data) && $data !== '/') {
$data = array('alias' => $data);
} elseif (is_string($data)) {
$this->error(__d('cake_console', '/ can not be used as an alias!') . __d('cake_console', " / is the root, please supply a sub alias"));
@ -144,7 +143,8 @@ class AclShell extends AppShell {
}
/**
* Delete an ARO/ACO node.
* Delete an ARO/ACO node. Note there may be (as a result of poor configuration)
* multiple records with the same logical identifier. All are deleted.
*
* @return void
*/
@ -152,12 +152,18 @@ class AclShell extends AppShell {
extract($this->_dataVars());
$identifier = $this->parseIdentifier($this->args[1]);
$nodeId = $this->_getNodeId($class, $identifier);
if (is_string($identifier)) {
$identifier = array('alias' => $identifier);
}
if (!$this->Acl->{$class}->delete($nodeId)) {
$this->error(__d('cake_console', 'Node Not Deleted') . __d('cake_console', 'There was an error deleting the %s. Check that the node exists.', $class) . "\n");
if ($this->Acl->{$class}->find('all', array('conditions' => $identifier))) {
if (!$this->Acl->{$class}->deleteAll($identifier)) {
$this->error(__d('cake_console', 'Node Not Deleted. ') . __d('cake_console', 'There was an error deleting the %s.', $class) . "\n");
}
$this->out(__d('cake_console', '<success>%s deleted.</success>', $class), 2);
} else {
$this->error(__d('cake_console', 'Node Not Deleted. ') . __d('cake_console', 'There was an error deleting the %s. Node does not exist.', $class) . "\n");
}
}
/**
@ -178,9 +184,9 @@ class AclShell extends AppShell {
);
$this->Acl->{$class}->create();
if (!$this->Acl->{$class}->save($data)) {
$this->out(__d('cake_console', 'Error in setting new parent. Please make sure the parent node exists, and is not a descendant of the node specified.'), true);
$this->out(__d('cake_console', 'Error in setting new parent. Please make sure the parent node exists, and is not a descendant of the node specified.'));
} else {
$this->out(__d('cake_console', 'Node parent set to %s', $this->args[2]) . "\n", true);
$this->out(__d('cake_console', 'Node parent set to %s', $this->args[2]) . "\n");
}
}
@ -214,7 +220,7 @@ class AclShell extends AppShell {
*
* @param string $class Class name that is being used.
* @param array $node Array of node information.
* @param integer $indent indent level.
* @param int $indent indent level.
* @return void
*/
protected function _outputNode($class, $node, $indent) {
@ -236,9 +242,9 @@ class AclShell extends AppShell {
extract($this->_getParams());
if ($this->Acl->check($aro, $aco, $action)) {
$this->out(__d('cake_console', '%s is <success>allowed</success>.', $aroName), true);
$this->out(__d('cake_console', '%s is <success>allowed</success>.', $aroName));
} else {
$this->out(__d('cake_console', '%s is <error>not allowed</error>.', $aroName), true);
$this->out(__d('cake_console', '%s is <error>not allowed</error>.', $aroName));
}
}
@ -251,9 +257,9 @@ class AclShell extends AppShell {
extract($this->_getParams());
if ($this->Acl->allow($aro, $aco, $action)) {
$this->out(__d('cake_console', 'Permission <success>granted</success>.'), true);
$this->out(__d('cake_console', 'Permission <success>granted</success>.'));
} else {
$this->out(__d('cake_console', 'Permission was <error>not granted</error>.'), true);
$this->out(__d('cake_console', 'Permission was <error>not granted</error>.'));
}
}
@ -266,9 +272,9 @@ class AclShell extends AppShell {
extract($this->_getParams());
if ($this->Acl->deny($aro, $aco, $action)) {
$this->out(__d('cake_console', 'Permission denied.'), true);
$this->out(__d('cake_console', 'Permission denied.'));
} else {
$this->out(__d('cake_console', 'Permission was not denied.'), true);
$this->out(__d('cake_console', 'Permission was not denied.'));
}
}
@ -281,9 +287,9 @@ class AclShell extends AppShell {
extract($this->_getParams());
if ($this->Acl->inherit($aro, $aco, $action)) {
$this->out(__d('cake_console', 'Permission inherited.'), true);
$this->out(__d('cake_console', 'Permission inherited.'));
} else {
$this->out(__d('cake_console', 'Permission was not inherited.'), true);
$this->out(__d('cake_console', 'Permission was not inherited.'));
}
}
@ -357,9 +363,9 @@ class AclShell extends AppShell {
}
/**
* Get the option parser.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
@ -376,6 +382,7 @@ class AclShell extends AppShell {
'help' => __d('cake_console', 'Create a new ACL node'),
'parser' => array(
'description' => __d('cake_console', 'Creates a new ACL object <node> under the parent'),
'epilog' => __d('cake_console', 'You can use `root` as the parent when creating nodes to create top level nodes.'),
'arguments' => array(
'type' => $type,
'parent' => array(
@ -494,8 +501,7 @@ class AclShell extends AppShell {
)
))->addSubcommand('initdb', array(
'help' => __d('cake_console', 'Initialize the DbAcl tables. Uses this command : cake schema create DbAcl')
))->epilog(
array(
))->epilog(array(
'Node and parent arguments can be in one of the following formats:',
'',
' - <model>.<id> - The node will be bound to a specific record of the given model.',
@ -505,15 +511,15 @@ class AclShell extends AppShell {
" i.e. <group>/<subgroup>/<parent>.",
'',
"To add a node at the root level, enter 'root' or '/' as the <parent> parameter."
)
);
));
return $parser;
}
/**
* Checks that given node exists
*
* @return boolean Success
* @return bool Success
*/
public function nodeExists() {
if (!isset($this->args[0]) || !isset($this->args[1])) {
@ -552,8 +558,8 @@ class AclShell extends AppShell {
* or an array of properties to use in AcoNode::node()
*
* @param string $class Class type you want (Aro/Aco)
* @param string|array $identifier A mixed identifier for finding the node.
* @return integer Integer of NodeId. Will trigger an error if nothing is found.
* @param string|array|null $identifier A mixed identifier for finding the node, otherwise null.
* @return int Integer of NodeId. Will trigger an error if nothing is found.
*/
protected function _getNodeId($class, $identifier) {
$node = $this->Acl->{$class}->node($identifier);
@ -562,7 +568,7 @@ class AclShell extends AppShell {
$identifier = var_export($identifier, true);
}
$this->error(__d('cake_console', 'Could not find node using reference "%s"', $identifier));
return;
return null;
}
return Hash::get($node, "0.{$class}.id");
}
@ -573,8 +579,8 @@ class AclShell extends AppShell {
* @return array aro, aco, action
*/
protected function _getParams() {
$aro = is_numeric($this->args[0]) ? intval($this->args[0]) : $this->args[0];
$aco = is_numeric($this->args[1]) ? intval($this->args[1]) : $this->args[1];
$aro = is_numeric($this->args[0]) ? (int)$this->args[0] : $this->args[0];
$aco = is_numeric($this->args[1]) ? (int)$this->args[1] : $this->args[1];
$aroName = $aro;
$acoName = $aco;
@ -598,12 +604,12 @@ class AclShell extends AppShell {
* @return array Variables
*/
protected function _dataVars($type = null) {
if ($type == null) {
if (!$type) {
$type = $this->args[0];
}
$vars = array();
$class = ucwords($type);
$vars['secondary_id'] = (strtolower($class) == 'aro') ? 'foreign_key' : 'object_id';
$vars['secondary_id'] = (strtolower($class) === 'aro') ? 'foreign_key' : 'object_id';
$vars['data_name'] = $type;
$vars['table_name'] = $type . 's';
$vars['class'] = $class;

View file

@ -4,18 +4,17 @@
*
* Implementation of a Cake Shell to show CakePHP core method signatures.
*
* 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');
@ -73,12 +72,13 @@ class ApiShell extends AppShell {
$path = $this->paths['core'];
}
if (count($this->args) == 1) {
$file = $type;
$class = Inflector::camelize($type);
} elseif (count($this->args) > 1) {
$count = count($this->args);
if ($count > 1) {
$file = Inflector::underscore($this->args[1]);
$class = Inflector::camelize($this->args[1]);
} elseif ($count) {
$file = $type;
$class = Inflector::camelize($type);
}
$objects = App::objects('class', $path);
if (in_array($class, $objects)) {
@ -98,7 +98,7 @@ class ApiShell extends AppShell {
if (isset($this->params['method'])) {
if (!isset($parsed[$this->params['method']])) {
$this->err(__d('cake_console', '%s::%s() could not be found', $class, $this->params['method']));
$this->_stop();
return $this->_stop();
}
$method = $parsed[$this->params['method']];
$this->out($class . '::' . $method['method'] . $method['parameters']);
@ -137,20 +137,24 @@ class ApiShell extends AppShell {
}
/**
* Get and configure the optionparser.
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->addArgument('type', array(
$parser->description(
__d('cake_console', 'Lookup doc block comments for classes in CakePHP.')
)->addArgument('type', array(
'help' => __d('cake_console', 'Either a full path or type of class (model, behavior, controller, component, view, helper)')
))->addArgument('className', array(
'help' => __d('cake_console', 'A CakePHP core class name (e.g: Component, HtmlHelper).')
))->addOption('method', array(
'short' => 'm',
'help' => __d('cake_console', 'The specific method you want help on.')
))->description(__d('cake_console', 'Lookup doc block comments for classes in CakePHP.'));
));
return $parser;
}

View file

@ -2,18 +2,17 @@
/**
* AppShell file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Shell', 'Console');

View file

@ -6,18 +6,17 @@
* application development by writing fully functional skeleton controllers,
* models, and views. Going further, Bake can also write Unit Tests for you.
*
* 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');
@ -65,6 +64,9 @@ class BakeShell extends AppShell {
$this->{$task}->connection = $this->params['connection'];
}
}
if (isset($this->params['connection'])) {
$this->connection = $this->params['connection'];
}
}
/**
@ -122,8 +124,7 @@ class BakeShell extends AppShell {
$this->Test->execute();
break;
case 'Q':
exit(0);
break;
return $this->_stop();
default:
$this->out(__d('cake_console', 'You have made an invalid selection. Please choose a type of class to Bake by entering D, M, V, F, T, or C.'));
}
@ -202,18 +203,19 @@ class BakeShell extends AppShell {
}
/**
* 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',
'The Bake script generates controllers, views and models for your application.' .
$parser->description(
__d('cake_console', 'The Bake script generates controllers, views and models for your application.' .
' If run with no command line arguments, Bake guides the user through the class creation process.' .
' You can customize the generation process by telling Bake where different parts of your application are using command line arguments.'
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake a complete MVC. optional <name> of a Model'),
' You can customize the generation process by telling Bake where different parts of your application are using command line arguments.')
)->addSubcommand('all', array(
'help' => __d('cake_console', 'Bake a complete MVC. optional <name> of a Model')
))->addSubcommand('project', array(
'help' => __d('cake_console', 'Bake a new app folder in the path supplied or in current directory if no path is specified'),
'parser' => $this->Project->getOptionParser()
@ -242,7 +244,12 @@ class BakeShell extends AppShell {
'help' => __d('cake_console', 'Database connection to use in conjunction with `bake all`.'),
'short' => 'c',
'default' => 'default'
))->addOption('theme', array(
'short' => 't',
'help' => __d('cake_console', 'Theme to use when baking code.')
));
return $parser;
}
}

View file

@ -1,16 +1,17 @@
<?php
/**
* 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 Project
* @package Cake.Console.Command
* @since CakePHP v 2.0
* @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');
@ -23,6 +24,13 @@ App::uses('Inflector', 'Utility');
*/
class CommandListShell extends AppShell {
/**
* Contains tasks to load and instantiate
*
* @var array
*/
public $tasks = array('Command');
/**
* startup
*
@ -46,15 +54,16 @@ class CommandListShell extends AppShell {
$this->out(" -working: " . rtrim(APP, DS));
$this->out(" -root: " . rtrim(ROOT, DS));
$this->out(" -core: " . rtrim(CORE_PATH, DS));
$this->out(" -webroot: " . rtrim(WWW_ROOT, DS));
$this->out("");
$this->out(__d('cake_console', "<info>Changing Paths:</info>"), 2);
$this->out(__d('cake_console', "Your working path should be the same as your application path to change your path use the '-app' param."));
$this->out(__d('cake_console', "Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp"), 2);
$this->out(__d('cake_console', "Your working path should be the same as your application path. To change your path use the '-app' param."));
$this->out(__d('cake_console', "Example: %s or %s", '-app relative/path/to/myapp', '-app /absolute/path/to/myapp'), 2);
$this->out(__d('cake_console', "<info>Available Shells:</info>"), 2);
}
$shellList = $this->_getShellList();
$shellList = $this->Command->getShellList();
if (empty($shellList)) {
return;
}
@ -66,52 +75,10 @@ class CommandListShell extends AppShell {
}
}
/**
* Gets the shell command listing.
*
* @return array
*/
protected 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
* @param array $shells
* @param array $shellList
* @return array
*/
protected function _appendShells($type, $shells, &$shellList) {
foreach ($shells as $shell) {
$shellList[$type][] = Inflector::underscore(str_replace('Shell', '', $shell));
}
}
/**
* Output text.
*
* @param array $shellList
* @param array $shellList The shell list.
* @return void
*/
protected function _asText($shellList) {
@ -129,7 +96,7 @@ class CommandListShell extends AppShell {
/**
* Output as XML
*
* @param array $shellList
* @param array $shellList The shell list.
* @return void
*/
protected function _asXml($shellList) {
@ -154,21 +121,24 @@ class CommandListShell extends AppShell {
}
/**
* 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', 'Get the list of available shells for this CakePHP application.'))
->addOption('sort', array(
$parser->description(
__d('cake_console', 'Get the list of available shells for this CakePHP application.')
)->addOption('sort', array(
'help' => __d('cake_console', 'Does nothing (deprecated)'),
'boolean' => true
))
->addOption('xml', array(
))->addOption('xml', array(
'help' => __d('cake_console', 'Get the listing as XML.'),
'boolean' => true
));
return $parser;
}
}

View file

@ -0,0 +1,155 @@
<?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 Project
* @package Cake.Console.Command
* @since CakePHP v 2.5
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
/**
* Provide command completion shells such as bash.
*
* @package Cake.Console.Command
*/
class CompletionShell extends AppShell {
/**
* Contains tasks to load and instantiate
*
* @var array
*/
public $tasks = array('Command');
/**
* Echo no header by overriding the startup method
*
* @return void
*/
public function startup() {
}
/**
* Not called by the autocomplete shell - this is for curious users
*
* @return void
*/
public function main() {
return $this->out($this->getOptionParser()->help());
}
/**
* list commands
*
* @return void
*/
public function commands() {
$options = $this->Command->commands();
return $this->_output($options);
}
/**
* list options for the named command
*
* @return void
*/
public function options() {
$commandName = '';
if (!empty($this->args[0])) {
$commandName = $this->args[0];
}
$options = $this->Command->options($commandName);
return $this->_output($options);
}
/**
* list subcommands for the named command
*
* @return void
*/
public function subCommands() {
if (!$this->args) {
return $this->_output();
}
$options = $this->Command->subCommands($this->args[0]);
return $this->_output($options);
}
/**
* Guess autocomplete from the whole argument string
*
* @return void
*/
public function fuzzy() {
return $this->_output();
}
/**
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->description(
__d('cake_console', 'Used by shells like bash to autocomplete command name, options and arguments')
)->addSubcommand('commands', array(
'help' => __d('cake_console', 'Output a list of available commands'),
'parser' => array(
'description' => __d('cake_console', 'List all availables'),
'arguments' => array(
)
)
))->addSubcommand('subcommands', array(
'help' => __d('cake_console', 'Output a list of available subcommands'),
'parser' => array(
'description' => __d('cake_console', 'List subcommands for a command'),
'arguments' => array(
'command' => array(
'help' => __d('cake_console', 'The command name'),
'required' => true,
)
)
)
))->addSubcommand('options', array(
'help' => __d('cake_console', 'Output a list of available options'),
'parser' => array(
'description' => __d('cake_console', 'List options'),
'arguments' => array(
'command' => array(
'help' => __d('cake_console', 'The command name'),
'required' => false,
)
)
)
))->epilog(
__d('cake_console', 'This command is not intended to be called manually')
);
return $parser;
}
/**
* Emit results as a string, space delimited
*
* @param array $options The options to output
* @return void
*/
protected function _output($options = array()) {
if ($options) {
return $this->out(implode($options, ' '));
}
}
}

View file

@ -1,15 +1,16 @@
<?php
/**
* 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');
@ -18,6 +19,7 @@ App::uses('AppShell', 'Console/Command');
* Provides a very basic 'interactive' console for CakePHP apps.
*
* @package Cake.Console.Command
* @deprecated 3.0.0 Deprecated since version 2.4, will be removed in 3.0
*/
class ConsoleShell extends AppShell {
@ -42,6 +44,35 @@ class ConsoleShell extends AppShell {
*/
public $models = array();
/**
* _finished
*
* This shell is perpetual, setting this property to true exits the process
*
* @var mixed
*/
protected $_finished = false;
/**
* _methodPatterns
*
* @var array
*/
protected $_methodPatterns = array(
'help' => '/^(help|\?)/',
'_exit' => '/^(quit|exit)/',
'_models' => '/^models/i',
'_bind' => '/^(\w+) bind (\w+) (\w+)/',
'_unbind' => '/^(\w+) unbind (\w+) (\w+)/',
'_find' => '/.+->find/',
'_save' => '/.+->save/',
'_columns' => '/^(\w+) columns/',
'_routesReload' => '/^routes\s+reload/i',
'_routesShow' => '/^routes\s+show/i',
'_routeToString' => '/^route\s+(\(.*\))$/i',
'_routeToArray' => '/^route\s+(.*)$/i',
);
/**
* Override startup of the Shell
*
@ -54,7 +85,6 @@ class ConsoleShell extends AppShell {
foreach ($this->models as $model) {
$class = $model;
$this->models[$model] = $class;
App::uses($class, 'Model');
$this->{$class} = new $class();
}
@ -74,15 +104,20 @@ class ConsoleShell extends AppShell {
}
}
/**
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$description = array(
$parser = parent::getOptionParser();
$parser->description(array(
'The interactive console is a tool for testing parts of your',
'app before you write code.',
'',
'See below for a list of supported commands.'
);
$epilog = array(
))->epilog(array(
'<info>Model testing</info>',
'',
'To test model results, use the name of your model without a leading $',
@ -141,10 +176,9 @@ class ConsoleShell extends AppShell {
'To show all connected routes, do the following:',
'',
"\tRoutes show",
);
return parent::getOptionParser()
->description($description)
->epilog($epilog);
));
return $parser;
}
/**
* Prints the help message
@ -159,30 +193,75 @@ class ConsoleShell extends AppShell {
/**
* Override main() to handle action
*
* @param string $command
* @param string $command The command to run.
* @return void
*/
public function main($command = null) {
while (true) {
$this->_finished = false;
while (!$this->_finished) {
if (empty($command)) {
$command = trim($this->in(''));
}
switch ($command) {
case 'help':
$this->help();
break;
case 'quit':
case 'exit':
return true;
case 'models':
$method = $this->_method($command);
if ($method) {
$this->$method($command);
} else {
$this->out(__d('cake_console', "Invalid command"));
$this->out();
}
$command = '';
}
}
/**
* Determine the method to process the current command
*
* @param string $command The command to run.
* @return string or false
*/
protected function _method($command) {
foreach ($this->_methodPatterns as $method => $pattern) {
if (preg_match($pattern, $command)) {
return $method;
}
}
return false;
}
/**
* Set the finiished property so that the loop in main method ends
*
* @return void
*/
protected function _exit() {
$this->_finished = true;
}
/**
* List all models
*
* @return void
*/
protected function _models() {
$this->out(__d('cake_console', 'Model classes:'));
$this->hr();
foreach ($this->models as $model) {
$this->out(" - {$model}");
}
break;
case (preg_match("/^(\w+) bind (\w+) (\w+)/", $command, $tmp) == true):
}
/**
* Bind an association
*
* @param mixed $command The command to run.
* @return void
*/
protected function _bind($command) {
preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp);
foreach ($tmp as $data) {
$data = strip_tags($data);
$data = str_replace($this->badCommandChars, "", $data);
@ -199,8 +278,17 @@ class ConsoleShell extends AppShell {
} else {
$this->out(__d('cake_console', "Please verify you are using valid models and association types"));
}
break;
case (preg_match("/^(\w+) unbind (\w+) (\w+)/", $command, $tmp) == true):
}
/**
* Unbind an association
*
* @param mixed $command The command to run.
* @return void
*/
protected function _unbind($command) {
preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp);
foreach ($tmp as $data) {
$data = strip_tags($data);
$data = str_replace($this->badCommandChars, "", $data);
@ -215,7 +303,7 @@ class ConsoleShell extends AppShell {
$validCurrentAssociation = false;
foreach ($currentAssociations as $model => $currentAssociation) {
if ($model == $modelB && $association == $currentAssociation) {
if ($model === $modelB && $association === $currentAssociation) {
$validCurrentAssociation = true;
}
}
@ -227,14 +315,20 @@ class ConsoleShell extends AppShell {
} else {
$this->out(__d('cake_console', "Please verify you are using valid models, valid current association, and valid association types"));
}
break;
case (strpos($command, "->find") > 0):
// Remove any bad info
}
/**
* Perform a find
*
* @param mixed $command The command to run.
* @return void
*/
protected function _find($command) {
$command = strip_tags($command);
$command = str_replace($this->badCommandChars, "", $command);
// Do we have a valid model?
list($modelToCheck, $tmp) = explode('->', $command);
list($modelToCheck) = explode('->', $command);
if ($this->_isValidModel($modelToCheck)) {
$findCommand = "\$data = \$this->$command;";
@ -283,17 +377,23 @@ class ConsoleShell extends AppShell {
} else {
$this->out(__d('cake_console', "%s is not a valid model", $modelToCheck));
}
}
break;
case (strpos($command, '->save') > 0):
/**
* Save a record
*
* @param mixed $command The command to run.
* @return void
*/
protected function _save($command) {
// Validate the model we're trying to save here
$command = strip_tags($command);
$command = str_replace($this->badCommandChars, "", $command);
list($modelToSave, $tmp) = explode("->", $command);
list($modelToSave) = explode("->", $command);
if ($this->_isValidModel($modelToSave)) {
// Extract the array of data we are trying to build
list($foo, $data) = explode("->save", $command);
list(, $data) = explode("->save", $command);
$data = preg_replace('/^\(*(array)?\(*(.+?)\)*$/i', '\\2', $data);
$saveCommand = "\$this->{$modelToSave}->save(array('{$modelToSave}' => array({$data})));";
//@codingStandardsIgnoreStart
@ -301,8 +401,17 @@ class ConsoleShell extends AppShell {
//@codingStandardsIgnoreEnd
$this->out(__d('cake_console', 'Saved record for %s', $modelToSave));
}
break;
case (preg_match("/^(\w+) columns/", $command, $tmp) == true):
}
/**
* Show the columns for a model
*
* @param mixed $command The command to run.
* @return void
*/
protected function _columns($command) {
preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp);
$modelToCheck = strip_tags(str_replace($this->badCommandChars, "", $tmp[1]));
if ($this->_isValidModel($modelToCheck)) {
@ -320,41 +429,62 @@ class ConsoleShell extends AppShell {
} else {
$this->out(__d('cake_console', "Please verify that you selected a valid model"));
}
break;
case (preg_match("/^routes\s+reload/i", $command, $tmp) == true):
}
/**
* Reload route definitions
*
* @return void
*/
protected function _routesReload() {
if (!$this->_loadRoutes()) {
$this->err(__d('cake_console', "There was an error loading the routes config. Please check that the file exists and is free of parse errors."));
break;
return $this->err(__d('cake_console', "There was an error loading the routes config. Please check that the file exists and is free of parse errors."));
}
$this->out(__d('cake_console', "Routes configuration reloaded, %d routes connected", count(Router::$routes)));
break;
case (preg_match("/^routes\s+show/i", $command, $tmp) == true):
}
/**
* Show all routes
*
* @return void
*/
protected function _routesShow() {
$this->out(print_r(Hash::combine(Router::$routes, '{n}.template', '{n}.defaults'), true));
break;
case (preg_match("/^route\s+(\(.*\))$/i", $command, $tmp) == true):
}
/**
* Parse an array URL and show the equivalent URL as a string
*
* @param mixed $command The command to run.
* @return void
*/
protected function _routeToString($command) {
preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp);
//@codingStandardsIgnoreStart
if ($url = eval('return array' . $tmp[1] . ';')) {
//@codingStandardsIgnoreEnd
$this->out(Router::url($url));
}
break;
case (preg_match("/^route\s+(.*)/i", $command, $tmp) == true):
}
/**
* Parse a string URL and show as an array
*
* @param mixed $command The command to run.
* @return void
*/
protected function _routeToArray($command) {
preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp);
$this->out(var_export(Router::parse($tmp[1]), true));
break;
default:
$this->out(__d('cake_console', "Invalid command"));
$this->out();
break;
}
$command = '';
}
}
/**
* Tells if the specified model is included in the list of available models
*
* @param string $modelToCheck
* @return boolean true if is an available model, false otherwise
* @param string $modelToCheck The model to check.
* @return bool true if is an available model, false otherwise
*/
protected function _isValidModel($modelToCheck) {
return in_array($modelToCheck, $this->models);
@ -364,7 +494,7 @@ class ConsoleShell extends AppShell {
* Reloads the routes configuration from app/Config/routes.php, and compiles
* all routes found
*
* @return boolean True if config reload was a success, otherwise false
* @return bool True if config reload was a success, otherwise false
*/
protected function _loadRoutes() {
Router::reload();

View file

@ -2,18 +2,17 @@
/**
* Internationalization Management Shell
*
* 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.5669
* @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');
@ -52,7 +51,7 @@ class I18nShell extends AppShell {
if ($this->command && !in_array($this->command, array('help'))) {
if (!config('database')) {
$this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.'), true);
$this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.'));
return $this->DbConfig->execute();
}
}
@ -83,8 +82,7 @@ class I18nShell extends AppShell {
$this->out($this->OptionParser->help());
break;
case 'q':
exit(0);
break;
return $this->_stop();
default:
$this->out(__d('cake_console', 'You have made an invalid selection. Please choose a command to execute by entering E, I, H, or Q.'));
}
@ -102,13 +100,14 @@ class I18nShell extends AppShell {
}
/**
* Get and configure the Option parser
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
return $parser->description(
$parser->description(
__d('cake_console', 'I18n Shell initializes i18n database table for your application and generates .pot files(s) with translations.')
)->addSubcommand('initdb', array(
'help' => __d('cake_console', 'Initialize the i18n table.')
@ -116,6 +115,8 @@ class I18nShell extends AppShell {
'help' => __d('cake_console', 'Extract the po translations from your application'),
'parser' => $this->Extract->getOptionParser()
));
return $parser;
}
}

View file

@ -1,15 +1,16 @@
<?php
/**
* 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.5550
* @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');
@ -38,7 +39,7 @@ class SchemaShell extends AppShell {
/**
* is this a dry run?
*
* @var boolean
* @var bool
*/
protected $_dry = null;
@ -52,6 +53,8 @@ class SchemaShell extends AppShell {
$this->out('Cake Schema Shell');
$this->hr();
Configure::write('Cache.disable', 1);
$name = $path = $connection = $plugin = null;
if (!empty($this->params['name'])) {
$name = $this->params['name'];
@ -63,12 +66,9 @@ class SchemaShell extends AppShell {
list($this->params['plugin'], $splitName) = pluginSplit($name);
$name = $this->params['name'] = $splitName;
}
if ($name) {
if ($name && empty($this->params['file'])) {
$this->params['file'] = Inflector::underscore($name);
}
if (empty($this->params['file'])) {
} elseif (empty($this->params['file'])) {
$this->params['file'] = 'schema.php';
}
if (strpos($this->params['file'], '.php') === false) {
@ -89,6 +89,7 @@ class SchemaShell extends AppShell {
$name = $plugin;
}
}
$name = Inflector::camelize($name);
$this->Schema = new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin'));
}
@ -102,12 +103,11 @@ class SchemaShell extends AppShell {
$File = new File($this->Schema->path . DS . $this->params['file']);
if ($File->exists()) {
$this->out($File->read());
$this->_stop();
} else {
return $this->_stop();
}
$file = $this->Schema->path . DS . $this->params['file'];
$this->err(__d('cake_console', 'Schema file (%s) could not be found.', $file));
$this->_stop();
}
return $this->_stop();
}
/**
@ -120,7 +120,9 @@ class SchemaShell extends AppShell {
$this->out(__d('cake_console', 'Generating Schema...'));
$options = array();
if ($this->params['force']) {
$options = array('models' => false);
$options['models'] = false;
} elseif (!empty($this->params['models'])) {
$options['models'] = CakeText::tokenize($this->params['models']);
}
$snapshot = false;
@ -148,8 +150,15 @@ class SchemaShell extends AppShell {
Configure::write('Cache.disable', $cacheDisable);
if (!empty($this->params['exclude']) && !empty($content)) {
$excluded = CakeText::tokenize($this->params['exclude']);
foreach ($excluded as $table) {
unset($content['tables'][$table]);
}
}
if ($snapshot === true) {
$fileName = rtrim($this->params['file'], '.php');
$fileName = basename($this->params['file'], '.php');
$Folder = new Folder($this->Schema->path);
$result = $Folder->read();
@ -178,11 +187,10 @@ class SchemaShell extends AppShell {
if ($this->Schema->write($content)) {
$this->out(__d('cake_console', 'Schema file: %s generated', $content['file']));
$this->_stop();
} else {
$this->err(__d('cake_console', 'Schema file: %s generated'));
$this->_stop();
return $this->_stop();
}
$this->err(__d('cake_console', 'Schema file: %s generated'));
return $this->_stop();
}
/**
@ -199,7 +207,7 @@ class SchemaShell extends AppShell {
$Schema = $this->Schema->load();
if (!$Schema) {
$this->err(__d('cake_console', 'Schema could not be loaded'));
$this->_stop();
return $this->_stop();
}
if (!empty($this->params['write'])) {
if ($this->params['write'] == 1) {
@ -223,11 +231,10 @@ class SchemaShell extends AppShell {
if ($File->write($contents)) {
$this->out(__d('cake_console', 'SQL dump file created in %s', $File->pwd()));
$this->_stop();
} else {
$this->err(__d('cake_console', 'SQL dump could not be created'));
$this->_stop();
return $this->_stop();
}
$this->err(__d('cake_console', 'SQL dump could not be created'));
return $this->_stop();
}
$this->out($contents);
return $contents;
@ -272,19 +279,23 @@ class SchemaShell extends AppShell {
$this->out(__d('cake_console', 'Performing a dry run.'));
}
$options = array('name' => $name, 'plugin' => $plugin);
$options = array(
'name' => $name,
'plugin' => $plugin,
'connection' => $this->params['connection'],
);
if (!empty($this->params['snapshot'])) {
$fileName = rtrim($this->Schema->file, '.php');
$fileName = basename($this->Schema->file, '.php');
$options['file'] = $fileName . '_' . $this->params['snapshot'] . '.php';
}
$Schema = $this->Schema->load($options);
if (!$Schema) {
$this->err(__d('cake_console', 'The chosen schema could not be loaded. Attempted to load:'));
$this->err(__d('cake_console', 'File: %s', $this->Schema->path . DS . $this->Schema->file));
$this->err(__d('cake_console', 'Name: %s', $this->Schema->name));
$this->_stop();
$this->err(__d('cake_console', '<error>Error</error>: The chosen schema could not be loaded. Attempted to load:'));
$this->err(__d('cake_console', '- file: %s', $this->Schema->path . DS . $this->Schema->file));
$this->err(__d('cake_console', '- name: %s', $this->Schema->name));
return $this->_stop(2);
}
$table = null;
if (isset($this->args[1])) {
@ -297,11 +308,11 @@ class SchemaShell extends AppShell {
* Create database from Schema object
* Should be called via the run method
*
* @param CakeSchema $Schema
* @param string $table
* @param CakeSchema $Schema The schema instance to create.
* @param string $table The table name.
* @return void
*/
protected function _create($Schema, $table = null) {
protected function _create(CakeSchema $Schema, $table = null) {
$db = ConnectionManager::getDataSource($this->Schema->connection);
$drop = $create = array();
@ -317,13 +328,15 @@ class SchemaShell extends AppShell {
}
if (empty($drop) || empty($create)) {
$this->out(__d('cake_console', 'Schema is up to date.'));
$this->_stop();
return $this->_stop();
}
$this->out("\n" . __d('cake_console', 'The following table(s) will be dropped.'));
$this->out(array_keys($drop));
if ('y' == $this->in(__d('cake_console', 'Are you sure you want to drop the table(s)?'), array('y', 'n'), 'n')) {
if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to drop the table(s)?'), array('y', 'n'), 'n') === 'y'
) {
$this->out(__d('cake_console', 'Dropping table(s).'));
$this->_run($drop, 'drop', $Schema);
}
@ -331,7 +344,9 @@ class SchemaShell extends AppShell {
$this->out("\n" . __d('cake_console', 'The following table(s) will be created.'));
$this->out(array_keys($create));
if ('y' == $this->in(__d('cake_console', 'Are you sure you want to create the table(s)?'), array('y', 'n'), 'y')) {
if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to create the table(s)?'), array('y', 'n'), 'y') === 'y'
) {
$this->out(__d('cake_console', 'Creating table(s).'));
$this->_run($create, 'create', $Schema);
}
@ -342,8 +357,8 @@ class SchemaShell extends AppShell {
* Update database with Schema object
* Should be called via the run method
*
* @param CakeSchema $Schema
* @param string $table
* @param CakeSchema &$Schema The schema instance
* @param string $table The table name.
* @return void
*/
protected function _update(&$Schema, $table = null) {
@ -361,23 +376,36 @@ class SchemaShell extends AppShell {
if (empty($table)) {
foreach ($compare as $table => $changes) {
$contents[$table] = $db->alterSchema(array($table => $changes), $table);
if (isset($compare[$table]['create'])) {
$contents[$table] = $db->createSchema($Schema, $table);
} else {
$contents[$table] = $db->alterSchema(array($table => $compare[$table]), $table);
}
}
} elseif (isset($compare[$table])) {
if (isset($compare[$table]['create'])) {
$contents[$table] = $db->createSchema($Schema, $table);
} else {
$contents[$table] = $db->alterSchema(array($table => $compare[$table]), $table);
}
}
if (empty($contents)) {
$this->out(__d('cake_console', 'Schema is up to date.'));
$this->_stop();
return $this->_stop();
}
$this->out("\n" . __d('cake_console', 'The following statements will run.'));
$this->out(array_map('trim', $contents));
if ('y' == $this->in(__d('cake_console', 'Are you sure you want to alter the tables?'), array('y', 'n'), 'n')) {
if (!empty($this->params['yes']) ||
$this->in(__d('cake_console', 'Are you sure you want to alter the tables?'), array('y', 'n'), 'n') === 'y'
) {
$this->out();
$this->out(__d('cake_console', 'Updating Database...'));
$this->_run($contents, 'update', $Schema);
Configure::write('Cache.disable', false);
Cache::clear(false, '_cake_model_');
}
$this->out(__d('cake_console', 'End update.'));
@ -386,12 +414,12 @@ class SchemaShell extends AppShell {
/**
* Runs sql from _create() or _update()
*
* @param array $contents
* @param string $event
* @param CakeSchema $Schema
* @param array $contents The contents to execute.
* @param string $event The event to fire
* @param CakeSchema $Schema The schema instance.
* @return void
*/
protected function _run($contents, $event, &$Schema) {
protected function _run($contents, $event, CakeSchema $Schema) {
if (empty($contents)) {
$this->err(__d('cake_console', 'Sql could not be run'));
return;
@ -430,11 +458,13 @@ class SchemaShell extends AppShell {
}
/**
* get the option parser
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$plugin = array(
'short' => 'p',
'help' => __d('cake_console', 'The plugin to use.'),
@ -450,17 +480,24 @@ class SchemaShell extends AppShell {
);
$file = array(
'help' => __d('cake_console', 'File name to read and write.'),
'default' => 'schema.php'
);
$name = array(
'help' => __d('cake_console', 'Classname to use. If its Plugin.class, both name and plugin options will be set.')
'help' => __d('cake_console',
'Classname to use. If its Plugin.class, both name and plugin options will be set.'
)
);
$snapshot = array(
'short' => 's',
'help' => __d('cake_console', 'Snapshot number to use/make.')
);
$models = array(
'short' => 'm',
'help' => __d('cake_console', 'Specify models as comma separated list.'),
);
$dry = array(
'help' => __d('cake_console', 'Perform a dry run on create and update commands. Queries will be output instead of run.'),
'help' => __d('cake_console',
'Perform a dry run on create and update commands. Queries will be output instead of run.'
),
'boolean' => true
);
$force = array(
@ -471,8 +508,15 @@ class SchemaShell extends AppShell {
$write = array(
'help' => __d('cake_console', 'Write the dumped SQL to a file.')
);
$exclude = array(
'help' => __d('cake_console', 'Tables to exclude as comma separated list.')
);
$yes = array(
'short' => 'y',
'help' => __d('cake_console', 'Do not prompt for confirmation. Be careful!'),
'boolean' => true
);
$parser = parent::getOptionParser();
$parser->description(
__d('cake_console', 'The Schema Shell generates a schema object from the database and updates the database from the schema.')
)->addSubcommand('view', array(
@ -484,7 +528,7 @@ class SchemaShell extends AppShell {
))->addSubcommand('generate', array(
'help' => __d('cake_console', 'Reads from --connection and writes to --path. Generate snapshots with -s'),
'parser' => array(
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'snapshot', 'force'),
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'snapshot', 'force', 'models', 'exclude'),
'arguments' => array(
'snapshot' => array('help' => __d('cake_console', 'Generate a snapshot.'))
)
@ -498,7 +542,7 @@ class SchemaShell extends AppShell {
))->addSubcommand('create', array(
'help' => __d('cake_console', 'Drop and create tables based on the schema file.'),
'parser' => array(
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot'),
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot', 'yes'),
'args' => array(
'name' => array(
'help' => __d('cake_console', 'Name of schema to use.')
@ -511,7 +555,7 @@ class SchemaShell extends AppShell {
))->addSubcommand('update', array(
'help' => __d('cake_console', 'Alter the tables based on the schema file.'),
'parser' => array(
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot', 'force'),
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot', 'force', 'yes'),
'args' => array(
'name' => array(
'help' => __d('cake_console', 'Name of schema to use.')
@ -522,6 +566,7 @@ class SchemaShell extends AppShell {
)
)
));
return $parser;
}

View file

@ -0,0 +1,167 @@
<?php
/**
* built-in Server Shell
*
* 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.3.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('AppShell', 'Console/Command');
/**
* built-in Server Shell
*
* @package Cake.Console.Command
*/
class ServerShell extends AppShell {
/**
* Default ServerHost
*
* @var string
*/
const DEFAULT_HOST = 'localhost';
/**
* Default ListenPort
*
* @var int
*/
const DEFAULT_PORT = 80;
/**
* server host
*
* @var string
*/
protected $_host = null;
/**
* listen port
*
* @var string
*/
protected $_port = null;
/**
* document root
*
* @var string
*/
protected $_documentRoot = null;
/**
* Override initialize of the Shell
*
* @return void
*/
public function initialize() {
$this->_host = static::DEFAULT_HOST;
$this->_port = static::DEFAULT_PORT;
$this->_documentRoot = WWW_ROOT;
}
/**
* Starts up the Shell and displays the welcome message.
* Allows for checking and configuring prior to command or main execution
*
* Override this method if you want to remove the welcome information,
* or otherwise modify the pre-command flow.
*
* @return void
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::startup
*/
public function startup() {
if (!empty($this->params['host'])) {
$this->_host = $this->params['host'];
}
if (!empty($this->params['port'])) {
$this->_port = $this->params['port'];
}
if (!empty($this->params['document_root'])) {
$this->_documentRoot = $this->params['document_root'];
}
// for Windows
if (substr($this->_documentRoot, -1, 1) === DIRECTORY_SEPARATOR) {
$this->_documentRoot = substr($this->_documentRoot, 0, strlen($this->_documentRoot) - 1);
}
if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_documentRoot, $m)) {
$this->_documentRoot = $m[1] . '\\' . $m[2];
}
parent::startup();
}
/**
* Displays a header for the shell
*
* @return void
*/
protected function _welcome() {
$this->out();
$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));
$this->out(__d('cake_console', 'DocumentRoot: %s', $this->_documentRoot));
$this->hr();
}
/**
* Override main() to handle action
*
* @return void
*/
public function main() {
if (version_compare(PHP_VERSION, '5.4.0') < 0) {
$this->out(__d('cake_console', '<warning>This command is available on %s or above</warning>', 'PHP5.4'));
return;
}
$command = sprintf("php -S %s:%d -t %s %s",
$this->_host,
$this->_port,
escapeshellarg($this->_documentRoot),
escapeshellarg($this->_documentRoot . '/index.php')
);
$port = ($this->_port == static::DEFAULT_PORT) ? '' : ':' . $this->_port;
$this->out(__d('cake_console', 'built-in server is running in http://%s%s/', $this->_host, $port));
system($command);
}
/**
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->description(array(
__d('cake_console', 'PHP Built-in Server for CakePHP'),
__d('cake_console', '<warning>[WARN] Don\'t use this at the production environment</warning>')
))->addOption('host', array(
'short' => 'H',
'help' => __d('cake_console', 'ServerHost')
))->addOption('port', array(
'short' => 'p',
'help' => __d('cake_console', 'ListenPort')
))->addOption('document_root', array(
'short' => 'd',
'help' => __d('cake_console', 'DocumentRoot')
));
return $parser;
}
}

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;

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();
}
@ -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,19 +182,24 @@ 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;
@ -187,7 +207,7 @@ class ControllerTask extends BakeTask {
$this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components);
$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 {
@ -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'")
);
));
}
/**
@ -375,7 +401,7 @@ class ControllerTask extends BakeTask {
protected function _doPropertyChoices($prompt, $example) {
$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,15 +467,16 @@ 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(
$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).'),
@ -463,9 +490,19 @@ class ControllerTask extends BakeTask {
))->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.'));
))->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,11 +199,11 @@ 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();
@ -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(
$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.'),
$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('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(
))->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(
))->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(
))->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(
' 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(
))->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(
' 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(
))->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,9 +571,18 @@ 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) {
usort($paths, function ($a, $b) {
return strlen($b) - strlen($a);
});
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) {
@ -523,21 +590,28 @@ class ExtractTask extends AppShell {
$occurrences[] = $file . ':' . implode(';', $lines);
}
$occurrences = implode("\n#: ", $occurrences);
$header = '#: ' . str_replace($paths, '', $occurrences) . "\n";
$header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n";
}
$sentence = '';
if ($context) {
$sentence .= "msgctxt \"{$context}\"\n";
}
if ($plural === false) {
$sentence = "msgid \"{$msgid}\"\n";
$sentence .= "msgid \"{$msgid}\"\n";
$sentence .= "msgstr \"\"\n\n";
} else {
$sentence = "msgid \"{$msgid}\"\n";
$sentence .= "msgid \"{$msgid}\"\n";
$sentence .= "msgid_plural \"{$plural}\"\n";
$sentence .= "msgstr[0] \"\"\n";
$sentence .= "msgstr[1] \"\"\n\n";
}
$this->_store($domain, $header, $sentence);
if ($domain != 'default' && $this->_merge) {
$this->_store('default', $header, $sentence);
$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,15 +650,20 @@ class ExtractTask extends AppShell {
if (!empty($this->params['overwrite'])) {
$overwriteAll = true;
}
foreach ($this->_storage as $domain => $sentences) {
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();
@ -591,7 +674,7 @@ class ExtractTask extends AppShell {
);
if (strtoupper($response) === 'N') {
$response = '';
while ($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;
@ -604,6 +687,7 @@ class ExtractTask extends AppShell {
$File->close();
}
}
}
/**
* Build the translation template header
@ -618,7 +702,6 @@ class ExtractTask extends AppShell {
$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,11 +121,12 @@ 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);
}
}
@ -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();
$plugin = '';
if (isset($this->params['plugin'])) {
$plugin = $this->params['plugin'] . '.';
}
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') {
if ($doSchema === 'y') {
$options['schema'] = $modelName;
}
}
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') {
if ($doRecords === 'y') {
$options['records'] = true;
}
if ($doRecords == 'n') {
}
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,6 +333,7 @@ class FixtureTask extends BakeTask {
if (empty($fieldInfo['type'])) {
continue;
}
$insert = '';
switch ($fieldInfo['type']) {
case 'integer':
case 'float':
@ -306,11 +342,11 @@ class FixtureTask extends BakeTask {
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'])) {
@ -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;
}
}
@ -234,13 +233,13 @@ 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') {
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') {
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';
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,10 +729,10 @@ 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."));
@ -700,7 +741,7 @@ class ModelTask extends BakeTask {
$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);
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,44 +973,44 @@ 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(
$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.')
@ -974,10 +1019,20 @@ class ModelTask extends BakeTask {
))->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.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
))->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(
$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.')
'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');
@ -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();
@ -296,13 +296,13 @@ class TestTask extends BakeTask {
* @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,7 +422,7 @@ class TestTask extends BakeTask {
$models = $subject->uses;
}
foreach ($models as $model) {
list($plugin, $model) = pluginSplit($model);
list(, $model) = pluginSplit($model);
$this->_processModel($subject->{$model});
}
}
@ -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,11 +466,11 @@ 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';
}
/**
@ -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";
}
@ -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,14 +543,16 @@ 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(
$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',
@ -561,10 +563,20 @@ class TestTask extends BakeTask {
)
))->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.')
))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
))->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');
@ -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,13 +412,14 @@ 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.')
@ -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'];

View file

@ -4,18 +4,17 @@
*
* This Shell allows the running of test suites via the cake command line
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
* 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://book.cakephp.org/2.0/en/development/testing.html
* @since CakePHP(tm) v 1.2.0.4433
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Shell', 'Console');
@ -39,20 +38,21 @@ class TestShell extends Shell {
protected $_dispatcher = null;
/**
* get the option parser for the test suite.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = new ConsoleOptionParser($this->name);
$parser->description(array(
__d('cake_console', 'The CakePHP Testsuite allows you to run test cases from the command line'),
))->addArgument('category', array(
$parser->description(
__d('cake_console', 'The CakePHP Testsuite allows you to run test cases from the command line')
)->addArgument('category', array(
'help' => __d('cake_console', 'The category for the test, or test file, to test.'),
'required' => false,
'required' => false
))->addArgument('file', array(
'help' => __d('cake_console', 'The path to the file, or test file, to test.'),
'required' => false,
'required' => false
))->addOption('log-junit', array(
'help' => __d('cake_console', '<file> Log test execution in JUnit XML format to file.'),
'default' => false
@ -71,6 +71,9 @@ class TestShell extends Shell {
))->addOption('coverage-clover', array(
'help' => __d('cake_console', '<file> Write code coverage data in Clover XML format.'),
'default' => false
))->addOption('coverage-text', array(
'help' => __d('cake_console', 'Output code coverage report in Text format.'),
'boolean' => true
))->addOption('testdox-html', array(
'help' => __d('cake_console', '<file> Write agile documentation in HTML format to file.'),
'default' => false
@ -152,11 +155,12 @@ class TestShell extends Shell {
'default' => false
))->addOption('directive', array(
'help' => __d('cake_console', 'key[=value] Sets a php.ini value.'),
'short' => 'd',
'default' => false
))->addOption('fixture', array(
'help' => __d('cake_console', 'Choose a custom fixture manager.'),
'help' => __d('cake_console', 'Choose a custom fixture manager.')
))->addOption('debug', array(
'help' => __d('cake_console', 'More verbose output.'),
'help' => __d('cake_console', 'More verbose output.')
));
return $parser;
@ -170,20 +174,20 @@ class TestShell extends Shell {
*/
public function initialize() {
$this->_dispatcher = new CakeTestSuiteDispatcher();
$sucess = $this->_dispatcher->loadTestFramework();
if (!$sucess) {
throw new Exception(__d('cake_dev', 'Please install PHPUnit framework <info>(http://www.phpunit.de)</info>'));
$success = $this->_dispatcher->loadTestFramework();
if (!$success) {
throw new Exception(__d('cake_dev', 'Please install PHPUnit framework v3.7 <info>(http://www.phpunit.de)</info>'));
}
}
/**
* Parse the CLI options into an array CakeTestDispatcher can use.
*
* @return array Array of params for CakeTestDispatcher
* @return array|null Array of params for CakeTestDispatcher or null.
*/
protected function _parseArgs() {
if (empty($this->args)) {
return;
return null;
}
$params = array(
'core' => false,
@ -222,6 +226,7 @@ class TestShell extends Shell {
$options = array();
$params = $this->params;
unset($params['help']);
unset($params['quiet']);
if (!empty($params['no-colors'])) {
unset($params['no-colors'], $params['colors']);
@ -233,7 +238,11 @@ class TestShell extends Shell {
if ($value === false) {
continue;
}
if ($param === 'directive') {
$options[] = '-d';
} else {
$options[] = '--' . $param;
}
if (is_string($value)) {
$options[] = $value;
}
@ -303,7 +312,7 @@ class TestShell extends Shell {
$this->out($title);
$i = 1;
$cases = array();
foreach ($testCases as $testCaseFile => $testCase) {
foreach ($testCases as $testCase) {
$case = str_replace('Test.php', '', $testCase);
$this->out("[$i] $case");
$cases[$i] = $case;
@ -325,7 +334,7 @@ class TestShell extends Shell {
break;
}
if ($choice == 'q') {
if ($choice === 'q') {
break;
}
}
@ -334,11 +343,10 @@ class TestShell extends Shell {
/**
* Find the test case for the passed file. The file could itself be a test.
*
* @param string $file
* @param string $category
* @param boolean $throwOnMissingFile
* @access protected
* @return array(type, case)
* @param string $file The file to map.
* @param string $category The test file category.
* @param bool $throwOnMissingFile Whether or not to throw an exception.
* @return array array(type, case)
* @throws Exception
*/
protected function _mapFileToCase($file, $category, $throwOnMissingFile = true) {
@ -412,8 +420,7 @@ class TestShell extends Shell {
/**
* For the given file, what category of test is it? returns app, core or the name of the plugin
*
* @param string $file
* @access protected
* @param string $file The file to map.
* @return string
*/
protected function _mapFileToCategory($file) {

View file

@ -4,18 +4,17 @@
*
* This is a bc wrapper for the newer Test shell
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
* 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://book.cakephp.org/2.0/en/development/testing.html
* @since CakePHP(tm) v 1.2.0.4433
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('TestShell', 'Console/Command');
@ -33,16 +32,16 @@ App::uses('CakeTestLoader', 'TestSuite');
class TestsuiteShell extends TestShell {
/**
* get the option parser for the test suite.
* Gets the option parser instance and configures it.
*
* @return void
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$parser->description(array(
__d('cake_console', 'The CakePHP Testsuite allows you to run test cases from the command line'),
__d('cake_console', '<warning>This shell is for backwards-compatibility only</warning>'),
__d('cake_console', 'use the test shell instead')
__d('cake_console', "<warning>This shell is for backwards-compatibility only</warning>\nuse the test shell instead")
));
return $parser;
@ -66,11 +65,11 @@ class TestsuiteShell extends TestShell {
$category = $this->args[0];
if ($category == 'core') {
if ($category === 'core') {
$params['core'] = true;
} elseif ($category == 'app') {
} elseif ($category === 'app') {
$params['app'] = true;
} elseif ($category != 'core') {
} elseif ($category !== 'core') {
$params['plugin'] = $category;
}

View file

@ -2,23 +2,23 @@
/**
* Upgrade Shell
*
* 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
* @package Cake.Console.Command
* @since CakePHP(tm) v 2.0
* @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('Folder', 'Utility');
App::uses('CakePlugin', 'Core');
/**
* A shell class to help developers upgrade applications to CakePHP 2.0
@ -103,7 +103,7 @@ class UpgradeShell extends AppShell {
public function tests() {
$this->_paths = array(APP . 'tests' . DS);
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']) . 'tests' . DS);
$this->_paths = array(CakePlugin::path($this->params['plugin']) . 'tests' . DS);
}
$patterns = array(
array(
@ -129,7 +129,7 @@ class UpgradeShell extends AppShell {
$cwd = getcwd();
if (!empty($this->params['plugin'])) {
chdir(App::pluginPath($this->params['plugin']));
chdir(CakePlugin::path($this->params['plugin']));
}
if (is_dir('plugins')) {
@ -200,7 +200,7 @@ class UpgradeShell extends AppShell {
$dir = $options;
$options = array();
}
$options = array_merge($defaultOptions, $options);
$options += $defaultOptions;
$this->_movePhpFiles($dir, $options);
}
}
@ -216,7 +216,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_diff(App::path('views'), App::core('views'));
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']) . 'views' . DS);
$this->_paths = array(CakePlugin::path($this->params['plugin']) . 'views' . DS);
}
$patterns = array();
@ -230,7 +230,7 @@ class UpgradeShell extends AppShell {
CakePlugin::load($plugin);
$pluginHelpers = array_merge(
$pluginHelpers,
App::objects('helper', App::pluginPath($plugin) . DS . 'views' . DS . 'helpers' . DS, false)
App::objects('helper', CakePlugin::path($plugin) . DS . 'views' . DS . 'helpers' . DS, false)
);
}
$helpers = array_merge($pluginHelpers, $helpers);
@ -261,7 +261,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']));
$this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
@ -300,7 +300,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']));
$this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@ -355,7 +355,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_merge($views, $controllers, $components);
if (!empty($this->params['plugin'])) {
$pluginPath = App::pluginPath($this->params['plugin']);
$pluginPath = CakePlugin::path($this->params['plugin']);
$this->_paths = array(
$pluginPath . 'controllers' . DS,
$pluginPath . 'controllers' . DS . 'components' . DS,
@ -393,6 +393,11 @@ class UpgradeShell extends AppShell {
'/(\$this->action\b(?!\())/',
'$this->request->action'
),
array(
'$this->request->onlyAllow() -> $this->request->allowMethod()',
'/\$this->request->onlyAllow\(/',
'$this->request->allowMethod('
)
);
$this->_filesRegexpUpdate($patterns);
}
@ -407,7 +412,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']));
$this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@ -429,7 +434,7 @@ class UpgradeShell extends AppShell {
APP
);
if (!empty($this->params['plugin'])) {
$this->_paths = array(App::pluginPath($this->params['plugin']));
$this->_paths = array(CakePlugin::path($this->params['plugin']));
}
$patterns = array(
array(
@ -501,10 +506,33 @@ class UpgradeShell extends AppShell {
$this->_filesRegexpUpdate($patterns);
}
/**
* Update controller redirects.
*
* - Make redirect statements return early.
*
* @return void
*/
public function controller_redirects() {
$this->_paths = App::Path('Controller');
if (!empty($this->params['plugin'])) {
$this->_paths = App::Path('Controller', $this->params['plugin']);
}
$patterns = array(
array(
'$this->redirect() to return $this->redirect()',
'/\t\$this-\>redirect\(/',
"\t" . 'return $this->redirect('
),
);
$this->_filesRegexpUpdate($patterns);
}
/**
* Update components.
*
* - Make components that extend Object to extend Component.
* - Make components that extend CakeObject to extend Component.
*
* @return void
*/
@ -519,6 +547,11 @@ class UpgradeShell extends AppShell {
'/([a-zA-Z]*Component extends) Object/',
'\1 Component'
),
array(
'*Component extends CakeObject to *Component extends Component',
'/([a-zA-Z]*Component extends) CakeObject/',
'\1 Component'
),
);
$this->_filesRegexpUpdate($patterns);
@ -527,6 +560,7 @@ class UpgradeShell extends AppShell {
/**
* Replace cakeError with built-in exceptions.
* NOTE: this ignores calls where you've passed your own secondary parameters to cakeError().
*
* @return void
*/
public function exceptions() {
@ -536,7 +570,7 @@ class UpgradeShell extends AppShell {
$this->_paths = array_merge($controllers, $components);
if (!empty($this->params['plugin'])) {
$pluginPath = App::pluginPath($this->params['plugin']);
$pluginPath = CakePlugin::path($this->params['plugin']);
$this->_paths = array(
$pluginPath . 'controllers' . DS,
$pluginPath . 'controllers' . DS . 'components' . DS,
@ -582,7 +616,7 @@ class UpgradeShell extends AppShell {
$new = 'View' . DS . Inflector::camelize($old);
$old = 'View' . DS . $old;
if ($new == $old) {
if ($new === $old) {
continue;
}
@ -631,10 +665,10 @@ class UpgradeShell extends AppShell {
/**
* Move application php files to where they now should be
*
* Find all php files in the folder (honoring recursive) and determine where cake expects the file to be
* If the file is not exactly where cake expects it - move it.
* Find all php files in the folder (honoring recursive) and determine where CakePHP expects the file to be
* If the file is not exactly where CakePHP expects it - move it.
*
* @param string $path
* @param string $path The path to move files in.
* @param array $options array(recursive, checkFolder)
* @return void
*/
@ -736,7 +770,7 @@ class UpgradeShell extends AppShell {
/**
* Searches the paths and finds files based on extension.
*
* @param string $extensions
* @param string $extensions The extensions to include. Defaults to none.
* @return void
*/
protected function _findFiles($extensions = '') {
@ -780,11 +814,13 @@ class UpgradeShell extends AppShell {
}
/**
* get the option parser
* Gets the option parser instance and configures it.
*
* @return ConsoleOptionParser
*/
public function getOptionParser() {
$parser = parent::getOptionParser();
$subcommandParser = array(
'options' => array(
'plugin' => array(
@ -809,53 +845,49 @@ class UpgradeShell extends AppShell {
)
);
return parent::getOptionParser()
->description(__d('cake_console', "A shell to help automate upgrading from CakePHP 1.3 to 2.0. \n" .
"Be sure to have a backup of your application before running these commands."))
->addSubcommand('all', array(
$parser->description(
__d('cake_console', "A tool to help automate upgrading an application or plugin " .
"from CakePHP 1.3 to 2.0. Be sure to have a backup of your application before " .
"running these commands."
))->addSubcommand('all', array(
'help' => __d('cake_console', 'Run all upgrade commands.'),
'parser' => $subcommandParser
))
->addSubcommand('tests', array(
))->addSubcommand('tests', array(
'help' => __d('cake_console', 'Update tests class names to FooTest rather than FooTestCase.'),
'parser' => $subcommandParser
))
->addSubcommand('locations', array(
))->addSubcommand('locations', array(
'help' => __d('cake_console', 'Move files and folders to their new homes.'),
'parser' => $subcommandParser
))
->addSubcommand('i18n', array(
))->addSubcommand('i18n', array(
'help' => __d('cake_console', 'Update the i18n translation method calls.'),
'parser' => $subcommandParser
))
->addSubcommand('helpers', array(
))->addSubcommand('helpers', array(
'help' => __d('cake_console', 'Update calls to helpers.'),
'parser' => $subcommandParser
))
->addSubcommand('basics', array(
))->addSubcommand('basics', array(
'help' => __d('cake_console', 'Update removed basics functions to PHP native functions.'),
'parser' => $subcommandParser
))
->addSubcommand('request', array(
))->addSubcommand('request', array(
'help' => __d('cake_console', 'Update removed request access, and replace with $this->request.'),
'parser' => $subcommandParser
))
->addSubcommand('configure', array(
))->addSubcommand('configure', array(
'help' => __d('cake_console', "Update Configure::read() to Configure::read('debug')"),
'parser' => $subcommandParser
))
->addSubcommand('constants', array(
))->addSubcommand('constants', array(
'help' => __d('cake_console', "Replace Obsolete constants"),
'parser' => $subcommandParser
))
->addSubcommand('components', array(
))->addSubcommand('controller_redirects', array(
'help' => __d('cake_console', 'Return early on controller redirect calls.'),
'parser' => $subcommandParser
))->addSubcommand('components', array(
'help' => __d('cake_console', 'Update components to extend Component class.'),
'parser' => $subcommandParser
))
->addSubcommand('exceptions', array(
))->addSubcommand('exceptions', array(
'help' => __d('cake_console', 'Replace use of cakeError with exceptions.'),
'parser' => $subcommandParser
));
return $parser;
}
}

View file

@ -2,19 +2,19 @@
/**
* ErrorHandler for Console Shells
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('ErrorHandler', 'Error');
App::uses('ConsoleOutput', 'Console');
App::uses('CakeLog', 'Log');
@ -40,35 +40,37 @@ class ConsoleErrorHandler {
* @return ConsoleOutput
*/
public static function getStderr() {
if (empty(self::$stderr)) {
self::$stderr = new ConsoleOutput('php://stderr');
if (empty(static::$stderr)) {
static::$stderr = new ConsoleOutput('php://stderr');
}
return self::$stderr;
return static::$stderr;
}
/**
* Handle a exception in the console environment. Prints a message to stderr.
* Handle an exception in the console environment. Prints a message to stderr.
*
* @param Exception $exception The exception to handle
* @param Exception|ParserError $exception The exception to handle
* @return void
*/
public function handleException(Exception $exception) {
$stderr = self::getStderr();
public function handleException($exception) {
$stderr = static::getStderr();
$stderr->write(__d('cake_console', "<error>Error:</error> %s\n%s",
$exception->getMessage(),
$exception->getTraceAsString()
));
$this->_stop($exception->getCode() ? $exception->getCode() : 1);
$code = $exception->getCode();
$code = ($code && is_int($code)) ? $code : 1;
return $this->_stop($code);
}
/**
* Handle errors in the console environment. Writes errors to stderr,
* and logs messages if Configure::read('debug') is 0.
*
* @param integer $code Error code
* @param int $code Error code
* @param string $description Description of the error.
* @param string $file The file the error occurred in.
* @param integer $line The line the error occurred on.
* @param int $line The line the error occurred on.
* @param array $context The backtrace of the error.
* @return void
*/
@ -76,24 +78,25 @@ class ConsoleErrorHandler {
if (error_reporting() === 0) {
return;
}
$stderr = self::getStderr();
$stderr = static::getStderr();
list($name, $log) = ErrorHandler::mapErrorCode($code);
$message = __d('cake_console', '%s in [%s, line %s]', $description, $file, $line);
$stderr->write(__d('cake_console', "<error>%s Error:</error> %s\n", $name, $message));
if (Configure::read('debug') == 0) {
if (!Configure::read('debug')) {
CakeLog::write($log, $message);
}
if ($log === LOG_ERR) {
$this->_stop(1);
return $this->_stop(1);
}
}
/**
* Wrapper for exit(), used for testing.
*
* @param $code int The exit code.
* @param int $code The exit code.
* @return void
*/
protected function _stop($code = 0) {
exit($code);

View file

@ -2,20 +2,20 @@
/**
* ConsoleInput file.
*
* 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
* @package Cake.Console
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Object wrapper for interacting with stdin
*
@ -30,12 +30,24 @@ class ConsoleInput {
*/
protected $_input;
/**
* Can this instance use readline?
* Two conditions must be met:
* 1. Readline support must be enabled.
* 2. Handle we are attached to must be stdin.
* Allows rich editing with arrow keys and history when inputting a string.
*
* @var bool
*/
protected $_canReadline;
/**
* Constructor
*
* @param string $handle The location of the stream to use as input.
*/
public function __construct($handle = 'php://stdin') {
$this->_canReadline = extension_loaded('readline') && $handle === 'php://stdin' ? true : false;
$this->_input = fopen($handle, 'r');
}
@ -45,7 +57,26 @@ class ConsoleInput {
* @return mixed The value of the stream
*/
public function read() {
if ($this->_canReadline) {
$line = readline('');
if (!empty($line)) {
readline_add_history($line);
}
return $line;
}
return fgets($this->_input);
}
/**
* Checks if data is available on the stream
*
* @param int $timeout An optional time to wait for data
* @return bool True for data available, false otherwise
*/
public function dataAvailable($timeout = 0) {
$readFds = array($this->_input);
$readyFds = stream_select($readFds, $writeFds, $errorFds, $timeout);
return ($readyFds > 0);
}
}

View file

@ -2,19 +2,19 @@
/**
* ConsoleArgumentOption file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* An object to represent a single argument used in the command line.
* ConsoleOptionParser creates these when you use addArgument()
@ -41,7 +41,7 @@ class ConsoleInputArgument {
/**
* Is this option required?
*
* @var boolean
* @var bool
*/
protected $_required;
@ -57,7 +57,7 @@ class ConsoleInputArgument {
*
* @param string|array $name The long name of the option, or an array with all the properties.
* @param string $help The help text for this option
* @param boolean $required Whether this argument is required. Missing required args will trigger exceptions
* @param bool $required Whether this argument is required. Missing required args will trigger exceptions
* @param array $choices Valid choices for this option.
*/
public function __construct($name, $help = '', $required = false, $choices = array()) {
@ -85,7 +85,7 @@ class ConsoleInputArgument {
/**
* Generate the help for this argument.
*
* @param integer $width The width to make the name of the option.
* @param int $width The width to make the name of the option.
* @return string
*/
public function help($width = 0) {
@ -123,7 +123,7 @@ class ConsoleInputArgument {
/**
* Check if this argument is a required argument
*
* @return boolean
* @return bool
*/
public function isRequired() {
return (bool)$this->_required;
@ -132,8 +132,8 @@ class ConsoleInputArgument {
/**
* Check that $value is a valid choice for this argument.
*
* @param string $value
* @return boolean
* @param string $value The choice to validate.
* @return bool
* @throws ConsoleException
*/
public function validChoice($value) {

View file

@ -2,18 +2,17 @@
/**
* ConsoleInputOption file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -49,7 +48,7 @@ class ConsoleInputOption {
/**
* Is the option a boolean option. Boolean options do not consume a parameter.
*
* @var boolean
* @var bool
*/
protected $_boolean;
@ -73,7 +72,7 @@ class ConsoleInputOption {
* @param string|array $name The long name of the option, or an array with all the properties.
* @param string $short The short alias for this option
* @param string $help The help text for this option
* @param boolean $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
* @param bool $boolean Whether this option is a boolean option. Boolean options don't consume extra tokens
* @param string $default The default value for this option.
* @param array $choices Valid choices for this option.
* @throws ConsoleException
@ -119,7 +118,7 @@ class ConsoleInputOption {
/**
* Generate the help for this this option.
*
* @param integer $width The width to make the name of the option.
* @param int $width The width to make the name of the option.
* @return string
*/
public function help($width = 0) {
@ -169,7 +168,7 @@ class ConsoleInputOption {
/**
* Check if this option is a boolean option
*
* @return boolean
* @return bool
*/
public function isBoolean() {
return (bool)$this->_boolean;
@ -178,8 +177,8 @@ class ConsoleInputOption {
/**
* Check that a value is a valid choice for this option.
*
* @param string $value
* @return boolean
* @param string $value The choice to validate.
* @return bool
* @throws ConsoleException
*/
public function validChoice($value) {

View file

@ -2,18 +2,17 @@
/**
* ConsoleInputSubcommand file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -82,7 +81,7 @@ class ConsoleInputSubcommand {
/**
* Generate the help for this this subcommand.
*
* @param integer $width The width to make the name of the subcommand.
* @param int $width The width to make the name of the subcommand.
* @return string
*/
public function help($width = 0) {

View file

@ -2,18 +2,17 @@
/**
* ConsoleOptionParser file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('TaskCollection', 'Console');
@ -137,7 +136,7 @@ class ConsoleOptionParser {
* Construct an OptionParser so you can define its behavior
*
* @param string $command The command name this parser is for. The command name is used for generating help.
* @param boolean $defaultOptions Whether you want the verbose and quiet options set. Setting
* @param bool $defaultOptions Whether you want the verbose and quiet options set. Setting
* this to false will prevent the addition of `--verbose` & `--quiet` options.
*/
public function __construct($command = null, $defaultOptions = true) {
@ -166,7 +165,7 @@ class ConsoleOptionParser {
* Static factory method for creating new OptionParsers so you can chain methods off of them.
*
* @param string $command The command name this parser is for. The command name is used for generating help.
* @param boolean $defaultOptions Whether you want the verbose and quiet options set.
* @param bool $defaultOptions Whether you want the verbose and quiet options set.
* @return ConsoleOptionParser
*/
public static function create($command, $defaultOptions = true) {
@ -176,7 +175,7 @@ class ConsoleOptionParser {
/**
* Build a parser from an array. Uses an array like
*
* {{{
* ```
* $spec = array(
* 'description' => 'text',
* 'epilog' => 'text',
@ -190,7 +189,7 @@ class ConsoleOptionParser {
* // list of subcommands to add.
* )
* );
* }}}
* ```
*
* @param array $spec The spec to build the OptionParser with.
* @return ConsoleOptionParser
@ -219,7 +218,7 @@ class ConsoleOptionParser {
* Get or set the command name for shell/task.
*
* @param string $text The text to set, or null if you want to read
* @return mixed If reading, the value of the command. If setting $this will be returned
* @return string|self If reading, the value of the command. If setting $this will be returned.
*/
public function command($text = null) {
if ($text !== null) {
@ -234,7 +233,7 @@ class ConsoleOptionParser {
*
* @param string|array $text The text to set, or null if you want to read. If an array the
* text will be imploded with "\n"
* @return mixed If reading, the value of the description. If setting $this will be returned
* @return string|self If reading, the value of the description. If setting $this will be returned.
*/
public function description($text = null) {
if ($text !== null) {
@ -252,7 +251,7 @@ class ConsoleOptionParser {
* the options and arguments listing when help is generated.
*
* @param string|array $text Text when setting or null when reading. If an array the text will be imploded with "\n"
* @return mixed If reading, the value of the epilog. If setting $this will be returned.
* @return string|self If reading, the value of the epilog. If setting $this will be returned.
*/
public function epilog($text = null) {
if ($text !== null) {
@ -285,7 +284,7 @@ class ConsoleOptionParser {
* @param ConsoleInputOption|string $name The long name you want to the value to be parsed out as when options are parsed.
* Will also accept an instance of ConsoleInputOption
* @param array $options An array of parameters that define the behavior of the option
* @return ConsoleOptionParser $this.
* @return self
*/
public function addOption($name, $options = array()) {
if (is_object($name) && $name instanceof ConsoleInputOption) {
@ -300,7 +299,7 @@ class ConsoleOptionParser {
'boolean' => false,
'choices' => array()
);
$options = array_merge($defaults, $options);
$options += $defaults;
$option = new ConsoleInputOption($options);
}
$this->_options[$name] = $option;
@ -325,7 +324,7 @@ class ConsoleOptionParser {
*
* @param ConsoleInputArgument|string $name The name of the argument. Will also accept an instance of ConsoleInputArgument
* @param array $params Parameters for the argument, see above.
* @return ConsoleOptionParser $this.
* @return self
*/
public function addArgument($name, $params = array()) {
if (is_object($name) && $name instanceof ConsoleInputArgument) {
@ -339,7 +338,7 @@ class ConsoleOptionParser {
'required' => false,
'choices' => array()
);
$options = array_merge($defaults, $params);
$options = $params + $defaults;
$index = $options['index'];
unset($options['index']);
$arg = new ConsoleInputArgument($options);
@ -355,7 +354,7 @@ class ConsoleOptionParser {
*
* @param array $args Array of arguments to add.
* @see ConsoleOptionParser::addArgument()
* @return ConsoleOptionParser $this
* @return self
*/
public function addArguments(array $args) {
foreach ($args as $name => $params) {
@ -370,7 +369,7 @@ class ConsoleOptionParser {
*
* @param array $options Array of options to add.
* @see ConsoleOptionParser::addOption()
* @return ConsoleOptionParser $this
* @return self
*/
public function addOptions(array $options) {
foreach ($options as $name => $params) {
@ -392,7 +391,7 @@ class ConsoleOptionParser {
*
* @param ConsoleInputSubcommand|string $name Name of the subcommand. Will also accept an instance of ConsoleInputSubcommand
* @param array $options Array of params, see above.
* @return ConsoleOptionParser $this.
* @return self
*/
public function addSubcommand($name, $options = array()) {
if (is_object($name) && $name instanceof ConsoleInputSubcommand) {
@ -404,18 +403,29 @@ class ConsoleOptionParser {
'help' => '',
'parser' => null
);
$options = array_merge($defaults, $options);
$options += $defaults;
$command = new ConsoleInputSubcommand($options);
}
$this->_subcommands[$name] = $command;
return $this;
}
/**
* Remove a subcommand from the option parser.
*
* @param string $name The subcommand name to remove.
* @return self
*/
public function removeSubcommand($name) {
unset($this->_subcommands[$name]);
return $this;
}
/**
* Add multiple subcommands at once.
*
* @param array $commands Array of subcommands.
* @return ConsoleOptionParser $this
* @return self
*/
public function addSubcommands(array $commands) {
foreach ($commands as $name => $params) {
@ -459,7 +469,7 @@ class ConsoleOptionParser {
* @param array $argv Array of args (argv) to parse.
* @param string $command The subcommand to use. If this parameter is a subcommand, that has a parser,
* That parser will be used to parse $argv instead.
* @return Array array($params, $args)
* @return array array($params, $args)
* @throws ConsoleException When an invalid parameter is encountered.
*/
public function parse($argv, $command = null) {
@ -469,9 +479,9 @@ class ConsoleOptionParser {
$params = $args = array();
$this->_tokens = $argv;
while (($token = array_shift($this->_tokens)) !== null) {
if (substr($token, 0, 2) == '--') {
if (substr($token, 0, 2) === '--') {
$params = $this->_parseLongOption($token, $params);
} elseif (substr($token, 0, 1) == '-') {
} elseif (substr($token, 0, 1) === '-') {
$params = $this->_parseShortOption($token, $params);
} else {
$args = $this->_parseArg($token, $args);
@ -507,12 +517,11 @@ class ConsoleOptionParser {
* @param string $subcommand If present and a valid subcommand that has a linked parser.
* That subcommands help will be shown instead.
* @param string $format Define the output format, can be text or xml
* @param integer $width The width to format user content to. Defaults to 72
* @param int $width The width to format user content to. Defaults to 72
* @return string Generated help.
*/
public function help($subcommand = null, $format = 'text', $width = 72) {
if (
isset($this->_subcommands[$subcommand]) &&
if (isset($this->_subcommands[$subcommand]) &&
$this->_subcommands[$subcommand]->parser() instanceof self
) {
$subparser = $this->_subcommands[$subcommand]->parser();
@ -520,9 +529,9 @@ class ConsoleOptionParser {
return $subparser->help(null, $format, $width);
}
$formatter = new HelpFormatter($this);
if ($format == 'text' || $format === true) {
if ($format === 'text' || $format === true) {
return $formatter->text($width);
} elseif ($format == 'xml') {
} elseif ($format === 'xml') {
return $formatter->xml();
}
}
@ -598,13 +607,14 @@ class ConsoleOptionParser {
$params[$name] = $value;
return $params;
}
return array();
}
/**
* Check to see if $name has an option (short/long) defined for it.
*
* @param string $name The name of the option.
* @return boolean
* @return bool
*/
protected function _optionExists($name) {
if (substr($name, 0, 2) === '--') {

View file

@ -2,19 +2,19 @@
/**
* ConsoleOutput file.
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Object wrapper for outputting information from a shell application.
* Can be connected to any stream resource that can be used with fopen()
@ -43,23 +43,32 @@
* @package Cake.Console
*/
class ConsoleOutput {
/**
* Raw output constant - no modification of output text.
*
* @var int
*/
const RAW = 0;
/**
* Plain output - tags will be stripped.
*
* @var int
*/
const PLAIN = 1;
/**
* Color output - Convert known tags in to ANSI color escape codes.
*
* @var int
*/
const COLOR = 2;
/**
* Constant for a newline.
*
* @var string
*/
const LF = PHP_EOL;
@ -70,10 +79,18 @@ class ConsoleOutput {
*/
protected $_output;
/**
* The number of bytes last written to the output stream
* used when overwriting the previous message.
*
* @var int
*/
protected $_lastWritten = 0;
/**
* The current output type. Manipulated with ConsoleOutput::outputAs();
*
* @var integer.
* @var int
*/
protected $_outputAs = self::COLOR;
@ -138,21 +155,25 @@ class ConsoleOutput {
'success' => array('text' => 'green'),
'comment' => array('text' => 'blue'),
'question' => array('text' => 'magenta'),
'notice' => array('text' => 'cyan')
);
/**
* Construct the output object.
*
* Checks for a pretty console environment. Ansicon allows pretty consoles
* on windows, and is supported.
* Checks for a pretty console environment. Ansicon and ConEmu allows
* pretty consoles on Windows, and is supported.
*
* @param string $stream The identifier of the stream to write output to.
*/
public function __construct($stream = 'php://stdout') {
$this->_output = fopen($stream, 'w');
if (DS == '\\' && !(bool)env('ANSICON')) {
$this->_outputAs = self::PLAIN;
if ((DS === '\\' && !(bool)env('ANSICON') && env('ConEmuANSI') !== 'ON') ||
$stream === 'php://output' ||
(function_exists('posix_isatty') && !posix_isatty($this->_output))
) {
$this->_outputAs = static::PLAIN;
}
}
@ -160,15 +181,44 @@ class ConsoleOutput {
* Outputs a single or multiple messages to stdout. If no parameters
* are passed, outputs just a newline.
*
* @param string|array $message A string or a an array of strings to output
* @param integer $newlines Number of newlines to append
* @return integer Returns the number of bytes returned from writing to stdout.
* @param string|array $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
* @return int Returns the number of bytes returned from writing to stdout.
*/
public function write($message, $newlines = 1) {
if (is_array($message)) {
$message = implode(self::LF, $message);
$message = implode(static::LF, $message);
}
return $this->_write($this->styleText($message . str_repeat(static::LF, $newlines)));
}
/**
* Overwrite some already output text.
*
* Useful for building progress bars, or when you want to replace
* text already output to the screen with new text.
*
* **Warning** You cannot overwrite text that contains newlines.
*
* @param array|string $message The message to output.
* @param int $newlines Number of newlines to append.
* @param int|null $size The number of bytes to overwrite. Defaults to the
* length of the last message output.
* @return void
*/
public function overwrite($message, $newlines = 1, $size = null) {
$size = $size ?: $this->_lastWritten;
// Output backspaces.
$this->write(str_repeat("\x08", $size), 0);
$newBytes = $this->write($message, 0);
// Fill any remaining bytes with spaces.
$fill = $size - $newBytes;
if ($fill > 0) {
$this->write(str_repeat(' ', $fill), 0);
}
if ($newlines) {
$this->write("", $newlines);
}
return $this->_write($this->styleText($message . str_repeat(self::LF, $newlines)));
}
/**
@ -178,11 +228,11 @@ class ConsoleOutput {
* @return string String with color codes added.
*/
public function styleText($text) {
if ($this->_outputAs == self::RAW) {
if ($this->_outputAs == static::RAW) {
return $text;
}
if ($this->_outputAs == self::PLAIN) {
$tags = implode('|', array_keys(self::$_styles));
if ($this->_outputAs == static::PLAIN) {
$tags = implode('|', array_keys(static::$_styles));
return preg_replace('#</?(?:' . $tags . ')>#', '', $text);
}
return preg_replace_callback(
@ -193,7 +243,7 @@ class ConsoleOutput {
/**
* Replace tags with color codes.
*
* @param array $matches.
* @param array $matches An array of matches to replace.
* @return string
*/
protected function _replaceTags($matches) {
@ -203,16 +253,16 @@ class ConsoleOutput {
}
$styleInfo = array();
if (!empty($style['text']) && isset(self::$_foregroundColors[$style['text']])) {
$styleInfo[] = self::$_foregroundColors[$style['text']];
if (!empty($style['text']) && isset(static::$_foregroundColors[$style['text']])) {
$styleInfo[] = static::$_foregroundColors[$style['text']];
}
if (!empty($style['background']) && isset(self::$_backgroundColors[$style['background']])) {
$styleInfo[] = self::$_backgroundColors[$style['background']];
if (!empty($style['background']) && isset(static::$_backgroundColors[$style['background']])) {
$styleInfo[] = static::$_backgroundColors[$style['background']];
}
unset($style['text'], $style['background']);
foreach ($style as $option => $value) {
if ($value) {
$styleInfo[] = self::$_options[$option];
$styleInfo[] = static::$_options[$option];
}
}
return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m";
@ -222,10 +272,11 @@ class ConsoleOutput {
* Writes a message to the output stream.
*
* @param string $message Message to write.
* @return boolean success
* @return bool success
*/
protected function _write($message) {
return fwrite($this->_output, $message);
$this->_lastWritten = fwrite($this->_output, $message);
return $this->_lastWritten;
}
/**
@ -255,23 +306,23 @@ class ConsoleOutput {
*/
public function styles($style = null, $definition = null) {
if ($style === null && $definition === null) {
return self::$_styles;
return static::$_styles;
}
if (is_string($style) && $definition === null) {
return isset(self::$_styles[$style]) ? self::$_styles[$style] : null;
return isset(static::$_styles[$style]) ? static::$_styles[$style] : null;
}
if ($definition === false) {
unset(self::$_styles[$style]);
unset(static::$_styles[$style]);
return true;
}
self::$_styles[$style] = $definition;
static::$_styles[$style] = $definition;
return true;
}
/**
* Get/Set the output type to use. The output type how formatting tags are treated.
*
* @param integer $type The output type to use. Should be one of the class constants.
* @param int $type The output type to use. Should be one of the class constants.
* @return mixed Either null or the value if getting.
*/
public function outputAs($type = null) {
@ -282,11 +333,12 @@ class ConsoleOutput {
}
/**
* clean up and close handles
*
* Clean up and close handles
*/
public function __destruct() {
if (is_resource($this->_output)) {
fclose($this->_output);
}
}
}

View file

@ -2,19 +2,19 @@
/**
* HelpFormatter
*
* 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
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('String', 'Utility');
App::uses('CakeText', 'Utility');
/**
* HelpFormatter formats help for console shells. Can format to either
@ -33,19 +33,19 @@ class HelpFormatter {
/**
* The maximum number of arguments shown when generating usage.
*
* @var integer
* @var int
*/
protected $_maxArgs = 6;
/**
* The maximum number of options shown when generating usage.
*
* @var integer
* @var int
*/
protected $_maxOptions = 6;
/**
* Build the help formatter for a an OptionParser
* Build the help formatter for an OptionParser
*
* @param ConsoleOptionParser $parser The option parser help is being generated for.
*/
@ -56,7 +56,7 @@ class HelpFormatter {
/**
* Get the help as formatted text suitable for output on the command line.
*
* @param integer $width The width of the help output.
* @param int $width The width of the help output.
* @return string
*/
public function text($width = 72) {
@ -64,7 +64,7 @@ class HelpFormatter {
$out = array();
$description = $parser->description();
if (!empty($description)) {
$out[] = String::wrap($description, $width);
$out[] = CakeText::wrap($description, $width);
$out[] = '';
}
$out[] = __d('cake_console', '<info>Usage:</info>');
@ -76,7 +76,7 @@ class HelpFormatter {
$out[] = '';
$max = $this->_getMaxLength($subcommands) + 2;
foreach ($subcommands as $command) {
$out[] = String::wrap($command->help($max), array(
$out[] = CakeText::wrap($command->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@ -93,7 +93,7 @@ class HelpFormatter {
$out[] = __d('cake_console', '<info>Options:</info>');
$out[] = '';
foreach ($options as $option) {
$out[] = String::wrap($option->help($max), array(
$out[] = CakeText::wrap($option->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@ -108,7 +108,7 @@ class HelpFormatter {
$out[] = __d('cake_console', '<info>Arguments:</info>');
$out[] = '';
foreach ($arguments as $argument) {
$out[] = String::wrap($argument->help($max), array(
$out[] = CakeText::wrap($argument->help($max), array(
'width' => $width,
'indent' => str_repeat(' ', $max),
'indentAt' => 1
@ -118,7 +118,7 @@ class HelpFormatter {
}
$epilog = $parser->epilog();
if (!empty($epilog)) {
$out[] = String::wrap($epilog, $width);
$out[] = CakeText::wrap($epilog, $width);
$out[] = '';
}
return implode("\n", $out);
@ -159,8 +159,8 @@ class HelpFormatter {
/**
* Iterate over a collection and find the longest named thing.
*
* @param array $collection
* @return integer
* @param array $collection The collection to find a max length of.
* @return int
*/
protected function _getMaxLength($collection) {
$max = 0;
@ -173,8 +173,8 @@ class HelpFormatter {
/**
* Get the help as an xml string.
*
* @param boolean $string Return the SimpleXml object or a string. Defaults to true.
* @return mixed. See $string
* @param bool $string Return the SimpleXml object or a string. Defaults to true.
* @return string|SimpleXmlElement See $string
*/
public function xml($string = true) {
$parser = $this->_parser;

View file

@ -0,0 +1,82 @@
<?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 2.8
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
abstract class BaseShellHelper {
/**
* Default config for this helper.
*
* @var array
*/
protected $_defaultConfig = array();
/**
* ConsoleOutput instance.
*
* @var ConsoleOutput
*/
protected $_consoleOutput;
/**
* Runtime config
*
* @var array
*/
protected $_config = array();
/**
* Whether the config property has already been configured with defaults
*
* @var bool
*/
protected $_configInitialized = false;
/**
* Constructor.
*
* @param ConsoleOutput $consoleOutput The ConsoleOutput instance to use.
* @param array $config The settings for this helper.
*/
public function __construct(ConsoleOutput $consoleOutput, array $config = array()) {
$this->_consoleOutput = $consoleOutput;
$this->config($config);
}
/**
* Initialize config & store config values
*
* @param null $config Config values to set
* @return array|void
*/
public function config($config = null) {
if ($config === null) {
return $this->_config;
}
if (!$this->_configInitialized) {
$this->_config = array_merge($this->_defaultConfig, $config);
$this->_configInitialized = true;
} else {
$this->_config = array_merge($this->_config, $config);
}
}
/**
* This method should output content using `$this->_consoleOutput`.
*
* @param array $args The arguments for the helper.
* @return void
*/
abstract public function output($args);
}

View file

@ -0,0 +1,122 @@
<?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 2.8
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses("BaseShellHelper", "Console/Helper");
/**
* Create a progress bar using a supplied callback.
*/
class ProgressShellHelper extends BaseShellHelper {
/**
* The current progress.
*
* @var int
*/
protected $_progress = 0;
/**
* The total number of 'items' to progress through.
*
* @var int
*/
protected $_total = 0;
/**
* The width of the bar.
*
* @var int
*/
protected $_width = 0;
/**
* Output a progress bar.
*
* Takes a number of options to customize the behavior:
*
* - `total` The total number of items in the progress bar. Defaults
* to 100.
* - `width` The width of the progress bar. Defaults to 80.
* - `callback` The callback that will be called in a loop to advance the progress bar.
*
* @param array $args The arguments/options to use when outputing the progress bar.
* @return void
* @throws RuntimeException
*/
public function output($args) {
$args += array('callback' => null);
if (isset($args[0])) {
$args['callback'] = $args[0];
}
if (!$args['callback'] || !is_callable($args['callback'])) {
throw new RuntimeException('Callback option must be a callable.');
}
$this->init($args);
$callback = $args['callback'];
while ($this->_progress < $this->_total) {
$callback($this);
$this->draw();
}
$this->_consoleOutput->write('');
}
/**
* Initialize the progress bar for use.
*
* - `total` The total number of items in the progress bar. Defaults
* to 100.
* - `width` The width of the progress bar. Defaults to 80.
*
* @param array $args The initialization data.
* @return void
*/
public function init(array $args = array()) {
$args += array('total' => 100, 'width' => 80);
$this->_progress = 0;
$this->_width = $args['width'];
$this->_total = $args['total'];
}
/**
* Increment the progress bar.
*
* @param int $num The amount of progress to advance by.
* @return void
*/
public function increment($num = 1) {
$this->_progress = min(max(0, $this->_progress + $num), $this->_total);
}
/**
* Render the progress bar based on the current state.
*
* @return void
*/
public function draw() {
$numberLen = strlen(' 100%');
$complete = round($this->_progress / $this->_total, 2);
$barLen = ($this->_width - $numberLen) * ($this->_progress / $this->_total);
$bar = '';
if ($barLen > 1) {
$bar = str_repeat('=', $barLen - 1) . '>';
}
$pad = ceil($this->_width - $numberLen - $barLen);
if ($pad > 0) {
$bar .= str_repeat(' ', $pad);
}
$percent = ($complete * 100) . '%';
$bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
$this->_consoleOutput->overwrite($bar, 0);
}
}

View file

@ -0,0 +1,124 @@
<?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 2.8
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses("BaseShellHelper", "Console/Helper");
/**
* Create a visually pleasing ASCII art table
* from 2 dimensional array data.
*/
class TableShellHelper extends BaseShellHelper {
/**
* Default config for this helper.
*
* @var array
*/
protected $_defaultConfig = array(
'headers' => true,
'rowSeparator' => false,
'headerStyle' => 'info',
);
/**
* Calculate the column widths
*
* @param array $rows The rows on which the columns width will be calculated on.
* @return array
*/
protected function _calculateWidths($rows) {
$widths = array();
foreach ($rows as $line) {
for ($i = 0, $len = count($line); $i < $len; $i++) {
$columnLength = mb_strlen($line[$i]);
if ($columnLength > (isset($widths[$i]) ? $widths[$i] : 0)) {
$widths[$i] = $columnLength;
}
}
}
return $widths;
}
/**
* Output a row separator.
*
* @param array $widths The widths of each column to output.
* @return void
*/
protected function _rowSeparator($widths) {
$out = '';
foreach ($widths as $column) {
$out .= '+' . str_repeat('-', $column + 2);
}
$out .= '+';
$this->_consoleOutput->write($out);
}
/**
* Output a row.
*
* @param array $row The row to output.
* @param array $widths The widths of each column to output.
* @param array $options Options to be passed.
* @return void
*/
protected function _render($row, $widths, $options = array()) {
$out = '';
foreach ($row as $i => $column) {
$pad = $widths[$i] - mb_strlen($column);
if (!empty($options['style'])) {
$column = $this->_addStyle($column, $options['style']);
}
$out .= '| ' . $column . str_repeat(' ', $pad) . ' ';
}
$out .= '|';
$this->_consoleOutput->write($out);
}
/**
* Output a table.
*
* @param array $rows The data to render out.
* @return void
*/
public function output($rows) {
$config = $this->config();
$widths = $this->_calculateWidths($rows);
$this->_rowSeparator($widths);
if ($config['headers'] === true) {
$this->_render(array_shift($rows), $widths, array('style' => $config['headerStyle']));
$this->_rowSeparator($widths);
}
foreach ($rows as $line) {
$this->_render($line, $widths);
if ($config['rowSeparator'] === true) {
$this->_rowSeparator($widths);
}
}
if ($config['rowSeparator'] !== true) {
$this->_rowSeparator($widths);
}
}
/**
* Add style tags
*
* @param string $text The text to be surrounded
* @param string $style The style to be applied
* @return string
*/
protected function _addStyle($text, $style) {
return '<' . $style . '>' . $text . '</' . $style . '>';
}
}

View file

@ -2,18 +2,17 @@
/**
* Base class for Shells
*
* 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('TaskCollection', 'Console');
@ -21,6 +20,7 @@ App::uses('ConsoleOutput', 'Console');
App::uses('ConsoleInput', 'Console');
App::uses('ConsoleInputSubcommand', 'Console');
App::uses('ConsoleOptionParser', 'Console');
App::uses('ClassRegistry', 'Utility');
App::uses('File', 'Utility');
/**
@ -28,13 +28,34 @@ App::uses('File', 'Utility');
*
* @package Cake.Console
*/
class Shell extends Object {
class Shell extends CakeObject {
/**
* Output constants for making verbose and quiet shells.
* Default error code
*
* @var int
*/
const CODE_ERROR = 1;
/**
* Output constant making verbose shells.
*
* @var int
*/
const VERBOSE = 2;
/**
* Output constant for making normal shells.
*
* @var int
*/
const NORMAL = 1;
/**
* Output constants for making quiet shells.
*
* @var int
*/
const QUIET = 0;
/**
@ -47,7 +68,7 @@ class Shell extends Object {
/**
* If true, the script will ask for permission to perform actions.
*
* @var boolean
* @var bool
*/
public $interactive = true;
@ -110,6 +131,13 @@ class Shell extends Object {
*/
public $uses = array();
/**
* This shell's primary model class name, the first model in the $uses property
*
* @var string
*/
public $modelClass = null;
/**
* Task Collection for the command, used to create Tasks.
*
@ -145,6 +173,21 @@ class Shell extends Object {
*/
public $stdin;
/**
* The number of bytes last written to the output stream
* used when overwriting the previous message.
*
* @var int
*/
protected $_lastWritten = 0;
/**
* Contains helpers which have been previously instantiated
*
* @var array
*/
protected $_helpers = array();
/**
* Constructs this Shell instance.
*
@ -154,29 +197,21 @@ class Shell extends Object {
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell
*/
public function __construct($stdout = null, $stderr = null, $stdin = null) {
if ($this->name == null) {
if (!$this->name) {
$this->name = Inflector::camelize(str_replace(array('Shell', 'Task'), '', get_class($this)));
}
$this->Tasks = new TaskCollection($this);
$this->stdout = $stdout;
$this->stderr = $stderr;
$this->stdin = $stdin;
if ($this->stdout == null) {
$this->stdout = new ConsoleOutput('php://stdout');
}
if ($this->stderr == null) {
$this->stderr = new ConsoleOutput('php://stderr');
}
if ($this->stdin == null) {
$this->stdin = new ConsoleInput('php://stdin');
}
$this->stdout = $stdout ? $stdout : new ConsoleOutput('php://stdout');
$this->stderr = $stderr ? $stderr : new ConsoleOutput('php://stderr');
$this->stdin = $stdin ? $stdin : new ConsoleInput('php://stdin');
$this->_useLogger();
$parent = get_parent_class($this);
if ($this->tasks !== null && $this->tasks !== false) {
$this->_mergeVars(array('tasks'), $parent, true);
}
if ($this->uses !== null && $this->uses !== false) {
if (!empty($this->uses)) {
$this->_mergeVars(array('uses'), $parent, false);
}
}
@ -191,6 +226,7 @@ class Shell extends Object {
*/
public function initialize() {
$this->_loadModels();
$this->loadTasks();
}
/**
@ -222,50 +258,80 @@ class Shell extends Object {
}
/**
* If $uses = true
* Loads AppModel file and constructs AppModel class
* makes $this->AppModel available to subclasses
* If public $uses is an array of models will load those models
* If $uses is an array load each of the models in the array
*
* @return boolean
* @return bool
*/
protected function _loadModels() {
if ($this->uses === null || $this->uses === false) {
return;
if (is_array($this->uses)) {
list(, $this->modelClass) = pluginSplit(current($this->uses));
foreach ($this->uses as $modelClass) {
$this->loadModel($modelClass);
}
App::uses('ClassRegistry', 'Utility');
if ($this->uses !== true && !empty($this->uses)) {
$uses = is_array($this->uses) ? $this->uses : array($this->uses);
$modelClassName = $uses[0];
if (strpos($uses[0], '.') !== false) {
list($plugin, $modelClassName) = explode('.', $uses[0]);
}
$this->modelClass = $modelClassName;
foreach ($uses as $modelClass) {
list($plugin, $modelClass) = pluginSplit($modelClass, true);
$this->{$modelClass} = ClassRegistry::init($plugin . $modelClass);
}
return true;
}
return false;
/**
* Lazy loads models using the loadModel() method if declared in $uses
*
* @param string $name The name of the model to look for.
* @return void
*/
public function __isset($name) {
if (is_array($this->uses)) {
foreach ($this->uses as $modelClass) {
list(, $class) = pluginSplit($modelClass);
if ($name === $class) {
return $this->loadModel($modelClass);
}
}
}
}
/**
* Loads and instantiates models required by this shell.
*
* @param string $modelClass Name of model class to load
* @param mixed $id Initial ID the instanced model class should have
* @return mixed true when single model found and instance created, error returned if model not found.
* @throws MissingModelException if the model class cannot be found.
*/
public function loadModel($modelClass = null, $id = null) {
if ($modelClass === null) {
$modelClass = $this->modelClass;
}
$this->uses = ($this->uses) ? (array)$this->uses : array();
if (!in_array($modelClass, $this->uses)) {
$this->uses[] = $modelClass;
}
list($plugin, $modelClass) = pluginSplit($modelClass, true);
if (!isset($this->modelClass)) {
$this->modelClass = $modelClass;
}
$this->{$modelClass} = ClassRegistry::init(array(
'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id
));
if (!$this->{$modelClass}) {
throw new MissingModelException($modelClass);
}
return true;
}
/**
* Loads tasks defined in public $tasks
*
* @return boolean
* @return bool
*/
public function loadTasks() {
if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) {
return true;
}
$this->_taskMap = TaskCollection::normalizeObjectArray((array)$this->tasks);
foreach ($this->_taskMap as $task => $properties) {
$this->taskNames[] = $task;
}
$this->taskNames = array_merge($this->taskNames, array_keys($this->_taskMap));
return true;
}
@ -273,7 +339,7 @@ class Shell extends Object {
* Check to see if this shell has a task with the provided name.
*
* @param string $task The task name to check.
* @return boolean Success
* @return bool Success
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasTask
*/
public function hasTask($task) {
@ -284,7 +350,7 @@ class Shell extends Object {
* Check to see if this shell has a callable method by the given name.
*
* @param string $name The method name to check.
* @return boolean
* @return bool
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasMethod
*/
public function hasMethod($name) {
@ -293,7 +359,7 @@ class Shell extends Object {
if (!$method->isPublic() || substr($name, 0, 1) === '_') {
return false;
}
if ($method->getDeclaringClass()->name == 'Shell') {
if ($method->getDeclaringClass()->name === 'Shell') {
return false;
}
return true;
@ -303,7 +369,7 @@ class Shell extends Object {
}
/**
* Dispatch a command to another Shell. Similar to Object::requestAction()
* Dispatch a command to another Shell. Similar to CakeObject::requestAction()
* but intended for running shells from other shells.
*
* ### Usage:
@ -325,7 +391,7 @@ class Shell extends Object {
*/
public function dispatchShell() {
$args = func_get_args();
if (is_string($args[0]) && count($args) == 1) {
if (is_string($args[0]) && count($args) === 1) {
$args = explode(' ', $args[0]);
}
@ -401,12 +467,12 @@ class Shell extends Object {
/**
* Display the help in the correct format
*
* @param string $command
* @param string $command The command to get help for.
* @return void
*/
protected function _displayHelp($command) {
$format = 'text';
if (!empty($this->args[0]) && $this->args[0] == 'xml') {
if (!empty($this->args[0]) && $this->args[0] === 'xml') {
$format = 'xml';
$this->stdout->outputAs(ConsoleOutput::RAW);
} else {
@ -417,6 +483,7 @@ class Shell extends Object {
/**
* Gets the option parser instance and configures it.
*
* By overriding this method you can configure the ConsoleOptionParser before returning it.
*
* @return ConsoleOptionParser
@ -431,7 +498,7 @@ class Shell extends Object {
/**
* Overload get for lazy building of tasks
*
* @param string $name
* @param string $name The property name to access.
* @return Shell Object of Task
*/
public function __get($name) {
@ -446,6 +513,19 @@ class Shell extends Object {
return $this->{$name};
}
/**
* Safely access the values in $this->params.
*
* @param string $name The name of the parameter to get.
* @return string|bool|null Value. Will return null if it doesn't exist.
*/
public function param($name) {
if (!isset($this->params[$name])) {
return null;
}
return $this->params[$name];
}
/**
* Prompts the user for input, and returns it.
*
@ -507,7 +587,8 @@ class Shell extends Object {
$result = $this->stdin->read();
if ($result === false) {
$this->_stop(1);
$this->_stop(self::CODE_ERROR);
return self::CODE_ERROR;
}
$result = trim($result);
@ -528,13 +609,13 @@ class Shell extends Object {
* - `indent` Indent the text with the string provided. Defaults to null.
*
* @param string $text Text the text to format.
* @param string|integer|array $options Array of options to use, or an integer to wrap the text to.
* @param string|int|array $options Array of options to use, or an integer to wrap the text to.
* @return string Wrapped / indented text
* @see String::wrap()
* @see CakeText::wrap()
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::wrapText
*/
public function wrapText($text, $options = array()) {
return String::wrap($text, $options);
return CakeText::wrap($text, $options);
}
/**
@ -548,10 +629,10 @@ class Shell extends Object {
* present in most shells. Using Shell::QUIET for a message means it will always display.
* While using Shell::VERBOSE means it will only display when verbose output is toggled.
*
* @param string|array $message A string or a an array of strings to output
* @param integer $newlines Number of newlines to append
* @param integer $level The message's output level, see above.
* @return integer|boolean Returns the number of bytes returned from writing to stdout.
* @param string|array $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
* @param int $level The message's output level, see above.
* @return int|bool Returns the number of bytes returned from writing to stdout.
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::out
*/
public function out($message = null, $newlines = 1, $level = Shell::NORMAL) {
@ -563,17 +644,49 @@ class Shell extends Object {
$currentLevel = Shell::QUIET;
}
if ($level <= $currentLevel) {
return $this->stdout->write($message, $newlines);
$this->_lastWritten = $this->stdout->write($message, $newlines);
return $this->_lastWritten;
}
return true;
}
/**
* Overwrite some already output text.
*
* Useful for building progress bars, or when you want to replace
* text already output to the screen with new text.
*
* **Warning** You cannot overwrite text that contains newlines.
*
* @param array|string $message The message to output.
* @param int $newlines Number of newlines to append.
* @param int $size The number of bytes to overwrite. Defaults to the length of the last message output.
* @return int|bool Returns the number of bytes returned from writing to stdout.
*/
public function overwrite($message, $newlines = 1, $size = null) {
$size = $size ? $size : $this->_lastWritten;
// Output backspaces.
$this->out(str_repeat("\x08", $size), 0);
$newBytes = $this->out($message, 0);
// Fill any remaining bytes with spaces.
$fill = $size - $newBytes;
if ($fill > 0) {
$this->out(str_repeat(' ', $fill), 0);
}
if ($newlines) {
$this->out($this->nl($newlines), 0);
}
}
/**
* Outputs a single or multiple error messages to stderr. If no parameters
* are passed outputs just a newline.
*
* @param string|array $message A string or a an array of strings to output
* @param integer $newlines Number of newlines to append
* @param string|array $message A string or an array of strings to output
* @param int $newlines Number of newlines to append
* @return void
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::err
*/
@ -584,7 +697,7 @@ class Shell extends Object {
/**
* Returns a single or multiple linefeeds sequences.
*
* @param integer $multiplier Number of times the linefeed sequence should be repeated
* @param int $multiplier Number of times the linefeed sequence should be repeated
* @return string
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::nl
*/
@ -595,8 +708,8 @@ class Shell extends Object {
/**
* Outputs a series of minus characters to the standard output, acts as a visual separator.
*
* @param integer $newlines Number of newlines to pre- and append
* @param integer $width Width of the line, defaults to 63
* @param int $newlines Number of newlines to pre- and append
* @param int $width Width of the line, defaults to 63
* @return void
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hr
*/
@ -621,7 +734,8 @@ class Shell extends Object {
if (!empty($message)) {
$this->err($message);
}
$this->_stop(1);
$this->_stop(self::CODE_ERROR);
return self::CODE_ERROR;
}
/**
@ -645,7 +759,7 @@ class Shell extends Object {
*
* @param string $path Where to put the file.
* @param string $contents Content to put in the file.
* @return boolean Success
* @return bool Success
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::createFile
*/
public function createFile($path, $contents) {
@ -653,14 +767,15 @@ class Shell extends Object {
$this->out();
if (is_file($path) && $this->interactive === true) {
if (is_file($path) && empty($this->params['force']) && $this->interactive === true) {
$this->out(__d('cake_console', '<warning>File `%s` exists</warning>', $path));
$key = $this->in(__d('cake_console', 'Do you want to overwrite?'), array('y', 'n', 'q'), 'n');
if (strtolower($key) == 'q') {
if (strtolower($key) === 'q') {
$this->out(__d('cake_console', '<error>Quitting</error>.'), 2);
$this->_stop();
} elseif (strtolower($key) != 'y') {
return true;
} elseif (strtolower($key) !== 'y') {
$this->out(__d('cake_console', 'Skip `%s`', $path), 2);
return false;
}
@ -674,16 +789,38 @@ class Shell extends Object {
$File->write($data);
$this->out(__d('cake_console', '<success>Wrote</success> `%s`', $path));
return true;
} else {
}
$this->err(__d('cake_console', '<error>Could not write to `%s`</error>.', $path), 2);
return false;
}
/**
* Load given shell helper class
*
* @param string $name Name of the helper class. Supports plugin syntax.
* @return BaseShellHelper Instance of helper class
* @throws RuntimeException If invalid class name is provided
*/
public function helper($name) {
if (isset($this->_helpers[$name])) {
return $this->_helpers[$name];
}
list($plugin, $helperClassName) = pluginSplit($name, true);
$helperClassName = Inflector::camelize($name) . "ShellHelper";
App::uses($helperClassName, $plugin . "Console/Helper");
if (!class_exists($helperClassName)) {
throw new RuntimeException("Class " . $helperClassName . " not found");
}
$helper = new $helperClassName($this->stdout);
$this->_helpers[$name] = $helper;
return $helper;
}
/**
* Action to create a Unit Test
*
* @return boolean Success
* @return bool Success
*/
protected function _checkUnitTest() {
if (class_exists('PHPUnit_Framework_TestCase')) {
@ -698,7 +835,7 @@ class Shell extends Object {
$prompt = __d('cake_console', 'PHPUnit is not installed. Do you want to bake unit test files anyway?');
$unitTest = $this->in($prompt, array('y', 'n'), 'y');
$result = strtolower($unitTest) == 'y' || strtolower($unitTest) == 'yes';
$result = strtolower($unitTest) === 'y' || strtolower($unitTest) === 'yes';
if ($result) {
$this->out();
@ -773,8 +910,8 @@ class Shell extends Object {
/**
* creates the singular name for use in views.
*
* @param string $name
* @return string $name
* @param string $name The plural underscored value.
* @return string name
*/
protected function _singularName($name) {
return Inflector::variable(Inflector::singularize($name));
@ -814,7 +951,7 @@ class Shell extends Object {
* Find the correct path for a plugin. Scans $pluginPaths for the plugin you want.
*
* @param string $pluginName Name of the plugin you want ie. DebugKit
* @return string $path path to the correct plugin.
* @return string path path to the correct plugin.
*/
protected function _pluginPath($pluginName) {
if (CakePlugin::loaded($pluginName)) {
@ -828,24 +965,57 @@ class Shell extends Object {
* If you don't wish to see in your stdout or stderr everything that is logged
* through CakeLog, call this function with first param as false
*
* @param boolean $enable wheter to enable CakeLog output or not
* @param bool $enable whether to enable CakeLog output or not
* @return void
**/
*/
protected function _useLogger($enable = true) {
if (!$enable) {
CakeLog::drop('stdout');
CakeLog::drop('stderr');
return;
}
if (!$this->_loggerIsConfigured("stdout")) {
$this->_configureStdOutLogger();
}
if (!$this->_loggerIsConfigured("stderr")) {
$this->_configureStdErrLogger();
}
}
/**
* Configure the stdout logger
*
* @return void
*/
protected function _configureStdOutLogger() {
CakeLog::config('stdout', array(
'engine' => 'ConsoleLog',
'engine' => 'Console',
'types' => array('notice', 'info'),
'stream' => $this->stdout,
));
}
/**
* Configure the stderr logger
*
* @return void
*/
protected function _configureStdErrLogger() {
CakeLog::config('stderr', array(
'engine' => 'ConsoleLog',
'engine' => 'Console',
'types' => array('emergency', 'alert', 'critical', 'error', 'warning', 'debug'),
'stream' => $this->stderr,
));
}
/**
* Checks if the given logger is configured
*
* @param string $logger The name of the logger to check
* @return bool
*/
protected function _loggerIsConfigured($logger) {
$configured = CakeLog::configured();
return in_array($logger, $configured);
}
}

View file

@ -2,18 +2,17 @@
/**
* ShellDispatcher file
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -44,16 +43,14 @@ class ShellDispatcher {
* a status code of either 0 or 1 according to the result of the dispatch.
*
* @param array $args the argv from PHP
* @param boolean $bootstrap Should the environment be bootstrapped.
* @param bool $bootstrap Should the environment be bootstrapped.
*/
public function __construct($args = array(), $bootstrap = true) {
set_time_limit(0);
$this->parseParams($args);
if ($bootstrap) {
$this->_initConstants();
}
$this->parseParams($args);
if ($bootstrap) {
$this->_initEnvironment();
}
}
@ -66,7 +63,7 @@ class ShellDispatcher {
*/
public static function run($argv) {
$dispatcher = new ShellDispatcher($argv);
$dispatcher->_stop($dispatcher->dispatch() === false ? 1 : 0);
return $dispatcher->_stop($dispatcher->dispatch() === false ? 1 : 0);
}
/**
@ -82,9 +79,11 @@ class ShellDispatcher {
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('DS', DIRECTORY_SEPARATOR);
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__))));
define('CAKEPHP_SHELL', true);
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
if (!defined('CORE_PATH')) {
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
@ -115,18 +114,33 @@ class ShellDispatcher {
}
/**
* Initializes the environment and loads the Cake core.
* Initializes the environment and loads the CakePHP core.
*
* @return boolean Success.
* @return bool Success.
*/
protected function _bootstrap() {
if (!defined('ROOT')) {
define('ROOT', $this->params['root']);
}
if (!defined('APP_DIR')) {
define('APP_DIR', $this->params['app']);
}
if (!defined('APP')) {
define('APP', $this->params['working'] . DS);
define('WWW_ROOT', APP . $this->params['webroot'] . DS);
if (!is_dir(ROOT . DS . APP_DIR . DS . 'tmp')) {
}
if (!defined('WWW_ROOT')) {
if (!$this->_isAbsolutePath($this->params['webroot'])) {
$webroot = realpath(APP . $this->params['webroot']);
} else {
$webroot = $this->params['webroot'];
}
define('WWW_ROOT', $webroot . DS);
}
if (!defined('TMP') && !is_dir(APP . 'tmp')) {
define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS);
}
// $boot is used by Cake/bootstrap.php file
$boot = file_exists(ROOT . DS . APP_DIR . DS . 'Config' . DS . 'bootstrap.php');
require CORE_PATH . 'Cake' . DS . 'bootstrap.php';
@ -138,7 +152,9 @@ class ShellDispatcher {
$this->setErrorHandlers();
if (!defined('FULL_BASE_URL')) {
define('FULL_BASE_URL', 'http://localhost');
$url = Configure::read('App.fullBaseUrl');
define('FULL_BASE_URL', $url ? $url : 'http://localhost');
Configure::write('App.fullBaseUrl', FULL_BASE_URL);
}
return true;
@ -168,12 +184,15 @@ class ShellDispatcher {
}
set_exception_handler($exception['consoleHandler']);
set_error_handler($error['consoleHandler'], Configure::read('Error.level'));
App::uses('Debugger', 'Utility');
Debugger::getInstance()->output('txt');
}
/**
* Dispatches a CLI request
*
* @return boolean
* @return bool
* @throws MissingShellMethodException
*/
public function dispatch() {
@ -197,12 +216,11 @@ class ShellDispatcher {
if ($Shell instanceof Shell) {
$Shell->initialize();
$Shell->loadTasks();
return $Shell->runCommand($command, $this->args);
}
$methods = array_diff(get_class_methods($Shell), get_class_methods('Shell'));
$added = in_array($command, $methods);
$private = $command[0] == '_' && method_exists($Shell, $command);
$private = $command[0] === '_' && method_exists($Shell, $command);
if (!$private) {
if ($added) {
@ -238,6 +256,11 @@ class ShellDispatcher {
App::uses('AppShell', 'Console/Command');
App::uses($class, $plugin . 'Console/Command');
if (!class_exists($class)) {
$plugin = Inflector::camelize($shell) . '.';
App::uses($class, $plugin . 'Console/Command');
}
if (!class_exists($class)) {
throw new MissingShellException(array(
'class' => $class
@ -276,7 +299,11 @@ class ShellDispatcher {
if (isset($params['working'])) {
$params['working'] = trim($params['working']);
}
if (!empty($params['working']) && (!isset($this->args[0]) || isset($this->args[0]) && $this->args[0]{0} !== '.')) {
if (!empty($params['working']) && (!isset($this->args[0]) || isset($this->args[0]) && $this->args[0][0] !== '.')) {
if ($params['working'][0] === '.') {
$params['working'] = realpath($params['working']);
}
if (empty($this->params['app']) && $params['working'] != $params['root']) {
$params['root'] = dirname($params['working']);
$params['app'] = basename($params['working']);
@ -285,34 +312,55 @@ class ShellDispatcher {
}
}
if ($params['app'][0] == '/' || preg_match('/([a-z])(:)/i', $params['app'], $matches)) {
if ($this->_isAbsolutePath($params['app'])) {
$params['root'] = dirname($params['app']);
} elseif (strpos($params['app'], '/')) {
$params['root'] .= '/' . dirname($params['app']);
}
$isWindowsAppPath = $this->_isWindowsPath($params['app']);
$params['app'] = basename($params['app']);
$params['working'] = rtrim($params['root'], '/');
if (!$isWin || !preg_match('/^[A-Z]:$/i', $params['app'])) {
$params['working'] .= '/' . $params['app'];
}
if (!empty($matches[0]) || !empty($isWin)) {
if ($isWindowsAppPath || !empty($isWin)) {
$params = str_replace('/', '\\', $params);
}
$this->params = array_merge($this->params, $params);
$this->params = $params + $this->params;
}
/**
* Checks whether the given path is absolute or relative.
*
* @param string $path absolute or relative path.
* @return bool
*/
protected function _isAbsolutePath($path) {
return $path[0] === '/' || $this->_isWindowsPath($path);
}
/**
* Checks whether the given path is Window OS path.
*
* @param string $path absolute path.
* @return bool
*/
protected function _isWindowsPath($path) {
return preg_match('/([a-z])(:)/i', $path) == 1;
}
/**
* Parses out the paths from from the argv
*
* @param array $args
* @param array $args The argv to parse.
* @return void
*/
protected function _parsePaths($args) {
$parsed = array();
$keys = array('-working', '--working', '-app', '--app', '-root', '--root');
$keys = array('-working', '--working', '-app', '--app', '-root', '--root', '-webroot', '--webroot');
$args = (array)$args;
foreach ($keys as $key) {
while (($index = array_search($key, $args)) !== false) {
$keyname = str_replace('-', '', $key);
@ -347,7 +395,7 @@ class ShellDispatcher {
/**
* Stop execution of the current script
*
* @param integer|string $status see http://php.net/exit for values
* @param int|string $status see http://php.net/exit for values
* @return void
*/
protected function _stop($status = 0) {

View file

@ -4,15 +4,16 @@
* and constructing task class objects.
*
* 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 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('ObjectCollection', 'Utility');
@ -42,15 +43,24 @@ class TaskCollection extends ObjectCollection {
/**
* Constructor
*
* @param Shell $Shell
* @param Shell $Shell The shell this task collection is attached to.
*/
public function __construct(Shell $Shell) {
$this->_Shell = $Shell;
}
/**
* Loads/constructs a task. Will return the instance in the collection
* if it already exists.
* Loads/constructs a task. Will return the instance in the registry if it already exists.
*
* You can alias your task as an existing task by setting the 'className' key, i.e.,
* ```
* public $tasks = array(
* 'DbConfig' => array(
* 'className' => 'Bakeplus.DbConfigure'
* );
* );
* ```
* All calls to the `DbConfig` task would use `DbConfigure` found in the `Bakeplus` plugin instead.
*
* @param string $task Task name to load
* @param array $settings Settings for the task.
@ -58,25 +68,33 @@ class TaskCollection extends ObjectCollection {
* @throws MissingTaskException when the task could not be found
*/
public function load($task, $settings = array()) {
if (is_array($settings) && isset($settings['className'])) {
$alias = $task;
$task = $settings['className'];
}
list($plugin, $name) = pluginSplit($task, true);
if (!isset($alias)) {
$alias = $name;
}
if (isset($this->_loaded[$name])) {
return $this->_loaded[$name];
if (isset($this->_loaded[$alias])) {
return $this->_loaded[$alias];
}
$taskClass = $name . 'Task';
App::uses($taskClass, $plugin . 'Console/Command/Task');
if (!class_exists($taskClass)) {
if (!class_exists($taskClass)) {
$exists = class_exists($taskClass);
if (!$exists) {
throw new MissingTaskException(array(
'class' => $taskClass
'class' => $taskClass,
'plugin' => substr($plugin, 0, -1)
));
}
}
$this->_loaded[$name] = new $taskClass(
$this->_loaded[$alias] = new $taskClass(
$this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin
);
return $this->_loaded[$name];
return $this->_loaded[$alias];
}
}

View file

@ -2,19 +2,18 @@
/**
* Bake Template for Controller action generation.
*
* 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
* @package Cake.Console.Templates.default.actions
* @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
*/
?>
@ -25,7 +24,7 @@
*/
public function <?php echo $admin ?>index() {
$this-><?php echo $currentModelName ?>->recursive = 0;
$this->set('<?php echo $pluralName ?>', $this->paginate());
$this->set('<?php echo $pluralName ?>', $this->Paginator->paginate());
}
/**
@ -36,11 +35,11 @@
* @return void
*/
public function <?php echo $admin ?>view($id = null) {
$this-><?php echo $currentModelName; ?>->id = $id;
if (!$this-><?php echo $currentModelName; ?>->exists()) {
if (!$this-><?php echo $currentModelName; ?>->exists($id)) {
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
}
$this->set('<?php echo $singularName; ?>', $this-><?php echo $currentModelName; ?>->read(null, $id));
$options = array('conditions' => array('<?php echo $currentModelName; ?>.' . $this-><?php echo $currentModelName; ?>->primaryKey => $id));
$this->set('<?php echo $singularName; ?>', $this-><?php echo $currentModelName; ?>->find('first', $options));
}
<?php $compact = array(); ?>
@ -54,14 +53,12 @@
$this-><?php echo $currentModelName; ?>->create();
if ($this-><?php echo $currentModelName; ?>->save($this->request->data)) {
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('The <?php echo strtolower($singularHumanName); ?> has been saved'));
$this->redirect(array('action' => 'index'));
<?php else: ?>
$this->flash(__('<?php echo ucfirst(strtolower($currentModelName)); ?> saved.'), array('action' => 'index'));
<?php endif; ?>
$this->Flash->success(__('The <?php echo strtolower($singularHumanName); ?> has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('The <?php echo strtolower($singularHumanName); ?> could not be saved. Please, try again.'));
$this->Flash->error(__('The <?php echo strtolower($singularHumanName); ?> could not be saved. Please, try again.'));
<?php else: ?>
return $this->flash(__('The <?php echo strtolower($singularHumanName); ?> has been saved.'), array('action' => 'index'));
<?php endif; ?>
}
}
@ -91,25 +88,23 @@
* @return void
*/
public function <?php echo $admin; ?>edit($id = null) {
$this-><?php echo $currentModelName; ?>->id = $id;
if (!$this-><?php echo $currentModelName; ?>->exists()) {
if (!$this-><?php echo $currentModelName; ?>->exists($id)) {
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->request->is(array('post', 'put'))) {
if ($this-><?php echo $currentModelName; ?>->save($this->request->data)) {
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('The <?php echo strtolower($singularHumanName); ?> has been saved'));
$this->redirect(array('action' => 'index'));
<?php else: ?>
$this->flash(__('The <?php echo strtolower($singularHumanName); ?> has been saved.'), array('action' => 'index'));
<?php endif; ?>
$this->Flash->success(__('The <?php echo strtolower($singularHumanName); ?> has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('The <?php echo strtolower($singularHumanName); ?> could not be saved. Please, try again.'));
$this->Flash->error(__('The <?php echo strtolower($singularHumanName); ?> could not be saved. Please, try again.'));
<?php else: ?>
return $this->flash(__('The <?php echo strtolower($singularHumanName); ?> has been saved.'), array('action' => 'index'));
<?php endif; ?>
}
} else {
$this->request->data = $this-><?php echo $currentModelName; ?>->read(null, $id);
$options = array('conditions' => array('<?php echo $currentModelName; ?>.' . $this-><?php echo $currentModelName; ?>->primaryKey => $id));
$this->request->data = $this-><?php echo $currentModelName; ?>->find('first', $options);
}
<?php
foreach (array('belongsTo', 'hasAndBelongsToMany') as $assoc):
@ -131,31 +126,27 @@
/**
* <?php echo $admin ?>delete method
*
* @throws MethodNotAllowedException
* @throws NotFoundException
* @param string $id
* @return void
*/
public function <?php echo $admin; ?>delete($id = null) {
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this-><?php echo $currentModelName; ?>->id = $id;
if (!$this-><?php echo $currentModelName; ?>->exists()) {
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
}
$this->request->allowMethod('post', 'delete');
if ($this-><?php echo $currentModelName; ?>->delete()) {
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> deleted'));
$this->redirect(array('action' => 'index'));
$this->Flash->success(__('The <?php echo strtolower($singularHumanName); ?> has been deleted.'));
} else {
$this->Flash->error(__('The <?php echo strtolower($singularHumanName); ?> could not be deleted. Please, try again.'));
}
return $this->redirect(array('action' => 'index'));
<?php else: ?>
$this->flash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> deleted'), array('action' => 'index'));
return $this->flash(__('The <?php echo strtolower($singularHumanName); ?> has been deleted.'), array('action' => 'index'));
} else {
return $this->flash(__('The <?php echo strtolower($singularHumanName); ?> could not be deleted. Please, try again.'), array('action' => 'index'));
}
<?php endif; ?>
}
<?php if ($wannaUseSession): ?>
$this->Session->setFlash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> was not deleted'));
<?php else: ?>
$this->flash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> was not deleted'), array('action' => 'index'));
<?php endif; ?>
$this->redirect(array('action' => 'index'));
}

View file

@ -4,19 +4,18 @@
*
* Allows templating of Controllers generated from bake.
*
* 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
* @package Cake.Console.Templates.default.classes
* @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
*/
echo "<?php\n";
@ -24,10 +23,10 @@ echo "App::uses('{$plugin}AppController', '{$pluginPath}Controller');\n";
?>
/**
* <?php echo $controllerName; ?> Controller
*
<?php
if (!$isScaffold) {
$defaultModel = Inflector::singularize($controllerName);
echo " *\n";
echo " * @property {$defaultModel} \${$defaultModel}\n";
if (!empty($components)) {
foreach ($components as $component) {
@ -75,7 +74,9 @@ class <?php echo $controllerName; ?>Controller extends <?php echo $plugin; ?>App
echo ");\n\n";
endif;
if (!empty($actions)) {
echo trim($actions) . "\n";
}
endif; ?>
}

View file

@ -4,25 +4,24 @@
*
* Fixture Template used when baking fixtures with bake
*
* 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
* @package Cake.Console.Templates.default.classes
* @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
*/
echo "<?php\n";
?>
<?php echo '<?php' . "\n"; ?>
/**
* <?php echo $model; ?> Fixture
*
*/
class <?php echo $model; ?>Fixture extends CakeTestFixture {

View file

@ -4,19 +4,18 @@
*
* Used by bake to create new Model 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
* @package Cake.Console.Templates.default.classes
* @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
*/
echo "<?php\n";
@ -37,7 +36,7 @@ foreach (array('hasOne', 'belongsTo', 'hasMany', 'hasAndBelongsToMany') as $asso
*/
class <?php echo $name ?> extends <?php echo $plugin; ?>AppModel {
<?php if ($useDbConfig != 'default'): ?>
<?php if ($useDbConfig !== 'default'): ?>
/**
* Use database config
*
@ -73,6 +72,16 @@ if ($displayField): ?>
<?php endif;
if (!empty($actsAs)): ?>
/**
* Behaviors
*
* @var array
*/
public $actsAs = array(<?php echo "\n\t"; foreach ($actsAs as $behavior): echo "\t"; var_export($behavior); echo ",\n\t"; endforeach; ?>);
<?php endif;
if (!empty($validate)):
echo "/**\n * Validation rules\n *\n * @var array\n */\n";
echo "\tpublic \$validate = array(\n";
@ -168,8 +177,6 @@ if (!empty($associations['hasAndBelongsToMany'])):
$out .= "\t\t\t'limit' => '',\n";
$out .= "\t\t\t'offset' => '',\n";
$out .= "\t\t\t'finderQuery' => '',\n";
$out .= "\t\t\t'deleteQuery' => '',\n";
$out .= "\t\t\t'insertQuery' => ''\n";
$out .= "\t\t)";
if ($i + 1 < $habtmCount) {
$out .= ",";

View file

@ -2,21 +2,20 @@
/**
* Test Case bake template
*
*
* 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
* @package Cake.Console.Templates.default.classes
* @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
*/
echo "<?php\n";
?>
<?php foreach ($uses as $dependency): ?>
@ -25,7 +24,6 @@ App::uses('<?php echo $dependency[0]; ?>', '<?php echo $dependency[1]; ?>');
/**
* <?php echo $fullClassName; ?> Test Case
*
*/
<?php if ($type === 'Controller'): ?>
class <?php echo $fullClassName; ?>Test extends ControllerTestCase {
@ -76,6 +74,7 @@ class <?php echo $fullClassName; ?>Test extends CakeTestCase {
* @return void
*/
public function test<?php echo Inflector::camelize($method); ?>() {
$this->markTestIncomplete('test<?php echo Inflector::camelize($method); ?> not implemented.');
}
<?php endforeach; ?>

View file

@ -1,19 +1,17 @@
<?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
* @package Cake.Console.Templates.default.views
* @since CakePHP(tm) v 1.2.0.5234
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
?>
<div class="<?php echo $pluralVar; ?> form">
@ -23,7 +21,7 @@
<?php
echo "\t<?php\n";
foreach ($fields as $field) {
if (strpos($action, 'add') !== false && $field == $primaryKey) {
if (strpos($action, 'add') !== false && $field === $primaryKey) {
continue;
} elseif (!in_array($field, array('created', 'modified', 'updated'))) {
echo "\t\techo \$this->Form->input('{$field}');\n";
@ -46,7 +44,7 @@
<ul>
<?php if (strpos($action, 'add') === false): ?>
<li><?php echo "<?php echo \$this->Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), null, __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}'))); ?>"; ?></li>
<li><?php echo "<?php echo \$this->Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), array('confirm' => __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}')))); ?>"; ?></li>
<?php endif; ?>
<li><?php echo "<?php echo \$this->Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?>"; ?></li>
<?php

View file

@ -1,33 +1,33 @@
<?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
* @package Cake.Console.Templates.default.views
* @since CakePHP(tm) v 1.2.0.5234
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
?>
<div class="<?php echo $pluralVar; ?> index">
<h2><?php echo "<?php echo __('{$pluralHumanName}'); ?>"; ?></h2>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<?php foreach ($fields as $field): ?>
<th><?php echo "<?php echo \$this->Paginator->sort('{$field}'); ?>"; ?></th>
<?php endforeach; ?>
<th class="actions"><?php echo "<?php echo __('Actions'); ?>"; ?></th>
</tr>
</thead>
<tbody>
<?php
echo "<?php
foreach (\${$pluralVar} as \${$singularVar}): ?>\n";
echo "<?php foreach (\${$pluralVar} as \${$singularVar}): ?>\n";
echo "\t<tr>\n";
foreach ($fields as $field) {
$isKey = false;
@ -48,12 +48,13 @@
echo "\t\t<td class=\"actions\">\n";
echo "\t\t\t<?php echo \$this->Html->link(__('View'), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
echo "\t\t\t<?php echo \$this->Html->link(__('Edit'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
echo "\t\t\t<?php echo \$this->Form->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
echo "\t\t\t<?php echo \$this->Form->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?>\n";
echo "\t\t</td>\n";
echo "\t</tr>\n";
echo "<?php endforeach; ?>\n";
?>
</tbody>
</table>
<p>
<?php echo "<?php
@ -62,7 +63,6 @@
));
?>"; ?>
</p>
<div class="paging">
<?php
echo "<?php\n";

View file

@ -1,19 +1,17 @@
<?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
* @package Cake.Console.Templates.default.views
* @since CakePHP(tm) v 1.2.0.5234
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
?>
<div class="<?php echo $pluralVar; ?> view">
@ -45,7 +43,7 @@ foreach ($fields as $field) {
<ul>
<?php
echo "\t\t<li><?php echo \$this->Html->link(__('Edit " . $singularHumanName ."'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> </li>\n";
echo "\t\t<li><?php echo \$this->Form->postLink(__('Delete " . $singularHumanName . "'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> </li>\n";
echo "\t\t<li><?php echo \$this->Form->postLink(__('Delete " . $singularHumanName . "'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?> </li>\n";
echo "\t\t<li><?php echo \$this->Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?> </li>\n";
echo "\t\t<li><?php echo \$this->Html->link(__('New " . $singularHumanName . "'), array('action' => 'add')); ?> </li>\n";
@ -93,7 +91,6 @@ if (empty($associations['hasAndBelongsToMany'])) {
$associations['hasAndBelongsToMany'] = array();
}
$relations = array_merge($associations['hasMany'], $associations['hasAndBelongsToMany']);
$i = 0;
foreach ($relations as $alias => $details):
$otherSingularVar = Inflector::variable($alias);
$otherPluralHumanName = Inflector::humanize($details['controller']);
@ -111,9 +108,7 @@ foreach ($relations as $alias => $details):
<th class="actions"><?php echo "<?php echo __('Actions'); ?>"; ?></th>
</tr>
<?php
echo "\t<?php
\$i = 0;
foreach (\${$singularVar}['{$alias}'] as \${$otherSingularVar}): ?>\n";
echo "\t<?php foreach (\${$singularVar}['{$alias}'] as \${$otherSingularVar}): ?>\n";
echo "\t\t<tr>\n";
foreach ($details['fields'] as $field) {
echo "\t\t\t<td><?php echo \${$otherSingularVar}['{$field}']; ?></td>\n";
@ -122,7 +117,7 @@ echo "\t<?php
echo "\t\t\t<td class=\"actions\">\n";
echo "\t\t\t\t<?php echo \$this->Html->link(__('View'), array('controller' => '{$details['controller']}', 'action' => 'view', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n";
echo "\t\t\t\t<?php echo \$this->Html->link(__('Edit'), array('controller' => '{$details['controller']}', 'action' => 'edit', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n";
echo "\t\t\t\t<?php echo \$this->Form->postLink(__('Delete'), array('controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']), null, __('Are you sure you want to delete # %s?', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n";
echo "\t\t\t\t<?php echo \$this->Form->postLink(__('Delete'), array('controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$otherSingularVar}['{$details['primaryKey']}']))); ?>\n";
echo "\t\t\t</td>\n";
echo "\t\t</tr>\n";
@ -136,4 +131,6 @@ echo "\t<?php endforeach; ?>\n";
</ul>
</div>
</div>
<?php endforeach; ?>
<?php
endforeach;
?>

View file

@ -1,43 +1,42 @@
<?php
/*DbAcl schema generated on: 2007-11-24 15:11:13 : 1195945453*/
/**
* This is Acl Schema file
*
* Use it to configure database for ACL
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config.Schema
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/*
*
/**
* Using the Schema command line utility
* cake schema run create DbAcl
*
*/
class DbAclSchema extends CakeSchema {
public $name = 'DbAcl';
/**
* Before event.
*
* @param array $event The event data.
* @return bool success
*/
public function before($event = array()) {
return true;
}
/**
* After event.
*
* @param array $event The event data.
* @return void
*/
public function after($event = array()) {
}
/**
* ACO - Access Control Object - Something that is wanted
*/
public $acos = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10),
@ -49,6 +48,9 @@ class DbAclSchema extends CakeSchema {
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
);
/**
* ARO - Access Request Object - Something that wants something
*/
public $aros = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'),
'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10),
@ -60,6 +62,10 @@ class DbAclSchema extends CakeSchema {
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
);
/**
* Used by the Cake::Model:Permission class.
* Checks if the given $aro has access to action $action in $aco.
*/
public $aros_acos = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'),
'aro_id' => array('type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'),

View file

@ -1,8 +1,9 @@
# $Id$
#
# 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.
# MIT License (http://www.opensource.org/licenses/mit-license.php)
@ -38,3 +39,14 @@ CREATE TABLE aros (
rght INTEGER(10) DEFAULT NULL,
PRIMARY KEY (id)
);
/* this indexes will improve acl perfomance */
CREATE INDEX idx_acos_lft_rght ON `acos` (`lft`, `rght`);
CREATE INDEX idx_acos_alias ON `acos` (`alias`);
CREATE INDEX idx_aros_lft_rght ON `aros` (`lft`, `rght`);
CREATE INDEX idx_aros_alias ON `aros` (`alias`);
CREATE INDEX idx_aco_id ON `aros_acos` (`aco_id`);

View file

@ -1,46 +1,63 @@
<?php
/*i18n schema generated on: 2007-11-25 07:11:25 : 1196004805*/
/**
* This is i18n Schema file
*
* Use it to configure database for i18n
*
* 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
* @package app.Config.Schema
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
// @codingStandardsIgnoreStart
/*
*
/**
* Using the Schema command line utility
*
* Use it to configure database for i18n
*
* cake schema run create i18n
*/
class i18nSchema extends CakeSchema {
// @codingStandardsIgnoreEnd
class I18nSchema extends CakeSchema {
/**
* The name property
*
* @var string
*/
public $name = 'i18n';
/**
* Before callback.
*
* @param array $event Schema object properties
* @return bool Should process continue
*/
public function before($event = array()) {
return true;
}
/**
* After callback.
*
* @param array $event Schema object properties
* @return void
*/
public function after($event = array()) {
}
/**
* The i18n table definition
*
* @var array
*/
public $i18n = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'),
'locale' => array('type' => 'string', 'null' => false, 'length' => 6, 'key' => 'index'),

View file

@ -1,8 +1,9 @@
# $Id$
#
# 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.
# MIT License (http://www.opensource.org/licenses/mit-license.php)

View file

@ -1,43 +1,60 @@
<?php
/*Sessions schema generated on: 2007-11-25 07:11:54 : 1196004714*/
/**
* This is Sessions Schema file
*
* Use it to configure database for Sessions
*
* 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
* @package app.Config.Schema
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/*
*
/**
* Using the Schema command line utility
* cake schema run create Sessions
*
*/
class SessionsSchema extends CakeSchema {
/**
* Name property
*
* @var string
*/
public $name = 'Sessions';
/**
* Before callback.
*
* @param array $event Schema object properties
* @return bool Should process continue
*/
public function before($event = array()) {
return true;
}
/**
* After callback.
*
* @param array $event Schema object properties
* @return void
*/
public function after($event = array()) {
}
/**
* The cake_sessions table definition
*
* @var array
*/
public $cake_sessions = array(
'id' => array('type' => 'string', 'null' => false, 'key' => 'primary'),
'data' => array('type' => 'text', 'null' => true, 'default' => null),

View file

@ -1,10 +1,11 @@
# $Id$
#
# Copyright 2005-2012, Cake Software Foundation, Inc.
# Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
# 1785 E. Sahara Avenue, Suite 490-204
# Las Vegas, Nevada 89104
#
# 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.
# MIT License (http://www.opensource.org/licenses/mit-license.php)

View file

@ -2,23 +2,12 @@
;/**
; * ACL Configuration
; *
; *
; * PHP 5
; *
; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
; * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; *
; * Licensed under The MIT License
; * Redistributions of files must retain the above copyright notice.
; *
; * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
; * @link http://cakephp.org CakePHP(tm) Project
; * @package app.Config
; * @since CakePHP(tm) v 0.10.0.1076
; * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
; */
; acl.ini.php - Cake ACL Configuration
; acl.ini.php - CakePHP ACL Configuration
; ---------------------------------------------------------------------
; Use this file to specify user permissions.
; aco = access control object (something in your application)

View file

@ -0,0 +1,124 @@
<?php
/**
* This is the PHP base ACL configuration file.
*
* Use it to configure access control of your CakePHP application.
*
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 2.1
*/
/**
* Example
* -------
*
* Assumptions:
*
* 1. In your application you created a User model with the following properties:
* username, group_id, password, email, firstname, lastname and so on.
* 2. You configured AuthComponent to authorize actions via
* $this->Auth->authorize = array('Actions' => array('actionPath' => 'controllers/'),...)
*
* Now, when a user (i.e. jeff) authenticates successfully and requests a controller action (i.e. /invoices/delete)
* that is not allowed by default (e.g. via $this->Auth->allow('edit') in the Invoices controller) then AuthComponent
* will ask the configured ACL interface if access is granted. Under the assumptions 1. and 2. this will be
* done via a call to Acl->check() with
*
* array('User' => array('username' => 'jeff', 'group_id' => 4, ...))
*
* as ARO and
*
* '/controllers/invoices/delete'
*
* as ACO.
*
* If the configured map looks like
*
* $config['map'] = array(
* 'User' => 'User/username',
* 'Role' => 'User/group_id',
* );
*
* then PhpAcl will lookup if we defined a role like User/jeff. If that role is not found, PhpAcl will try to
* find a definition for Role/4. If the definition isn't found then a default role (Role/default) will be used to
* check rules for the given ACO. The search can be expanded by defining aliases in the alias configuration.
* E.g. if you want to use a more readable name than Role/4 in your definitions you can define an alias like
*
* $config['alias'] = array(
* 'Role/4' => 'Role/editor',
* );
*
* In the roles configuration you can define roles on the lhs and inherited roles on the rhs:
*
* $config['roles'] = array(
* 'Role/admin' => null,
* 'Role/accountant' => null,
* 'Role/editor' => null,
* 'Role/manager' => 'Role/editor, Role/accountant',
* 'User/jeff' => 'Role/manager',
* );
*
* In this example manager inherits all rules from editor and accountant. Role/admin doesn't inherit from any role.
* Lets define some rules:
*
* $config['rules'] = array(
* 'allow' => array(
* '*' => 'Role/admin',
* 'controllers/users/(dashboard|profile)' => 'Role/default',
* 'controllers/invoices/*' => 'Role/accountant',
* 'controllers/articles/*' => 'Role/editor',
* 'controllers/users/*' => 'Role/manager',
* 'controllers/invoices/delete' => 'Role/manager',
* ),
* 'deny' => array(
* 'controllers/invoices/delete' => 'Role/accountant, User/jeff',
* 'controllers/articles/(delete|publish)' => 'Role/editor',
* ),
* );
*
* Ok, so as jeff inherits from Role/manager he's matched every rule that references User/jeff, Role/manager,
* Role/editor, Role/accountant and Role/default. However, for jeff, rules for User/jeff are more specific than
* rules for Role/manager, rules for Role/manager are more specific than rules for Role/editor and so on.
* This is important when allow and deny rules match for a role. E.g. Role/accountant is allowed
* controllers/invoices/* but at the same time controllers/invoices/delete is denied. But there is a more
* specific rule defined for Role/manager which is allowed controllers/invoices/delete. However, the most specific
* rule denies access to the delete action explicitly for User/jeff, so he'll be denied access to the resource.
*
* If we would remove the role definition for User/jeff, then jeff would be granted access as he would be resolved
* to Role/manager and Role/manager has an allow rule.
*/
/**
* The role map defines how to resolve the user record from your application
* to the roles you defined in the roles configuration.
*/
$config['map'] = array(
'User' => 'User/username',
'Role' => 'User/group_id',
);
/**
* define aliases to map your model information to
* the roles defined in your role configuration.
*/
$config['alias'] = array(
'Role/4' => 'Role/editor',
);
/**
* role configuration
*/
$config['roles'] = array(
'Role/admin' => null,
);
/**
* rule configuration
*/
$config['rules'] = array(
'allow' => array(
'*' => 'Role/admin',
),
'deny' => array(),
);

View file

@ -8,19 +8,9 @@
* You should also use this file to include any files that provide global functions/constants
* that your application uses.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.10.8.2117
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
// Setup a 'default' cache configuration for use in the application.
@ -30,49 +20,46 @@ Cache::config('default', array('engine' => 'File'));
* The settings below can be used to set additional paths to models, views and controllers.
*
* App::build(array(
* 'Model' => array('/path/to/models', '/next/path/to/models'),
* 'Model/Behavior' => array('/path/to/behaviors', '/next/path/to/behaviors'),
* 'Model/Datasource' => array('/path/to/datasources', '/next/path/to/datasources'),
* 'Model/Datasource/Database' => array('/path/to/databases', '/next/path/to/database'),
* 'Model/Datasource/Session' => array('/path/to/sessions', '/next/path/to/sessions'),
* 'Controller' => array('/path/to/controllers', '/next/path/to/controllers'),
* 'Controller/Component' => array('/path/to/components', '/next/path/to/components'),
* 'Controller/Component/Auth' => array('/path/to/auths', '/next/path/to/auths'),
* 'Controller/Component/Acl' => array('/path/to/acls', '/next/path/to/acls'),
* 'View' => array('/path/to/views', '/next/path/to/views'),
* 'View/Helper' => array('/path/to/helpers', '/next/path/to/helpers'),
* 'Console' => array('/path/to/consoles', '/next/path/to/consoles'),
* 'Console/Command' => array('/path/to/commands', '/next/path/to/commands'),
* 'Console/Command/Task' => array('/path/to/tasks', '/next/path/to/tasks'),
* 'Lib' => array('/path/to/libs', '/next/path/to/libs'),
* 'Locale' => array('/path/to/locales', '/next/path/to/locales'),
* 'Vendor' => array('/path/to/vendors', '/next/path/to/vendors'),
* 'Plugin' => array('/path/to/plugins', '/next/path/to/plugins'),
* 'Model' => array('/path/to/models/', '/next/path/to/models/'),
* 'Model/Behavior' => array('/path/to/behaviors/', '/next/path/to/behaviors/'),
* 'Model/Datasource' => array('/path/to/datasources/', '/next/path/to/datasources/'),
* 'Model/Datasource/Database' => array('/path/to/databases/', '/next/path/to/database/'),
* 'Model/Datasource/Session' => array('/path/to/sessions/', '/next/path/to/sessions/'),
* 'Controller' => array('/path/to/controllers/', '/next/path/to/controllers/'),
* 'Controller/Component' => array('/path/to/components/', '/next/path/to/components/'),
* 'Controller/Component/Auth' => array('/path/to/auths/', '/next/path/to/auths/'),
* 'Controller/Component/Acl' => array('/path/to/acls/', '/next/path/to/acls/'),
* 'View' => array('/path/to/views/', '/next/path/to/views/'),
* 'View/Helper' => array('/path/to/helpers/', '/next/path/to/helpers/'),
* 'Console' => array('/path/to/consoles/', '/next/path/to/consoles/'),
* 'Console/Command' => array('/path/to/commands/', '/next/path/to/commands/'),
* 'Console/Command/Task' => array('/path/to/tasks/', '/next/path/to/tasks/'),
* 'Lib' => array('/path/to/libs/', '/next/path/to/libs/'),
* 'Locale' => array('/path/to/locales/', '/next/path/to/locales/'),
* 'Vendor' => array('/path/to/vendors/', '/next/path/to/vendors/'),
* 'Plugin' => array('/path/to/plugins/', '/next/path/to/plugins/'),
* ));
*
*/
/**
* Custom Inflector rules, can be set to correctly pluralize or singularize table, model, controller names or whatever other
* Custom Inflector rules can be set to correctly pluralize or singularize table, model, controller names or whatever other
* string is passed to the inflection functions
*
* Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
* Inflector::rules('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array()));
*
*/
/**
* Plugins need to be loaded manually, you can either load them one by one or all of them in a single call
* Uncomment one of the lines below, as you need. make sure you read the documentation on CakePlugin to use more
* Uncomment one of the lines below, as you need. Make sure you read the documentation on CakePlugin to use more
* advanced ways of loading plugins
*
* CakePlugin::loadAll(); // Loads all plugins at once
* CakePlugin::load('DebugKit'); // Loads a single plugin named DebugKit
*
*/
/**
* You can attach event listeners to the request lifecyle as Dispatcher Filter . By Default CakePHP bundles two filters:
* You can attach event listeners to the request lifecycle as Dispatcher Filter . By default CakePHP bundles two filters:
*
* - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins
* - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers
@ -82,8 +69,8 @@ Cache::config('default', array('engine' => 'File'));
* Configure::write('Dispatcher.filters', array(
* 'MyCacheFilter', // will use MyCacheFilter class from the Routing/Filter package in your app.
* 'MyPlugin.MyFilter', // will use MyFilter class from the Routing/Filter package in MyPlugin plugin.
* array('callbale' => $aFunction, 'on' => 'before', 'priority' => 9), // A valid PHP callback type to be called on beforeDispatch
* array('callbale' => $anotherMethod, 'on' => 'after'), // A valid PHP callback type to be called on afterDispatch
* array('callable' => $aFunction, 'on' => 'before', 'priority' => 9), // A valid PHP callback type to be called on beforeDispatch
* array('callable' => $anotherMethod, 'on' => 'after'), // A valid PHP callback type to be called on afterDispatch
*
* ));
*/
@ -97,12 +84,12 @@ Configure::write('Dispatcher.filters', array(
*/
App::uses('CakeLog', 'Log');
CakeLog::config('debug', array(
'engine' => 'FileLog',
'engine' => 'File',
'types' => array('notice', 'info', 'debug'),
'file' => 'debug',
));
CakeLog::config('error', array(
'engine' => 'FileLog',
'engine' => 'File',
'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
'file' => 'error',
));

View file

@ -4,19 +4,9 @@
*
* Use it to configure core behavior of Cake.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
@ -44,7 +34,7 @@
* - `handler` - callback - The callback to handle errors. You can set this to any callable type,
* including anonymous functions.
* Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class
* - `level` - int - The level of errors you are interested in capturing.
* - `level` - integer - The level of errors you are interested in capturing.
* - `trace` - boolean - Include stack traces for errors in log files.
*
* @see ErrorHandler for more information on error handling and configuration.
@ -69,6 +59,9 @@
* - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you
* should place the file for that class in app/Lib/Error. This class needs to implement a render method.
* - `log` - boolean - Should Exceptions be logged?
* - `skipLog` - array - list of exceptions to skip for logging. Exceptions that
* extend one of the listed exceptions will also be skipped for logging.
* Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')`
*
* @see ErrorHandler for more information on exception handling and configuration.
*/
@ -92,10 +85,45 @@
* /app/.htaccess
* /app/webroot/.htaccess
*
* And uncomment the App.baseUrl below:
* And uncomment the App.baseUrl below. But keep in mind
* that plugin assets such as images, CSS and JavaScript files
* will not work without URL rewriting!
* To work around this issue you should either symlink or copy
* the plugin assets into you app's webroot directory. This is
* recommended even when you are using mod_rewrite. Handling static
* assets through the Dispatcher is incredibly inefficient and
* included primarily as a development convenience - and
* thus not recommended for production applications.
*/
//Configure::write('App.baseUrl', env('SCRIPT_NAME'));
/**
* To configure CakePHP to use a particular domain URL
* for any URL generation inside the application, set the following
* configuration variable to the http(s) address to your domain. This
* will override the automatic detection of full base URL and can be
* useful when generating links from the CLI (e.g. sending emails)
*/
//Configure::write('App.fullBaseUrl', 'http://example.com');
/**
* Web path to the public images directory under webroot.
* If not set defaults to 'img/'
*/
//Configure::write('App.imageBaseUrl', 'img/');
/**
* Web path to the CSS files directory under webroot.
* If not set defaults to 'css/'
*/
//Configure::write('App.cssBaseUrl', 'css/');
/**
* Web path to the js files directory under webroot.
* If not set defaults to 'js/'
*/
//Configure::write('App.jsBaseUrl', 'js/');
/**
* Uncomment the define below to use CakePHP prefix routes.
*
@ -110,13 +138,11 @@
* Enables:
* `admin_index()` and `/admin/controller/index`
* `manager_index()` and `/manager/controller/index`
*
*/
//Configure::write('Routing.prefixes', array('admin'));
/**
* Turn off all caching application-wide.
*
*/
//Configure::write('Cache.disable', true);
@ -127,15 +153,18 @@
* public $cacheAction inside your controllers to define caching settings.
* You can either set it controller-wide by setting public $cacheAction = true,
* or in each action using $this->cacheAction = true.
*
*/
//Configure::write('Cache.check', true);
/**
* Defines the default error type when using the log() function. Used for
* differentiating error logging and debugging. Currently PHP supports LOG_DEBUG.
* Enable cache view prefixes.
*
* If set it will be prepended to the cache name for view file caching. This is
* helpful if you deploy the same application via multiple subdomains and languages,
* for instance. Each version can then have its own view cache namespace.
* Note: The final cache file name will then be `prefix_cachefilename`.
*/
define('LOG_ERROR', LOG_ERR);
//Configure::write('Cache.viewPrefix', 'prefix');
/**
* Session configuration.
@ -153,7 +182,7 @@
* value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX
* - `Session.defaults` - The default configuration set to use as a basis for your session.
* There are four builtins: php, cake, cache, database.
* - `Session.handler` - Can be used to enable a custom session handler. Expects an array of of callables,
* - `Session.handler` - Can be used to enable a custom session handler. Expects an array of callables,
* that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler`
* to the ini array.
* - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and
@ -172,17 +201,11 @@
*
* To use database sessions, run the app/Config/Schema/sessions.php schema using
* the cake shell command: cake schema create Sessions
*
*/
Configure::write('Session', array(
'defaults' => 'php'
));
/**
* The level of CakePHP security.
*/
Configure::write('Security.level', 'medium');
/**
* A random string used in security hashing methods.
*/
@ -216,7 +239,7 @@
* Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the
* output, and setting the config below to the name of the script.
*
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JavaScriptHelper::link().
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JsHelper::link().
*/
//Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php');
@ -234,7 +257,6 @@
//date_default_timezone_set('UTC');
/**
*
* Cache Engine Configuration
* Default settings provided below
*
@ -247,7 +269,8 @@
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
* 'lock' => false, //[optional] use file locking
* 'serialize' => true, [optional]
* 'serialize' => true, //[optional]
* 'mask' => 0664, //[optional]
* ));
*
* APC (http://pecl.php.net/package/APC)
@ -295,18 +318,20 @@
*/
/**
* Pick the caching engine to use. If APC is enabled use it.
* If running via cli - apc is disabled by default. ensure it's available and enabled in this case
* Configure the cache handlers that CakePHP will use for internal
* metadata like class maps, and model schema.
*
* By default File is used, but for improved performance you should use APC.
*
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
* Please check the comments in bootstrap.php for more info on the cache engines available
* and their settings.
*/
$engine = 'File';
if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) {
$engine = 'Apc';
}
// In development mode, caches should expire quickly.
$duration = '+999 days';
if (Configure::read('debug') >= 1) {
if (Configure::read('debug') > 0) {
$duration = '+10 seconds';
}

View file

@ -1,28 +1,10 @@
<?php
/**
* This is core configuration file.
*
* Use it to configure core behaviour of Cake.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* In this file you set up your database connection details.
*
* @package cake.config
*/
/**
* Database configuration class.
* You can specify multiple configurations for production, development and testing.
@ -57,6 +39,15 @@
*
* unix_socket =>
* For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port`
*
* settings =>
* Array of key/value pairs, on connection it executes SET statements for each pair
* For MySQL : http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
* For Postgres : http://www.postgresql.org/docs/9.2/static/sql-set.html
* For Sql Server : http://msdn.microsoft.com/en-us/library/ms190356.aspx
*
* flags =>
* A key/value array of driver specific connection options.
*/
class DATABASE_CONFIG {

View file

@ -4,25 +4,11 @@
*
* Use it to configure email transports of Cake.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 2.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* In this file you set up your send email details.
*
* @package cake.config
*/
/**
* Email configuration class.
* You can specify multiple configurations for production, development and testing.
@ -38,7 +24,6 @@
*
* from =>
* The origin email. See CakeEmail::from() about the valid values
*
*/
class EmailConfig {
@ -58,7 +43,7 @@ class EmailConfig {
'username' => 'user',
'password' => 'secret',
'client' => null,
'log' => false
'log' => false,
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

View file

@ -4,22 +4,13 @@
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different urls to chosen controllers and their actions (functions).
* different URLs to chosen controllers and their actions (functions).
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Here, we are connecting '/' (base path) to controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
@ -27,7 +18,7 @@
*/
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's urls.
* ...and connect the rest of 'Pages' controller's URLs.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));

View file

@ -2,18 +2,8 @@
/**
* AppShell file
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('Shell', 'Console');

View file

@ -2,32 +2,40 @@
################################################################################
#
# Bake is a shell script for running CakePHP bake script
# 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.
# @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
# @link http://cakephp.org CakePHP(tm) Project
# @package app.Console
# @since CakePHP(tm) v 2.0
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
# @since CakePHP(tm) v 1.2.0.5012
# @license http://www.opensource.org/licenses/mit-license.php MIT License
#
################################################################################
LIB=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && LIB=$LIB/$(basename -- "$0")
while [ -h "$LIB" ]; do
DIR=$(dirname -- "$LIB")
SYM=$(readlink "$LIB")
LIB=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
# Canonicalize by following every symlink of the given name recursively
canonicalize() {
NAME="$1"
if [ -f "$NAME" ]
then
DIR=$(dirname -- "$NAME")
NAME=$(cd -P "$DIR" && pwd -P)/$(basename -- "$NAME")
fi
while [ -h "$NAME" ]; do
DIR=$(dirname -- "$NAME")
SYM=$(readlink "$NAME")
NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
done
echo "$NAME"
}
LIB=$(dirname -- "$LIB")/
APP=`pwd`
CONSOLE=$(dirname -- "$(canonicalize "$0")")
APP=$(dirname "$CONSOLE")
exec php -q "$LIB"cake.php -working "$APP" "$@"
exit;
exec php -q "$CONSOLE"/cake.php -working "$APP" "$@"
exit

View file

@ -1,19 +1,17 @@
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: Bake is a shell script for running CakePHP bake script
:: 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
:: Redistributions of files must retain the above copyright notice.
::
:: @copyright Copyright 2005-2012, Cake Software Foundation, Inc.
:: @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
:: @link http://cakephp.org CakePHP(tm) Project
:: @package app.Console
:: @since CakePHP(tm) v 2.0
:: @license MIT License (http://www.opensource.org/licenses/mit-license.php)
::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

View file

@ -3,31 +3,46 @@
/**
* Command-line code generation utility to automate programmer chores.
*
* 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
* @package app.Console
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
$dispatcher = 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php';
if (function_exists('ini_set')) {
$root = dirname(dirname(dirname(__FILE__)));
ini_set('include_path', $root . PATH_SEPARATOR . __CAKE_PATH__ . PATH_SEPARATOR . ini_get('include_path'));
$appDir = basename(dirname(dirname(__FILE__)));
$install = $root . DS . 'lib';
$composerInstall = $root . DS . $appDir . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib';
// the following lines differ from its sibling
// /app/Console/cake.php
if (file_exists($composerInstall . DS . $dispatcher)) {
$install = $composerInstall;
} elseif (!file_exists($install . DS . $dispatcher)) {
$install = $root . PATH_SEPARATOR . __CAKE_PATH__;
}
ini_set('include_path', $install . PATH_SEPARATOR . ini_get('include_path'));
unset($root, $appDir, $install, $composerInstall);
}
if (!include $dispatcher) {
trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $dispatcher, $root, $ds);
unset($dispatcher);
return ShellDispatcher::run($argv);

View file

@ -5,19 +5,9 @@
* This file is application-wide controller file. You can put all
* application-wide controller-related methods here.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Controller
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('Controller', 'Controller');

View file

@ -4,21 +4,13 @@
*
* This file will render views from views/pages/
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Controller
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('AppController', 'Controller');
/**
* Static content controller
*
@ -39,16 +31,22 @@ class PagesController extends AppController {
/**
* Displays a view
*
* @param string What page to display
* @return void
* @throws ForbiddenException When a directory traversal attempt.
* @throws NotFoundException When the view file could not be found
* or MissingViewException in debug mode.
*/
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
$this->redirect('/');
return $this->redirect('/');
}
$page = $subpage = $title = null;
if (in_array('..', $path, true) || in_array('.', $path, true)) {
throw new ForbiddenException();
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
@ -57,11 +55,17 @@ class PagesController extends AppController {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage'));
$this->set('title_for_layout', $title);
$this->render(implode('/', $path));
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
try {
$this->render(implode('/', $path));
} catch (MissingViewException $e) {
if (Configure::read('debug')) {
throw $e;
}
throw new NotFoundException();
}
}
}

View file

@ -5,19 +5,9 @@
* This file is application-wide model file. You can put all
* application-wide model-related methods here.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Model
* @since CakePHP(tm) v 0.2.9
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('Model', 'Model');

Some files were not shown because too many files have changed in this diff Show more