mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
CakePHP 2.5.0
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (Darwin) iQEcBAABAgAGBQJTcYCoAAoJEDwHD15Vs66g4PQH+wZkDgvrGK5AoMBU63tLhM68 txYUfV2g7YCjoWC/q0R5QbEYa7otBAAtREEdPisTU34pWPPGcar4/Q8M+bsztaJv UfOWOzmVLqNqDGMfvJKL5Y3kWtuKDpUVGupa4SBdt/jQ0RxwsG5SBolwu7QQ15gr BstQjA6RpTmdBjzbHVfX6WO3a//4utY3Nf0G4+aL5Q/y1FDNzyAmBq4OKahbBY0K MnaWiANHXN/3YfFFaWxDk+P23gsiWckaqq3Q2ipaGGGQoWq0rMeWFw3OrSc4w4xS L94poTkNDPqEzEjO7A4GvyvgXW4NhuuDbGkrSXciArfxihVSyB1mziDWSSYanAI= =y8NE -----END PGP SIGNATURE----- CakePHP 2.5.0
This commit is contained in:
commit
3c57300816
199 changed files with 7235 additions and 2048 deletions
33
.gitattributes
vendored
Normal file
33
.gitattributes
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Define the line ending behavior of the different file extensions
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files we want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.php text
|
||||
*.default text
|
||||
*.ctp text
|
||||
*.sql text
|
||||
*.md text
|
||||
*.po text
|
||||
*.js text
|
||||
*.css text
|
||||
*.ini text
|
||||
*.properties text
|
||||
*.txt text
|
||||
*.xml text
|
||||
*.yml text
|
||||
.htaccess text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.bat eol=crlf
|
||||
|
||||
# Declare files that will always have LF line endings on checkout.
|
||||
*.pem eol=lf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mo binary
|
|
@ -12,6 +12,9 @@ env:
|
|||
- DB=pgsql
|
||||
- DB=sqlite
|
||||
|
||||
services:
|
||||
- memcached
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.4
|
||||
|
@ -32,6 +35,7 @@ before_script:
|
|||
- sudo apt-get install lighttpd
|
||||
- sh -c "if [ '$PHPCS' = '1' ]; then pear channel-discover pear.cakephp.org; fi"
|
||||
- sh -c "if [ '$PHPCS' = '1' ]; then pear install --alldeps cakephp/CakePHP_CodeSniffer; fi"
|
||||
- echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
|
||||
- phpenv rehash
|
||||
- set +H
|
||||
- echo "<?php
|
||||
|
|
|
@ -80,6 +80,7 @@ Cache::config('default', array('engine' => 'File'));
|
|||
*
|
||||
* Configure::write('Dispatcher.filters', array(
|
||||
* 'MyCacheFilter', // will use MyCacheFilter class from the Routing/Filter package in your app.
|
||||
* 'MyCacheFilter' => array('prefix' => 'my_cache_'), // will use MyCacheFilter class from the Routing/Filter package in your app with settings array.
|
||||
* 'MyPlugin.MyFilter', // will use MyFilter class from the Routing/Filter package in MyPlugin plugin.
|
||||
* 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
|
||||
|
|
|
@ -315,18 +315,20 @@
|
|||
* 'password' => 'password', //plaintext password (xcache.admin.pass)
|
||||
* ));
|
||||
*
|
||||
* Memcache (http://www.danga.com/memcached/)
|
||||
* Memcached (http://www.danga.com/memcached/)
|
||||
*
|
||||
* Uses the memcached extension. See http://php.net/memcached
|
||||
*
|
||||
* Cache::config('default', array(
|
||||
* 'engine' => 'Memcache', //[required]
|
||||
* 'engine' => 'Memcached', //[required]
|
||||
* 'duration' => 3600, //[optional]
|
||||
* 'probability' => 100, //[optional]
|
||||
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||
* 'servers' => array(
|
||||
* '127.0.0.1:11211' // localhost, default port 11211
|
||||
* ), //[optional]
|
||||
* 'persistent' => true, // [optional] set this to false for non-persistent connections
|
||||
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
|
||||
* 'persistent' => 'my_connection', // [optional] The name of the persistent connection.
|
||||
* 'compress' => false, // [optional] compress data in Memcached (slower, but uses less memory)
|
||||
* ));
|
||||
*
|
||||
* Wincache (http://php.net/wincache)
|
||||
|
|
|
@ -58,6 +58,9 @@
|
|||
* 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 {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo $name; ?></h2>
|
||||
<h2><?php echo $message; ?></h2>
|
||||
<p class="error">
|
||||
<strong><?php echo __d('cake', 'Error'); ?>: </strong>
|
||||
<?php printf(
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo $name; ?></h2>
|
||||
<h2><?php echo $message; ?></h2>
|
||||
<p class="error">
|
||||
<strong><?php echo __d('cake', 'Error'); ?>: </strong>
|
||||
<?php echo __d('cake', 'An Internal Error Has Occurred.'); ?>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
$cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework');
|
||||
$cakeVersion = __d('cake_dev', 'CakePHP %s', Configure::version())
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
@ -51,9 +52,12 @@ $cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework
|
|||
<?php echo $this->Html->link(
|
||||
$this->Html->image('cake.power.gif', array('alt' => $cakeDescription, 'border' => '0')),
|
||||
'http://www.cakephp.org/',
|
||||
array('target' => '_blank', 'escape' => false)
|
||||
array('target' => '_blank', 'escape' => false, 'id' => 'cake-powered')
|
||||
);
|
||||
?>
|
||||
<p>
|
||||
<?php echo $cakeVersion; ?>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo $this->element('sql_dump'); ?>
|
||||
|
|
|
@ -107,11 +107,13 @@ p {
|
|||
#footer {
|
||||
clear: both;
|
||||
padding: 6px 10px;
|
||||
text-align: right;
|
||||
}
|
||||
#header a, #footer a {
|
||||
color: #fff;
|
||||
}
|
||||
#cake-powered {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** containers **/
|
||||
div.form,
|
||||
|
|
|
@ -130,7 +130,7 @@ class Cache {
|
|||
}
|
||||
|
||||
if (!empty($settings)) {
|
||||
self::$_config[$name] = array_merge($current, $settings);
|
||||
self::$_config[$name] = $settings + $current;
|
||||
}
|
||||
|
||||
if (empty(self::$_config[$name]['engine'])) {
|
||||
|
@ -253,7 +253,7 @@ class Cache {
|
|||
if (is_string($settings) && $value !== null) {
|
||||
$settings = array($settings => $value);
|
||||
}
|
||||
$settings = array_merge(self::$_config[$config], $settings);
|
||||
$settings += self::$_config[$config];
|
||||
if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
|
||||
$settings['duration'] = strtotime($settings['duration']) - time();
|
||||
}
|
||||
|
@ -538,4 +538,38 @@ class Cache {
|
|||
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.
|
||||
*/
|
||||
public static function remember($key, $callable, $config = 'default') {
|
||||
$existing = self::read($key, $config);
|
||||
if ($existing !== false) {
|
||||
return $existing;
|
||||
}
|
||||
$results = call_user_func($callable);
|
||||
self::write($key, $results, $config);
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* more information.
|
||||
*
|
||||
* @package Cake.Cache.Engine
|
||||
* @deprecated You should use the Memcached adapter instead.
|
||||
*/
|
||||
class MemcacheEngine extends CacheEngine {
|
||||
|
||||
|
|
322
lib/Cake/Cache/Engine/MemcachedEngine.php
Executable file
322
lib/Cake/Cache/Engine/MemcachedEngine.php
Executable file
|
@ -0,0 +1,322 @@
|
|||
<?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
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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 boolean 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'
|
||||
);
|
||||
parent::init($settings);
|
||||
|
||||
if (!is_array($this->settings['servers'])) {
|
||||
$this->settings['servers'] = array($this->settings['servers']);
|
||||
}
|
||||
|
||||
if (isset($this->_Memcached)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->_Memcached = new Memcached($this->settings['persistent'] ? (string)$this->settings['persistent'] : null);
|
||||
$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->setSaslAuthData($this->settings['login'], $this->settings['password']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings the memcached instance
|
||||
*
|
||||
* @throws CacheException when the Memcached extension is not built with the desired serializer engine
|
||||
*/
|
||||
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) {
|
||||
if ($server[0] === 'u') {
|
||||
return array($server, 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 integer $duration How long to cache the data, in seconds
|
||||
* @return boolean 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 integer $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 integer $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 boolean 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 boolean $check
|
||||
* @return boolean True if the cache was successfully cleared, false otherwise
|
||||
*/
|
||||
public function clear($check) {
|
||||
if ($check) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$keys = $this->_Memcached->getAllKeys();
|
||||
|
||||
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.
|
||||
*
|
||||
* @return boolean success
|
||||
*/
|
||||
public function clearGroup($group) {
|
||||
return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group);
|
||||
}
|
||||
}
|
|
@ -34,9 +34,11 @@ class RedisEngine extends CacheEngine {
|
|||
* Settings
|
||||
*
|
||||
* - 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 = boolean Connects to the Redis server with a persistent connection (default: true)
|
||||
* - unix_socket = path to the unix socket file (default: false)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
|
@ -59,10 +61,12 @@ class RedisEngine extends CacheEngine {
|
|||
'engine' => 'Redis',
|
||||
'prefix' => null,
|
||||
'server' => '127.0.0.1',
|
||||
'database' => 0,
|
||||
'port' => 6379,
|
||||
'password' => false,
|
||||
'timeout' => 0,
|
||||
'persistent' => true
|
||||
'persistent' => true,
|
||||
'unix_socket' => false
|
||||
), $settings)
|
||||
);
|
||||
|
||||
|
@ -78,10 +82,13 @@ class RedisEngine extends CacheEngine {
|
|||
$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;
|
||||
|
@ -89,6 +96,9 @@ class RedisEngine extends CacheEngine {
|
|||
if ($return && $this->settings['password']) {
|
||||
$return = $this->_Redis->auth($this->settings['password']);
|
||||
}
|
||||
if ($return) {
|
||||
$return = $this->_Redis->select($this->settings['database']);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
|
|
@ -363,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();
|
||||
|
@ -501,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.',
|
||||
|
@ -512,8 +511,8 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,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()
|
||||
|
@ -247,6 +248,8 @@ class BakeShell extends AppShell {
|
|||
'short' => 't',
|
||||
'help' => __d('cake_console', 'Theme to use when baking code.')
|
||||
));
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,13 @@ App::uses('Inflector', 'Utility');
|
|||
*/
|
||||
class CommandListShell extends AppShell {
|
||||
|
||||
/**
|
||||
* Contains tasks to load and instantiate
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $tasks = array('Command');
|
||||
|
||||
/**
|
||||
* startup
|
||||
*
|
||||
|
@ -55,7 +62,7 @@ class CommandListShell extends AppShell {
|
|||
$this->out(__d('cake_console', "<info>Available Shells:</info>"), 2);
|
||||
}
|
||||
|
||||
$shellList = $this->_getShellList();
|
||||
$shellList = $this->Command->getShellList();
|
||||
if (empty($shellList)) {
|
||||
return;
|
||||
}
|
||||
|
@ -67,48 +74,6 @@ 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 void
|
||||
*/
|
||||
protected function _appendShells($type, $shells, &$shellList) {
|
||||
foreach ($shells as $shell) {
|
||||
$shellList[$type][] = Inflector::underscore(str_replace('Shell', '', $shell));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output text.
|
||||
*
|
||||
|
@ -155,21 +120,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
155
lib/Cake/Console/Command/CompletionShell.php
Normal file
155
lib/Cake/Console/Command/CompletionShell.php
Normal 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
|
||||
* @return void
|
||||
*/
|
||||
protected function _output($options = array()) {
|
||||
if ($options) {
|
||||
return $this->out(implode($options, ' '));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,19 +105,19 @@ class ConsoleShell extends AppShell {
|
|||
}
|
||||
|
||||
/**
|
||||
* getOptionParser
|
||||
* Gets the option parser instance and configures it.
|
||||
*
|
||||
* @return void
|
||||
* @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 $',
|
||||
|
@ -176,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
|
||||
|
|
|
@ -100,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.')
|
||||
|
@ -114,6 +115,8 @@ class I18nShell extends AppShell {
|
|||
'help' => __d('cake_console', 'Extract the po translations from your application'),
|
||||
'parser' => $this->Extract->getOptionParser()
|
||||
));
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -337,7 +337,10 @@ class SchemaShell extends AppShell {
|
|||
$this->out("\n" . __d('cake_console', 'The following table(s) will be dropped.'));
|
||||
$this->out(array_keys($drop));
|
||||
|
||||
if ($this->in(__d('cake_console', 'Are you sure you want to drop the table(s)?'), array('y', 'n'), 'n') === 'y') {
|
||||
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);
|
||||
}
|
||||
|
@ -345,7 +348,10 @@ class SchemaShell extends AppShell {
|
|||
$this->out("\n" . __d('cake_console', 'The following table(s) will be created.'));
|
||||
$this->out(array_keys($create));
|
||||
|
||||
if ($this->in(__d('cake_console', 'Are you sure you want to create the table(s)?'), array('y', 'n'), 'y') === '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);
|
||||
}
|
||||
|
@ -396,7 +402,10 @@ class SchemaShell extends AppShell {
|
|||
|
||||
$this->out("\n" . __d('cake_console', 'The following statements will run.'));
|
||||
$this->out(array_map('trim', $contents));
|
||||
if ($this->in(__d('cake_console', 'Are you sure you want to alter the tables?'), array('y', 'n'), 'n') === 'y') {
|
||||
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);
|
||||
|
@ -452,11 +461,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.'),
|
||||
|
@ -475,7 +486,9 @@ class SchemaShell extends AppShell {
|
|||
'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',
|
||||
|
@ -486,7 +499,9 @@ class SchemaShell extends AppShell {
|
|||
'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(
|
||||
|
@ -500,8 +515,12 @@ class SchemaShell extends AppShell {
|
|||
$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(
|
||||
|
@ -527,7 +546,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.')
|
||||
|
@ -540,7 +559,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.')
|
||||
|
@ -551,6 +570,7 @@ class SchemaShell extends AppShell {
|
|||
)
|
||||
)
|
||||
));
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,29 +141,25 @@ class ServerShell extends AppShell {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get and configure the optionparser.
|
||||
* Gets the option parser instance and configures it.
|
||||
*
|
||||
* @return ConsoleOptionParser
|
||||
*/
|
||||
public function getOptionParser() {
|
||||
$parser = parent::getOptionParser();
|
||||
|
||||
$parser->addOption('host', array(
|
||||
'short' => 'H',
|
||||
'help' => __d('cake_console', 'ServerHost')
|
||||
));
|
||||
$parser->addOption('port', array(
|
||||
'short' => 'p',
|
||||
'help' => __d('cake_console', 'ListenPort')
|
||||
));
|
||||
$parser->addOption('document_root', array(
|
||||
'short' => 'd',
|
||||
'help' => __d('cake_console', 'DocumentRoot')
|
||||
));
|
||||
|
||||
$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>'),
|
||||
__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;
|
||||
|
|
183
lib/Cake/Console/Command/Task/CommandTask.php
Normal file
183
lib/Cake/Console/Command/Task/CommandTask.php
Normal 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
|
||||
* @param array $shells
|
||||
* @param array $shellList
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
|
@ -466,15 +466,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).'),
|
||||
|
@ -496,7 +497,11 @@ class ControllerTask extends BakeTask {
|
|||
'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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ class DbConfigTask extends AppShell {
|
|||
* @return boolean 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();
|
||||
|
@ -264,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;
|
||||
|
@ -307,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) {
|
||||
|
@ -368,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -296,52 +296,55 @@ 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(
|
||||
|
||||
$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('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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -60,13 +60,14 @@ 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.')
|
||||
|
@ -80,7 +81,7 @@ class FixtureTask extends BakeTask {
|
|||
'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',
|
||||
|
@ -92,10 +93,15 @@ class FixtureTask extends BakeTask {
|
|||
'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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -348,18 +348,27 @@ class ModelTask extends BakeTask {
|
|||
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;
|
||||
}
|
||||
|
@ -399,6 +408,11 @@ class ModelTask extends BakeTask {
|
|||
$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') {
|
||||
if ($this->interactive) {
|
||||
|
@ -422,8 +436,6 @@ 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') {
|
||||
|
@ -453,6 +465,10 @@ class ModelTask extends BakeTask {
|
|||
|
||||
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;
|
||||
|
@ -480,7 +496,12 @@ class ModelTask extends BakeTask {
|
|||
}
|
||||
$anotherValidator = 'n';
|
||||
if ($this->interactive && $choice != $defaultChoice) {
|
||||
$anotherValidator = $this->in(__d('cake_console', 'Would you like to add another validation rule?'), array('y', 'n'), 'n');
|
||||
$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;
|
||||
|
@ -978,13 +999,14 @@ class ModelTask 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', 'Bake models.')
|
||||
)->addArgument('name', array(
|
||||
'help' => __d('cake_console', 'Name of the model to bake. Can use Plugin.name to bake plugin models.')
|
||||
|
@ -1002,7 +1024,11 @@ class ModelTask extends BakeTask {
|
|||
))->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.'));
|
||||
))->epilog(
|
||||
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
|
||||
);
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -211,18 +211,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -419,13 +419,14 @@ 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.')
|
||||
|
@ -437,8 +438,11 @@ class ProjectTask extends AppShell {
|
|||
'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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
@ -570,7 +572,11 @@ class TestTask extends BakeTask {
|
|||
))->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.'));
|
||||
))->epilog(
|
||||
__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.')
|
||||
);
|
||||
|
||||
return $parser;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -412,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.')
|
||||
|
@ -443,7 +444,11 @@ class ViewTask extends BakeTask {
|
|||
'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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,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
|
||||
|
@ -153,9 +154,9 @@ class TestShell extends Shell {
|
|||
'help' => __d('cake_console', 'key[=value] Sets a php.ini value.'),
|
||||
'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;
|
||||
|
|
|
@ -32,15 +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>\nuse the test shell instead"),
|
||||
__d('cake_console', "<warning>This shell is for backwards-compatibility only</warning>\nuse the test shell instead")
|
||||
));
|
||||
|
||||
return $parser;
|
||||
|
|
|
@ -199,7 +199,7 @@ class UpgradeShell extends AppShell {
|
|||
$dir = $options;
|
||||
$options = array();
|
||||
}
|
||||
$options = array_merge($defaultOptions, $options);
|
||||
$options += $defaultOptions;
|
||||
$this->_movePhpFiles($dir, $options);
|
||||
}
|
||||
}
|
||||
|
@ -392,6 +392,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);
|
||||
}
|
||||
|
@ -500,6 +505,29 @@ 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.
|
||||
*
|
||||
|
@ -779,11 +807,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(
|
||||
|
@ -808,53 +838,48 @@ 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 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(
|
||||
'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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ class ConsoleOptionParser {
|
|||
'boolean' => false,
|
||||
'choices' => array()
|
||||
);
|
||||
$options = array_merge($defaults, $options);
|
||||
$options += $defaults;
|
||||
$option = new ConsoleInputOption($options);
|
||||
}
|
||||
$this->_options[$name] = $option;
|
||||
|
@ -338,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);
|
||||
|
@ -403,7 +403,7 @@ class ConsoleOptionParser {
|
|||
'help' => '',
|
||||
'parser' => null
|
||||
);
|
||||
$options = array_merge($defaults, $options);
|
||||
$options += $defaults;
|
||||
$command = new ConsoleInputSubcommand($options);
|
||||
}
|
||||
$this->_subcommands[$name] = $command;
|
||||
|
|
|
@ -462,6 +462,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
|
||||
|
|
|
@ -311,7 +311,7 @@ class ShellDispatcher {
|
|||
$params = str_replace('/', '\\', $params);
|
||||
}
|
||||
|
||||
$this->params = array_merge($this->params, $params);
|
||||
$this->params = $params + $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
if (!$this-><?php echo $currentModelName; ?>->exists()) {
|
||||
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
||||
}
|
||||
$this->request->onlyAllow('post', 'delete');
|
||||
$this->request->allowMethod('post', 'delete');
|
||||
if ($this-><?php echo $currentModelName; ?>->delete()) {
|
||||
<?php if ($wannaUseSession): ?>
|
||||
$this->Session->setFlash(__('The <?php echo strtolower($singularHumanName); ?> has been deleted.'));
|
||||
|
|
|
@ -75,6 +75,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; ?>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
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(), __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
|
||||
echo "\t\t</td>\n";
|
||||
echo "\t</tr>\n";
|
||||
|
||||
|
|
|
@ -41,12 +41,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 {
|
||||
|
||||
|
|
26
lib/Cake/Console/Templates/skel/Test/Case/AllTestsTest.php
Normal file
26
lib/Cake/Console/Templates/skel/Test/Case/AllTestsTest.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
/**
|
||||
* AllTests file
|
||||
*
|
||||
* 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
|
||||
* @package app.Test.Case
|
||||
* @since CakePHP(tm) v 2.5
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
class AllTestsTest extends CakeTestSuite {
|
||||
|
||||
public static function suite() {
|
||||
$suite = new CakeTestSuite('All application tests');
|
||||
$suite->addTestDirectoryRecursive(TESTS . 'Case');
|
||||
return $suite;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
* @since CakePHP(tm) v 0.10.0.1076
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo $name; ?></h2>
|
||||
<h2><?php echo $message; ?></h2>
|
||||
<p class="error">
|
||||
<strong><?php echo __d('cake', 'Error'); ?>: </strong>
|
||||
<?php printf(
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* @since CakePHP(tm) v 0.10.0.1076
|
||||
*/
|
||||
?>
|
||||
<h2><?php echo $name; ?></h2>
|
||||
<h2><?php echo $message; ?></h2>
|
||||
<p class="error">
|
||||
<strong><?php echo __d('cake', 'Error'); ?>: </strong>
|
||||
<?php echo __d('cake', 'An Internal Error Has Occurred.'); ?>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title><?php echo $title_for_layout; ?></title>
|
||||
<title><?php echo $this->fetch('title'); ?></title>
|
||||
</head>
|
||||
<body>
|
||||
<?php echo $this->fetch('content'); ?>
|
||||
|
|
|
@ -15,7 +15,7 @@ $cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework
|
|||
<?php echo $this->Html->charset(); ?>
|
||||
<title>
|
||||
<?php echo $cakeDescription ?>:
|
||||
<?php echo $title_for_layout; ?>
|
||||
<?php echo $this->fetch('title'); ?>
|
||||
</title>
|
||||
<?php
|
||||
echo $this->Html->meta('icon');
|
||||
|
|
|
@ -15,7 +15,7 @@ $cakeDescription = __d('cake_dev', 'CakePHP: the rapid development php framework
|
|||
<?php echo $this->Html->charset(); ?>
|
||||
<title>
|
||||
<?php echo $cakeDescription ?>:
|
||||
<?php echo $title_for_layout; ?>
|
||||
<?php echo $this->fetch('title'); ?>
|
||||
</title>
|
||||
<?php
|
||||
echo $this->Html->meta('icon');
|
||||
|
|
|
@ -3,7 +3,7 @@ if (!isset($channel)):
|
|||
$channel = array();
|
||||
endif;
|
||||
if (!isset($channel['title'])):
|
||||
$channel['title'] = $title_for_layout;
|
||||
$channel['title'] = $this->fetch('title');
|
||||
endif;
|
||||
|
||||
echo $this->Rss->document(
|
||||
|
|
|
@ -92,7 +92,7 @@ class Component extends Object {
|
|||
*/
|
||||
public function __get($name) {
|
||||
if (isset($this->_componentMap[$name]) && !isset($this->{$name})) {
|
||||
$settings = array_merge((array)$this->_componentMap[$name]['settings'], array('enabled' => false));
|
||||
$settings = array('enabled' => false) + (array)$this->_componentMap[$name]['settings'];
|
||||
$this->{$name} = $this->_Collection->load($this->_componentMap[$name]['class'], $settings);
|
||||
}
|
||||
if (isset($this->{$name})) {
|
||||
|
|
|
@ -81,7 +81,7 @@ class PhpAcl extends Object implements AclInterface {
|
|||
*/
|
||||
public function initialize(Component $Component) {
|
||||
if (!empty($Component->settings['adapter'])) {
|
||||
$this->options = array_merge($this->options, $Component->settings['adapter']);
|
||||
$this->options = $Component->settings['adapter'] + $this->options;
|
||||
}
|
||||
|
||||
App::uses('PhpReader', 'Configure');
|
||||
|
@ -546,7 +546,7 @@ class PhpAro {
|
|||
* @return void
|
||||
*/
|
||||
public function addAlias(array $alias) {
|
||||
$this->aliases = array_merge($this->aliases, $alias);
|
||||
$this->aliases = $alias + $this->aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -365,6 +365,7 @@ class AuthComponent extends Component {
|
|||
return false;
|
||||
}
|
||||
if (!empty($this->ajaxLogin)) {
|
||||
$controller->response->statusCode(403);
|
||||
$controller->viewPath = 'Elements';
|
||||
echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
|
||||
$this->_stop();
|
||||
|
@ -775,6 +776,10 @@ class AuthComponent extends Component {
|
|||
unset($config[AuthComponent::ALL]);
|
||||
}
|
||||
foreach ($config as $class => $settings) {
|
||||
if (!empty($settings['className'])) {
|
||||
$class = $settings['className'];
|
||||
unset($settings['className']);
|
||||
}
|
||||
list($plugin, $class) = pluginSplit($class, true);
|
||||
$className = $class . 'Authenticate';
|
||||
App::uses($className, $plugin . 'Controller/Component/Auth');
|
||||
|
@ -808,6 +813,7 @@ class AuthComponent extends Component {
|
|||
* Check whether or not the current user has data in the session, and is considered logged in.
|
||||
*
|
||||
* @return boolean true if the user is logged in, false otherwise
|
||||
* @deprecated Since 2.5. Use AuthComponent::user() directly.
|
||||
*/
|
||||
public function loggedIn() {
|
||||
return (bool)$this->user();
|
||||
|
|
|
@ -130,7 +130,9 @@ class CookieComponent extends Component {
|
|||
* Type of encryption to use.
|
||||
*
|
||||
* Currently two methods are available: cipher and rijndael
|
||||
* Defaults to Security::cipher();
|
||||
* Defaults to Security::cipher(). Cipher is horribly insecure and only
|
||||
* the default because of backwards compatibility. In new applications you should
|
||||
* always change this to 'aes' or 'rijndael'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -378,10 +380,11 @@ class CookieComponent extends Component {
|
|||
public function type($type = 'cipher') {
|
||||
$availableTypes = array(
|
||||
'cipher',
|
||||
'rijndael'
|
||||
'rijndael',
|
||||
'aes'
|
||||
);
|
||||
if (!in_array($type, $availableTypes)) {
|
||||
trigger_error(__d('cake_dev', 'You must use cipher or rijndael for cookie encryption type'), E_USER_WARNING);
|
||||
trigger_error(__d('cake_dev', 'You must use cipher, rijndael or aes for cookie encryption type'), E_USER_WARNING);
|
||||
$type = 'cipher';
|
||||
}
|
||||
$this->_type = $type;
|
||||
|
@ -469,13 +472,21 @@ class CookieComponent extends Component {
|
|||
if (is_array($value)) {
|
||||
$value = $this->_implode($value);
|
||||
}
|
||||
|
||||
if ($this->_encrypted === true) {
|
||||
$type = $this->_type;
|
||||
$value = "Q2FrZQ==." . base64_encode(Security::$type($value, $this->key, 'encrypt'));
|
||||
}
|
||||
if (!$this->_encrypted) {
|
||||
return $value;
|
||||
}
|
||||
$prefix = "Q2FrZQ==.";
|
||||
if ($this->_type === 'rijndael') {
|
||||
$cipher = Security::rijndael($value, $this->key, 'encrypt');
|
||||
}
|
||||
if ($this->_type === 'cipher') {
|
||||
$cipher = Security::cipher($value, $this->key);
|
||||
}
|
||||
if ($this->_type === 'aes') {
|
||||
$cipher = Security::encrypt($value, $this->key);
|
||||
}
|
||||
return $prefix . base64_encode($cipher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts $value using public $type method in Security class
|
||||
|
@ -490,27 +501,40 @@ class CookieComponent extends Component {
|
|||
foreach ((array)$values as $name => $value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $key => $val) {
|
||||
$pos = strpos($val, 'Q2FrZQ==.');
|
||||
$decrypted[$name][$key] = $this->_explode($val);
|
||||
|
||||
if ($pos !== false) {
|
||||
$val = substr($val, 8);
|
||||
$decrypted[$name][$key] = $this->_explode(Security::$type(base64_decode($val), $this->key, 'decrypt'));
|
||||
}
|
||||
$decrypted[$name][$key] = $this->_decode($val);
|
||||
}
|
||||
} else {
|
||||
$pos = strpos($value, 'Q2FrZQ==.');
|
||||
$decrypted[$name] = $this->_explode($value);
|
||||
|
||||
if ($pos !== false) {
|
||||
$value = substr($value, 8);
|
||||
$decrypted[$name] = $this->_explode(Security::$type(base64_decode($value), $this->key, 'decrypt'));
|
||||
}
|
||||
$decrypted[$name] = $this->_decode($value);
|
||||
}
|
||||
}
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes and decrypts a single value.
|
||||
*
|
||||
* @param string $value The value to decode & decrypt.
|
||||
* @return string Decoded value.
|
||||
*/
|
||||
protected function _decode($value) {
|
||||
$prefix = 'Q2FrZQ==.';
|
||||
$pos = strpos($value, $prefix);
|
||||
if ($pos === false) {
|
||||
return $this->_explode($value);
|
||||
}
|
||||
$value = base64_decode(substr($value, strlen($prefix)));
|
||||
if ($this->_type === 'rijndael') {
|
||||
$plain = Security::rijndael($value, $this->key, 'decrypt');
|
||||
}
|
||||
if ($this->_type === 'cipher') {
|
||||
$plain = Security::cipher($value, $this->key);
|
||||
}
|
||||
if ($this->_type === 'aes') {
|
||||
$plain = Security::decrypt($value, $this->key);
|
||||
}
|
||||
return $this->_explode($plain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implode method to keep keys are multidimensional arrays
|
||||
*
|
||||
|
|
|
@ -202,6 +202,8 @@ class PaginatorComponent extends Component {
|
|||
$count = 0;
|
||||
} elseif ($object->hasMethod('paginateCount')) {
|
||||
$count = $object->paginateCount($conditions, $recursive, $extra);
|
||||
} elseif ($page === 1 && count($results) < $limit) {
|
||||
$count = count($results);
|
||||
} else {
|
||||
$parameters = compact('conditions');
|
||||
if ($recursive != $object->recursive) {
|
||||
|
|
|
@ -603,13 +603,12 @@ class RequestHandlerComponent extends Component {
|
|||
if (Configure::read('App.encoding') !== null) {
|
||||
$defaults['charset'] = Configure::read('App.encoding');
|
||||
}
|
||||
$options = array_merge($defaults, $options);
|
||||
$options += $defaults;
|
||||
|
||||
if ($type === 'ajax') {
|
||||
$controller->layout = $this->ajaxLayout;
|
||||
return $this->respondAs('html', $options);
|
||||
}
|
||||
$controller->ext = '.ctp';
|
||||
|
||||
$pluginDot = null;
|
||||
$viewClassMap = $this->viewClassMap();
|
||||
|
|
|
@ -29,6 +29,7 @@ App::uses('Scaffold', 'View');
|
|||
* scaffolded actions with custom-made ones.
|
||||
*
|
||||
* @package Cake.Controller
|
||||
* @deprecated Dynamic scaffolding will be removed and replaced in 3.0
|
||||
*/
|
||||
class Scaffold {
|
||||
|
||||
|
|
|
@ -108,12 +108,12 @@ class CakePlugin {
|
|||
* {{{
|
||||
* CakePlugin::loadAll(array(
|
||||
* array('bootstrap' => true),
|
||||
* 'DebugKit' => array('routes' => true),
|
||||
* 'DebugKit' => array('routes' => true, 'bootstrap' => false),
|
||||
* ))
|
||||
* }}}
|
||||
*
|
||||
* The above example will load the bootstrap file for all plugins, but for DebugKit it will only load the routes file
|
||||
* and will not look for any bootstrap script.
|
||||
* The above example will load the bootstrap file for all plugins, but for DebugKit it will only load
|
||||
* the routes file and will not look for any bootstrap script.
|
||||
*
|
||||
* @param array $options
|
||||
* @return void
|
||||
|
@ -121,11 +121,11 @@ class CakePlugin {
|
|||
public static function loadAll($options = array()) {
|
||||
$plugins = App::objects('plugins');
|
||||
foreach ($plugins as $p) {
|
||||
$opts = isset($options[$p]) ? $options[$p] : null;
|
||||
if ($opts === null && isset($options[0])) {
|
||||
$opts = $options[0];
|
||||
$opts = isset($options[$p]) ? (array)$options[$p] : array();
|
||||
if (isset($options[0])) {
|
||||
$opts += $options[0];
|
||||
}
|
||||
self::load($p, (array)$opts);
|
||||
self::load($p, $opts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,7 +287,7 @@ class Configure {
|
|||
* @param string $key name of configuration resource to load.
|
||||
* @param string $config Name of the configured reader to use to read the resource identified by $key.
|
||||
* @param boolean $merge if config files should be merged instead of simply overridden
|
||||
* @return mixed false if file not found, void if load successful.
|
||||
* @return boolean False if file not found, true if load successful.
|
||||
* @throws ConfigureException Will throw any exceptions the reader raises.
|
||||
*/
|
||||
public static function load($key, $config = 'default', $merge = true) {
|
||||
|
@ -424,6 +424,7 @@ class Configure {
|
|||
self::$_values = array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error and exception handlers.
|
||||
*
|
||||
|
@ -444,4 +445,5 @@ class Configure {
|
|||
set_exception_handler($exception['handler']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class Object {
|
|||
if ($arrayUrl && !isset($extra['data'])) {
|
||||
$extra['data'] = array();
|
||||
}
|
||||
$extra = array_merge(array('autoRender' => 0, 'return' => 1, 'bare' => 1, 'requested' => 1), $extra);
|
||||
$extra += array('autoRender' => 0, 'return' => 1, 'bare' => 1, 'requested' => 1);
|
||||
$data = isset($extra['data']) ? $extra['data'] : null;
|
||||
unset($extra['data']);
|
||||
|
||||
|
@ -95,7 +95,7 @@ class Object {
|
|||
$request = new CakeRequest($url);
|
||||
} elseif (is_array($url)) {
|
||||
$params = $url + array('pass' => array(), 'named' => array(), 'base' => false);
|
||||
$params = array_merge($params, $extra);
|
||||
$params = $extra + $params;
|
||||
$request = new CakeRequest(Router::reverse($params));
|
||||
}
|
||||
if (isset($data)) {
|
||||
|
|
|
@ -189,10 +189,11 @@ class ExceptionRenderer {
|
|||
$this->controller->response->statusCode($code);
|
||||
$this->controller->set(array(
|
||||
'code' => $code,
|
||||
'url' => h($url),
|
||||
'name' => h($error->getMessage()),
|
||||
'message' => h($error->getMessage()),
|
||||
'url' => h($url),
|
||||
'error' => $error,
|
||||
'_serialize' => array('code', 'url', 'name')
|
||||
'_serialize' => array('code', 'name', 'message', 'url')
|
||||
));
|
||||
$this->controller->set($error->getAttributes());
|
||||
$this->_outputMessage($this->template);
|
||||
|
@ -213,9 +214,10 @@ class ExceptionRenderer {
|
|||
$this->controller->response->statusCode($error->getCode());
|
||||
$this->controller->set(array(
|
||||
'name' => h($message),
|
||||
'message' => h($message),
|
||||
'url' => h($url),
|
||||
'error' => $error,
|
||||
'_serialize' => array('name', 'url')
|
||||
'_serialize' => array('name', 'message', 'url')
|
||||
));
|
||||
$this->_outputMessage('error400');
|
||||
}
|
||||
|
@ -236,9 +238,10 @@ class ExceptionRenderer {
|
|||
$this->controller->response->statusCode($code);
|
||||
$this->controller->set(array(
|
||||
'name' => h($message),
|
||||
'message' => h($url),
|
||||
'message' => h($message),
|
||||
'url' => h($url),
|
||||
'error' => $error,
|
||||
'_serialize' => array('name', 'message')
|
||||
'_serialize' => array('name', 'message', 'url')
|
||||
));
|
||||
$this->_outputMessage('error500');
|
||||
}
|
||||
|
@ -255,10 +258,11 @@ class ExceptionRenderer {
|
|||
$this->controller->response->statusCode($code);
|
||||
$this->controller->set(array(
|
||||
'code' => $code,
|
||||
'url' => h($url),
|
||||
'name' => h($error->getMessage()),
|
||||
'message' => h($error->getMessage()),
|
||||
'url' => h($url),
|
||||
'error' => $error,
|
||||
'_serialize' => array('code', 'url', 'name', 'error')
|
||||
'_serialize' => array('code', 'name', 'message', 'url', 'error')
|
||||
));
|
||||
$this->_outputMessage($this->template);
|
||||
}
|
||||
|
|
|
@ -222,22 +222,19 @@ class CakeEventManager {
|
|||
* Dispatches a new event to all configured listeners
|
||||
*
|
||||
* @param string|CakeEvent $event the event key name or instance of CakeEvent
|
||||
* @return void
|
||||
* @return CakeEvent
|
||||
*/
|
||||
public function dispatch($event) {
|
||||
if (is_string($event)) {
|
||||
$event = new CakeEvent($event);
|
||||
}
|
||||
|
||||
if (!$this->_isGlobal) {
|
||||
self::instance()->dispatch($event);
|
||||
$listeners = $this->listeners($event->name());
|
||||
if (empty($listeners)) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
if (empty($this->_listeners[$event->name()])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->listeners($event->name()) as $listener) {
|
||||
foreach ($listeners as $listener) {
|
||||
if ($event->isStopped()) {
|
||||
break;
|
||||
}
|
||||
|
@ -253,6 +250,7 @@ class CakeEventManager {
|
|||
$event->result = $result;
|
||||
}
|
||||
}
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -262,15 +260,41 @@ class CakeEventManager {
|
|||
* @return array
|
||||
*/
|
||||
public function listeners($eventKey) {
|
||||
if (empty($this->_listeners[$eventKey])) {
|
||||
return array();
|
||||
$localListeners = array();
|
||||
$priorities = array();
|
||||
if (!$this->_isGlobal) {
|
||||
$localListeners = $this->prioritisedListeners($eventKey);
|
||||
$localListeners = empty($localListeners) ? array() : $localListeners;
|
||||
}
|
||||
ksort($this->_listeners[$eventKey]);
|
||||
$globalListeners = self::instance()->prioritisedListeners($eventKey);
|
||||
$globalListeners = empty($globalListeners) ? array() : $globalListeners;
|
||||
|
||||
$priorities = array_merge(array_keys($globalListeners), array_keys($localListeners));
|
||||
$priorities = array_unique($priorities);
|
||||
asort($priorities);
|
||||
|
||||
$result = array();
|
||||
foreach ($this->_listeners[$eventKey] as $priorityQ) {
|
||||
$result = array_merge($result, $priorityQ);
|
||||
foreach ($priorities as $priority) {
|
||||
if (isset($globalListeners[$priority])) {
|
||||
$result = array_merge($result, $globalListeners[$priority]);
|
||||
}
|
||||
if (isset($localListeners[$priority])) {
|
||||
$result = array_merge($result, $localListeners[$priority]);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the listeners for the specified event key indexed by priority
|
||||
*
|
||||
* @param string $eventKey
|
||||
* @return array
|
||||
*/
|
||||
public function prioritisedListeners($eventKey) {
|
||||
if (empty($this->_listeners[$eventKey])) {
|
||||
return array();
|
||||
}
|
||||
return $this->_listeners[$eventKey];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,68 @@ class I18n {
|
|||
'LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME', 'LC_MESSAGES'
|
||||
);
|
||||
|
||||
/**
|
||||
* Constants for the translation categories.
|
||||
*
|
||||
* The constants may be used in translation fetching
|
||||
* instead of hardcoded integers.
|
||||
* Example:
|
||||
* {{{
|
||||
* I18n::translate('CakePHP is awesome.', null, null, I18n::LC_MESSAGES)
|
||||
* }}}
|
||||
*
|
||||
* To keep the code more readable, I18n constants are preferred over
|
||||
* hardcoded integers.
|
||||
*/
|
||||
/**
|
||||
* Constant for LC_ALL.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_ALL = 0;
|
||||
|
||||
/**
|
||||
* Constant for LC_COLLATE.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_COLLATE = 1;
|
||||
|
||||
/**
|
||||
* Constant for LC_CTYPE.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_CTYPE = 2;
|
||||
|
||||
/**
|
||||
* Constant for LC_MONETARY.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_MONETARY = 3;
|
||||
|
||||
/**
|
||||
* Constant for LC_NUMERIC.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_NUMERIC = 4;
|
||||
|
||||
/**
|
||||
* Constant for LC_TIME.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_TIME = 5;
|
||||
|
||||
/**
|
||||
* Constant for LC_MESSAGES.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const LC_MESSAGES = 6;
|
||||
|
||||
/**
|
||||
* Escape string
|
||||
*
|
||||
|
@ -129,7 +191,7 @@ class I18n {
|
|||
* @return string translated string.
|
||||
* @throws CakeException When '' is provided as a domain.
|
||||
*/
|
||||
public static function translate($singular, $plural = null, $domain = null, $category = 6, $count = null, $language = null) {
|
||||
public static function translate($singular, $plural = null, $domain = null, $category = self::LC_MESSAGES, $count = null, $language = null) {
|
||||
$_this = I18n::getInstance();
|
||||
|
||||
if (strpos($singular, "\r\n") !== false) {
|
||||
|
|
|
@ -370,18 +370,6 @@ class CakeLog {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the automatic/default stream a FileLog.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function _autoConfig() {
|
||||
self::$_Collection->load('default', array(
|
||||
'engine' => 'File',
|
||||
'path' => LOGS,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given message and type to all of the configured log adapters.
|
||||
* Configured adapters are passed both the $type and $message variables. $type
|
||||
|
@ -453,11 +441,7 @@ class CakeLog {
|
|||
$logged = true;
|
||||
}
|
||||
}
|
||||
if (!$logged) {
|
||||
self::_autoConfig();
|
||||
self::stream('default')->write($type, $message);
|
||||
}
|
||||
return true;
|
||||
return $logged;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,7 +67,7 @@ class TreeBehavior extends ModelBehavior {
|
|||
$config['type'] = $config[0];
|
||||
unset($config[0]);
|
||||
}
|
||||
$settings = array_merge($this->_defaults, $config);
|
||||
$settings = $config + $this->_defaults;
|
||||
|
||||
if (in_array($settings['scope'], $Model->getAssociated('belongsTo'))) {
|
||||
$data = $Model->getAssociated($settings['scope']);
|
||||
|
@ -744,7 +744,7 @@ class TreeBehavior extends ModelBehavior {
|
|||
* @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::reorder
|
||||
*/
|
||||
public function reorder(Model $Model, $options = array()) {
|
||||
$options = array_merge(array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true), $options);
|
||||
$options += array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true);
|
||||
extract($options);
|
||||
if ($verify && !$this->verify($Model)) {
|
||||
return false;
|
||||
|
|
|
@ -127,6 +127,13 @@ class CakeSession {
|
|||
*/
|
||||
protected static $_initialized = false;
|
||||
|
||||
/**
|
||||
* Session cookie name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_cookieName = null;
|
||||
|
||||
/**
|
||||
* Pseudo constructor.
|
||||
*
|
||||
|
@ -221,12 +228,10 @@ class CakeSession {
|
|||
* @return boolean True if variable is there
|
||||
*/
|
||||
public static function check($name = null) {
|
||||
if (!self::start()) {
|
||||
return false;
|
||||
}
|
||||
if (empty($name)) {
|
||||
if (empty($name) || !self::_hasSession() || !self::start()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Hash::get($_SESSION, $name) !== null;
|
||||
}
|
||||
|
||||
|
@ -320,7 +325,7 @@ class CakeSession {
|
|||
* @return boolean Success
|
||||
*/
|
||||
public static function valid() {
|
||||
if (self::read('Config')) {
|
||||
if (self::start() && self::read('Config')) {
|
||||
if (self::_validAgentAndTime() && self::$error === false) {
|
||||
self::$valid = true;
|
||||
} else {
|
||||
|
@ -368,18 +373,19 @@ class CakeSession {
|
|||
* Returns given session variable, or all of them, if no parameters given.
|
||||
*
|
||||
* @param string|array $name The name of the session variable (or a path as sent to Set.extract)
|
||||
* @return mixed The value of the session variable
|
||||
* @return mixed The value of the session variable, null if session not available,
|
||||
* session not started, or provided name not found in the session.
|
||||
*/
|
||||
public static function read($name = null) {
|
||||
if (!self::start()) {
|
||||
if (empty($name) && $name !== null) {
|
||||
return false;
|
||||
}
|
||||
if (!self::_hasSession() || !self::start()) {
|
||||
return null;
|
||||
}
|
||||
if ($name === null) {
|
||||
return self::_returnSessionVars();
|
||||
}
|
||||
if (empty($name)) {
|
||||
return false;
|
||||
}
|
||||
$result = Hash::get($_SESSION, $name);
|
||||
|
||||
if (isset($result)) {
|
||||
|
@ -409,12 +415,10 @@ class CakeSession {
|
|||
* @return boolean True if the write was successful, false if the write failed
|
||||
*/
|
||||
public static function write($name, $value = null) {
|
||||
if (!self::start()) {
|
||||
return false;
|
||||
}
|
||||
if (empty($name)) {
|
||||
if (empty($name) || !self::start()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$write = $name;
|
||||
if (!is_array($name)) {
|
||||
$write = array($name => $value);
|
||||
|
@ -442,6 +446,7 @@ class CakeSession {
|
|||
|
||||
$_SESSION = null;
|
||||
self::$id = null;
|
||||
self::$_cookieName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -481,9 +486,12 @@ class CakeSession {
|
|||
if (!isset($sessionConfig['ini']['session.cookie_lifetime'])) {
|
||||
$sessionConfig['ini']['session.cookie_lifetime'] = $sessionConfig['cookieTimeout'] * 60;
|
||||
}
|
||||
|
||||
if (!isset($sessionConfig['ini']['session.name'])) {
|
||||
$sessionConfig['ini']['session.name'] = $sessionConfig['cookie'];
|
||||
}
|
||||
self::$_cookieName = $sessionConfig['ini']['session.name'];
|
||||
|
||||
if (!empty($sessionConfig['handler'])) {
|
||||
$sessionConfig['ini']['session.save_handler'] = 'user';
|
||||
}
|
||||
|
@ -521,6 +529,30 @@ class CakeSession {
|
|||
self::$sessionTime = self::$time + ($sessionConfig['timeout'] * 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get session cookie name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _cookieName() {
|
||||
if (self::$_cookieName !== null) {
|
||||
return self::$_cookieName;
|
||||
}
|
||||
|
||||
self::init();
|
||||
self::_configureSession();
|
||||
|
||||
return self::$_cookieName = session_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a session exists
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function _hasSession() {
|
||||
return self::started() || isset($_COOKIE[self::_cookieName()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the handler class and make sure it implements the correct interface.
|
||||
*
|
||||
|
|
|
@ -183,12 +183,12 @@ class DataSource extends Object {
|
|||
*
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model The Model to be created.
|
||||
* @param Model $Model The Model to be created.
|
||||
* @param array $fields An Array of fields to be saved.
|
||||
* @param array $values An Array of values to save.
|
||||
* @return boolean success
|
||||
*/
|
||||
public function create(Model $model, $fields = null, $values = null) {
|
||||
public function create(Model $Model, $fields = null, $values = null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -197,12 +197,12 @@ class DataSource extends Object {
|
|||
*
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model The model being read.
|
||||
* @param Model $Model The model being read.
|
||||
* @param array $queryData An array of query data used to find the data you want
|
||||
* @param integer $recursive Number of levels of association
|
||||
* @return mixed
|
||||
*/
|
||||
public function read(Model $model, $queryData = array(), $recursive = null) {
|
||||
public function read(Model $Model, $queryData = array(), $recursive = null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -211,13 +211,13 @@ class DataSource extends Object {
|
|||
*
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model Instance of the model class being updated
|
||||
* @param Model $Model Instance of the model class being updated
|
||||
* @param array $fields Array of fields to be updated
|
||||
* @param array $values Array of values to be update $fields to.
|
||||
* @param mixed $conditions
|
||||
* @return boolean Success
|
||||
*/
|
||||
public function update(Model $model, $fields = null, $values = null, $conditions = null) {
|
||||
public function update(Model $Model, $fields = null, $values = null, $conditions = null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -226,11 +226,11 @@ class DataSource extends Object {
|
|||
*
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model The model class having record(s) deleted
|
||||
* @param Model $Model The model class having record(s) deleted
|
||||
* @param mixed $conditions The conditions to use for deleting.
|
||||
* @return boolean Success
|
||||
*/
|
||||
public function delete(Model $model, $conditions = null) {
|
||||
public function delete(Model $Model, $conditions = null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -318,95 +318,90 @@ class DataSource extends Object {
|
|||
*
|
||||
* @param string $query Query string needing replacements done.
|
||||
* @param array $data Array of data with values that will be inserted in placeholders.
|
||||
* @param string $association Name of association model being replaced
|
||||
* @param array $assocData
|
||||
* @param Model $model Instance of the model to replace $__cakeID__$
|
||||
* @param Model $linkModel Instance of model to replace $__cakeForeignKey__$
|
||||
* @param string $association Name of association model being replaced.
|
||||
* @param Model $Model Model instance.
|
||||
* @param array $stack
|
||||
* @return string String of query data with placeholders replaced.
|
||||
* @return mixed String of query data with placeholders replaced, or false on failure.
|
||||
*/
|
||||
public function insertQueryData($query, $data, $association, $assocData, Model $model, Model $linkModel, $stack) {
|
||||
public function insertQueryData($query, $data, $association, Model $Model, $stack) {
|
||||
$keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}');
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$val = null;
|
||||
$type = null;
|
||||
$modelAlias = $Model->alias;
|
||||
|
||||
if (strpos($query, $key) !== false) {
|
||||
foreach ($keys as $key) {
|
||||
if (strpos($query, $key) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$insertKey = $InsertModel = null;
|
||||
switch ($key) {
|
||||
case '{$__cakeID__$}':
|
||||
if (isset($data[$model->alias]) || isset($data[$association])) {
|
||||
if (isset($data[$model->alias][$model->primaryKey])) {
|
||||
$val = $data[$model->alias][$model->primaryKey];
|
||||
} elseif (isset($data[$association][$model->primaryKey])) {
|
||||
$val = $data[$association][$model->primaryKey];
|
||||
}
|
||||
} else {
|
||||
$found = false;
|
||||
foreach (array_reverse($stack) as $assoc) {
|
||||
if (isset($data[$assoc]) && isset($data[$assoc][$model->primaryKey])) {
|
||||
$val = $data[$assoc][$model->primaryKey];
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$val = '';
|
||||
}
|
||||
}
|
||||
$type = $model->getColumnType($model->primaryKey);
|
||||
$InsertModel = $Model;
|
||||
$insertKey = $Model->primaryKey;
|
||||
|
||||
break;
|
||||
case '{$__cakeForeignKey__$}':
|
||||
foreach ($model->associations() as $name) {
|
||||
foreach ($model->$name as $assocName => $assoc) {
|
||||
if ($assocName === $association) {
|
||||
if (isset($assoc['foreignKey'])) {
|
||||
$foreignKey = $assoc['foreignKey'];
|
||||
$assocModel = $model->$assocName;
|
||||
$type = $assocModel->getColumnType($assocModel->primaryKey);
|
||||
foreach ($Model->associations() as $type) {
|
||||
foreach ($Model->{$type} as $assoc => $assocData) {
|
||||
if ($assoc !== $association) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($data[$model->alias][$foreignKey])) {
|
||||
$val = $data[$model->alias][$foreignKey];
|
||||
} elseif (isset($data[$association][$foreignKey])) {
|
||||
$val = $data[$association][$foreignKey];
|
||||
} else {
|
||||
$found = false;
|
||||
foreach (array_reverse($stack) as $assoc) {
|
||||
if (isset($data[$assoc]) && isset($data[$assoc][$foreignKey])) {
|
||||
$val = $data[$assoc][$foreignKey];
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$val = '';
|
||||
}
|
||||
}
|
||||
if (isset($assocData['foreignKey'])) {
|
||||
$InsertModel = $Model->{$assoc};
|
||||
$insertKey = $assocData['foreignKey'];
|
||||
}
|
||||
|
||||
break 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$val = $dataType = null;
|
||||
if (!empty($insertKey) && !empty($InsertModel)) {
|
||||
if (isset($data[$modelAlias][$insertKey])) {
|
||||
$val = $data[$modelAlias][$insertKey];
|
||||
} elseif (isset($data[$association][$insertKey])) {
|
||||
$val = $data[$association][$insertKey];
|
||||
} else {
|
||||
$found = false;
|
||||
foreach (array_reverse($stack) as $assocData) {
|
||||
if (isset($data[$assocData]) && isset($data[$assocData][$insertKey])) {
|
||||
$val = $data[$assocData][$insertKey];
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$val = '';
|
||||
}
|
||||
}
|
||||
|
||||
$dataType = $InsertModel->getColumnType($InsertModel->primaryKey);
|
||||
}
|
||||
|
||||
if (empty($val) && $val !== '0') {
|
||||
return false;
|
||||
}
|
||||
$query = str_replace($key, $this->value($val, $type), $query);
|
||||
}
|
||||
|
||||
$query = str_replace($key, $this->value($val, $dataType), $query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* To-be-overridden in subclasses.
|
||||
*
|
||||
* @param Model $model Model instance
|
||||
* @param Model $Model Model instance
|
||||
* @param string $key Key name to make
|
||||
* @return string Key name for model.
|
||||
*/
|
||||
public function resolveKey(Model $model, $key) {
|
||||
return $model->alias . $key;
|
||||
public function resolveKey(Model $Model, $key) {
|
||||
return $Model->alias . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -45,7 +45,8 @@ class Mysql extends DboSource {
|
|||
'login' => 'root',
|
||||
'password' => '',
|
||||
'database' => 'cake',
|
||||
'port' => '3306'
|
||||
'port' => '3306',
|
||||
'flags' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -84,7 +85,13 @@ class Mysql extends DboSource {
|
|||
public $fieldParameters = array(
|
||||
'charset' => array('value' => 'CHARACTER SET', 'quote' => false, 'join' => ' ', 'column' => false, 'position' => 'beforeDefault'),
|
||||
'collate' => array('value' => 'COLLATE', 'quote' => false, 'join' => ' ', 'column' => 'Collation', 'position' => 'beforeDefault'),
|
||||
'comment' => array('value' => 'COMMENT', 'quote' => true, 'join' => ' ', 'column' => 'Comment', 'position' => 'afterDefault')
|
||||
'comment' => array('value' => 'COMMENT', 'quote' => true, 'join' => ' ', 'column' => 'Comment', 'position' => 'afterDefault'),
|
||||
'unsigned' => array(
|
||||
'value' => 'UNSIGNED', 'quote' => false, 'join' => ' ', 'column' => false, 'position' => 'beforeDefault',
|
||||
'noVal' => true,
|
||||
'options' => array(true),
|
||||
'types' => array('integer', 'float', 'decimal', 'biginteger')
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -110,6 +117,7 @@ class Mysql extends DboSource {
|
|||
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
|
||||
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
|
||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'),
|
||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
|
||||
|
@ -144,7 +152,7 @@ class Mysql extends DboSource {
|
|||
$config = $this->config;
|
||||
$this->connected = false;
|
||||
|
||||
$flags = array(
|
||||
$flags = $config['flags'] + array(
|
||||
PDO::ATTR_PERSISTENT => $config['persistent'],
|
||||
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
|
@ -338,8 +346,11 @@ class Mysql extends DboSource {
|
|||
'type' => $this->column($column->Type),
|
||||
'null' => ($column->Null === 'YES' ? true : false),
|
||||
'default' => $column->Default,
|
||||
'length' => $this->length($column->Type),
|
||||
'length' => $this->length($column->Type)
|
||||
);
|
||||
if (in_array($fields[$column->Field]['type'], $this->fieldParameters['unsigned']['types'], true)) {
|
||||
$fields[$column->Field]['unsigned'] = $this->_unsigned($column->Type);
|
||||
}
|
||||
if (!empty($column->Key) && isset($this->index[$column->Key])) {
|
||||
$fields[$column->Field]['key'] = $this->index[$column->Key];
|
||||
}
|
||||
|
@ -761,9 +772,12 @@ class Mysql extends DboSource {
|
|||
if (strpos($col, 'blob') !== false || $col === 'binary') {
|
||||
return 'binary';
|
||||
}
|
||||
if (strpos($col, 'float') !== false || strpos($col, 'double') !== false || strpos($col, 'decimal') !== false) {
|
||||
if (strpos($col, 'float') !== false || strpos($col, 'double') !== false) {
|
||||
return 'float';
|
||||
}
|
||||
if (strpos($col, 'decimal') !== false || strpos($col, 'numeric') !== false) {
|
||||
return 'decimal';
|
||||
}
|
||||
if (strpos($col, 'enum') !== false) {
|
||||
return "enum($vals)";
|
||||
}
|
||||
|
@ -788,4 +802,14 @@ class Mysql extends DboSource {
|
|||
return $this->useNestedTransactions && version_compare($this->getVersion(), '4.1', '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if column type is unsigned
|
||||
*
|
||||
* @param string $real Real database-layer column type (i.e. "varchar(255)")
|
||||
* @return bool True if column is unsigned, false otherwise
|
||||
*/
|
||||
protected function _unsigned($real) {
|
||||
return strpos(strtolower($real), 'unsigned') !== false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ class Postgres extends DboSource {
|
|||
'database' => 'cake',
|
||||
'schema' => 'public',
|
||||
'port' => 5432,
|
||||
'encoding' => ''
|
||||
'encoding' => '',
|
||||
'flags' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -60,6 +61,7 @@ class Postgres extends DboSource {
|
|||
'integer' => array('name' => 'integer', 'formatter' => 'intval'),
|
||||
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
|
||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'),
|
||||
'datetime' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
|
||||
|
@ -109,7 +111,7 @@ class Postgres extends DboSource {
|
|||
$config = $this->config;
|
||||
$this->connected = false;
|
||||
|
||||
$flags = array(
|
||||
$flags = $config['flags'] + array(
|
||||
PDO::ATTR_PERSISTENT => $config['persistent'],
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
|
@ -675,7 +677,7 @@ class Postgres extends DboSource {
|
|||
}
|
||||
|
||||
$floats = array(
|
||||
'float', 'float4', 'float8', 'double', 'double precision', 'decimal', 'real', 'numeric'
|
||||
'float', 'float4', 'float8', 'double', 'double precision', 'real'
|
||||
);
|
||||
|
||||
switch (true) {
|
||||
|
@ -695,6 +697,8 @@ class Postgres extends DboSource {
|
|||
return 'text';
|
||||
case (strpos($col, 'bytea') !== false):
|
||||
return 'binary';
|
||||
case ($col === 'decimal' || $col === 'numeric'):
|
||||
return 'decimal';
|
||||
case (in_array($col, $floats)):
|
||||
return 'float';
|
||||
default:
|
||||
|
|
|
@ -56,7 +56,8 @@ class Sqlite extends DboSource {
|
|||
*/
|
||||
protected $_baseConfig = array(
|
||||
'persistent' => false,
|
||||
'database' => null
|
||||
'database' => null,
|
||||
'flags' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -71,6 +72,7 @@ class Sqlite extends DboSource {
|
|||
'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'),
|
||||
'biginteger' => array('name' => 'bigint', 'limit' => 20),
|
||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'),
|
||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
|
||||
|
@ -105,7 +107,7 @@ class Sqlite extends DboSource {
|
|||
*/
|
||||
public function connect() {
|
||||
$config = $this->config;
|
||||
$flags = array(
|
||||
$flags = $config['flags'] + array(
|
||||
PDO::ATTR_PERSISTENT => $config['persistent'],
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
|
@ -277,7 +279,7 @@ class Sqlite extends DboSource {
|
|||
return 'binary';
|
||||
}
|
||||
if (strpos($col, 'numeric') !== false || strpos($col, 'decimal') !== false) {
|
||||
return 'float';
|
||||
return 'decimal';
|
||||
}
|
||||
return 'text';
|
||||
}
|
||||
|
@ -393,7 +395,7 @@ class Sqlite extends DboSource {
|
|||
*/
|
||||
public function buildColumn($column) {
|
||||
$name = $type = null;
|
||||
$column = array_merge(array('null' => true), $column);
|
||||
$column += array('null' => true);
|
||||
extract($column);
|
||||
|
||||
if (empty($name) || empty($type)) {
|
||||
|
|
|
@ -78,6 +78,7 @@ class Sqlserver extends DboSource {
|
|||
'password' => '',
|
||||
'database' => 'cake',
|
||||
'schema' => '',
|
||||
'flags' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -91,7 +92,10 @@ class Sqlserver extends DboSource {
|
|||
'text' => array('name' => 'nvarchar', 'limit' => 'MAX'),
|
||||
'integer' => array('name' => 'int', 'formatter' => 'intval'),
|
||||
'biginteger' => array('name' => 'bigint'),
|
||||
'float' => array('name' => 'numeric', 'formatter' => 'floatval'),
|
||||
'numeric' => array('name' => 'decimal', 'formatter' => 'floatval'),
|
||||
'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'),
|
||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'real' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||
'time' => array('name' => 'datetime', 'format' => 'H:i:s', 'formatter' => 'date'),
|
||||
|
@ -118,7 +122,7 @@ class Sqlserver extends DboSource {
|
|||
$config = $this->config;
|
||||
$this->connected = false;
|
||||
|
||||
$flags = array(
|
||||
$flags = $config['flags'] + array(
|
||||
PDO::ATTR_PERSISTENT => $config['persistent'],
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
|
@ -204,7 +208,7 @@ class Sqlserver extends DboSource {
|
|||
}
|
||||
|
||||
$fields = array();
|
||||
$schema = $model->schemaName;
|
||||
$schema = is_object($model) ? $model->schemaName : false;
|
||||
|
||||
$cols = $this->_execute(
|
||||
"SELECT
|
||||
|
@ -446,9 +450,12 @@ class Sqlserver extends DboSource {
|
|||
if (strpos($col, 'binary') !== false || $col === 'image') {
|
||||
return 'binary';
|
||||
}
|
||||
if (in_array($col, array('float', 'real', 'decimal', 'numeric'))) {
|
||||
if (in_array($col, array('float', 'real'))) {
|
||||
return 'float';
|
||||
}
|
||||
if (in_array($col, array('decimal', 'numeric'))) {
|
||||
return 'decimal';
|
||||
}
|
||||
return 'text';
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -952,9 +952,11 @@ class Model extends Object implements CakeEventListener {
|
|||
* Example: Turn off the associated Model Support request,
|
||||
* to temporarily lighten the User model:
|
||||
*
|
||||
* `$this->User->unbindModel(array('hasMany' => array('Supportrequest')));`
|
||||
* `$this->User->unbindModel(array('hasMany' => array('SupportRequest')));`
|
||||
* Or alternatively:
|
||||
* `$this->User->unbindModel(array('hasMany' => 'SupportRequest'));`
|
||||
*
|
||||
* unbound models that are not made permanent will reset with the next call to Model::find()
|
||||
* Unbound models that are not made permanent will reset with the next call to Model::find()
|
||||
*
|
||||
* @param array $params Set of bindings to unbind (indexed by binding type)
|
||||
* @param boolean $reset Set to false to make the unbinding permanent
|
||||
|
@ -966,7 +968,7 @@ class Model extends Object implements CakeEventListener {
|
|||
if ($reset === true && !isset($this->__backAssociation[$assoc])) {
|
||||
$this->__backAssociation[$assoc] = $this->{$assoc};
|
||||
}
|
||||
|
||||
$models = Hash::normalize((array)$models, false);
|
||||
foreach ($models as $model) {
|
||||
if ($reset === false && isset($this->__backAssociation[$assoc][$model])) {
|
||||
unset($this->__backAssociation[$assoc][$model]);
|
||||
|
@ -1661,7 +1663,7 @@ class Model extends Object implements CakeEventListener {
|
|||
|
||||
$options = array('validate' => $validate, 'fieldList' => array($name));
|
||||
if (is_array($validate)) {
|
||||
$options = array_merge(array('validate' => false, 'fieldList' => array($name)), $validate);
|
||||
$options = $validate + array('validate' => false, 'fieldList' => array($name));
|
||||
}
|
||||
|
||||
return $this->save(array($this->alias => array($this->primaryKey => $id, $name => $value)), $options);
|
||||
|
@ -1695,9 +1697,9 @@ class Model extends Object implements CakeEventListener {
|
|||
$fields = array();
|
||||
|
||||
if (!is_array($validate)) {
|
||||
$options = array_merge($defaults, compact('validate', 'fieldList'));
|
||||
$options = compact('validate', 'fieldList') + $defaults;
|
||||
} else {
|
||||
$options = array_merge($defaults, $validate);
|
||||
$options = $validate + $defaults;
|
||||
}
|
||||
|
||||
if (!empty($options['fieldList'])) {
|
||||
|
@ -2162,7 +2164,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array
|
||||
*/
|
||||
public function saveAll($data = array(), $options = array()) {
|
||||
$options = array_merge(array('validate' => 'first'), $options);
|
||||
$options += array('validate' => 'first');
|
||||
if (Hash::numeric(array_keys($data))) {
|
||||
if ($options['validate'] === 'only') {
|
||||
return $this->validateMany($data, $options);
|
||||
|
@ -2204,7 +2206,7 @@ class Model extends Object implements CakeEventListener {
|
|||
$data = $this->data;
|
||||
}
|
||||
|
||||
$options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
|
||||
$options += array('validate' => 'first', 'atomic' => true, 'deep' => false);
|
||||
$this->validationErrors = $validationErrors = array();
|
||||
|
||||
if (empty($data) && $options['validate'] !== false) {
|
||||
|
@ -2326,7 +2328,7 @@ class Model extends Object implements CakeEventListener {
|
|||
$data = $this->data;
|
||||
}
|
||||
|
||||
$options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
|
||||
$options += array('validate' => 'first', 'atomic' => true, 'deep' => false);
|
||||
$this->validationErrors = $validationErrors = array();
|
||||
|
||||
if (empty($data) && $options['validate'] !== false) {
|
||||
|
@ -2367,9 +2369,9 @@ class Model extends Object implements CakeEventListener {
|
|||
$saved = false;
|
||||
if ($validates) {
|
||||
if ($options['deep']) {
|
||||
$saved = $Model->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
||||
$saved = $Model->saveAssociated($values, array('atomic' => false) + $options);
|
||||
} else {
|
||||
$saved = $Model->save($values, array_merge($options, array('atomic' => false)));
|
||||
$saved = $Model->save($values, array('atomic' => false) + $options);
|
||||
}
|
||||
$validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
|
||||
}
|
||||
|
@ -2423,7 +2425,7 @@ class Model extends Object implements CakeEventListener {
|
|||
if ($validates) {
|
||||
$options = $Model->_addToWhiteList($key, $options);
|
||||
if ($options['deep']) {
|
||||
$saved = $Model->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
||||
$saved = $Model->saveAssociated($values, array('atomic' => false) + $options);
|
||||
} else {
|
||||
$saved = $Model->save($values, $options);
|
||||
}
|
||||
|
@ -2446,7 +2448,7 @@ class Model extends Object implements CakeEventListener {
|
|||
}
|
||||
|
||||
$options = $Model->_addToWhiteList($key, $options);
|
||||
$_return = $Model->saveMany($values, array_merge($options, array('atomic' => false)));
|
||||
$_return = $Model->saveMany($values, array('atomic' => false) + $options);
|
||||
if (in_array(false, $_return, true)) {
|
||||
$validationErrors[$association] = $Model->validationErrors;
|
||||
$validates = false;
|
||||
|
|
|
@ -127,7 +127,7 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
|
|||
*/
|
||||
public function validateAssociated(&$data, $options = array()) {
|
||||
$model = $this->getModel();
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$options += array('atomic' => true, 'deep' => false);
|
||||
$model->validationErrors = $validationErrors = $return = array();
|
||||
$model->create(null);
|
||||
$return[$model->alias] = true;
|
||||
|
@ -204,7 +204,7 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
|
|||
*/
|
||||
public function validateMany(&$data, $options = array()) {
|
||||
$model = $this->getModel();
|
||||
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
||||
$options += array('atomic' => true, 'deep' => false);
|
||||
$model->validationErrors = $validationErrors = $return = array();
|
||||
foreach ($data as $key => &$record) {
|
||||
if ($options['deep']) {
|
||||
|
@ -247,7 +247,15 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
|
|||
return $model->validationErrors;
|
||||
}
|
||||
|
||||
$fieldList = isset($options['fieldList']) ? $options['fieldList'] : array();
|
||||
$fieldList = $model->whitelist;
|
||||
if (empty($fieldList) && !empty($options['fieldList'])) {
|
||||
if (!empty($options['fieldList'][$model->alias]) && is_array($options['fieldList'][$model->alias])) {
|
||||
$fieldList = $options['fieldList'][$model->alias];
|
||||
} else {
|
||||
$fieldList = $options['fieldList'];
|
||||
}
|
||||
}
|
||||
|
||||
$exists = $model->exists();
|
||||
$methods = $this->getMethods();
|
||||
$fields = $this->_validationList($fieldList);
|
||||
|
@ -374,32 +382,19 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Processes the Model's whitelist or passed fieldList and returns the list of fields
|
||||
* to be validated
|
||||
* Processes the passed fieldList and returns the list of fields to be validated
|
||||
*
|
||||
* @param array $fieldList list of fields to be used for validation
|
||||
* @return array List of validation rules to be applied
|
||||
*/
|
||||
protected function _validationList($fieldList = array()) {
|
||||
$model = $this->getModel();
|
||||
$whitelist = $model->whitelist;
|
||||
|
||||
if (!empty($fieldList)) {
|
||||
if (!empty($fieldList[$model->alias]) && is_array($fieldList[$model->alias])) {
|
||||
$whitelist = $fieldList[$model->alias];
|
||||
} else {
|
||||
$whitelist = $fieldList;
|
||||
}
|
||||
}
|
||||
unset($fieldList);
|
||||
|
||||
if (empty($whitelist) || Hash::dimensions($whitelist) > 1) {
|
||||
if (empty($fieldList) || Hash::dimensions($fieldList) > 1) {
|
||||
return $this->_fields;
|
||||
}
|
||||
|
||||
$validateList = array();
|
||||
$this->validationErrors = array();
|
||||
foreach ((array)$whitelist as $f) {
|
||||
foreach ((array)$fieldList as $f) {
|
||||
if (!empty($this->_fields[$f])) {
|
||||
$validateList[$f] = $this->_fields[$f];
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ class Permission extends AppModel {
|
|||
$acoPath = $this->Aco->node($aco);
|
||||
|
||||
if (!$aroPath) {
|
||||
trigger_error(__d('cake_dev',
|
||||
$this->log(__d('cake_dev',
|
||||
"%s - Failed ARO node lookup in permissions check. Node references:\nAro: %s\nAco: %s",
|
||||
'DbAcl::check()',
|
||||
print_r($aro, true),
|
||||
|
@ -94,7 +94,7 @@ class Permission extends AppModel {
|
|||
}
|
||||
|
||||
if (!$acoPath) {
|
||||
trigger_error(__d('cake_dev',
|
||||
$this->log(__d('cake_dev',
|
||||
"%s - Failed ACO node lookup in permissions check. Node references:\nAro: %s\nAco: %s",
|
||||
'DbAcl::check()',
|
||||
print_r($aro, true),
|
||||
|
@ -105,7 +105,7 @@ class Permission extends AppModel {
|
|||
}
|
||||
|
||||
if ($action !== '*' && !in_array('_' . $action, $permKeys)) {
|
||||
trigger_error(__d('cake_dev', "ACO permissions key %s does not exist in %s", $action, 'DbAcl::check()'), E_USER_NOTICE);
|
||||
$this->log(__d('cake_dev', "ACO permissions key %s does not exist in %s", $action, 'DbAcl::check()'), E_USER_NOTICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ class Permission extends AppModel {
|
|||
$save = array();
|
||||
|
||||
if (!$perms) {
|
||||
trigger_error(__d('cake_dev', '%s - Invalid node', 'DbAcl::allow()'), E_USER_WARNING);
|
||||
$this->log(__d('cake_dev', '%s - Invalid node', 'DbAcl::allow()'), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (isset($perms[0])) {
|
||||
|
|
|
@ -325,7 +325,12 @@ class CakeValidationSet implements ArrayAccess, IteratorAggregate, Countable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets or replace a validation rule
|
||||
* Sets or replace a validation rule.
|
||||
*
|
||||
* This is a wrapper for ArrayAccess. Use setRule() directly for
|
||||
* chainable access.
|
||||
*
|
||||
* @see http://www.php.net/manual/en/arrayobject.offsetset.php
|
||||
*
|
||||
* @param string $index name of the rule
|
||||
* @param CakeValidationRule|array rule to add to $index
|
||||
|
|
|
@ -512,9 +512,14 @@ class CakeRequest implements ArrayAccess {
|
|||
}
|
||||
if (isset($detect['param'])) {
|
||||
$key = $detect['param'];
|
||||
if (isset($detect['value'])) {
|
||||
$value = $detect['value'];
|
||||
return isset($this->params[$key]) ? $this->params[$key] == $value : false;
|
||||
}
|
||||
if (isset($detect['options'])) {
|
||||
return isset($this->params[$key]) ? in_array($this->params[$key], $detect['options']) : false;
|
||||
}
|
||||
}
|
||||
if (isset($detect['callback']) && is_callable($detect['callback'])) {
|
||||
return call_user_func($detect['callback'], $this);
|
||||
}
|
||||
|
@ -572,7 +577,13 @@ class CakeRequest implements ArrayAccess {
|
|||
*
|
||||
* Allows for custom detectors on the request parameters.
|
||||
*
|
||||
* e.g `addDetector('post', array('param' => 'requested', 'value' => 1)`
|
||||
* e.g `addDetector('requested', array('param' => 'requested', 'value' => 1)`
|
||||
*
|
||||
* You can also make parameter detectors that accept multiple values
|
||||
* using the `options` key. This is useful when you want to check
|
||||
* if a request parameter is in a list of options.
|
||||
*
|
||||
* `addDetector('extension', array('param' => 'ext', 'options' => array('pdf', 'csv'))`
|
||||
*
|
||||
* @param string $name The name of the detector.
|
||||
* @param array $options The options for the detector definition. See above.
|
||||
|
@ -900,23 +911,23 @@ class CakeRequest implements ArrayAccess {
|
|||
}
|
||||
|
||||
/**
|
||||
* Only allow certain HTTP request methods, if the request method does not match
|
||||
* Allow only certain HTTP request methods. If the request method does not match
|
||||
* a 405 error will be shown and the required "Allow" response header will be set.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* $this->request->onlyAllow('post', 'delete');
|
||||
* $this->request->allowMethod('post', 'delete');
|
||||
* or
|
||||
* $this->request->onlyAllow(array('post', 'delete'));
|
||||
* $this->request->allowMethod(array('post', 'delete'));
|
||||
*
|
||||
* If the request would be GET, response header "Allow: POST, DELETE" will be set
|
||||
* and a 405 error will be returned
|
||||
* and a 405 error will be returned.
|
||||
*
|
||||
* @param string|array $methods Allowed HTTP request methods
|
||||
* @param string|array $methods Allowed HTTP request methods.
|
||||
* @return boolean true
|
||||
* @throws MethodNotAllowedException
|
||||
*/
|
||||
public function onlyAllow($methods) {
|
||||
public function allowMethod($methods) {
|
||||
if (!is_array($methods)) {
|
||||
$methods = func_get_args();
|
||||
}
|
||||
|
@ -931,6 +942,22 @@ class CakeRequest implements ArrayAccess {
|
|||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of CakeRequest::allowMethod() for backwards compatibility.
|
||||
*
|
||||
* @see CakeRequest::allowMethod()
|
||||
* @deprecated 2.5 Use CakeRequest::allowMethod() instead.
|
||||
* @param string|array $methods Allowed HTTP request methods.
|
||||
* @return boolean true
|
||||
* @throws MethodNotAllowedException
|
||||
*/
|
||||
public function onlyAllow($methods) {
|
||||
if (!is_array($methods)) {
|
||||
$methods = func_get_args();
|
||||
}
|
||||
return $this->allowMethod($methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read data from php://input, mocked in tests.
|
||||
*
|
||||
|
|
|
@ -379,6 +379,7 @@ class CakeResponse {
|
|||
*
|
||||
* @param array $options list of parameters to setup the response. Possible values are:
|
||||
* - body: the response text that should be sent to the client
|
||||
* - statusCodes: additional allowable response codes
|
||||
* - status: the HTTP status code to respond with
|
||||
* - type: a complete mime-type string or an extension mapped in this class
|
||||
* - charset: the charset for the response body
|
||||
|
@ -387,6 +388,9 @@ class CakeResponse {
|
|||
if (isset($options['body'])) {
|
||||
$this->body($options['body']);
|
||||
}
|
||||
if (isset($options['statusCodes'])) {
|
||||
$this->httpCodes($options['statusCodes']);
|
||||
}
|
||||
if (isset($options['status'])) {
|
||||
$this->statusCode($options['status']);
|
||||
}
|
||||
|
@ -1236,6 +1240,75 @@ class CakeResponse {
|
|||
$this->_cookies[$options['name']] = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup access for origin and methods on cross origin requests
|
||||
*
|
||||
* This method allow multiple ways to setup the domains, see the examples
|
||||
*
|
||||
* ### Full URI
|
||||
* e.g `cors($request, 'http://www.cakephp.org');`
|
||||
*
|
||||
* ### URI with wildcard
|
||||
* e.g `cors($request, 'http://*.cakephp.org');`
|
||||
*
|
||||
* ### Ignoring the requested protocol
|
||||
* e.g `cors($request, 'www.cakephp.org');`
|
||||
*
|
||||
* ### Any URI
|
||||
* e.g `cors($request, '*');`
|
||||
*
|
||||
* ### Whitelist of URIs
|
||||
* e.g `cors($request, array('http://www.cakephp.org', '*.google.com', 'https://myproject.github.io'));`
|
||||
*
|
||||
* @param CakeRequest $request Request object
|
||||
* @param string|array $allowedDomains List of allowed domains, see method description for more details
|
||||
* @param string|array $allowedMethods List of HTTP verbs allowed
|
||||
* @param string|array $allowedHeaders List of HTTP headers allowed
|
||||
* @return void
|
||||
*/
|
||||
public function cors(CakeRequest $request, $allowedDomains, $allowedMethods = array(), $allowedHeaders = array()) {
|
||||
$origin = $request->header('Origin');
|
||||
if (!$origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
$allowedDomains = $this->_normalizeCorsDomains((array)$allowedDomains, $request->is('ssl'));
|
||||
foreach ($allowedDomains as $domain) {
|
||||
if (!preg_match($domain['preg'], $origin)) {
|
||||
continue;
|
||||
}
|
||||
$this->header('Access-Control-Allow-Origin', $domain['original'] === '*' ? '*' : $origin);
|
||||
$allowedMethods && $this->header('Access-Control-Allow-Methods', implode(', ', (array)$allowedMethods));
|
||||
$allowedHeaders && $this->header('Access-Control-Allow-Headers', implode(', ', (array)$allowedHeaders));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the origin to regular expressions and put in an array format
|
||||
*
|
||||
* @param array $domains
|
||||
* @param boolean $requestIsSSL
|
||||
* @return array
|
||||
*/
|
||||
protected function _normalizeCorsDomains($domains, $requestIsSSL = false) {
|
||||
$result = array();
|
||||
foreach ($domains as $domain) {
|
||||
if ($domain === '*') {
|
||||
$result[] = array('preg' => '@.@', 'original' => '*');
|
||||
continue;
|
||||
}
|
||||
|
||||
$original = $preg = $domain;
|
||||
if (strpos($domain, '://') === false) {
|
||||
$preg = ($requestIsSSL ? 'https://' : 'http://') . $domain;
|
||||
}
|
||||
$preg = '@' . str_replace('*', '.*', $domain) . '@';
|
||||
$result[] = compact('original', 'preg');
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup for display or download the given file.
|
||||
*
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Validation', 'Utility');
|
||||
App::uses('Multibyte', 'I18n');
|
||||
App::uses('AbstractTransport', 'Network/Email');
|
||||
App::uses('File', 'Utility');
|
||||
|
@ -315,7 +314,7 @@ class CakeEmail {
|
|||
|
||||
/**
|
||||
* Regex for email validation
|
||||
* If null, it will use built in regex
|
||||
* If null, filter_var() will be used.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
@ -552,13 +551,10 @@ class CakeEmail {
|
|||
* @param string|array $email
|
||||
* @param string $name
|
||||
* @return CakeEmail $this
|
||||
* @throws SocketException
|
||||
*/
|
||||
protected function _setEmail($varName, $email, $name) {
|
||||
if (!is_array($email)) {
|
||||
if (!Validation::email($email, false, $this->_emailPattern)) {
|
||||
throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email));
|
||||
}
|
||||
$this->_validateEmail($email);
|
||||
if ($name === null) {
|
||||
$name = $email;
|
||||
}
|
||||
|
@ -570,15 +566,30 @@ class CakeEmail {
|
|||
if (is_int($key)) {
|
||||
$key = $value;
|
||||
}
|
||||
if (!Validation::email($key, false, $this->_emailPattern)) {
|
||||
throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $key));
|
||||
}
|
||||
$this->_validateEmail($key);
|
||||
$list[$key] = $value;
|
||||
}
|
||||
$this->{$varName} = $list;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate email address
|
||||
*
|
||||
* @param string $email
|
||||
* @return void
|
||||
* @throws SocketException If email address does not validate
|
||||
*/
|
||||
protected function _validateEmail($email) {
|
||||
$valid = (($this->_emailPattern !== null &&
|
||||
preg_match($this->_emailPattern, $email)) ||
|
||||
filter_var($email, FILTER_VALIDATE_EMAIL)
|
||||
);
|
||||
if (!$valid) {
|
||||
throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set only 1 email
|
||||
*
|
||||
|
@ -610,9 +621,7 @@ class CakeEmail {
|
|||
*/
|
||||
protected function _addEmail($varName, $email, $name) {
|
||||
if (!is_array($email)) {
|
||||
if (!Validation::email($email, false, $this->_emailPattern)) {
|
||||
throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email));
|
||||
}
|
||||
$this->_validateEmail($email);
|
||||
if ($name === null) {
|
||||
$name = $email;
|
||||
}
|
||||
|
@ -624,9 +633,7 @@ class CakeEmail {
|
|||
if (is_int($key)) {
|
||||
$key = $value;
|
||||
}
|
||||
if (!Validation::email($key, false, $this->_emailPattern)) {
|
||||
throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $key));
|
||||
}
|
||||
$this->_validateEmail($key);
|
||||
$list[$key] = $value;
|
||||
}
|
||||
$this->{$varName} = array_merge($this->{$varName}, $list);
|
||||
|
@ -1128,7 +1135,7 @@ class CakeEmail {
|
|||
if (!is_array($this->_config['log'])) {
|
||||
$this->_config['log'] = array('level' => $this->_config['log']);
|
||||
}
|
||||
$config = array_merge($config, $this->_config['log']);
|
||||
$config = $this->_config['log'] + $config;
|
||||
}
|
||||
CakeLog::write(
|
||||
$config['level'],
|
||||
|
@ -1192,7 +1199,7 @@ class CakeEmail {
|
|||
}
|
||||
$config = $configs->{$config};
|
||||
}
|
||||
$this->_config = array_merge($this->_config, $config);
|
||||
$this->_config = $config + $this->_config;
|
||||
if (!empty($config['charset'])) {
|
||||
$this->charset = $config['charset'];
|
||||
}
|
||||
|
@ -1217,15 +1224,14 @@ class CakeEmail {
|
|||
$this->setHeaders($config['headers']);
|
||||
unset($config['headers']);
|
||||
}
|
||||
|
||||
if (array_key_exists('template', $config)) {
|
||||
$layout = false;
|
||||
$this->_template = $config['template'];
|
||||
}
|
||||
if (array_key_exists('layout', $config)) {
|
||||
$layout = $config['layout'];
|
||||
unset($config['layout']);
|
||||
}
|
||||
$this->template($config['template'], $layout);
|
||||
unset($config['template']);
|
||||
$this->_layout = $config['layout'];
|
||||
}
|
||||
|
||||
$this->transportClass()->config($config);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,42 @@ class SmtpTransport extends AbstractTransport {
|
|||
*/
|
||||
protected $_content;
|
||||
|
||||
/**
|
||||
* The response of the last sent SMTP command.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_lastResponse = array();
|
||||
|
||||
/**
|
||||
* Returns the response of the last sent SMTP command.
|
||||
*
|
||||
* A response consists of one or more lines containing a response
|
||||
* code and an optional response message text:
|
||||
* {{{
|
||||
* array(
|
||||
* array(
|
||||
* 'code' => '250',
|
||||
* 'message' => 'mail.example.com'
|
||||
* ),
|
||||
* array(
|
||||
* 'code' => '250',
|
||||
* 'message' => 'PIPELINING'
|
||||
* ),
|
||||
* array(
|
||||
* 'code' => '250',
|
||||
* 'message' => '8BITMIME'
|
||||
* ),
|
||||
* // etc...
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLastResponse() {
|
||||
return $this->_lastResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail
|
||||
*
|
||||
|
@ -88,6 +124,25 @@ class SmtpTransport extends AbstractTransport {
|
|||
return $this->_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and stores the reponse lines in `'code' => 'message'` format.
|
||||
*
|
||||
* @param array $responseLines
|
||||
* @return void
|
||||
*/
|
||||
protected function _bufferResponseLines(array $responseLines) {
|
||||
$response = array();
|
||||
foreach ($responseLines as $responseLine) {
|
||||
if (preg_match('/^(\d{3})(?:[ -]+(.*))?$/', $responseLine, $match)) {
|
||||
$response[] = array(
|
||||
'code' => $match[1],
|
||||
'message' => isset($match[2]) ? $match[2] : null
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->_lastResponse = array_merge($this->_lastResponse, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to SMTP Server
|
||||
*
|
||||
|
@ -152,6 +207,78 @@ class SmtpTransport extends AbstractTransport {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the `MAIL FROM` SMTP command.
|
||||
*
|
||||
* @param string $email The email address to send with the command.
|
||||
* @return string
|
||||
*/
|
||||
protected function _prepareFromCmd($email) {
|
||||
return 'MAIL FROM:<' . $email . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the `RCPT TO` SMTP command.
|
||||
*
|
||||
* @param string $email The email address to send with the command.
|
||||
* @return string
|
||||
*/
|
||||
protected function _prepareRcptCmd($email) {
|
||||
return 'RCPT TO:<' . $email . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the `from` email address.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepareFromAddress() {
|
||||
$from = $this->_cakeEmail->returnPath();
|
||||
if (empty($from)) {
|
||||
$from = $this->_cakeEmail->from();
|
||||
}
|
||||
return $from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the recipient email addresses.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepareRecipientAddresses() {
|
||||
$to = $this->_cakeEmail->to();
|
||||
$cc = $this->_cakeEmail->cc();
|
||||
$bcc = $this->_cakeEmail->bcc();
|
||||
return array_merge(array_keys($to), array_keys($cc), array_keys($bcc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the message headers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _prepareMessageHeaders() {
|
||||
return $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the message body.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _prepareMessage() {
|
||||
$lines = $this->_cakeEmail->message();
|
||||
$messages = array();
|
||||
foreach ($lines as $line) {
|
||||
if ((!empty($line)) && ($line[0] === '.')) {
|
||||
$messages[] = '.' . $line;
|
||||
} else {
|
||||
$messages[] = $line;
|
||||
}
|
||||
}
|
||||
return implode("\r\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emails
|
||||
*
|
||||
|
@ -159,18 +286,12 @@ class SmtpTransport extends AbstractTransport {
|
|||
* @throws SocketException
|
||||
*/
|
||||
protected function _sendRcpt() {
|
||||
$from = $this->_cakeEmail->returnPath();
|
||||
if (empty($from)) {
|
||||
$from = $this->_cakeEmail->from();
|
||||
}
|
||||
$this->_smtpSend('MAIL FROM:<' . key($from) . '>');
|
||||
$from = $this->_prepareFromAddress();
|
||||
$this->_smtpSend($this->_prepareFromCmd(key($from)));
|
||||
|
||||
$to = $this->_cakeEmail->to();
|
||||
$cc = $this->_cakeEmail->cc();
|
||||
$bcc = $this->_cakeEmail->bcc();
|
||||
$emails = array_merge(array_keys($to), array_keys($cc), array_keys($bcc));
|
||||
$emails = $this->_prepareRecipientAddresses();
|
||||
foreach ($emails as $email) {
|
||||
$this->_smtpSend('RCPT TO:<' . $email . '>');
|
||||
$this->_smtpSend($this->_prepareRcptCmd($email));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,18 +304,9 @@ class SmtpTransport extends AbstractTransport {
|
|||
protected function _sendData() {
|
||||
$this->_smtpSend('DATA', '354');
|
||||
|
||||
$headers = $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject'));
|
||||
$headers = $this->_headersToString($headers);
|
||||
$lines = $this->_cakeEmail->message();
|
||||
$messages = array();
|
||||
foreach ($lines as $line) {
|
||||
if ((!empty($line)) && ($line[0] === '.')) {
|
||||
$messages[] = '.' . $line;
|
||||
} else {
|
||||
$messages[] = $line;
|
||||
}
|
||||
}
|
||||
$message = implode("\r\n", $messages);
|
||||
$headers = $this->_headersToString($this->_prepareMessageHeaders());
|
||||
$message = $this->_prepareMessage();
|
||||
|
||||
$this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n.");
|
||||
$this->_content = array('headers' => $headers, 'message' => $message);
|
||||
}
|
||||
|
@ -229,6 +341,8 @@ class SmtpTransport extends AbstractTransport {
|
|||
* @throws SocketException
|
||||
*/
|
||||
protected function _smtpSend($data, $checkCode = '250') {
|
||||
$this->_lastResponse = array();
|
||||
|
||||
if ($data !== null) {
|
||||
$this->_socket->write($data . "\r\n");
|
||||
}
|
||||
|
@ -244,6 +358,8 @@ class SmtpTransport extends AbstractTransport {
|
|||
$responseLines = explode("\r\n", rtrim($response, "\r\n"));
|
||||
$response = end($responseLines);
|
||||
|
||||
$this->_bufferResponseLines($responseLines);
|
||||
|
||||
if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) {
|
||||
if ($code[2] === '-') {
|
||||
continue;
|
||||
|
|
|
@ -893,7 +893,7 @@ class HttpSocket extends CakeSocket {
|
|||
}
|
||||
|
||||
$request['uri'] = $this->_parseUri($request['uri']);
|
||||
$request = array_merge(array('method' => 'GET'), $request);
|
||||
$request += array('method' => 'GET');
|
||||
if (!empty($this->_proxy['host'])) {
|
||||
$request['uri'] = $this->_buildUri($request['uri'], '%scheme://%host:%port/%path?%query');
|
||||
} else {
|
||||
|
|
|
@ -95,7 +95,12 @@ class Dispatcher implements CakeEventListener {
|
|||
return;
|
||||
}
|
||||
|
||||
foreach ($filters as $filter) {
|
||||
foreach ($filters as $index => $filter) {
|
||||
$settings = array();
|
||||
if (is_array($filter) && !is_int($index)) {
|
||||
$settings = $filter;
|
||||
$filter = $index;
|
||||
}
|
||||
if (is_string($filter)) {
|
||||
$filter = array('callable' => $filter);
|
||||
}
|
||||
|
@ -105,7 +110,7 @@ class Dispatcher implements CakeEventListener {
|
|||
if (!class_exists($callable)) {
|
||||
throw new MissingDispatcherFilterException($callable);
|
||||
}
|
||||
$manager->attach(new $callable);
|
||||
$manager->attach(new $callable($settings));
|
||||
} else {
|
||||
$on = strtolower($filter['on']);
|
||||
$options = array();
|
||||
|
@ -157,7 +162,7 @@ class Dispatcher implements CakeEventListener {
|
|||
));
|
||||
}
|
||||
|
||||
$response = $this->_invoke($controller, $request, $response);
|
||||
$response = $this->_invoke($controller, $request);
|
||||
if (isset($request->params['return'])) {
|
||||
return $response->body();
|
||||
}
|
||||
|
@ -169,18 +174,19 @@ class Dispatcher implements CakeEventListener {
|
|||
|
||||
/**
|
||||
* Initializes the components and models a controller will be using.
|
||||
* Triggers the controller action, and invokes the rendering if Controller::$autoRender is true and echo's the output.
|
||||
* Otherwise the return value of the controller action are returned.
|
||||
* Triggers the controller action, and invokes the rendering if Controller::$autoRender
|
||||
* is true and echo's the output. Otherwise the return value of the controller
|
||||
* action are returned.
|
||||
*
|
||||
* @param Controller $controller Controller to invoke
|
||||
* @param CakeRequest $request The request object to invoke the controller for.
|
||||
* @param CakeResponse $response The response object to receive the output
|
||||
* @return CakeResponse the resulting response object
|
||||
*/
|
||||
protected function _invoke(Controller $controller, CakeRequest $request, CakeResponse $response) {
|
||||
protected function _invoke(Controller $controller, CakeRequest $request) {
|
||||
$controller->constructClasses();
|
||||
$controller->startupProcess();
|
||||
|
||||
$response = $controller->response;
|
||||
$render = true;
|
||||
$result = $controller->invokeAction($request);
|
||||
if ($result instanceof CakeResponse) {
|
||||
|
|
|
@ -34,6 +34,22 @@ abstract class DispatcherFilter implements CakeEventListener {
|
|||
*/
|
||||
public $priority = 10;
|
||||
|
||||
/**
|
||||
* Settings for this filter
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $settings = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $setting Configuration settings for the filter.
|
||||
*/
|
||||
public function __construct($settings = array()) {
|
||||
$this->settings = Hash::merge($this->settings, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of events this filter listens to.
|
||||
* Dispatcher notifies 2 different events `Dispatcher.before` and `Dispatcher.after`.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
*
|
||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||
*
|
||||
|
@ -38,7 +36,8 @@ class AssetDispatcher extends DispatcherFilter {
|
|||
* Checks if a requested asset exists and sends it to the browser
|
||||
*
|
||||
* @param CakeEvent $event containing the request and response object
|
||||
* @return CakeResponse if the client is requesting a recognized asset, null otherwise
|
||||
* @return mixed The resulting response.
|
||||
* @throws NotFoundException When asset not found
|
||||
*/
|
||||
public function beforeDispatch(CakeEvent $event) {
|
||||
$url = urldecode($event->data['request']->url);
|
||||
|
@ -55,7 +54,6 @@ class AssetDispatcher extends DispatcherFilter {
|
|||
if ($assetFile === null || !file_exists($assetFile)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$response = $event->data['response'];
|
||||
$event->stopPropagation();
|
||||
|
||||
|
@ -66,6 +64,7 @@ class AssetDispatcher extends DispatcherFilter {
|
|||
|
||||
$pathSegments = explode('.', $url);
|
||||
$ext = array_pop($pathSegments);
|
||||
|
||||
$this->_deliverAsset($response, $assetFile, $ext);
|
||||
return $response;
|
||||
}
|
||||
|
|
|
@ -480,10 +480,10 @@ class Router {
|
|||
}
|
||||
|
||||
if ($named === true || $named === false) {
|
||||
$options = array_merge(array('default' => $named, 'reset' => true, 'greedy' => $named), $options);
|
||||
$options += array('default' => $named, 'reset' => true, 'greedy' => $named);
|
||||
$named = array();
|
||||
} else {
|
||||
$options = array_merge(array('default' => false, 'reset' => false, 'greedy' => true), $options);
|
||||
$options += array('default' => false, 'reset' => false, 'greedy' => true);
|
||||
}
|
||||
|
||||
if ($options['reset'] || self::$_namedConfig['rules'] === false) {
|
||||
|
@ -532,12 +532,15 @@ class Router {
|
|||
*/
|
||||
public static function mapResources($controller, $options = array()) {
|
||||
$hasPrefix = isset($options['prefix']);
|
||||
$options = array_merge(array(
|
||||
$options += array(
|
||||
'connectOptions' => array(),
|
||||
'prefix' => '/',
|
||||
'id' => self::ID . '|' . self::UUID
|
||||
), $options);
|
||||
);
|
||||
|
||||
$prefix = $options['prefix'];
|
||||
$connectOptions = $options['connectOptions'];
|
||||
unset($options['connectOptions']);
|
||||
if (strpos($prefix, '/') !== 0) {
|
||||
$prefix = '/' . $prefix;
|
||||
}
|
||||
|
@ -563,7 +566,10 @@ class Router {
|
|||
'action' => $params['action'],
|
||||
'[method]' => $params['method']
|
||||
),
|
||||
array('id' => $options['id'], 'pass' => array('id'))
|
||||
array_merge(
|
||||
array('id' => $options['id'], 'pass' => array('id')),
|
||||
$connectOptions
|
||||
)
|
||||
);
|
||||
}
|
||||
self::$_resourceMapped[] = $urlName;
|
||||
|
@ -1074,7 +1080,7 @@ class Router {
|
|||
}
|
||||
$addition = http_build_query($q, null, $join);
|
||||
|
||||
if ($out && $addition && substr($out, strlen($join) * -1, strlen($join)) != $join) {
|
||||
if ($out && $addition && substr($out, strlen($join) * -1, strlen($join)) !== $join) {
|
||||
$out .= $join;
|
||||
}
|
||||
|
||||
|
|
|
@ -397,6 +397,181 @@ class BasicsTest extends CakeTestCase {
|
|||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testTranslatePercent
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslatePercent() {
|
||||
$result = __('%s are 100% real fruit', 'Apples');
|
||||
$expected = 'Apples are 100% real fruit';
|
||||
$this->assertEquals($expected, $result, 'Percent sign at end of word should be considered literal');
|
||||
|
||||
$result = __('%s are %d% real fruit', 'Apples', 100);
|
||||
$expected = 'Apples are 100% real fruit';
|
||||
$this->assertEquals($expected, $result, 'A digit marker should not be misinterpreted');
|
||||
|
||||
$result = __('%s are %s% real fruit', 'Apples', 100);
|
||||
$expected = 'Apples are 100% real fruit';
|
||||
$this->assertEquals($expected, $result, 'A string marker should not be misinterpreted');
|
||||
|
||||
$result = __('%nonsense %s', 'Apples');
|
||||
$expected = '%nonsense Apples';
|
||||
$this->assertEquals($expected, $result, 'A percent sign at the start of the string should be considered literal');
|
||||
|
||||
$result = __('%s are awesome%', 'Apples');
|
||||
$expected = 'Apples are awesome%';
|
||||
$this->assertEquals($expected, $result, 'A percent sign at the end of the string should be considered literal');
|
||||
|
||||
$result = __('%2$d %1$s entered the bowl', 'Apples', 2);
|
||||
$expected = '2 Apples entered the bowl';
|
||||
$this->assertEquals($expected, $result, 'Positional replacement markers should not be misinterpreted');
|
||||
|
||||
$result = __('%.2f% of all %s agree', 99.44444, 'Cats');
|
||||
$expected = '99.44% of all Cats agree';
|
||||
$this->assertEquals($expected, $result, 'significant-digit placeholder should not be misinterpreted');
|
||||
}
|
||||
|
||||
/**
|
||||
* testTranslateWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslateWithFormatSpecifiers() {
|
||||
$expected = 'Check, one, two, three';
|
||||
$result = __('Check, %+10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, +1, two, three';
|
||||
$result = __('Check, %+5d, two, three', 1);
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, @@one, two, three';
|
||||
$result = __('Check, %\'@+10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, one, two , three';
|
||||
$result = __('Check, %-10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, one, two##, three';
|
||||
$result = __('Check, %\'#-10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, one, two, three';
|
||||
$result = __d('default', 'Check, %+10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, @@one, two, three';
|
||||
$result = __d('default', 'Check, %\'@+10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, one, two , three';
|
||||
$result = __d('default', 'Check, %-10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$expected = 'Check, one, two##, three';
|
||||
$result = __d('default', 'Check, %\'#-10s, three', 'one, two');
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testTranslateDomainPluralWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslateDomainPluralWithFormatSpecifiers() {
|
||||
$result = __dn('core', '%+5d item.', '%+5d items.', 1, 1);
|
||||
$expected = ' +1 item.';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dn('core', '%-5d item.', '%-5d items.', 10, 10);
|
||||
$expected = '10 items.';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 1, 1);
|
||||
$expected = '###+1 item.';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 90, 90);
|
||||
$expected = '**+90 items.';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 9000, 9000);
|
||||
$expected = '+9000 items.';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test testTranslatePluralWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslatePluralWithFormatSpecifiers() {
|
||||
Configure::write('Config.language', 'rule_1_po');
|
||||
|
||||
$result = __n('%-5d = 1', '%-5d = 0 or > 1', 10);
|
||||
$expected = '%-5d = 0 or > 1 (translated)';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test testTranslateDomainCategoryWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslateDomainCategoryWithFormatSpecifiers() {
|
||||
Configure::write('Config.language', 'rule_1_po');
|
||||
|
||||
$result = __dc('default', '%+10s world', 6, 'hello');
|
||||
$expected = ' hello world';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dc('default', '%-10s world', 6, 'hello');
|
||||
$expected = 'hello world';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dc('default', '%\'@-10s world', 6, 'hello');
|
||||
$expected = 'hello@@@@@ world';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test testTranslateDomainCategoryPluralWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslateDomainCategoryPluralWithFormatSpecifiers() {
|
||||
Configure::write('Config.language', 'rule_1_po');
|
||||
|
||||
$result = __dcn('default', '%-5d = 1', '%-5d = 0 or > 1', 0, 6);
|
||||
$expected = '%-5d = 0 or > 1 (translated)';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __dcn('default', '%-5d = 1', '%-5d = 0 or > 1', 1, 6);
|
||||
$expected = '%-5d = 1 (translated)';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test testTranslateCategoryWithFormatSpecifiers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTranslateCategoryWithFormatSpecifiers() {
|
||||
$result = __c('Some string with %+10s', 6, 'arguments');
|
||||
$expected = 'Some string with arguments';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __c('Some string with %-10s: args', 6, 'arguments');
|
||||
$expected = 'Some string with arguments : args';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = __c('Some string with %\'*-10s: args', 6, 'arguments');
|
||||
$expected = 'Some string with arguments*: args';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test __n()
|
||||
*
|
||||
|
|
|
@ -25,6 +25,8 @@ App::uses('Cache', 'Cache');
|
|||
*/
|
||||
class CacheTest extends CakeTestCase {
|
||||
|
||||
protected $_count = 0;
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
|
@ -493,4 +495,28 @@ class CacheTest extends CakeTestCase {
|
|||
$this->assertEquals('test_file_', $settings['prefix']);
|
||||
$this->assertEquals(strtotime('+1 year') - time(), $settings['duration']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test remember method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRemember() {
|
||||
$expected = 'This is some data 0';
|
||||
$result = Cache::remember('test_key', array($this, 'cacher'), 'default');
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$this->_count = 1;
|
||||
$result = Cache::remember('test_key', array($this, 'cacher'), 'default');
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for testing Cache::remember()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function cacher() {
|
||||
return 'This is some data ' . $this->_count;
|
||||
}
|
||||
}
|
||||
|
|
776
lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php
Executable file
776
lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php
Executable file
|
@ -0,0 +1,776 @@
|
|||
<?php
|
||||
/**
|
||||
* MemcachedEngineTest file
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
|
||||
* 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://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
|
||||
* @package Cake.Test.Case.Cache.Engine
|
||||
* @since CakePHP(tm) v 2.5.0
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('Cache', 'Cache');
|
||||
App::uses('MemcachedEngine', 'Cache/Engine');
|
||||
|
||||
/**
|
||||
* Class TestMemcachedEngine
|
||||
*
|
||||
* @package Cake.Test.Case.Cache.Engine
|
||||
*/
|
||||
class TestMemcachedEngine extends MemcachedEngine {
|
||||
|
||||
/**
|
||||
* public accessor to _parseServerString
|
||||
*
|
||||
* @param string $server
|
||||
* @return array
|
||||
*/
|
||||
public function parseServerString($server) {
|
||||
return $this->_parseServerString($server);
|
||||
}
|
||||
|
||||
public function setMemcached($memcached) {
|
||||
$this->_Memcached = $memcached;
|
||||
}
|
||||
|
||||
public function getMemcached() {
|
||||
return $this->_Memcached;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* MemcachedEngineTest class
|
||||
*
|
||||
* @package Cake.Test.Case.Cache.Engine
|
||||
*/
|
||||
class MemcachedEngineTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.');
|
||||
|
||||
Cache::config('memcached', array(
|
||||
'engine' => 'Memcached',
|
||||
'prefix' => 'cake_',
|
||||
'duration' => 3600
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
Cache::drop('memcached');
|
||||
Cache::drop('memcached_groups');
|
||||
Cache::drop('memcached_helper');
|
||||
Cache::config('default');
|
||||
}
|
||||
|
||||
/**
|
||||
* testSettings method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSettings() {
|
||||
$settings = Cache::settings('memcached');
|
||||
unset($settings['path']);
|
||||
$expecting = array(
|
||||
'prefix' => 'cake_',
|
||||
'duration' => 3600,
|
||||
'probability' => 100,
|
||||
'servers' => array('127.0.0.1'),
|
||||
'persistent' => false,
|
||||
'compress' => false,
|
||||
'engine' => 'Memcached',
|
||||
'login' => null,
|
||||
'password' => null,
|
||||
'groups' => array(),
|
||||
'serialize' => 'php'
|
||||
);
|
||||
$this->assertEquals($expecting, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* testCompressionSetting method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCompressionSetting() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$Memcached->init(array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'compress' => false
|
||||
));
|
||||
|
||||
$this->assertFalse($Memcached->getMemcached()->getOption(Memcached::OPT_COMPRESSION));
|
||||
|
||||
$MemcachedCompressed = new TestMemcachedEngine();
|
||||
$MemcachedCompressed->init(array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'compress' => true
|
||||
));
|
||||
|
||||
$this->assertTrue($MemcachedCompressed->getMemcached()->getOption(Memcached::OPT_COMPRESSION));
|
||||
}
|
||||
|
||||
/**
|
||||
* test accepts only valid serializer engine
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidSerializerSetting() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'invalid_serializer'
|
||||
);
|
||||
|
||||
$this->setExpectedException(
|
||||
'CacheException', 'invalid_serializer is not a valid serializer engine for Memcached'
|
||||
);
|
||||
$Memcached->init($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* testPhpSerializerSetting method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testPhpSerializerSetting() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'php'
|
||||
);
|
||||
|
||||
$Memcached->init($settings);
|
||||
$this->assertEquals(Memcached::SERIALIZER_PHP, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
|
||||
}
|
||||
|
||||
/**
|
||||
* testJsonSerializerSetting method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testJsonSerializerSetting() {
|
||||
$this->skipIf(
|
||||
!Memcached::HAVE_JSON,
|
||||
'Memcached extension is not compiled with json support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'json'
|
||||
);
|
||||
|
||||
$Memcached->init($settings);
|
||||
$this->assertEquals(Memcached::SERIALIZER_JSON, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
|
||||
}
|
||||
|
||||
/**
|
||||
* testIgbinarySerializerSetting method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIgbinarySerializerSetting() {
|
||||
$this->skipIf(
|
||||
!Memcached::HAVE_IGBINARY,
|
||||
'Memcached extension is not compiled with igbinary support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'igbinary'
|
||||
);
|
||||
|
||||
$Memcached->init($settings);
|
||||
$this->assertEquals(Memcached::SERIALIZER_IGBINARY, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
|
||||
}
|
||||
|
||||
/**
|
||||
* testMsgpackSerializerSetting method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMsgpackSerializerSetting() {
|
||||
$this->skipIf(
|
||||
!defined('Memcached::HAVE_MSGPACK') || !Memcached::HAVE_MSGPACK,
|
||||
'Memcached extension is not compiled with msgpack support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'msgpack'
|
||||
);
|
||||
|
||||
$Memcached->init($settings);
|
||||
$this->assertEquals(Memcached::SERIALIZER_MSGPACK, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER));
|
||||
}
|
||||
|
||||
/**
|
||||
* testJsonSerializerThrowException method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testJsonSerializerThrowException() {
|
||||
$this->skipIf(
|
||||
Memcached::HAVE_JSON,
|
||||
'Memcached extension is compiled with json support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'json'
|
||||
);
|
||||
|
||||
$this->setExpectedException(
|
||||
'CacheException', 'Memcached extension is not compiled with json support'
|
||||
);
|
||||
$Memcached->init($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* testMsgpackSerializerThrowException method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMsgpackSerializerThrowException() {
|
||||
$this->skipIf(
|
||||
defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK,
|
||||
'Memcached extension is compiled with msgpack support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'msgpack'
|
||||
);
|
||||
|
||||
$this->setExpectedException(
|
||||
'CacheException', 'msgpack is not a valid serializer engine for Memcached'
|
||||
);
|
||||
$Memcached->init($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* testIgbinarySerializerThrowException method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIgbinarySerializerThrowException() {
|
||||
$this->skipIf(
|
||||
Memcached::HAVE_IGBINARY,
|
||||
'Memcached extension is compiled with igbinary support'
|
||||
);
|
||||
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'serialize' => 'igbinary'
|
||||
);
|
||||
|
||||
$this->setExpectedException(
|
||||
'CacheException', 'Memcached extension is not compiled with igbinary support'
|
||||
);
|
||||
$Memcached->init($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* test using authentication without memcached installed with SASL support
|
||||
* throw an exception
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSaslAuthException() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$settings = array(
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'persistent' => false,
|
||||
'login' => 'test',
|
||||
'password' => 'password'
|
||||
);
|
||||
|
||||
$this->skipIf(
|
||||
method_exists($Memcached->getMemcached(), 'setSaslAuthData'),
|
||||
'Memcached extension is installed with SASL support'
|
||||
);
|
||||
|
||||
$this->setExpectedException(
|
||||
'CacheException', 'Memcached extension is not build with SASL support'
|
||||
);
|
||||
$Memcached->init($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* testSettings method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultipleServers() {
|
||||
$servers = array('127.0.0.1:11211', '127.0.0.1:11222');
|
||||
$available = true;
|
||||
$Memcached = new Memcached();
|
||||
|
||||
foreach ($servers as $server) {
|
||||
list($host, $port) = explode(':', $server);
|
||||
//@codingStandardsIgnoreStart
|
||||
if (!$Memcached->addServer($host, $port)) {
|
||||
$available = false;
|
||||
}
|
||||
//@codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
$this->skipIf(!$available, 'Need memcached servers at ' . implode(', ', $servers) . ' to run this test.');
|
||||
|
||||
$Memcached = new MemcachedEngine();
|
||||
$Memcached->init(array('engine' => 'Memcached', 'servers' => $servers));
|
||||
|
||||
$settings = $Memcached->settings();
|
||||
$this->assertEquals($settings['servers'], $servers);
|
||||
Cache::drop('dual_server');
|
||||
}
|
||||
|
||||
/**
|
||||
* test connecting to an ipv6 server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConnectIpv6() {
|
||||
$Memcached = new MemcachedEngine();
|
||||
$result = $Memcached->init(array(
|
||||
'prefix' => 'cake_',
|
||||
'duration' => 200,
|
||||
'engine' => 'Memcached',
|
||||
'servers' => array(
|
||||
'[::1]:11211'
|
||||
)
|
||||
));
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test non latin domains.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testParseServerStringNonLatin() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$result = $Memcached->parseServerString('schülervz.net:13211');
|
||||
$this->assertEquals(array('schülervz.net', '13211'), $result);
|
||||
|
||||
$result = $Memcached->parseServerString('sülül:1111');
|
||||
$this->assertEquals(array('sülül', '1111'), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test unix sockets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testParseServerStringUnix() {
|
||||
$Memcached = new TestMemcachedEngine();
|
||||
$result = $Memcached->parseServerString('unix:///path/to/memcachedd.sock');
|
||||
$this->assertEquals(array('unix:///path/to/memcachedd.sock', 0), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testReadAndWriteCache method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testReadAndWriteCache() {
|
||||
Cache::set(array('duration' => 1), null, 'memcached');
|
||||
|
||||
$result = Cache::read('test', 'memcached');
|
||||
$expecting = '';
|
||||
$this->assertEquals($expecting, $result);
|
||||
|
||||
$data = 'this is a test of the emergency broadcasting system';
|
||||
$result = Cache::write('test', $data, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::read('test', 'memcached');
|
||||
$expecting = $data;
|
||||
$this->assertEquals($expecting, $result);
|
||||
|
||||
Cache::delete('test', 'memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* testExpiry method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testExpiry() {
|
||||
Cache::set(array('duration' => 1), 'memcached');
|
||||
|
||||
$result = Cache::read('test', 'memcached');
|
||||
$this->assertFalse($result);
|
||||
|
||||
$data = 'this is a test of the emergency broadcasting system';
|
||||
$result = Cache::write('other_test', $data, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
sleep(2);
|
||||
$result = Cache::read('other_test', 'memcached');
|
||||
$this->assertFalse($result);
|
||||
|
||||
Cache::set(array('duration' => "+1 second"), 'memcached');
|
||||
|
||||
$data = 'this is a test of the emergency broadcasting system';
|
||||
$result = Cache::write('other_test', $data, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
sleep(3);
|
||||
$result = Cache::read('other_test', 'memcached');
|
||||
$this->assertFalse($result);
|
||||
|
||||
Cache::config('memcached', array('duration' => '+1 second'));
|
||||
|
||||
$result = Cache::read('other_test', 'memcached');
|
||||
$this->assertFalse($result);
|
||||
|
||||
Cache::config('memcached', array('duration' => '+29 days'));
|
||||
$data = 'this is a test of the emergency broadcasting system';
|
||||
$result = Cache::write('long_expiry_test', $data, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
sleep(2);
|
||||
$result = Cache::read('long_expiry_test', 'memcached');
|
||||
$expecting = $data;
|
||||
$this->assertEquals($expecting, $result);
|
||||
|
||||
Cache::config('memcached', array('duration' => 3600));
|
||||
}
|
||||
|
||||
/**
|
||||
* testDeleteCache method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDeleteCache() {
|
||||
$data = 'this is a test of the emergency broadcasting system';
|
||||
$result = Cache::write('delete_test', $data, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::delete('delete_test', 'memcached');
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testDecrement method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDecrement() {
|
||||
$result = Cache::write('test_decrement', 5, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::decrement('test_decrement', 1, 'memcached');
|
||||
$this->assertEquals(4, $result);
|
||||
|
||||
$result = Cache::read('test_decrement', 'memcached');
|
||||
$this->assertEquals(4, $result);
|
||||
|
||||
$result = Cache::decrement('test_decrement', 2, 'memcached');
|
||||
$this->assertEquals(2, $result);
|
||||
|
||||
$result = Cache::read('test_decrement', 'memcached');
|
||||
$this->assertEquals(2, $result);
|
||||
|
||||
Cache::delete('test_decrement', 'memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* test decrementing compressed keys
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDecrementCompressedKeys() {
|
||||
Cache::config('compressed_memcached', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => '+2 seconds',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'compress' => true
|
||||
));
|
||||
|
||||
$result = Cache::write('test_decrement', 5, 'compressed_memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::decrement('test_decrement', 1, 'compressed_memcached');
|
||||
$this->assertEquals(4, $result);
|
||||
|
||||
$result = Cache::read('test_decrement', 'compressed_memcached');
|
||||
$this->assertEquals(4, $result);
|
||||
|
||||
$result = Cache::decrement('test_decrement', 2, 'compressed_memcached');
|
||||
$this->assertEquals(2, $result);
|
||||
|
||||
$result = Cache::read('test_decrement', 'compressed_memcached');
|
||||
$this->assertEquals(2, $result);
|
||||
|
||||
Cache::delete('test_decrement', 'compressed_memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* testIncrement method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIncrement() {
|
||||
$result = Cache::write('test_increment', 5, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::increment('test_increment', 1, 'memcached');
|
||||
$this->assertEquals(6, $result);
|
||||
|
||||
$result = Cache::read('test_increment', 'memcached');
|
||||
$this->assertEquals(6, $result);
|
||||
|
||||
$result = Cache::increment('test_increment', 2, 'memcached');
|
||||
$this->assertEquals(8, $result);
|
||||
|
||||
$result = Cache::read('test_increment', 'memcached');
|
||||
$this->assertEquals(8, $result);
|
||||
|
||||
Cache::delete('test_increment', 'memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* test incrementing compressed keys
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIncrementCompressedKeys() {
|
||||
Cache::config('compressed_memcached', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => '+2 seconds',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
'compress' => true
|
||||
));
|
||||
|
||||
$result = Cache::write('test_increment', 5, 'compressed_memcached');
|
||||
$this->assertTrue($result);
|
||||
|
||||
$result = Cache::increment('test_increment', 1, 'compressed_memcached');
|
||||
$this->assertEquals(6, $result);
|
||||
|
||||
$result = Cache::read('test_increment', 'compressed_memcached');
|
||||
$this->assertEquals(6, $result);
|
||||
|
||||
$result = Cache::increment('test_increment', 2, 'compressed_memcached');
|
||||
$this->assertEquals(8, $result);
|
||||
|
||||
$result = Cache::read('test_increment', 'compressed_memcached');
|
||||
$this->assertEquals(8, $result);
|
||||
|
||||
Cache::delete('test_increment', 'compressed_memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* test that configurations don't conflict, when a file engine is declared after a memcached one.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConfigurationConflict() {
|
||||
Cache::config('long_memcached', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => '+2 seconds',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
));
|
||||
Cache::config('short_memcached', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => '+1 seconds',
|
||||
'servers' => array('127.0.0.1:11211'),
|
||||
));
|
||||
Cache::config('some_file', array('engine' => 'File'));
|
||||
|
||||
$this->assertTrue(Cache::write('duration_test', 'yay', 'long_memcached'));
|
||||
$this->assertTrue(Cache::write('short_duration_test', 'boo', 'short_memcached'));
|
||||
|
||||
$this->assertEquals('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s');
|
||||
$this->assertEquals('boo', Cache::read('short_duration_test', 'short_memcached'), 'Value was not read %s');
|
||||
|
||||
sleep(1);
|
||||
$this->assertEquals('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s');
|
||||
|
||||
sleep(2);
|
||||
$this->assertFalse(Cache::read('short_duration_test', 'short_memcached'), 'Cache was not invalidated %s');
|
||||
$this->assertFalse(Cache::read('duration_test', 'long_memcached'), 'Value did not expire %s');
|
||||
|
||||
Cache::delete('duration_test', 'long_memcached');
|
||||
Cache::delete('short_duration_test', 'short_memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* test clearing memcached.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testClear() {
|
||||
Cache::config('memcached2', array(
|
||||
'engine' => 'Memcached',
|
||||
'prefix' => 'cake2_',
|
||||
'duration' => 3600
|
||||
));
|
||||
|
||||
Cache::write('some_value', 'cache1', 'memcached');
|
||||
$result = Cache::clear(true, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals('cache1', Cache::read('some_value', 'memcached'));
|
||||
|
||||
Cache::write('some_value', 'cache2', 'memcached2');
|
||||
$result = Cache::clear(false, 'memcached');
|
||||
$this->assertTrue($result);
|
||||
$this->assertFalse(Cache::read('some_value', 'memcached'));
|
||||
$this->assertEquals('cache2', Cache::read('some_value', 'memcached2'));
|
||||
|
||||
Cache::clear(false, 'memcached2');
|
||||
}
|
||||
|
||||
/**
|
||||
* test that a 0 duration can successfully write.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testZeroDuration() {
|
||||
Cache::config('memcached', array('duration' => 0));
|
||||
$result = Cache::write('test_key', 'written!', 'memcached');
|
||||
|
||||
$this->assertTrue($result);
|
||||
$result = Cache::read('test_key', 'memcached');
|
||||
$this->assertEquals('written!', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that durations greater than 30 days never expire
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLongDurationEqualToZero() {
|
||||
$memcached = new TestMemcachedEngine();
|
||||
$memcached->settings['compress'] = false;
|
||||
|
||||
$mock = $this->getMock('Memcached');
|
||||
$memcached->setMemcached($mock);
|
||||
$mock->expects($this->once())
|
||||
->method('set')
|
||||
->with('key', 'value', 0);
|
||||
|
||||
$value = 'value';
|
||||
$memcached->write('key', $value, 50 * DAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that configuring groups for stored keys return the correct values when read/written
|
||||
* Shows that altering the group value is equivalent to deleting all keys under the same
|
||||
* group
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGroupReadWrite() {
|
||||
Cache::config('memcached_groups', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => 3600,
|
||||
'groups' => array('group_a', 'group_b'),
|
||||
'prefix' => 'test_'
|
||||
));
|
||||
Cache::config('memcached_helper', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => 3600,
|
||||
'prefix' => 'test_'
|
||||
));
|
||||
$this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
|
||||
$this->assertEquals('value', Cache::read('test_groups', 'memcached_groups'));
|
||||
|
||||
Cache::increment('group_a', 1, 'memcached_helper');
|
||||
$this->assertFalse(Cache::read('test_groups', 'memcached_groups'));
|
||||
$this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups'));
|
||||
$this->assertEquals('value2', Cache::read('test_groups', 'memcached_groups'));
|
||||
|
||||
Cache::increment('group_b', 1, 'memcached_helper');
|
||||
$this->assertFalse(Cache::read('test_groups', 'memcached_groups'));
|
||||
$this->assertTrue(Cache::write('test_groups', 'value3', 'memcached_groups'));
|
||||
$this->assertEquals('value3', Cache::read('test_groups', 'memcached_groups'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deleteing from a groups-enabled config is possible
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGroupDelete() {
|
||||
Cache::config('memcached_groups', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => 3600,
|
||||
'groups' => array('group_a', 'group_b')
|
||||
));
|
||||
$this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
|
||||
$this->assertEquals('value', Cache::read('test_groups', 'memcached_groups'));
|
||||
$this->assertTrue(Cache::delete('test_groups', 'memcached_groups'));
|
||||
|
||||
$this->assertFalse(Cache::read('test_groups', 'memcached_groups'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clearing a cache group
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGroupClear() {
|
||||
Cache::config('memcached_groups', array(
|
||||
'engine' => 'Memcached',
|
||||
'duration' => 3600,
|
||||
'groups' => array('group_a', 'group_b')
|
||||
));
|
||||
|
||||
$this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
|
||||
$this->assertTrue(Cache::clearGroup('group_a', 'memcached_groups'));
|
||||
$this->assertFalse(Cache::read('test_groups', 'memcached_groups'));
|
||||
|
||||
$this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups'));
|
||||
$this->assertTrue(Cache::clearGroup('group_b', 'memcached_groups'));
|
||||
$this->assertFalse(Cache::read('test_groups', 'memcached_groups'));
|
||||
}
|
||||
}
|
|
@ -76,6 +76,7 @@ class RedisEngineTest extends CakeTestCase {
|
|||
'timeout' => 0,
|
||||
'persistent' => true,
|
||||
'password' => false,
|
||||
'database' => 0,
|
||||
);
|
||||
$this->assertEquals($expecting, $settings);
|
||||
}
|
||||
|
@ -90,6 +91,51 @@ class RedisEngineTest extends CakeTestCase {
|
|||
$this->assertTrue($Redis->init(Cache::settings('redis')));
|
||||
}
|
||||
|
||||
/**
|
||||
* testMultiDatabaseOperations method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultiDatabaseOperations() {
|
||||
Cache::config('redisdb0', array(
|
||||
'engine' => 'Redis',
|
||||
'prefix' => 'cake2_',
|
||||
'duration' => 3600,
|
||||
'persistent' => false,
|
||||
));
|
||||
|
||||
Cache::config('redisdb1', array(
|
||||
'engine' => 'Redis',
|
||||
'database' => 1,
|
||||
'prefix' => 'cake2_',
|
||||
'duration' => 3600,
|
||||
'persistent' => false,
|
||||
));
|
||||
|
||||
$result = Cache::write('save_in_0', true, 'redisdb0');
|
||||
$exist = Cache::read('save_in_0', 'redisdb0');
|
||||
$this->assertTrue($result);
|
||||
$this->assertTrue($exist);
|
||||
|
||||
$result = Cache::write('save_in_1', true, 'redisdb1');
|
||||
$this->assertTrue($result);
|
||||
$exist = Cache::read('save_in_0', 'redisdb1');
|
||||
$this->assertFalse($exist);
|
||||
$exist = Cache::read('save_in_1', 'redisdb1');
|
||||
$this->assertTrue($exist);
|
||||
|
||||
Cache::delete('save_in_0', 'redisdb0');
|
||||
$exist = Cache::read('save_in_0', 'redisdb0');
|
||||
$this->assertFalse($exist);
|
||||
|
||||
Cache::delete('save_in_1', 'redisdb1');
|
||||
$exist = Cache::read('save_in_1', 'redisdb1');
|
||||
$this->assertFalse($exist);
|
||||
|
||||
Cache::drop('redisdb0');
|
||||
Cache::drop('redisdb1');
|
||||
}
|
||||
|
||||
/**
|
||||
* testReadAndWriteCache method
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ App::uses('CommandListShell', 'Console/Command');
|
|||
App::uses('ConsoleOutput', 'Console');
|
||||
App::uses('ConsoleInput', 'Console');
|
||||
App::uses('Shell', 'Console');
|
||||
App::uses('CommandTask', 'Console/Command/Task');
|
||||
|
||||
/**
|
||||
* Class TestStringOutput
|
||||
|
@ -68,6 +69,12 @@ class CommandListShellTest extends CakeTestCase {
|
|||
array('in', '_stop', 'clear'),
|
||||
array($out, $out, $in)
|
||||
);
|
||||
|
||||
$this->Shell->Command = $this->getMock(
|
||||
'CommandTask',
|
||||
array('in', '_stop', 'clear'),
|
||||
array($out, $out, $in)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +103,7 @@ class CommandListShellTest extends CakeTestCase {
|
|||
$expected = "/\[.*TestPluginTwo.*\] example, welcome/";
|
||||
$this->assertRegExp($expected, $output);
|
||||
|
||||
$expected = "/\[.*CORE.*\] acl, api, bake, command_list, console, i18n, schema, server, test, testsuite, upgrade/";
|
||||
$expected = "/\[.*CORE.*\] acl, api, bake, command_list, completion, console, i18n, schema, server, test, testsuite, upgrade/";
|
||||
$this->assertRegExp($expected, $output);
|
||||
|
||||
$expected = "/\[.*app.*\] sample/";
|
||||
|
|
261
lib/Cake/Test/Case/Console/Command/CompletionShellTest.php
Normal file
261
lib/Cake/Test/Case/Console/Command/CompletionShellTest.php
Normal file
|
@ -0,0 +1,261 @@
|
|||
<?php
|
||||
/**
|
||||
* CompletionShellTest file
|
||||
*
|
||||
* PHP 5
|
||||
*
|
||||
* CakePHP : 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.Test.Case.Console.Command
|
||||
* @since CakePHP v 2.5
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('CompletionShell', 'Console/Command');
|
||||
App::uses('ConsoleOutput', 'Console');
|
||||
App::uses('ConsoleInput', 'Console');
|
||||
App::uses('Shell', 'Console');
|
||||
App::uses('CommandTask', 'Console/Command/Task');
|
||||
|
||||
/**
|
||||
* Class TestCompletionStringOutput
|
||||
*
|
||||
* @package Cake.Test.Case.Console.Command
|
||||
*/
|
||||
class TestCompletionStringOutput extends ConsoleOutput {
|
||||
|
||||
public $output = '';
|
||||
|
||||
protected function _write($message) {
|
||||
$this->output .= $message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class CompletionShellTest
|
||||
*
|
||||
* @package Cake.Test.Case.Console.Command
|
||||
*/
|
||||
class CompletionShellTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
App::build(array(
|
||||
'Plugin' => array(
|
||||
CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS
|
||||
),
|
||||
'Console/Command' => array(
|
||||
CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS
|
||||
)
|
||||
), App::RESET);
|
||||
CakePlugin::load(array('TestPlugin', 'TestPluginTwo'));
|
||||
|
||||
$out = new TestCompletionStringOutput();
|
||||
$in = $this->getMock('ConsoleInput', array(), array(), '', false);
|
||||
|
||||
$this->Shell = $this->getMock(
|
||||
'CompletionShell',
|
||||
array('in', '_stop', 'clear'),
|
||||
array($out, $out, $in)
|
||||
);
|
||||
|
||||
$this->Shell->Command = $this->getMock(
|
||||
'CommandTask',
|
||||
array('in', '_stop', 'clear'),
|
||||
array($out, $out, $in)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->Shell);
|
||||
CakePlugin::unload();
|
||||
}
|
||||
|
||||
/**
|
||||
* test that the startup method supresses the shell header
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testStartup() {
|
||||
$this->Shell->runCommand('main', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$needle = 'Welcome to CakePHP';
|
||||
$this->assertTextNotContains($needle, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that main displays a warning
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMain() {
|
||||
$this->Shell->runCommand('main', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "/This command is not intended to be called manually/";
|
||||
$this->assertRegExp($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test commands method that list all available commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCommands() {
|
||||
$this->Shell->runCommand('commands', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "TestPlugin.example TestPluginTwo.example TestPluginTwo.welcome acl api bake command_list completion console i18n schema server test testsuite upgrade sample\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that options without argument returns the default options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOptionsNoArguments() {
|
||||
$this->Shell->runCommand('options', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "--help -h --verbose -v --quiet -q\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that options with a nonexisting command returns the default options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOptionsNonExistingCommand() {
|
||||
$this->Shell->runCommand('options', array('options', 'foo'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "--help -h --verbose -v --quiet -q\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that options with a existing command returns the proper options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOptions() {
|
||||
$this->Shell->runCommand('options', array('options', 'bake'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "--help -h --verbose -v --quiet -q --connection -c --theme -t\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subCommands with a existing CORE command returns the proper sub commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsCorePlugin() {
|
||||
$this->Shell->runCommand('subCommands', array('subCommands', 'CORE.bake'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "controller db_config fixture model plugin project test view\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subCommands with a existing APP command returns the proper sub commands (in this case none)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsAppPlugin() {
|
||||
$this->Shell->runCommand('subCommands', array('subCommands', 'app.sample'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = '';
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subCommands with a existing plugin command returns the proper sub commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsPlugin() {
|
||||
$this->Shell->runCommand('subCommands', array('subCommands', 'TestPluginTwo.welcome'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "say_hello\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subcommands without arguments returns nothing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsNoArguments() {
|
||||
$this->Shell->runCommand('subCommands', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = '';
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subcommands with a nonexisting command returns nothing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsNonExistingCommand() {
|
||||
$this->Shell->runCommand('subCommands', array('subCommands', 'foo'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = '';
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that subcommands returns the available subcommands for the given command
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommands() {
|
||||
$this->Shell->runCommand('subCommands', array('subCommands', 'bake'));
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = "controller db_config fixture model plugin project test view\n";
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that fuzzy returns nothing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testFuzzy() {
|
||||
$this->Shell->runCommand('fuzzy', array());
|
||||
$output = $this->Shell->stdout->output;
|
||||
|
||||
$expected = '';
|
||||
$this->assertEquals($expected, $output);
|
||||
}
|
||||
}
|
|
@ -424,6 +424,29 @@ class SchemaShellTest extends CakeTestCase {
|
|||
$this->assertContains('public $aros_acos = array(', $contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test schema run create with --yes option
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCreateOptionYes() {
|
||||
$this->Shell = $this->getMock(
|
||||
'SchemaShell',
|
||||
array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'),
|
||||
array(&$this->Dispatcher)
|
||||
);
|
||||
|
||||
$this->Shell->params = array(
|
||||
'connection' => 'test',
|
||||
'yes' => true,
|
||||
);
|
||||
$this->Shell->args = array('i18n');
|
||||
$this->Shell->expects($this->never())->method('in');
|
||||
$this->Shell->expects($this->exactly(2))->method('_run');
|
||||
$this->Shell->startup();
|
||||
$this->Shell->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test schema run create with no table args.
|
||||
*
|
||||
|
@ -534,6 +557,33 @@ class SchemaShellTest extends CakeTestCase {
|
|||
$this->Shell->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* test run update with --yes option
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUpdateWithOptionYes() {
|
||||
$this->Shell = $this->getMock(
|
||||
'SchemaShell',
|
||||
array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'),
|
||||
array(&$this->Dispatcher)
|
||||
);
|
||||
|
||||
$this->Shell->params = array(
|
||||
'connection' => 'test',
|
||||
'force' => true,
|
||||
'yes' => true,
|
||||
);
|
||||
$this->Shell->args = array('SchemaShellTest', 'articles');
|
||||
$this->Shell->startup();
|
||||
$this->Shell->expects($this->never())->method('in');
|
||||
$this->Shell->expects($this->once())
|
||||
->method('_run')
|
||||
->with($this->arrayHasKey('articles'), 'update', $this->isInstanceOf('CakeSchema'));
|
||||
|
||||
$this->Shell->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* test that the plugin param creates the correct path in the schema object.
|
||||
*
|
||||
|
|
240
lib/Cake/Test/Case/Console/Command/Task/CommandTaskTest.php
Normal file
240
lib/Cake/Test/Case/Console/Command/Task/CommandTaskTest.php
Normal file
|
@ -0,0 +1,240 @@
|
|||
<?php
|
||||
/**
|
||||
* CakePHP : 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.Test.Case.Console.Command
|
||||
* @since CakePHP v 2.5
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
App::uses('CommandTask', 'Console/Command/Task');
|
||||
|
||||
/**
|
||||
* CommandTaskTest class
|
||||
*
|
||||
* @package Cake.Test.Case.Console.Command.Task
|
||||
*/
|
||||
class CommandTaskTest extends CakeTestCase {
|
||||
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
App::build(array(
|
||||
'Plugin' => array(
|
||||
CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS
|
||||
),
|
||||
'Console/Command' => array(
|
||||
CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS
|
||||
)
|
||||
), App::RESET);
|
||||
CakePlugin::load(array('TestPlugin', 'TestPluginTwo'));
|
||||
|
||||
$out = $this->getMock('ConsoleOutput', array(), array(), '', false);
|
||||
$in = $this->getMock('ConsoleInput', array(), array(), '', false);
|
||||
|
||||
$this->CommandTask = $this->getMock(
|
||||
'CommandTask',
|
||||
array('in', '_stop', 'clear'),
|
||||
array($out, $out, $in)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
unset($this->CommandTask);
|
||||
CakePlugin::unload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the resulting list of shells
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetShellList() {
|
||||
$result = $this->CommandTask->getShellList();
|
||||
|
||||
$expected = array(
|
||||
'CORE' => array(
|
||||
'acl',
|
||||
'api',
|
||||
'bake',
|
||||
'command_list',
|
||||
'completion',
|
||||
'console',
|
||||
'i18n',
|
||||
'schema',
|
||||
'server',
|
||||
'test',
|
||||
'testsuite',
|
||||
'upgrade'
|
||||
),
|
||||
'TestPlugin' => array(
|
||||
'example'
|
||||
),
|
||||
'TestPluginTwo' => array(
|
||||
'example',
|
||||
'welcome'
|
||||
),
|
||||
'app' => array(
|
||||
'sample'
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the resulting list of commands
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCommands() {
|
||||
$result = $this->CommandTask->commands();
|
||||
|
||||
$expected = array(
|
||||
'TestPlugin.example',
|
||||
'TestPluginTwo.example',
|
||||
'TestPluginTwo.welcome',
|
||||
'acl',
|
||||
'api',
|
||||
'bake',
|
||||
'command_list',
|
||||
'completion',
|
||||
'console',
|
||||
'i18n',
|
||||
'schema',
|
||||
'server',
|
||||
'test',
|
||||
'testsuite',
|
||||
'upgrade',
|
||||
'sample'
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the resulting list of subcommands for the given command
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommands() {
|
||||
$result = $this->CommandTask->subCommands('acl');
|
||||
|
||||
$expected = array(
|
||||
'check',
|
||||
'create',
|
||||
'db_config',
|
||||
'delete',
|
||||
'deny',
|
||||
'getPath',
|
||||
'grant',
|
||||
'inherit',
|
||||
'initdb',
|
||||
'nodeExists',
|
||||
'parseIdentifier',
|
||||
'setParent',
|
||||
'view'
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that unknown commands return an empty array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSubCommandsUnknownCommand() {
|
||||
$result = $this->CommandTask->subCommands('yoghurt');
|
||||
|
||||
$expected = array();
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getting a existing shell returns the shell instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetShell() {
|
||||
$result = $this->CommandTask->getShell('acl');
|
||||
$this->assertInstanceOf('AclShell', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getting a non-existing shell returns false
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetShellNonExisting() {
|
||||
$result = $this->CommandTask->getShell('strawberry');
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that getting a existing core shell with 'core.' prefix returns the correct shell instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGetShellCore() {
|
||||
$result = $this->CommandTask->getShell('core.bake');
|
||||
$this->assertInstanceOf('BakeShell', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the options array for a known command
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOptions() {
|
||||
$result = $this->CommandTask->options('bake');
|
||||
|
||||
$expected = array(
|
||||
'--help',
|
||||
'-h',
|
||||
'--verbose',
|
||||
'-v',
|
||||
'--quiet',
|
||||
'-q',
|
||||
'--connection',
|
||||
'-c',
|
||||
'--theme',
|
||||
'-t'
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the options array for an unknown command
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testOptionsUnknownCommand() {
|
||||
$result = $this->CommandTask->options('pie');
|
||||
|
||||
$expected = array(
|
||||
'--help',
|
||||
'-h',
|
||||
'--verbose',
|
||||
'-v',
|
||||
'--quiet',
|
||||
'-q'
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@ App::uses('ModelTask', 'Console/Command/Task');
|
|||
* ModelTaskTest class
|
||||
*
|
||||
* @package Cake.Test.Case.Console.Command.Task
|
||||
* @property ModelTask $Task
|
||||
*/
|
||||
class ModelTaskTest extends CakeTestCase {
|
||||
|
||||
|
@ -359,14 +360,53 @@ class ModelTaskTest extends CakeTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* test the validation Generation routine
|
||||
* Test that skipping fields during rule choice works when doing interactive field validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNonInteractiveDoValidation() {
|
||||
public function testSkippingChoiceInteractiveFieldValidation() {
|
||||
$this->Task->initValidations();
|
||||
$this->Task->interactive = true;
|
||||
$this->Task->expects($this->any())->method('in')
|
||||
->will($this->onConsecutiveCalls('24', 'y', 's'));
|
||||
|
||||
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
|
||||
$expected = array('notEmpty' => 'notEmpty', '_skipFields' => true);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that skipping fields after rule choice works when doing interactive field validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSkippingAnotherInteractiveFieldValidation() {
|
||||
$this->Task->initValidations();
|
||||
$this->Task->interactive = true;
|
||||
$this->Task->expects($this->any())->method('in')
|
||||
->will($this->onConsecutiveCalls('24', 's'));
|
||||
|
||||
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
|
||||
$expected = array('notEmpty' => 'notEmpty', '_skipFields' => true);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the validation generation routine with skipping the rest of the fields
|
||||
* when doing interactive field validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testInteractiveDoValidationWithSkipping() {
|
||||
$this->Task->expects($this->any())
|
||||
->method('in')
|
||||
->will($this->onConsecutiveCalls('35', '24', 'n', '11', 's'));
|
||||
$this->Task->interactive = true;
|
||||
$Model = $this->getMock('Model');
|
||||
$Model->primaryKey = 'id';
|
||||
$Model->expects($this->any())->method('schema')->will($this->returnValue(array(
|
||||
$Model->expects($this->any())
|
||||
->method('schema')
|
||||
->will($this->returnValue(array(
|
||||
'id' => array(
|
||||
'type' => 'integer',
|
||||
'length' => 11,
|
||||
|
@ -398,7 +438,65 @@ class ModelTaskTest extends CakeTestCase {
|
|||
'length' => '',
|
||||
'null' => false,
|
||||
)
|
||||
)));
|
||||
)
|
||||
));
|
||||
|
||||
$result = $this->Task->doValidation($Model);
|
||||
$expected = array(
|
||||
'name' => array(
|
||||
'notEmpty' => 'notEmpty'
|
||||
),
|
||||
'email' => array(
|
||||
'email' => 'email',
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test the validation Generation routine
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testNonInteractiveDoValidation() {
|
||||
$Model = $this->getMock('Model');
|
||||
$Model->primaryKey = 'id';
|
||||
$Model->expects($this->any())
|
||||
->method('schema')
|
||||
->will($this->returnValue(array(
|
||||
'id' => array(
|
||||
'type' => 'integer',
|
||||
'length' => 11,
|
||||
'null' => false,
|
||||
'key' => 'primary',
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'length' => 20,
|
||||
'null' => false,
|
||||
),
|
||||
'email' => array(
|
||||
'type' => 'string',
|
||||
'length' => 255,
|
||||
'null' => false,
|
||||
),
|
||||
'some_date' => array(
|
||||
'type' => 'date',
|
||||
'length' => '',
|
||||
'null' => false,
|
||||
),
|
||||
'some_time' => array(
|
||||
'type' => 'time',
|
||||
'length' => '',
|
||||
'null' => false,
|
||||
),
|
||||
'created' => array(
|
||||
'type' => 'datetime',
|
||||
'length' => '',
|
||||
'null' => false,
|
||||
)
|
||||
)
|
||||
));
|
||||
$this->Task->interactive = false;
|
||||
|
||||
$result = $this->Task->doValidation($Model);
|
||||
|
|
|
@ -413,6 +413,8 @@ class TestTaskTest extends CakeTestCase {
|
|||
|
||||
$this->assertContains('function testDoSomething()', $result);
|
||||
$this->assertContains('function testDoSomethingElse()', $result);
|
||||
$this->assertContains('$this->markTestIncomplete(\'testDoSomething not implemented.\')', $result);
|
||||
$this->assertContains('$this->markTestIncomplete(\'testDoSomethingElse not implemented.\')', $result);
|
||||
|
||||
$this->assertContains("'app.test_task_article'", $result);
|
||||
$this->assertContains("'app.test_task_comment'", $result);
|
||||
|
|
|
@ -256,7 +256,6 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testDbAclAllow method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testAllow() {
|
||||
|
@ -297,17 +296,16 @@ class DbAclTest extends CakeTestCase {
|
|||
* @return void
|
||||
*/
|
||||
public function testAllowInvalidPermission() {
|
||||
$this->Acl->allow('Micheal', 'tpsReports', 'derp');
|
||||
$this->assertFalse($this->Acl->allow('Micheal', 'tpsReports', 'derp'));
|
||||
}
|
||||
|
||||
/**
|
||||
* testAllowInvalidNode method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testAllowInvalidNode() {
|
||||
$this->Acl->allow('Homer', 'tpsReports', 'create');
|
||||
$this->assertFalse($this->Acl->allow('Homer', 'tpsReports', 'create'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -333,7 +331,6 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testCheckInvalidNode method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testCheckInvalidNode() {
|
||||
|
@ -343,21 +340,19 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testCheckInvalidPermission method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Notice
|
||||
* @return void
|
||||
*/
|
||||
public function testCheckInvalidPermission() {
|
||||
$this->Acl->check('Lumbergh', 'smash', 'foobar');
|
||||
$this->assertFalse($this->Acl->check('Lumbergh', 'smash', 'foobar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* testCheckMissingPermission method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testCheckMissingPermission() {
|
||||
$this->Acl->check('users', 'NonExistent', 'read');
|
||||
$this->assertFalse($this->Acl->check('users', 'NonExistent', 'read'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,7 +375,6 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testDbAclDeny method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testDeny() {
|
||||
|
@ -450,7 +444,6 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testDbGrant method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testGrant() {
|
||||
|
@ -471,7 +464,6 @@ class DbAclTest extends CakeTestCase {
|
|||
/**
|
||||
* testDbRevoke method
|
||||
*
|
||||
* @expectedException PHPUnit_Framework_Error_Warning
|
||||
* @return void
|
||||
*/
|
||||
public function testRevoke() {
|
||||
|
|
|
@ -590,6 +590,27 @@ class AuthComponentTest extends CakeTestCase {
|
|||
$this->assertEquals('AuthUser', $result->settings['userModel']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test defining the same Authenticate object but with different password hashers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSameAuthenticateWithDifferentHashers() {
|
||||
$this->Controller->Auth->authenticate = array(
|
||||
'FormSimple' => array('className' => 'Form', 'passwordHasher' => 'Simple'),
|
||||
'FormBlowfish' => array('className' => 'Form', 'passwordHasher' => 'Blowfish'),
|
||||
);
|
||||
|
||||
$objects = $this->Controller->Auth->constructAuthenticate();
|
||||
$this->assertEquals(2, count($objects));
|
||||
|
||||
$this->assertInstanceOf('FormAuthenticate', $objects[0]);
|
||||
$this->assertInstanceOf('FormAuthenticate', $objects[1]);
|
||||
|
||||
$this->assertInstanceOf('SimplePasswordHasher', $objects[0]->passwordHasher());
|
||||
$this->assertInstanceOf('BlowfishPasswordHasher', $objects[1]->passwordHasher());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that deny always takes precedence over allow
|
||||
*
|
||||
|
@ -1123,11 +1144,13 @@ class AuthComponentTest extends CakeTestCase {
|
|||
|
||||
App::uses('Dispatcher', 'Routing');
|
||||
|
||||
$Response = new CakeResponse();
|
||||
ob_start();
|
||||
$Dispatcher = new Dispatcher();
|
||||
$Dispatcher->dispatch(new CakeRequest('/ajax_auth/add'), new CakeResponse(), array('return' => 1));
|
||||
$Dispatcher->dispatch(new CakeRequest('/ajax_auth/add'), $Response, array('return' => 1));
|
||||
$result = ob_get_clean();
|
||||
|
||||
$this->assertEquals(403, $Response->statusCode());
|
||||
$this->assertEquals("Ajax!\nthis is the test element", str_replace("\r\n", "\n", $result));
|
||||
unset($_SERVER['HTTP_X_REQUESTED_WITH']);
|
||||
}
|
||||
|
|
|
@ -201,6 +201,40 @@ class CookieComponentTest extends CakeTestCase {
|
|||
$this->assertEquals('value', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test write() encrypted data with falsey value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testWriteWithFalseyValue() {
|
||||
$this->Cookie->type('aes');
|
||||
$this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^';
|
||||
|
||||
$this->Cookie->write('Testing');
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertNull($result);
|
||||
|
||||
$this->Cookie->write('Testing', '');
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertEquals('', $result);
|
||||
|
||||
$this->Cookie->write('Testing', false);
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertFalse($result);
|
||||
|
||||
$this->Cookie->write('Testing', 1);
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertEquals(1, $result);
|
||||
|
||||
$this->Cookie->write('Testing', '0');
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertSame('0', $result);
|
||||
|
||||
$this->Cookie->write('Testing', 0);
|
||||
$result = $this->Cookie->read('Testing');
|
||||
$this->assertSame(0, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that two write() calls use the expiry.
|
||||
*
|
||||
|
|
|
@ -191,14 +191,14 @@ This is the body of the message
|
|||
MSGBLOC;
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'text';
|
||||
$expect = str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $message);
|
||||
$expected = str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $message);
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
|
||||
$this->assertTextEquals(DebugCompTransport::$lastEmail, $expect);
|
||||
$this->assertTextEquals($expected, DebugCompTransport::$lastEmail);
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'html';
|
||||
$expect = str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $message);
|
||||
$expected = str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $message);
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
|
||||
$this->assertTextEquals(DebugCompTransport::$lastEmail, $expect);
|
||||
$this->assertTextEquals($expected, DebugCompTransport::$lastEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -262,18 +262,18 @@ TEXTBLOC;
|
|||
HTMLBLOC;
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'text';
|
||||
$expect = '<pre>' . str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $header) . $text . "\n" . '</pre>';
|
||||
$expected = '<pre>' . str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $header) . $text . "\n" . '</pre>';
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
|
||||
$this->assertTextEquals(DebugCompTransport::$lastEmail, $expect);
|
||||
$this->assertTextEquals($expected, DebugCompTransport::$lastEmail);
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'html';
|
||||
$expect = '<pre>' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . "\n" . '</pre>';
|
||||
$expected = '<pre>' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . "\n" . '</pre>';
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
|
||||
$this->assertTextEquals(DebugCompTransport::$lastEmail, $expect);
|
||||
$this->assertTextEquals($expected, DebugCompTransport::$lastEmail);
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'both';
|
||||
$expect = str_replace('{CONTENTTYPE}', 'multipart/mixed; boundary="{boundary}"', $header);
|
||||
$expect .= "--{boundary}\n" .
|
||||
$expected = str_replace('{CONTENTTYPE}', 'multipart/mixed; boundary="{boundary}"', $header);
|
||||
$expected .= "--{boundary}\n" .
|
||||
'Content-Type: multipart/alternative; boundary="alt-{boundary}"' . "\n\n" .
|
||||
'--alt-{boundary}' . "\n" .
|
||||
'Content-Type: text/plain; charset=UTF-8' . "\n" .
|
||||
|
@ -288,11 +288,11 @@ HTMLBLOC;
|
|||
'--alt-{boundary}--' . "\n\n\n" .
|
||||
'--{boundary}--' . "\n";
|
||||
|
||||
$expect = '<pre>' . $expect . '</pre>';
|
||||
$expected = '<pre>' . $expected . '</pre>';
|
||||
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
|
||||
$this->assertTextEquals(
|
||||
$expect,
|
||||
$expected,
|
||||
preg_replace('/[a-z0-9]{32}/i', '{boundary}', DebugCompTransport::$lastEmail)
|
||||
);
|
||||
|
||||
|
@ -313,9 +313,9 @@ HTMLBLOC;
|
|||
HTMLBLOC;
|
||||
|
||||
$this->Controller->EmailTest->sendAs = 'html';
|
||||
$expect = '<pre>' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . '</pre>';
|
||||
$expected = '<pre>' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . '</pre>';
|
||||
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message', 'default', 'thin'));
|
||||
$this->assertTextEquals(DebugCompTransport::$lastEmail, $expect);
|
||||
$this->assertTextEquals($expected, DebugCompTransport::$lastEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -358,7 +358,7 @@ class PaginatorComponentTest extends CakeTestCase {
|
|||
$this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']);
|
||||
$this->assertEquals(array(3, 2, 1), $results);
|
||||
|
||||
$Controller->request->params['named'] = array('sort' => 'NotExisting.field', 'direction' => 'desc');
|
||||
$Controller->request->params['named'] = array('sort' => 'NotExisting.field', 'direction' => 'desc', 'limit' => 2);
|
||||
$Controller->Paginator->paginate('PaginatorControllerPost');
|
||||
$this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']);
|
||||
$this->assertEquals(array(), $Controller->PaginatorControllerPost->lastQueries[1]['order'][0], 'no order should be set.');
|
||||
|
@ -367,7 +367,7 @@ class PaginatorComponentTest extends CakeTestCase {
|
|||
'sort' => 'PaginatorControllerPost.author_id', 'direction' => 'allYourBase'
|
||||
);
|
||||
$results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id');
|
||||
$this->assertEquals(array('PaginatorControllerPost.author_id' => 'asc'), $Controller->PaginatorControllerPost->lastQueries[1]['order'][0]);
|
||||
$this->assertEquals(array('PaginatorControllerPost.author_id' => 'asc'), $Controller->PaginatorControllerPost->lastQueries[0]['order'][0]);
|
||||
$this->assertEquals(array(1, 3, 2), $results);
|
||||
|
||||
$Controller->request->params['named'] = array();
|
||||
|
@ -466,7 +466,7 @@ class PaginatorComponentTest extends CakeTestCase {
|
|||
$result = $Controller->Paginator->paginate('PaginatorControllerPost');
|
||||
$this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']);
|
||||
$this->assertEquals(array(1, 2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id'));
|
||||
$this->assertTrue(isset($Controller->PaginatorControllerPost->lastQueries[1]['contain']));
|
||||
$this->assertTrue(isset($Controller->PaginatorControllerPost->lastQueries[0]['contain']));
|
||||
|
||||
$Controller->Paginator->settings = array(
|
||||
'PaginatorControllerPost' => array(
|
||||
|
@ -475,14 +475,14 @@ class PaginatorComponentTest extends CakeTestCase {
|
|||
);
|
||||
$result = $Controller->Paginator->paginate('PaginatorControllerPost');
|
||||
$this->assertEquals(array(2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id'));
|
||||
$this->assertEquals(array('PaginatorControllerPost.id > ' => '1'), $Controller->PaginatorControllerPost->lastQueries[1]['conditions']);
|
||||
$this->assertEquals(array('PaginatorControllerPost.id > ' => '1'), $Controller->PaginatorControllerPost->lastQueries[0]['conditions']);
|
||||
|
||||
$Controller->request->params['named'] = array('limit' => 12);
|
||||
$Controller->Paginator->settings = array('limit' => 30, 'maxLimit' => 100, 'paramType' => 'named');
|
||||
$result = $Controller->Paginator->paginate('PaginatorControllerPost');
|
||||
$paging = $Controller->params['paging']['PaginatorControllerPost'];
|
||||
|
||||
$this->assertEquals(12, $Controller->PaginatorControllerPost->lastQueries[1]['limit']);
|
||||
$this->assertEquals(12, $Controller->PaginatorControllerPost->lastQueries[0]['limit']);
|
||||
$this->assertEquals(12, $paging['options']['limit']);
|
||||
|
||||
$Controller = new PaginatorTestController($this->request);
|
||||
|
@ -551,7 +551,7 @@ class PaginatorComponentTest extends CakeTestCase {
|
|||
|
||||
$this->assertEquals(array(2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id'));
|
||||
$this->assertEquals(
|
||||
$Controller->PaginatorControllerPost->lastQueries[1]['conditions'],
|
||||
$Controller->PaginatorControllerPost->lastQueries[0]['conditions'],
|
||||
array('PaginatorControllerPost.id > ' => '1')
|
||||
);
|
||||
$this->assertFalse(isset($Controller->params['paging']['PaginatorControllerPost']['options'][0]));
|
||||
|
|
|
@ -352,19 +352,6 @@ class RequestHandlerComponentTest extends CakeTestCase {
|
|||
$this->assertEquals(true, $this->Controller->params['isAjax']);
|
||||
}
|
||||
|
||||
/**
|
||||
* testAutoResponseType method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAutoResponseType() {
|
||||
$this->Controller->ext = '.thtml';
|
||||
$this->Controller->request->params['ext'] = 'rss';
|
||||
$this->RequestHandler->initialize($this->Controller);
|
||||
$this->RequestHandler->startup($this->Controller);
|
||||
$this->assertEquals('.ctp', $this->Controller->ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* testAutoAjaxLayout method
|
||||
*
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue