mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-17 12:28:24 +00:00
Merge branch '2.3' of https://github.com/cakephp/cakephp
This commit is contained in:
commit
d1a591bd44
213 changed files with 11037 additions and 3108 deletions
|
@ -1,11 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* This is i18n Schema file
|
|
||||||
*
|
|
||||||
* Use it to configure database for i18n
|
|
||||||
*
|
|
||||||
* PHP 5
|
|
||||||
*
|
|
||||||
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||||
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
*
|
*
|
||||||
|
@ -19,15 +13,16 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @codingStandardsIgnoreStart
|
/**
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
*
|
||||||
* Using the Schema command line utility
|
* Using the Schema command line utility
|
||||||
|
*
|
||||||
|
* Use it to configure database for i18n
|
||||||
|
*
|
||||||
* cake schema run create i18n
|
* cake schema run create i18n
|
||||||
*/
|
*/
|
||||||
class i18nSchema extends CakeSchema {
|
// @codingStandardsIgnoreStart
|
||||||
|
class I18nSchema extends CakeSchema {
|
||||||
// @codingStandardsIgnoreEnd
|
// @codingStandardsIgnoreEnd
|
||||||
|
|
||||||
public $name = 'i18n';
|
public $name = 'i18n';
|
||||||
|
|
|
@ -232,17 +232,16 @@
|
||||||
//date_default_timezone_set('UTC');
|
//date_default_timezone_set('UTC');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick the caching engine to use. If APC is enabled use it.
|
* Configure the cache handlers that CakePHP will use for internal
|
||||||
* If running via cli - apc is disabled by default. ensure it's available and enabled in this case
|
* metadata like class maps, and model schema.
|
||||||
|
*
|
||||||
|
* By default File is used, but for improved performance you should use APC.
|
||||||
*
|
*
|
||||||
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
|
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
|
||||||
* Please check the comments in boostrap.php for more info on the cache engines available
|
* Please check the comments in boostrap.php for more info on the cache engines available
|
||||||
* and their setttings.
|
* and their setttings.
|
||||||
*/
|
*/
|
||||||
$engine = 'File';
|
$engine = 'File';
|
||||||
if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) {
|
|
||||||
$engine = 'Apc';
|
|
||||||
}
|
|
||||||
|
|
||||||
// In development mode, caches should expire quickly.
|
// In development mode, caches should expire quickly.
|
||||||
$duration = '+999 days';
|
$duration = '+999 days';
|
||||||
|
|
|
@ -17,17 +17,21 @@
|
||||||
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
LIB=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && LIB=$LIB/$(basename -- "$0")
|
|
||||||
|
|
||||||
while [ -h "$LIB" ]; do
|
# Canonicalize by following every symlink of the given name recursively
|
||||||
DIR=$(dirname -- "$LIB")
|
canonicalize() {
|
||||||
SYM=$(readlink "$LIB")
|
NAME=$1
|
||||||
LIB=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
while [ -h "$NAME" ]; do
|
||||||
|
DIR=$(dirname -- "$NAME")
|
||||||
|
SYM=$(readlink "$NAME")
|
||||||
|
NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
||||||
done
|
done
|
||||||
|
echo "$NAME"
|
||||||
|
}
|
||||||
|
|
||||||
LIB=$(dirname -- "$LIB")/
|
CONSOLE=$(dirname $(canonicalize "$0"))
|
||||||
APP=$(dirname $(cd $(dirname $0) && pwd))
|
APP=$(dirname "$CONSOLE")
|
||||||
|
|
||||||
exec php -q "$LIB"cake.php -working "$APP" "$@"
|
exec php -q $CONSOLE/cake.php -working "$APP" "$@"
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* @since CakePHP(tm) v 0.10.0.1076
|
* @since CakePHP(tm) v 0.10.0.1076
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
if (Configure::read('debug') == 0):
|
if (!Configure::read('debug')):
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
endif;
|
endif;
|
||||||
App::uses('Debugger', 'Utility');
|
App::uses('Debugger', 'Utility');
|
||||||
|
@ -127,6 +127,23 @@ if (isset($filePresent)):
|
||||||
echo '</span></p>';
|
echo '</span></p>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
if (CakePlugin::loaded('DebugKit')):
|
||||||
|
echo '<span class="notice success">';
|
||||||
|
echo __d('cake_dev', 'DebugKit plugin is present');
|
||||||
|
echo '</span>';
|
||||||
|
else:
|
||||||
|
echo '<span class="notice">';
|
||||||
|
echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.');
|
||||||
|
echo '<br/>';
|
||||||
|
echo __d('cake_dev', 'You can install it from %s', $this->Html->link('github', 'https://github.com/cakephp/debug_kit'));
|
||||||
|
echo '</span>';
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
|
<h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
|
||||||
<p>
|
<p>
|
||||||
<?php
|
<?php
|
||||||
|
@ -156,6 +173,20 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3><?php echo __d('cake_dev', 'Official Plugins'); ?></h3>
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<?php echo $this->Html->link('DebugKit', 'https://github.com/cakephp/debug_kit') ?>:
|
||||||
|
<?php echo __d('cake_dev', 'provides a debugging toolbar and enhanced debugging tools for CakePHP applications.'); ?>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<?php echo $this->Html->link('Localized', 'https://github.com/cakephp/localized') ?>:
|
||||||
|
<?php echo __d('cake_dev', 'contains various localized validation classes and translations for specific countries'); ?>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3>
|
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3>
|
||||||
<p>
|
<p>
|
||||||
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
|
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
|
||||||
|
@ -175,8 +206,8 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');
|
||||||
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li>
|
||||||
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
|
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
|
||||||
<li><a href="http://live.cakephp.org"><?php echo __d('cake_dev', 'The Show'); ?> </a>
|
<li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP plugins repo'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'The Show is a live and archived internet radio broadcast CakePHP-related topics and answer questions live via IRC, Skype, and telephone.'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li>
|
||||||
<li><a href="http://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
|
<li><a href="http://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
|
||||||
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
|
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
|
||||||
|
|
|
@ -70,6 +70,11 @@ if (!defined('WWW_ROOT')) {
|
||||||
define('WWW_ROOT', dirname(__FILE__) . DS);
|
define('WWW_ROOT', dirname(__FILE__) . DS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for built-in server
|
||||||
|
if (php_sapi_name() == 'cli-server') {
|
||||||
|
$_SERVER['PHP_SELF'] = '/' . basename(__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
|
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
|
||||||
if (function_exists('ini_set')) {
|
if (function_exists('ini_set')) {
|
||||||
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
|
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
|
||||||
|
@ -89,4 +94,4 @@ if (!empty($failed)) {
|
||||||
App::uses('Dispatcher', 'Routing');
|
App::uses('Dispatcher', 'Routing');
|
||||||
|
|
||||||
$Dispatcher = new Dispatcher();
|
$Dispatcher = new Dispatcher();
|
||||||
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse(array('charset' => Configure::read('App.encoding'))));
|
$Dispatcher->dispatch(new CakeRequest(), new CakeResponse());
|
||||||
|
|
|
@ -103,7 +103,7 @@ class Cache {
|
||||||
* - `path` Used by FileCache. Path to where cachefiles should be saved.
|
* - `path` Used by FileCache. Path to where cachefiles should be saved.
|
||||||
* - `lock` Used by FileCache. Should files be locked before writing to them?
|
* - `lock` Used by FileCache. Should files be locked before writing to them?
|
||||||
* - `user` Used by Xcache. Username for XCache
|
* - `user` Used by Xcache. Username for XCache
|
||||||
* - `password` Used by Xcache. Password for XCache
|
* - `password` Used by Xcache/Redis. Password for XCache/Redis
|
||||||
*
|
*
|
||||||
* @see app/Config/core.php for configuration settings
|
* @see app/Config/core.php for configuration settings
|
||||||
* @param string $name Name of the configuration
|
* @param string $name Name of the configuration
|
||||||
|
@ -366,7 +366,7 @@ class Cache {
|
||||||
}
|
}
|
||||||
$key = self::$_engines[$config]->key($key);
|
$key = self::$_engines[$config]->key($key);
|
||||||
|
|
||||||
if (!$key || !is_integer($offset) || $offset < 0) {
|
if (!$key || !is_int($offset) || $offset < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
|
$success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
|
||||||
|
@ -394,7 +394,7 @@ class Cache {
|
||||||
}
|
}
|
||||||
$key = self::$_engines[$config]->key($key);
|
$key = self::$_engines[$config]->key($key);
|
||||||
|
|
||||||
if (!$key || !is_integer($offset) || $offset < 0) {
|
if (!$key || !is_int($offset) || $offset < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
|
$success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
|
||||||
|
|
|
@ -61,9 +61,8 @@ class ApcEngine extends CacheEngine {
|
||||||
* @return boolean True if the data was successfully cached, false on failure
|
* @return boolean True if the data was successfully cached, false on failure
|
||||||
*/
|
*/
|
||||||
public function write($key, $value, $duration) {
|
public function write($key, $value, $duration) {
|
||||||
if ($duration == 0) {
|
|
||||||
$expires = 0;
|
$expires = 0;
|
||||||
} else {
|
if ($duration) {
|
||||||
$expires = time() + $duration;
|
$expires = time() + $duration;
|
||||||
}
|
}
|
||||||
apc_store($key . '_expires', $expires, $duration);
|
apc_store($key . '_expires', $expires, $duration);
|
||||||
|
|
|
@ -62,6 +62,7 @@ class RedisEngine extends CacheEngine {
|
||||||
'prefix' => null,
|
'prefix' => null,
|
||||||
'server' => '127.0.0.1',
|
'server' => '127.0.0.1',
|
||||||
'port' => 6379,
|
'port' => 6379,
|
||||||
|
'password' => false,
|
||||||
'timeout' => 0,
|
'timeout' => 0,
|
||||||
'persistent' => true
|
'persistent' => true
|
||||||
), $settings)
|
), $settings)
|
||||||
|
@ -87,6 +88,9 @@ class RedisEngine extends CacheEngine {
|
||||||
} catch (RedisException $e) {
|
} catch (RedisException $e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if ($return && $this->settings['password']) {
|
||||||
|
$return = $this->_Redis->auth($this->settings['password']);
|
||||||
|
}
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3920
lib/Cake/Config/cacert.pem
Normal file
3920
lib/Cake/Config/cacert.pem
Normal file
File diff suppressed because it is too large
Load diff
|
@ -173,8 +173,10 @@ class IniReader implements ConfigReaderInterface {
|
||||||
public function dump($filename, $data) {
|
public function dump($filename, $data) {
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach ($data as $key => $value) {
|
foreach ($data as $key => $value) {
|
||||||
|
$isSection = false;
|
||||||
if ($key[0] != '[') {
|
if ($key[0] != '[') {
|
||||||
$result[] = "[$key]";
|
$result[] = "[$key]";
|
||||||
|
$isSection = true;
|
||||||
}
|
}
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$keyValues = Hash::flatten($value, '.');
|
$keyValues = Hash::flatten($value, '.');
|
||||||
|
@ -182,8 +184,11 @@ class IniReader implements ConfigReaderInterface {
|
||||||
$result[] = "$k = " . $this->_value($v);
|
$result[] = "$k = " . $this->_value($v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($isSection) {
|
||||||
|
$result[] = '';
|
||||||
}
|
}
|
||||||
$contents = join("\n", $result);
|
}
|
||||||
|
$contents = trim(implode("\n", $result));
|
||||||
|
|
||||||
if (substr($filename, -4) !== '.ini') {
|
if (substr($filename, -4) !== '.ini') {
|
||||||
$filename .= '.ini';
|
$filename .= '.ini';
|
||||||
|
|
|
@ -598,7 +598,7 @@ class AclShell extends AppShell {
|
||||||
* @return array Variables
|
* @return array Variables
|
||||||
*/
|
*/
|
||||||
protected function _dataVars($type = null) {
|
protected function _dataVars($type = null) {
|
||||||
if ($type == null) {
|
if (!$type) {
|
||||||
$type = $this->args[0];
|
$type = $this->args[0];
|
||||||
}
|
}
|
||||||
$vars = array();
|
$vars = array();
|
||||||
|
|
|
@ -73,12 +73,13 @@ class ApiShell extends AppShell {
|
||||||
$path = $this->paths['core'];
|
$path = $this->paths['core'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->args) == 1) {
|
$count = count($this->args);
|
||||||
$file = $type;
|
if ($count > 1) {
|
||||||
$class = Inflector::camelize($type);
|
|
||||||
} elseif (count($this->args) > 1) {
|
|
||||||
$file = Inflector::underscore($this->args[1]);
|
$file = Inflector::underscore($this->args[1]);
|
||||||
$class = Inflector::camelize($this->args[1]);
|
$class = Inflector::camelize($this->args[1]);
|
||||||
|
} elseif ($count) {
|
||||||
|
$file = $type;
|
||||||
|
$class = Inflector::camelize($type);
|
||||||
}
|
}
|
||||||
$objects = App::objects('class', $path);
|
$objects = App::objects('class', $path);
|
||||||
if (in_array($class, $objects)) {
|
if (in_array($class, $objects)) {
|
||||||
|
|
|
@ -182,7 +182,7 @@ class ConsoleShell extends AppShell {
|
||||||
$this->out(" - {$model}");
|
$this->out(" - {$model}");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^(\w+) bind (\w+) (\w+)/", $command, $tmp) == true):
|
case preg_match("/^(\w+) bind (\w+) (\w+)/", $command, $tmp):
|
||||||
foreach ($tmp as $data) {
|
foreach ($tmp as $data) {
|
||||||
$data = strip_tags($data);
|
$data = strip_tags($data);
|
||||||
$data = str_replace($this->badCommandChars, "", $data);
|
$data = str_replace($this->badCommandChars, "", $data);
|
||||||
|
@ -200,7 +200,7 @@ class ConsoleShell extends AppShell {
|
||||||
$this->out(__d('cake_console', "Please verify you are using valid models and association types"));
|
$this->out(__d('cake_console', "Please verify you are using valid models and association types"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^(\w+) unbind (\w+) (\w+)/", $command, $tmp) == true):
|
case preg_match("/^(\w+) unbind (\w+) (\w+)/", $command, $tmp):
|
||||||
foreach ($tmp as $data) {
|
foreach ($tmp as $data) {
|
||||||
$data = strip_tags($data);
|
$data = strip_tags($data);
|
||||||
$data = str_replace($this->badCommandChars, "", $data);
|
$data = str_replace($this->badCommandChars, "", $data);
|
||||||
|
@ -298,7 +298,7 @@ class ConsoleShell extends AppShell {
|
||||||
$this->out(__d('cake_console', 'Saved record for %s', $modelToSave));
|
$this->out(__d('cake_console', 'Saved record for %s', $modelToSave));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^(\w+) columns/", $command, $tmp) == true):
|
case preg_match("/^(\w+) columns/", $command, $tmp):
|
||||||
$modelToCheck = strip_tags(str_replace($this->badCommandChars, "", $tmp[1]));
|
$modelToCheck = strip_tags(str_replace($this->badCommandChars, "", $tmp[1]));
|
||||||
|
|
||||||
if ($this->_isValidModel($modelToCheck)) {
|
if ($this->_isValidModel($modelToCheck)) {
|
||||||
|
@ -315,22 +315,22 @@ class ConsoleShell extends AppShell {
|
||||||
$this->out(__d('cake_console', "Please verify that you selected a valid model"));
|
$this->out(__d('cake_console', "Please verify that you selected a valid model"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^routes\s+reload/i", $command, $tmp) == true):
|
case preg_match("/^routes\s+reload/i", $command, $tmp):
|
||||||
if (!$this->_loadRoutes()) {
|
if (!$this->_loadRoutes()) {
|
||||||
$this->err(__d('cake_console', "There was an error loading the routes config. Please check that the file exists and is free of parse errors."));
|
$this->err(__d('cake_console', "There was an error loading the routes config. Please check that the file exists and is free of parse errors."));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->out(__d('cake_console', "Routes configuration reloaded, %d routes connected", count(Router::$routes)));
|
$this->out(__d('cake_console', "Routes configuration reloaded, %d routes connected", count(Router::$routes)));
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^routes\s+show/i", $command, $tmp) == true):
|
case preg_match("/^routes\s+show/i", $command, $tmp):
|
||||||
$this->out(print_r(Hash::combine(Router::$routes, '{n}.template', '{n}.defaults'), true));
|
$this->out(print_r(Hash::combine(Router::$routes, '{n}.template', '{n}.defaults'), true));
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^route\s+(\(.*\))$/i", $command, $tmp) == true):
|
case preg_match("/^route\s+(\(.*\))$/i", $command, $tmp):
|
||||||
if ($url = eval('return array' . $tmp[1] . ';')) {
|
if ($url = eval('return array' . $tmp[1] . ';')) {
|
||||||
$this->out(Router::url($url));
|
$this->out(Router::url($url));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (preg_match("/^route\s+(.*)/i", $command, $tmp) == true):
|
case preg_match("/^route\s+(.*)/i", $command, $tmp):
|
||||||
$this->out(var_export(Router::parse($tmp[1]), true));
|
$this->out(var_export(Router::parse($tmp[1]), true));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -89,6 +89,7 @@ class SchemaShell extends AppShell {
|
||||||
$name = $plugin;
|
$name = $plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$name = Inflector::classify($name);
|
||||||
$this->Schema = new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin'));
|
$this->Schema = new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +121,9 @@ class SchemaShell extends AppShell {
|
||||||
$this->out(__d('cake_console', 'Generating Schema...'));
|
$this->out(__d('cake_console', 'Generating Schema...'));
|
||||||
$options = array();
|
$options = array();
|
||||||
if ($this->params['force']) {
|
if ($this->params['force']) {
|
||||||
$options = array('models' => false);
|
$options['models'] = false;
|
||||||
|
} elseif (!empty($this->params['models'])) {
|
||||||
|
$options['models'] = String::tokenize($this->params['models']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$snapshot = false;
|
$snapshot = false;
|
||||||
|
@ -459,6 +462,10 @@ class SchemaShell extends AppShell {
|
||||||
'short' => 's',
|
'short' => 's',
|
||||||
'help' => __d('cake_console', 'Snapshot number to use/make.')
|
'help' => __d('cake_console', 'Snapshot number to use/make.')
|
||||||
);
|
);
|
||||||
|
$models = array(
|
||||||
|
'short' => 'm',
|
||||||
|
'help' => __d('cake_console', 'Specify models as comma separated list.'),
|
||||||
|
);
|
||||||
$dry = array(
|
$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
|
'boolean' => true
|
||||||
|
@ -484,7 +491,7 @@ class SchemaShell extends AppShell {
|
||||||
))->addSubcommand('generate', array(
|
))->addSubcommand('generate', array(
|
||||||
'help' => __d('cake_console', 'Reads from --connection and writes to --path. Generate snapshots with -s'),
|
'help' => __d('cake_console', 'Reads from --connection and writes to --path. Generate snapshots with -s'),
|
||||||
'parser' => array(
|
'parser' => array(
|
||||||
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'snapshot', 'force'),
|
'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'snapshot', 'force', 'models'),
|
||||||
'arguments' => array(
|
'arguments' => array(
|
||||||
'snapshot' => array('help' => __d('cake_console', 'Generate a snapshot.'))
|
'snapshot' => array('help' => __d('cake_console', 'Generate a snapshot.'))
|
||||||
)
|
)
|
||||||
|
|
167
lib/Cake/Console/Command/ServerShell.php
Normal file
167
lib/Cake/Console/Command/ServerShell.php
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* built-in Server Shell
|
||||||
|
*
|
||||||
|
* PHP 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||||
|
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
* @link http://cakephp.org CakePHP(tm) Project
|
||||||
|
* @since CakePHP(tm) v 2.3.0
|
||||||
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
*/
|
||||||
|
|
||||||
|
App::uses('AppShell', 'Console/Command');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* built-in Server Shell
|
||||||
|
*
|
||||||
|
* @package Cake.Console.Command
|
||||||
|
*/
|
||||||
|
class ServerShell extends AppShell {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default ServerHost
|
||||||
|
*/
|
||||||
|
const DEFAULT_HOST = 'localhost';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default ListenPort
|
||||||
|
*/
|
||||||
|
const DEFAULT_PORT = 80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* server host
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $_host = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* listen port
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $_port = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* document root
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $_documentRoot = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override initialize of the Shell
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function initialize() {
|
||||||
|
$this->_host = self::DEFAULT_HOST;
|
||||||
|
$this->_port = self::DEFAULT_PORT;
|
||||||
|
$this->_documentRoot = WWW_ROOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts up the Shell and displays the welcome message.
|
||||||
|
* Allows for checking and configuring prior to command or main execution
|
||||||
|
*
|
||||||
|
* Override this method if you want to remove the welcome information,
|
||||||
|
* or otherwise modify the pre-command flow.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::startup
|
||||||
|
*/
|
||||||
|
public function startup() {
|
||||||
|
if (!empty($this->params['host'])) {
|
||||||
|
$this->_host = $this->params['host'];
|
||||||
|
}
|
||||||
|
if (!empty($this->params['port'])) {
|
||||||
|
$this->_port = $this->params['port'];
|
||||||
|
}
|
||||||
|
if (!empty($this->params['document_root'])) {
|
||||||
|
$this->_documentRoot = $this->params['document_root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// for windows
|
||||||
|
if (substr($this->_documentRoot, -1, 1) == DIRECTORY_SEPARATOR) {
|
||||||
|
$this->_documentRoot = substr($this->_documentRoot, 0, strlen($this->_documentRoot) - 1);
|
||||||
|
}
|
||||||
|
if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_documentRoot, $m)) {
|
||||||
|
$this->_documentRoot = $m[1] . '\\' . $m[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::startup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a header for the shell
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function _welcome() {
|
||||||
|
$this->out();
|
||||||
|
$this->out(__d('cake_console', '<info>Welcome to CakePHP %s Console</info>', 'v' . Configure::version()));
|
||||||
|
$this->hr();
|
||||||
|
$this->out(__d('cake_console', 'App : %s', APP_DIR));
|
||||||
|
$this->out(__d('cake_console', 'Path: %s', APP));
|
||||||
|
$this->out(__d('cake_console', 'DocumentRoot: %s', $this->_documentRoot));
|
||||||
|
$this->hr();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override main() to handle action
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function main() {
|
||||||
|
if (version_compare(PHP_VERSION, '5.4.0') < 0) {
|
||||||
|
$this->out(__d('cake_console', '<warning>This command is available on PHP5.4 or above</warning>'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$command = sprintf("php -S %s:%d -t %s",
|
||||||
|
$this->_host,
|
||||||
|
$this->_port,
|
||||||
|
$this->_documentRoot
|
||||||
|
);
|
||||||
|
|
||||||
|
$port = ($this->_port == self::DEFAULT_PORT) ? '' : ':' . $this->_port;
|
||||||
|
$this->out(__d('cake_console', 'built-in server is running in http://%s%s/', $this->_host, $port));
|
||||||
|
$ret = system($command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and configure the optionparser.
|
||||||
|
*
|
||||||
|
* @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>'),
|
||||||
|
));
|
||||||
|
|
||||||
|
return $parser;
|
||||||
|
}
|
||||||
|
}
|
|
@ -349,7 +349,7 @@ class ControllerTask extends BakeTask {
|
||||||
public function doHelpers() {
|
public function doHelpers() {
|
||||||
return $this->_doPropertyChoices(
|
return $this->_doPropertyChoices(
|
||||||
__d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"),
|
__d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"),
|
||||||
__d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Ajax, Javascript, Time'")
|
__d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Text, Js, Time'")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ class ControllerTask extends BakeTask {
|
||||||
}
|
}
|
||||||
$this->__tables = $this->Model->getAllTables($useDbConfig);
|
$this->__tables = $this->Model->getAllTables($useDbConfig);
|
||||||
|
|
||||||
if ($this->interactive == true) {
|
if ($this->interactive) {
|
||||||
$this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
|
$this->out(__d('cake_console', 'Possible Controllers based on your current database:'));
|
||||||
$this->hr();
|
$this->hr();
|
||||||
$this->_controllerNames = array();
|
$this->_controllerNames = array();
|
||||||
|
@ -419,14 +419,14 @@ class ControllerTask extends BakeTask {
|
||||||
$controllers = $this->listAll($useDbConfig);
|
$controllers = $this->listAll($useDbConfig);
|
||||||
$enteredController = '';
|
$enteredController = '';
|
||||||
|
|
||||||
while ($enteredController == '') {
|
while (!$enteredController) {
|
||||||
$enteredController = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit"), null, 'q');
|
$enteredController = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit"), null, 'q');
|
||||||
if ($enteredController === 'q') {
|
if ($enteredController === 'q') {
|
||||||
$this->out(__d('cake_console', 'Exit'));
|
$this->out(__d('cake_console', 'Exit'));
|
||||||
return $this->_stop();
|
return $this->_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($enteredController == '' || intval($enteredController) > count($controllers)) {
|
if (!$enteredController || intval($enteredController) > count($controllers)) {
|
||||||
$this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
|
$this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again."));
|
||||||
$enteredController = '';
|
$enteredController = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,10 +92,10 @@ class DbConfigTask extends AppShell {
|
||||||
$done = false;
|
$done = false;
|
||||||
$dbConfigs = array();
|
$dbConfigs = array();
|
||||||
|
|
||||||
while ($done == false) {
|
while (!$done) {
|
||||||
$name = '';
|
$name = '';
|
||||||
|
|
||||||
while ($name == '') {
|
while (!$name) {
|
||||||
$name = $this->in(__d('cake_console', "Name:"), null, 'default');
|
$name = $this->in(__d('cake_console', "Name:"), null, 'default');
|
||||||
if (preg_match('/[^a-z0-9_]/i', $name)) {
|
if (preg_match('/[^a-z0-9_]/i', $name)) {
|
||||||
$name = '';
|
$name = '';
|
||||||
|
@ -116,12 +116,12 @@ class DbConfigTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$host = '';
|
$host = '';
|
||||||
while ($host == '') {
|
while (!$host) {
|
||||||
$host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost');
|
$host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost');
|
||||||
}
|
}
|
||||||
|
|
||||||
$port = '';
|
$port = '';
|
||||||
while ($port == '') {
|
while (!$port) {
|
||||||
$port = $this->in(__d('cake_console', 'Port?'), null, 'n');
|
$port = $this->in(__d('cake_console', 'Port?'), null, 'n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,16 +130,16 @@ class DbConfigTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$login = '';
|
$login = '';
|
||||||
while ($login == '') {
|
while (!$login) {
|
||||||
$login = $this->in(__d('cake_console', 'User:'), null, 'root');
|
$login = $this->in(__d('cake_console', 'User:'), null, 'root');
|
||||||
}
|
}
|
||||||
$password = '';
|
$password = '';
|
||||||
$blankPassword = false;
|
$blankPassword = false;
|
||||||
|
|
||||||
while ($password == '' && $blankPassword == false) {
|
while (!$password && !$blankPassword) {
|
||||||
$password = $this->in(__d('cake_console', 'Password:'));
|
$password = $this->in(__d('cake_console', 'Password:'));
|
||||||
|
|
||||||
if ($password == '') {
|
if (!$password) {
|
||||||
$blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n');
|
$blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n');
|
||||||
if ($blank == 'y') {
|
if ($blank == 'y') {
|
||||||
$blankPassword = true;
|
$blankPassword = true;
|
||||||
|
@ -148,12 +148,12 @@ class DbConfigTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$database = '';
|
$database = '';
|
||||||
while ($database == '') {
|
while (!$database) {
|
||||||
$database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake');
|
$database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake');
|
||||||
}
|
}
|
||||||
|
|
||||||
$prefix = '';
|
$prefix = '';
|
||||||
while ($prefix == '') {
|
while (!$prefix) {
|
||||||
$prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n');
|
$prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n');
|
||||||
}
|
}
|
||||||
if (strtolower($prefix) == 'n') {
|
if (strtolower($prefix) == 'n') {
|
||||||
|
@ -161,7 +161,7 @@ class DbConfigTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$encoding = '';
|
$encoding = '';
|
||||||
while ($encoding == '') {
|
while (!$encoding) {
|
||||||
$encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n');
|
$encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n');
|
||||||
}
|
}
|
||||||
if (strtolower($encoding) == 'n') {
|
if (strtolower($encoding) == 'n') {
|
||||||
|
@ -170,7 +170,7 @@ class DbConfigTask extends AppShell {
|
||||||
|
|
||||||
$schema = '';
|
$schema = '';
|
||||||
if ($datasource == 'postgres') {
|
if ($datasource == 'postgres') {
|
||||||
while ($schema == '') {
|
while (!$schema) {
|
||||||
$schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n');
|
$schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ class DbConfigTask extends AppShell {
|
||||||
|
|
||||||
$config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema');
|
$config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema');
|
||||||
|
|
||||||
while ($this->_verify($config) == false) {
|
while (!$this->_verify($config)) {
|
||||||
$this->_interactive();
|
$this->_interactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,11 +277,7 @@ class DbConfigTask extends AppShell {
|
||||||
$info['port'] = null;
|
$info['port'] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($info['persistent'] === false) {
|
$info['persistent'] = var_export((bool)$info['persistent'], true);
|
||||||
$info['persistent'] = 'false';
|
|
||||||
} else {
|
|
||||||
$info['persistent'] = ($info['persistent'] == true) ? 'true' : 'false';
|
|
||||||
}
|
|
||||||
|
|
||||||
$oldConfigs[] = array(
|
$oldConfigs[] = array(
|
||||||
'name' => $configName,
|
'name' => $configName,
|
||||||
|
|
|
@ -391,7 +391,7 @@ class ExtractTask extends AppShell {
|
||||||
$position = $count;
|
$position = $count;
|
||||||
$depth = 0;
|
$depth = 0;
|
||||||
|
|
||||||
while ($depth == 0) {
|
while (!$depth) {
|
||||||
if ($this->_tokens[$position] == '(') {
|
if ($this->_tokens[$position] == '(') {
|
||||||
$depth++;
|
$depth++;
|
||||||
} elseif ($this->_tokens[$position] == ')') {
|
} elseif ($this->_tokens[$position] == ')') {
|
||||||
|
@ -480,7 +480,7 @@ class ExtractTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$dims = Hash::dimensions($rules);
|
$dims = Hash::dimensions($rules);
|
||||||
if ($dims == 1 || ($dims == 2 && isset($rules['message']))) {
|
if ($dims === 1 || ($dims === 2 && isset($rules['message']))) {
|
||||||
$rules = array($rules);
|
$rules = array($rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ class ExtractTask extends AppShell {
|
||||||
$occurrences[] = $file . ':' . implode(';', $lines);
|
$occurrences[] = $file . ':' . implode(';', $lines);
|
||||||
}
|
}
|
||||||
$occurrences = implode("\n#: ", $occurrences);
|
$occurrences = implode("\n#: ", $occurrences);
|
||||||
$header = '#: ' . str_replace($paths, '', $occurrences) . "\n";
|
$header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n";
|
||||||
|
|
||||||
if ($plural === false) {
|
if ($plural === false) {
|
||||||
$sentence = "msgid \"{$msgid}\"\n";
|
$sentence = "msgid \"{$msgid}\"\n";
|
||||||
|
@ -591,7 +591,7 @@ class ExtractTask extends AppShell {
|
||||||
);
|
);
|
||||||
if (strtoupper($response) === 'N') {
|
if (strtoupper($response) === 'N') {
|
||||||
$response = '';
|
$response = '';
|
||||||
while ($response == '') {
|
while (!$response) {
|
||||||
$response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename);
|
$response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename);
|
||||||
$File = new File($this->_output . $response);
|
$File = new File($this->_output . $response);
|
||||||
$filename = $response;
|
$filename = $response;
|
||||||
|
|
|
@ -472,16 +472,14 @@ class ModelTask extends BakeTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($choice != $defaultChoice) {
|
if ($choice != $defaultChoice) {
|
||||||
|
$validate[$validatorName] = $choice;
|
||||||
if (is_numeric($choice) && isset($this->_validations[$choice])) {
|
if (is_numeric($choice) && isset($this->_validations[$choice])) {
|
||||||
$validate[$validatorName] = $this->_validations[$choice];
|
$validate[$validatorName] = $this->_validations[$choice];
|
||||||
} else {
|
|
||||||
$validate[$validatorName] = $choice;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->interactive == true && $choice != $defaultChoice) {
|
|
||||||
$anotherValidator = $this->in(__d('cake_console', 'Would you like to add another validation rule?'), array('y', 'n'), 'n');
|
|
||||||
} else {
|
|
||||||
$anotherValidator = 'n';
|
$anotherValidator = 'n';
|
||||||
|
if ($this->interactive && $choice != $defaultChoice) {
|
||||||
|
$anotherValidator = $this->in(__d('cake_console', 'Would you like to add another validation rule?'), array('y', 'n'), 'n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $validate;
|
return $validate;
|
||||||
|
@ -583,7 +581,7 @@ class ModelTask extends BakeTask {
|
||||||
|
|
||||||
$pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/';
|
$pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/';
|
||||||
$possibleJoinTable = preg_match($pattern, $otherTable);
|
$possibleJoinTable = preg_match($pattern, $otherTable);
|
||||||
if ($possibleJoinTable == true) {
|
if ($possibleJoinTable) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
foreach ($modelFieldsTemp as $fieldName => $field) {
|
foreach ($modelFieldsTemp as $fieldName => $field) {
|
||||||
|
@ -688,7 +686,7 @@ class ModelTask extends BakeTask {
|
||||||
$prompt = __d('cake_console', 'Would you like to define some additional model associations?');
|
$prompt = __d('cake_console', 'Would you like to define some additional model associations?');
|
||||||
$wannaDoMoreAssoc = $this->in($prompt, array('y', 'n'), 'n');
|
$wannaDoMoreAssoc = $this->in($prompt, array('y', 'n'), 'n');
|
||||||
$possibleKeys = $this->_generatePossibleKeys();
|
$possibleKeys = $this->_generatePossibleKeys();
|
||||||
while (strtolower($wannaDoMoreAssoc) == 'y') {
|
while (strtolower($wannaDoMoreAssoc) === 'y') {
|
||||||
$assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
|
$assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
|
||||||
$this->out(__d('cake_console', 'What is the association type?'));
|
$this->out(__d('cake_console', 'What is the association type?'));
|
||||||
$assocType = intval($this->inOptions($assocs, __d('cake_console', 'Enter a number')));
|
$assocType = intval($this->inOptions($assocs, __d('cake_console', 'Enter a number')));
|
||||||
|
@ -700,7 +698,7 @@ class ModelTask extends BakeTask {
|
||||||
$alias = $this->in(__d('cake_console', 'What is the alias for this association?'));
|
$alias = $this->in(__d('cake_console', 'What is the alias for this association?'));
|
||||||
$className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias);
|
$className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias);
|
||||||
|
|
||||||
if ($assocType == 0) {
|
if ($assocType === 0) {
|
||||||
if (!empty($possibleKeys[$model->table])) {
|
if (!empty($possibleKeys[$model->table])) {
|
||||||
$showKeys = $possibleKeys[$model->table];
|
$showKeys = $possibleKeys[$model->table];
|
||||||
} else {
|
} else {
|
||||||
|
@ -733,7 +731,7 @@ class ModelTask extends BakeTask {
|
||||||
if (!isset($foreignKey)) {
|
if (!isset($foreignKey)) {
|
||||||
$foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey);
|
$foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey);
|
||||||
}
|
}
|
||||||
if ($assocType == 3) {
|
if ($assocType === 3) {
|
||||||
$associationForeignKey = $this->in(__d('cake_console', 'What is the associationForeignKey?'), null, $this->_modelKey($model->name));
|
$associationForeignKey = $this->in(__d('cake_console', 'What is the associationForeignKey?'), null, $this->_modelKey($model->name));
|
||||||
$joinTable = $this->in(__d('cake_console', 'What is the joinTable?'));
|
$joinTable = $this->in(__d('cake_console', 'What is the joinTable?'));
|
||||||
}
|
}
|
||||||
|
@ -743,7 +741,7 @@ class ModelTask extends BakeTask {
|
||||||
$associations[$assocs[$assocType]][$i]['alias'] = $alias;
|
$associations[$assocs[$assocType]][$i]['alias'] = $alias;
|
||||||
$associations[$assocs[$assocType]][$i]['className'] = $className;
|
$associations[$assocs[$assocType]][$i]['className'] = $className;
|
||||||
$associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey;
|
$associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey;
|
||||||
if ($assocType == 3) {
|
if ($assocType === 3) {
|
||||||
$associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey;
|
$associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey;
|
||||||
$associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable;
|
$associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable;
|
||||||
}
|
}
|
||||||
|
@ -780,7 +778,7 @@ class ModelTask extends BakeTask {
|
||||||
*/
|
*/
|
||||||
public function bake($name, $data = array()) {
|
public function bake($name, $data = array()) {
|
||||||
if (is_object($name)) {
|
if (is_object($name)) {
|
||||||
if ($data == false) {
|
if (!$data) {
|
||||||
$data = array();
|
$data = array();
|
||||||
$data['associations'] = $this->doAssociations($name);
|
$data['associations'] = $this->doAssociations($name);
|
||||||
$data['validate'] = $this->doValidation($name);
|
$data['validate'] = $this->doValidation($name);
|
||||||
|
@ -935,7 +933,7 @@ class ModelTask extends BakeTask {
|
||||||
|
|
||||||
$enteredModel = '';
|
$enteredModel = '';
|
||||||
|
|
||||||
while ($enteredModel == '') {
|
while (!$enteredModel) {
|
||||||
$enteredModel = $this->in(__d('cake_console', "Enter a number from the list above,\n" .
|
$enteredModel = $this->in(__d('cake_console', "Enter a number from the list above,\n" .
|
||||||
"type in the name of another model, or 'q' to exit"), null, 'q');
|
"type in the name of another model, or 'q' to exit"), null, 'q');
|
||||||
|
|
||||||
|
@ -944,18 +942,17 @@ class ModelTask extends BakeTask {
|
||||||
$this->_stop();
|
$this->_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($enteredModel == '' || intval($enteredModel) > count($this->_modelNames)) {
|
if (!$enteredModel || intval($enteredModel) > count($this->_modelNames)) {
|
||||||
$this->err(__d('cake_console', "The model name you supplied was empty,\n" .
|
$this->err(__d('cake_console', "The model name you supplied was empty,\n" .
|
||||||
"or the number you selected was not an option. Please try again."));
|
"or the number you selected was not an option. Please try again."));
|
||||||
$enteredModel = '';
|
$enteredModel = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) {
|
if (intval($enteredModel) > 0 && intval($enteredModel) <= count($this->_modelNames)) {
|
||||||
$currentModelName = $this->_modelNames[intval($enteredModel) - 1];
|
return $this->_modelNames[intval($enteredModel) - 1];
|
||||||
} else {
|
|
||||||
$currentModelName = $enteredModel;
|
|
||||||
}
|
}
|
||||||
return $currentModelName;
|
|
||||||
|
return $enteredModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -66,7 +66,7 @@ class ProjectTask extends AppShell {
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = false;
|
$response = false;
|
||||||
while ($response == false && is_dir($project) === true && file_exists($project . 'Config' . 'core.php')) {
|
while (!$response && is_dir($project) === true && file_exists($project . 'Config' . 'core.php')) {
|
||||||
$prompt = __d('cake_console', '<warning>A project already exists in this location:</warning> %s Overwrite?', $project);
|
$prompt = __d('cake_console', '<warning>A project already exists in this location:</warning> %s Overwrite?', $project);
|
||||||
$response = $this->in($prompt, array('y', 'n'), 'n');
|
$response = $this->in($prompt, array('y', 'n'), 'n');
|
||||||
if (strtolower($response) === 'n') {
|
if (strtolower($response) === 'n') {
|
||||||
|
@ -92,6 +92,13 @@ class ProjectTask extends AppShell {
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->cachePrefix($path)) {
|
||||||
|
$this->out(__d('cake_console', ' * Cache prefix set'));
|
||||||
|
} else {
|
||||||
|
$this->err(__d('cake_console', 'The cache prefix was <error>NOT</error> set'));
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->consolePath($path) === true) {
|
if ($this->consolePath($path) === true) {
|
||||||
$this->out(__d('cake_console', ' * app/Console/cake.php path set.'));
|
$this->out(__d('cake_console', ' * app/Console/cake.php path set.'));
|
||||||
} else {
|
} else {
|
||||||
|
@ -284,6 +291,23 @@ class ProjectTask extends AppShell {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes cache prefix using app's name
|
||||||
|
*
|
||||||
|
* @param string $dir Path to project
|
||||||
|
* @return boolean Success
|
||||||
|
*/
|
||||||
|
public function cachePrefix($dir) {
|
||||||
|
$app = basename($dir);
|
||||||
|
$File = new File($dir . 'Config' . DS . 'core.php');
|
||||||
|
$contents = $File->read();
|
||||||
|
if (preg_match('/(\$prefix = \'myapp_\';)/', $contents, $match)) {
|
||||||
|
$result = str_replace($match[0], '$prefix = \'' . $app . '_\';', $contents);
|
||||||
|
return $File->write($result);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and writes CAKE_CORE_INCLUDE_PATH
|
* Generates and writes CAKE_CORE_INCLUDE_PATH
|
||||||
*
|
*
|
||||||
|
@ -325,10 +349,7 @@ class ProjectTask extends AppShell {
|
||||||
if (!file_put_contents($filename, $result)) {
|
if (!file_put_contents($filename, $result)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($count == 0) {
|
return (bool)$count;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -363,7 +384,7 @@ class ProjectTask extends AppShell {
|
||||||
$admin = '';
|
$admin = '';
|
||||||
$prefixes = Configure::read('Routing.prefixes');
|
$prefixes = Configure::read('Routing.prefixes');
|
||||||
if (!empty($prefixes)) {
|
if (!empty($prefixes)) {
|
||||||
if (count($prefixes) == 1) {
|
if (count($prefixes) === 1) {
|
||||||
return $prefixes[0] . '_';
|
return $prefixes[0] . '_';
|
||||||
}
|
}
|
||||||
if ($this->interactive) {
|
if ($this->interactive) {
|
||||||
|
@ -385,7 +406,7 @@ class ProjectTask extends AppShell {
|
||||||
$this->out(__d('cake_console', 'You need to enable Configure::write(\'Routing.prefixes\',array(\'admin\')) in /app/Config/core.php to use prefix routing.'));
|
$this->out(__d('cake_console', 'You need to enable Configure::write(\'Routing.prefixes\',array(\'admin\')) in /app/Config/core.php to use prefix routing.'));
|
||||||
$this->out(__d('cake_console', 'What would you like the prefix route to be?'));
|
$this->out(__d('cake_console', 'What would you like the prefix route to be?'));
|
||||||
$this->out(__d('cake_console', 'Example: www.example.com/admin/controller'));
|
$this->out(__d('cake_console', 'Example: www.example.com/admin/controller'));
|
||||||
while ($admin == '') {
|
while (!$admin) {
|
||||||
$admin = $this->in(__d('cake_console', 'Enter a routing prefix:'), null, 'admin');
|
$admin = $this->in(__d('cake_console', 'Enter a routing prefix:'), null, 'admin');
|
||||||
}
|
}
|
||||||
if ($this->cakeAdmin($admin) !== true) {
|
if ($this->cakeAdmin($admin) !== true) {
|
||||||
|
|
|
@ -123,7 +123,7 @@ class TemplateTask extends AppShell {
|
||||||
$data = array($one => $two);
|
$data = array($one => $two);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data == null) {
|
if (!$data) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$this->templateVars = $data + $this->templateVars;
|
$this->templateVars = $data + $this->templateVars;
|
||||||
|
@ -166,7 +166,7 @@ class TemplateTask extends AppShell {
|
||||||
* @return string returns the path to the selected theme.
|
* @return string returns the path to the selected theme.
|
||||||
*/
|
*/
|
||||||
public function getThemePath() {
|
public function getThemePath() {
|
||||||
if (count($this->templatePaths) == 1) {
|
if (count($this->templatePaths) === 1) {
|
||||||
$paths = array_values($this->templatePaths);
|
$paths = array_values($this->templatePaths);
|
||||||
return $paths[0];
|
return $paths[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,15 +83,16 @@ class TestTask extends BakeTask {
|
||||||
*/
|
*/
|
||||||
public function execute() {
|
public function execute() {
|
||||||
parent::execute();
|
parent::execute();
|
||||||
if (empty($this->args)) {
|
$count = count($this->args);
|
||||||
|
if (!$count) {
|
||||||
$this->_interactive();
|
$this->_interactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->args) == 1) {
|
if ($count === 1) {
|
||||||
$this->_interactive($this->args[0]);
|
$this->_interactive($this->args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->args) > 1) {
|
if ($count > 1) {
|
||||||
$type = Inflector::classify($this->args[0]);
|
$type = Inflector::classify($this->args[0]);
|
||||||
if ($this->bake($type, $this->args[1])) {
|
if ($this->bake($type, $this->args[1])) {
|
||||||
$this->out('<success>Done</success>');
|
$this->out('<success>Done</success>');
|
||||||
|
@ -334,7 +335,7 @@ class TestTask extends BakeTask {
|
||||||
* @param string $type The type the class having a test
|
* @param string $type The type the class having a test
|
||||||
* generated for is in.
|
* generated for is in.
|
||||||
* @return array Array of (class, type)
|
* @return array Array of (class, type)
|
||||||
* @throws CakeException On invalid typename
|
* @throws CakeException on invalid types.
|
||||||
*/
|
*/
|
||||||
public function getBaseType($type) {
|
public function getBaseType($type) {
|
||||||
if (empty($this->baseTypes[$type])) {
|
if (empty($this->baseTypes[$type])) {
|
||||||
|
|
|
@ -316,9 +316,9 @@ class ViewTask extends BakeTask {
|
||||||
*/
|
*/
|
||||||
public function customAction() {
|
public function customAction() {
|
||||||
$action = '';
|
$action = '';
|
||||||
while ($action == '') {
|
while (!$action) {
|
||||||
$action = $this->in(__d('cake_console', 'Action Name? (use lowercase_underscored function name)'));
|
$action = $this->in(__d('cake_console', 'Action Name? (use lowercase_underscored function name)'));
|
||||||
if ($action == '') {
|
if (!$action) {
|
||||||
$this->out(__d('cake_console', 'The action name you supplied was empty. Please try again.'));
|
$this->out(__d('cake_console', 'The action name you supplied was empty. Please try again.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class ConsoleErrorHandler {
|
||||||
$message = __d('cake_console', '%s in [%s, line %s]', $description, $file, $line);
|
$message = __d('cake_console', '%s in [%s, line %s]', $description, $file, $line);
|
||||||
$stderr->write(__d('cake_console', "<error>%s Error:</error> %s\n", $name, $message));
|
$stderr->write(__d('cake_console', "<error>%s Error:</error> %s\n", $name, $message));
|
||||||
|
|
||||||
if (Configure::read('debug') == 0) {
|
if (!Configure::read('debug')) {
|
||||||
CakeLog::write($log, $message);
|
CakeLog::write($log, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,7 @@ class Shell extends Object {
|
||||||
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell
|
* @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell
|
||||||
*/
|
*/
|
||||||
public function __construct($stdout = null, $stderr = null, $stdin = null) {
|
public function __construct($stdout = null, $stderr = null, $stdin = null) {
|
||||||
if ($this->name == null) {
|
if (!$this->name) {
|
||||||
$this->name = Inflector::camelize(str_replace(array('Shell', 'Task'), '', get_class($this)));
|
$this->name = Inflector::camelize(str_replace(array('Shell', 'Task'), '', get_class($this)));
|
||||||
}
|
}
|
||||||
$this->Tasks = new TaskCollection($this);
|
$this->Tasks = new TaskCollection($this);
|
||||||
|
@ -162,13 +162,13 @@ class Shell extends Object {
|
||||||
$this->stdout = $stdout;
|
$this->stdout = $stdout;
|
||||||
$this->stderr = $stderr;
|
$this->stderr = $stderr;
|
||||||
$this->stdin = $stdin;
|
$this->stdin = $stdin;
|
||||||
if ($this->stdout == null) {
|
if (!$this->stdout) {
|
||||||
$this->stdout = new ConsoleOutput('php://stdout');
|
$this->stdout = new ConsoleOutput('php://stdout');
|
||||||
}
|
}
|
||||||
if ($this->stderr == null) {
|
if (!$this->stderr) {
|
||||||
$this->stderr = new ConsoleOutput('php://stderr');
|
$this->stderr = new ConsoleOutput('php://stderr');
|
||||||
}
|
}
|
||||||
if ($this->stdin == null) {
|
if (!$this->stdin) {
|
||||||
$this->stdin = new ConsoleInput('php://stdin');
|
$this->stdin = new ConsoleInput('php://stdin');
|
||||||
}
|
}
|
||||||
$this->_useLogger();
|
$this->_useLogger();
|
||||||
|
@ -325,7 +325,7 @@ class Shell extends Object {
|
||||||
*/
|
*/
|
||||||
public function dispatchShell() {
|
public function dispatchShell() {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
if (is_string($args[0]) && count($args) == 1) {
|
if (is_string($args[0]) && count($args) === 1) {
|
||||||
$args = explode(' ', $args[0]);
|
$args = explode(' ', $args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,11 @@ class ShellDispatcher {
|
||||||
if (isset($params['working'])) {
|
if (isset($params['working'])) {
|
||||||
$params['working'] = trim($params['working']);
|
$params['working'] = trim($params['working']);
|
||||||
}
|
}
|
||||||
if (!empty($params['working']) && (!isset($this->args[0]) || isset($this->args[0]) && $this->args[0]{0} !== '.')) {
|
|
||||||
|
if (!empty($params['working']) && (!isset($this->args[0]) || isset($this->args[0]) && $this->args[0][0] !== '.')) {
|
||||||
|
if ($params['working'][0] === '.') {
|
||||||
|
$params['working'] = realpath($params['working']);
|
||||||
|
}
|
||||||
if (empty($this->params['app']) && $params['working'] != $params['root']) {
|
if (empty($this->params['app']) && $params['working'] != $params['root']) {
|
||||||
$params['root'] = dirname($params['working']);
|
$params['root'] = dirname($params['working']);
|
||||||
$params['app'] = basename($params['working']);
|
$params['app'] = basename($params['working']);
|
||||||
|
|
|
@ -36,11 +36,11 @@
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function <?php echo $admin ?>view($id = null) {
|
public function <?php echo $admin ?>view($id = null) {
|
||||||
$this-><?php echo $currentModelName; ?>->id = $id;
|
if (!$this-><?php echo $currentModelName; ?>->exists($id)) {
|
||||||
if (!$this-><?php echo $currentModelName; ?>->exists()) {
|
|
||||||
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
||||||
}
|
}
|
||||||
$this->set('<?php echo $singularName; ?>', $this-><?php echo $currentModelName; ?>->read(null, $id));
|
$options = array('conditions' => array('<?php echo $currentModelName; ?>.' . $this-><?php echo $currentModelName; ?>->primaryKey => $id));
|
||||||
|
$this->set('<?php echo $singularName; ?>', $this-><?php echo $currentModelName; ?>->find('first', $options));
|
||||||
}
|
}
|
||||||
|
|
||||||
<?php $compact = array(); ?>
|
<?php $compact = array(); ?>
|
||||||
|
@ -91,8 +91,7 @@
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function <?php echo $admin; ?>edit($id = null) {
|
public function <?php echo $admin; ?>edit($id = null) {
|
||||||
$this-><?php echo $currentModelName; ?>->id = $id;
|
if (!$this-><?php echo $currentModelName; ?>->exists($id)) {
|
||||||
if (!$this-><?php echo $currentModelName; ?>->exists()) {
|
|
||||||
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
||||||
}
|
}
|
||||||
if ($this->request->is('post') || $this->request->is('put')) {
|
if ($this->request->is('post') || $this->request->is('put')) {
|
||||||
|
@ -109,7 +108,8 @@
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->request->data = $this-><?php echo $currentModelName; ?>->read(null, $id);
|
$options = array('conditions' => array('<?php echo $currentModelName; ?>.' . $this-><?php echo $currentModelName; ?>->primaryKey => $id));
|
||||||
|
$this->request->data = $this-><?php echo $currentModelName; ?>->find('first', $options);
|
||||||
}
|
}
|
||||||
<?php
|
<?php
|
||||||
foreach (array('belongsTo', 'hasAndBelongsToMany') as $assoc):
|
foreach (array('belongsTo', 'hasAndBelongsToMany') as $assoc):
|
||||||
|
@ -131,19 +131,17 @@
|
||||||
/**
|
/**
|
||||||
* <?php echo $admin ?>delete method
|
* <?php echo $admin ?>delete method
|
||||||
*
|
*
|
||||||
* @throws MethodNotAllowedException
|
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
|
* @throws MethodNotAllowedException
|
||||||
* @param string $id
|
* @param string $id
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function <?php echo $admin; ?>delete($id = null) {
|
public function <?php echo $admin; ?>delete($id = null) {
|
||||||
if (!$this->request->is('post')) {
|
|
||||||
throw new MethodNotAllowedException();
|
|
||||||
}
|
|
||||||
$this-><?php echo $currentModelName; ?>->id = $id;
|
$this-><?php echo $currentModelName; ?>->id = $id;
|
||||||
if (!$this-><?php echo $currentModelName; ?>->exists()) {
|
if (!$this-><?php echo $currentModelName; ?>->exists()) {
|
||||||
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
throw new NotFoundException(__('Invalid <?php echo strtolower($singularHumanName); ?>'));
|
||||||
}
|
}
|
||||||
|
$this->request->onlyAllow('post', 'delete');
|
||||||
if ($this-><?php echo $currentModelName; ?>->delete()) {
|
if ($this-><?php echo $currentModelName; ?>->delete()) {
|
||||||
<?php if ($wannaUseSession): ?>
|
<?php if ($wannaUseSession): ?>
|
||||||
$this->Session->setFlash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> deleted'));
|
$this->Session->setFlash(__('<?php echo ucfirst(strtolower($singularHumanName)); ?> deleted'));
|
||||||
|
|
|
@ -26,8 +26,7 @@
|
||||||
<th class="actions"><?php echo "<?php echo __('Actions'); ?>"; ?></th>
|
<th class="actions"><?php echo "<?php echo __('Actions'); ?>"; ?></th>
|
||||||
</tr>
|
</tr>
|
||||||
<?php
|
<?php
|
||||||
echo "<?php
|
echo "<?php foreach (\${$pluralVar} as \${$singularVar}): ?>\n";
|
||||||
foreach (\${$pluralVar} as \${$singularVar}): ?>\n";
|
|
||||||
echo "\t<tr>\n";
|
echo "\t<tr>\n";
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
$isKey = false;
|
$isKey = false;
|
||||||
|
@ -62,7 +61,6 @@
|
||||||
));
|
));
|
||||||
?>"; ?>
|
?>"; ?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="paging">
|
<div class="paging">
|
||||||
<?php
|
<?php
|
||||||
echo "<?php\n";
|
echo "<?php\n";
|
||||||
|
|
|
@ -293,18 +293,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick the caching engine to use. If APC is enabled use it.
|
* Configure the cache handlers that CakePHP will use for internal
|
||||||
* If running via cli - apc is disabled by default. ensure it's available and enabled in this case
|
* metadata like class maps, and model schema.
|
||||||
*
|
*
|
||||||
|
* By default File is used, but for improved performance you should use APC.
|
||||||
|
*
|
||||||
|
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
|
||||||
|
* Please check the comments in boostrap.php for more info on the cache engines available
|
||||||
|
* and their setttings.
|
||||||
*/
|
*/
|
||||||
$engine = 'File';
|
$engine = 'File';
|
||||||
if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) {
|
|
||||||
$engine = 'Apc';
|
|
||||||
}
|
|
||||||
|
|
||||||
// In development mode, caches should expire quickly.
|
// In development mode, caches should expire quickly.
|
||||||
$duration = '+999 days';
|
$duration = '+999 days';
|
||||||
if (Configure::read('debug') >= 1) {
|
if (Configure::read('debug') > 0) {
|
||||||
$duration = '+10 seconds';
|
$duration = '+10 seconds';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,21 @@
|
||||||
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
LIB=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && LIB=$LIB/$(basename -- "$0")
|
|
||||||
|
|
||||||
while [ -h "$LIB" ]; do
|
# Canonicalize by following every symlink of the given name recursively
|
||||||
DIR=$(dirname -- "$LIB")
|
canonicalize() {
|
||||||
SYM=$(readlink "$LIB")
|
NAME=$1
|
||||||
LIB=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
while [ -h "$NAME" ]; do
|
||||||
|
DIR=$(dirname -- "$NAME")
|
||||||
|
SYM=$(readlink "$NAME")
|
||||||
|
NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
||||||
done
|
done
|
||||||
|
echo "$NAME"
|
||||||
|
}
|
||||||
|
|
||||||
LIB=$(dirname -- "$LIB")/
|
CONSOLE=$(dirname $(canonicalize "$0"))
|
||||||
APP=`pwd`
|
APP=$(dirname "$CONSOLE")
|
||||||
|
|
||||||
exec php -q "$LIB"cake.php -working "$APP" "$@"
|
exec php -q $CONSOLE/cake.php -working "$APP" "$@"
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* @since CakePHP(tm) v 0.2.9
|
* @since CakePHP(tm) v 0.2.9
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('AppController', 'Controller');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static content controller
|
* Static content controller
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<?php echo $this->Html->charset(); ?>
|
<?php echo $this->Html->charset(); ?>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<?php echo $this->Html->charset(); ?>
|
<?php echo $this->Html->charset(); ?>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<?php echo $this->Html->charset(); ?>
|
<?php echo $this->Html->charset(); ?>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* @since CakePHP(tm) v 0.10.0.1076
|
* @since CakePHP(tm) v 0.10.0.1076
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
if (Configure::read('debug') == 0):
|
if (!Configure::read('debug')):
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
endif;
|
endif;
|
||||||
App::uses('Debugger', 'Utility');
|
App::uses('Debugger', 'Utility');
|
||||||
|
@ -127,11 +127,28 @@ if (isset($filePresent)):
|
||||||
echo '</span></p>';
|
echo '</span></p>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
if (CakePlugin::loaded('DebugKit')):
|
||||||
|
echo '<span class="notice success">';
|
||||||
|
echo __d('cake_dev', 'DebugKit plugin is present');
|
||||||
|
echo '</span>';
|
||||||
|
else:
|
||||||
|
echo '<span class="notice">';
|
||||||
|
echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.');
|
||||||
|
echo '<br/>';
|
||||||
|
echo __d('cake_dev', 'You can install it from %s', $this->Html->link('github', 'https://github.com/cakephp/debug_kit'));
|
||||||
|
echo '</span>';
|
||||||
|
endif;
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
|
<h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
|
||||||
<p>
|
<p>
|
||||||
<?php
|
<?php
|
||||||
echo __d('cake_dev', 'To change the content of this page, create: APP/View/Pages/home.ctp.<br />
|
echo __d('cake_dev', 'To change the content of this page, edit: APP/View/Pages/home.ctp.<br />
|
||||||
To change its layout, create: APP/View/Layouts/default.ctp.<br />
|
To change its layout, edit: APP/View/Layouts/default.ctp.<br />
|
||||||
You can also add some CSS styles for your pages at: APP/webroot/css.');
|
You can also add some CSS styles for your pages at: APP/webroot/css.');
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
|
@ -156,6 +173,20 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');
|
||||||
?>
|
?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3><?php echo __d('cake_dev', 'Official Plugins'); ?></h3>
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<?php echo $this->Html->link('DebugKit', 'https://github.com/cakephp/debug_kit') ?>:
|
||||||
|
<?php echo __d('cake_dev', 'provides a debugging toolbar and enhanced debugging tools for CakePHP applications.'); ?>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<?php echo $this->Html->link('Localized', 'https://github.com/cakephp/localized') ?>:
|
||||||
|
<?php echo __d('cake_dev', 'contains various localized validation classes and translations for specific countries'); ?>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3>
|
<h3><?php echo __d('cake_dev', 'More about Cake'); ?></h3>
|
||||||
<p>
|
<p>
|
||||||
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
|
<?php echo __d('cake_dev', 'CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
|
||||||
|
@ -175,8 +206,8 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');
|
||||||
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Quick Reference'); ?></li></ul></li>
|
||||||
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
|
<li><a href="http://bakery.cakephp.org"><?php echo __d('cake_dev', 'The Bakery'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Everything CakePHP'); ?></li></ul></li>
|
||||||
<li><a href="http://live.cakephp.org"><?php echo __d('cake_dev', 'The Show'); ?> </a>
|
<li><a href="http://plugins.cakephp.org"><?php echo __d('cake_dev', 'CakePHP plugins repo'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'The Show is a live and archived internet radio broadcast CakePHP-related topics and answer questions live via IRC, Skype, and telephone.'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></li></ul></li>
|
||||||
<li><a href="http://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
|
<li><a href="http://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a>
|
||||||
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
|
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li>
|
||||||
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
|
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
|
||||||
|
|
|
@ -72,6 +72,11 @@ if (!defined('WWW_ROOT')) {
|
||||||
define('WWW_ROOT', dirname(__FILE__) . DS);
|
define('WWW_ROOT', dirname(__FILE__) . DS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for built-in server
|
||||||
|
if (php_sapi_name() == 'cli-server') {
|
||||||
|
$_SERVER['PHP_SELF'] = '/' . basename(__FILE__);
|
||||||
|
}
|
||||||
|
|
||||||
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
|
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
|
||||||
if (function_exists('ini_set')) {
|
if (function_exists('ini_set')) {
|
||||||
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
|
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
|
||||||
|
@ -93,5 +98,5 @@ App::uses('Dispatcher', 'Routing');
|
||||||
$Dispatcher = new Dispatcher();
|
$Dispatcher = new Dispatcher();
|
||||||
$Dispatcher->dispatch(
|
$Dispatcher->dispatch(
|
||||||
new CakeRequest(),
|
new CakeRequest(),
|
||||||
new CakeResponse(array('charset' => Configure::read('App.encoding')))
|
new CakeResponse()
|
||||||
);
|
);
|
||||||
|
|
|
@ -86,7 +86,7 @@ if (!empty($failed)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Configure::read('debug') < 1) {
|
if (Configure::read('debug') < 1) {
|
||||||
die(__d('cake_dev', 'Debug setting does not allow access to this url.'));
|
exit(__d('cake_dev', 'Debug setting does not allow access to this url.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once CAKE . 'TestSuite' . DS . 'CakeTestSuiteDispatcher.php';
|
require_once CAKE . 'TestSuite' . DS . 'CakeTestSuiteDispatcher.php';
|
||||||
|
|
|
@ -17,17 +17,21 @@
|
||||||
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
# @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
LIB=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && LIB=$LIB/$(basename -- "$0")
|
|
||||||
|
|
||||||
while [ -h "$LIB" ]; do
|
# Canonicalize by following every symlink of the given name recursively
|
||||||
DIR=$(dirname -- "$LIB")
|
canonicalize() {
|
||||||
SYM=$(readlink "$LIB")
|
NAME=$1
|
||||||
LIB=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
while [ -h "$NAME" ]; do
|
||||||
|
DIR=$(dirname -- "$NAME")
|
||||||
|
SYM=$(readlink "$NAME")
|
||||||
|
NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM")
|
||||||
done
|
done
|
||||||
|
echo "$NAME"
|
||||||
|
}
|
||||||
|
|
||||||
LIB=$(dirname -- "$LIB")/
|
CONSOLE=$(dirname $(canonicalize "$0"))
|
||||||
APP=`pwd`
|
APP=`pwd`
|
||||||
|
|
||||||
exec php -q "$LIB"cake.php -working "$APP" "$@"
|
exec php -q $CONSOLE/cake.php -working "$APP" "$@"
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
|
|
|
@ -71,18 +71,4 @@ class CakeErrorController extends AppController {
|
||||||
$this->_set(array('cacheAction' => false, 'viewPath' => 'Errors'));
|
$this->_set(array('cacheAction' => false, 'viewPath' => 'Errors'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes the viewVars.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function beforeRender() {
|
|
||||||
parent::beforeRender();
|
|
||||||
foreach ($this->viewVars as $key => $value) {
|
|
||||||
if (!is_object($value)) {
|
|
||||||
$this->viewVars[$key] = h($value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ class IniAcl extends Object implements AclInterface {
|
||||||
* @return boolean Success
|
* @return boolean Success
|
||||||
*/
|
*/
|
||||||
public function check($aro, $aco, $action = null) {
|
public function check($aro, $aco, $action = null) {
|
||||||
if ($this->config == null) {
|
if (!$this->config) {
|
||||||
$this->config = $this->readConfigFile(APP . 'Config' . DS . 'acl.ini.php');
|
$this->config = $this->readConfigFile(APP . 'Config' . DS . 'acl.ini.php');
|
||||||
}
|
}
|
||||||
$aclConfig = $this->config;
|
$aclConfig = $this->config;
|
||||||
|
|
|
@ -170,11 +170,11 @@ class PhpAcl extends Object implements AclInterface {
|
||||||
foreach ($path as $depth => $node) {
|
foreach ($path as $depth => $node) {
|
||||||
foreach ($prioritizedAros as $aros) {
|
foreach ($prioritizedAros as $aros) {
|
||||||
if (!empty($node['allow'])) {
|
if (!empty($node['allow'])) {
|
||||||
$allow = $allow || count(array_intersect($node['allow'], $aros)) > 0;
|
$allow = $allow || count(array_intersect($node['allow'], $aros));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($node['deny'])) {
|
if (!empty($node['deny'])) {
|
||||||
$allow = $allow && count(array_intersect($node['deny'], $aros)) == 0;
|
$allow = $allow && !count(array_intersect($node['deny'], $aros));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,19 +66,28 @@ abstract class BaseAuthenticate {
|
||||||
/**
|
/**
|
||||||
* Find a user record using the standard options.
|
* Find a user record using the standard options.
|
||||||
*
|
*
|
||||||
* @param string $username The username/identifier.
|
* The $conditions parameter can be a (string)username or an array containing conditions for Model::find('first'). If
|
||||||
* @param string $password The unhashed password.
|
* the password field is not included in the conditions the password will be returned.
|
||||||
|
*
|
||||||
|
* @param Mixed $conditions The username/identifier, or an array of find conditions.
|
||||||
|
* @param Mixed $password The password, only use if passing as $conditions = 'username'.
|
||||||
* @return Mixed Either false on failure, or an array of user data.
|
* @return Mixed Either false on failure, or an array of user data.
|
||||||
*/
|
*/
|
||||||
protected function _findUser($username, $password) {
|
protected function _findUser($conditions, $password = null) {
|
||||||
$userModel = $this->settings['userModel'];
|
$userModel = $this->settings['userModel'];
|
||||||
list($plugin, $model) = pluginSplit($userModel);
|
list($plugin, $model) = pluginSplit($userModel);
|
||||||
$fields = $this->settings['fields'];
|
$fields = $this->settings['fields'];
|
||||||
|
|
||||||
|
if (!is_array($conditions)) {
|
||||||
|
if (!$password) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$username = $conditions;
|
||||||
$conditions = array(
|
$conditions = array(
|
||||||
$model . '.' . $fields['username'] => $username,
|
$model . '.' . $fields['username'] => $username,
|
||||||
$model . '.' . $fields['password'] => $this->_password($password),
|
$model . '.' . $fields['password'] => $this->_password($password),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
if (!empty($this->settings['scope'])) {
|
if (!empty($this->settings['scope'])) {
|
||||||
$conditions = array_merge($conditions, $this->settings['scope']);
|
$conditions = array_merge($conditions, $this->settings['scope']);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +100,12 @@ abstract class BaseAuthenticate {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = $result[$model];
|
$user = $result[$model];
|
||||||
|
if (
|
||||||
|
isset($conditions[$model . '.' . $fields['password']]) ||
|
||||||
|
isset($conditions[$fields['password']])
|
||||||
|
) {
|
||||||
unset($user[$fields['password']]);
|
unset($user[$fields['password']]);
|
||||||
|
}
|
||||||
unset($result[$model]);
|
unset($result[$model]);
|
||||||
return array_merge($user, $result);
|
return array_merge($user, $result);
|
||||||
}
|
}
|
||||||
|
|
78
lib/Cake/Controller/Component/Auth/BlowfishAuthenticate.php
Normal file
78
lib/Cake/Controller/Component/Auth/BlowfishAuthenticate.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHP 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||||
|
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of the files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
* @link http://cakephp.org CakePHP(tm) Project
|
||||||
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
*/
|
||||||
|
|
||||||
|
App::uses('FormAuthenticate', 'Controller/Component/Auth');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An authentication adapter for AuthComponent. Provides the ability to authenticate using POST data using Blowfish
|
||||||
|
* hashing. Can be used by configuring AuthComponent to use it via the AuthComponent::$authenticate setting.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* $this->Auth->authenticate = array(
|
||||||
|
* 'Blowfish' => array(
|
||||||
|
* 'scope' => array('User.active' => 1)
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* When configuring BlowfishAuthenticate you can pass in settings to which fields, model and additional conditions
|
||||||
|
* are used. See FormAuthenticate::$settings for more information.
|
||||||
|
*
|
||||||
|
* For inital password hashing/creation see Security::hash(). Other than how the password is initally hashed,
|
||||||
|
* BlowfishAuthenticate works exactly the same way as FormAuthenticate.
|
||||||
|
*
|
||||||
|
* @package Cake.Controller.Component.Auth
|
||||||
|
* @since CakePHP(tm) v 2.3
|
||||||
|
* @see AuthComponent::$authenticate
|
||||||
|
*/
|
||||||
|
class BlowfishAuthenticate extends FormAuthenticate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticates the identity contained in a request. Will use the `settings.userModel`, and `settings.fields`
|
||||||
|
* to find POST data that is used to find a matching record in the`settings.userModel`. Will return false if
|
||||||
|
* there is no post data, either username or password is missing, or if the scope conditions have not been met.
|
||||||
|
*
|
||||||
|
* @param CakeRequest $request The request that contains login information.
|
||||||
|
* @param CakeResponse $response Unused response object.
|
||||||
|
* @return mixed False on login failure. An array of User data on success.
|
||||||
|
*/
|
||||||
|
public function authenticate(CakeRequest $request, CakeResponse $response) {
|
||||||
|
$userModel = $this->settings['userModel'];
|
||||||
|
list($plugin, $model) = pluginSplit($userModel);
|
||||||
|
|
||||||
|
$fields = $this->settings['fields'];
|
||||||
|
if (!$this->_checkFields($request, $model, $fields)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$user = $this->_findUser(
|
||||||
|
array(
|
||||||
|
$model . '.' . $fields['username'] => $request->data[$model][$fields['username']],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (!$user) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$password = Security::hash(
|
||||||
|
$request->data[$model][$fields['password']],
|
||||||
|
'blowfish',
|
||||||
|
$user[$fields['password']]
|
||||||
|
);
|
||||||
|
if ($password === $user[$fields['password']]) {
|
||||||
|
unset($user[$fields['password']]);
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -138,7 +138,7 @@ class DigestAuthenticate extends BaseAuthenticate {
|
||||||
if (empty($digest)) {
|
if (empty($digest)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = $this->_findUser($digest['username'], null);
|
$user = $this->_findUser($digest['username']);
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ class DigestAuthenticate extends BaseAuthenticate {
|
||||||
* @param string $password Unused password, digest doesn't require passwords.
|
* @param string $password Unused password, digest doesn't require passwords.
|
||||||
* @return Mixed Either false on failure, or an array of user data.
|
* @return Mixed Either false on failure, or an array of user data.
|
||||||
*/
|
*/
|
||||||
protected function _findUser($username, $password) {
|
protected function _findUser($username, $password = null) {
|
||||||
$userModel = $this->settings['userModel'];
|
$userModel = $this->settings['userModel'];
|
||||||
list($plugin, $model) = pluginSplit($userModel);
|
list($plugin, $model) = pluginSplit($userModel);
|
||||||
$fields = $this->settings['fields'];
|
$fields = $this->settings['fields'];
|
||||||
|
|
|
@ -36,6 +36,27 @@ App::uses('BaseAuthenticate', 'Controller/Component/Auth');
|
||||||
*/
|
*/
|
||||||
class FormAuthenticate extends BaseAuthenticate {
|
class FormAuthenticate extends BaseAuthenticate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the fields to ensure they are supplied.
|
||||||
|
*
|
||||||
|
* @param CakeRequest $request The request that contains login information.
|
||||||
|
* @param string $model The model used for login verification.
|
||||||
|
* @param array $fields The fields to be checked.
|
||||||
|
* @return boolean False if the fields have not been supplied. True if they exist.
|
||||||
|
*/
|
||||||
|
protected function _checkFields(CakeRequest $request, $model, $fields) {
|
||||||
|
if (empty($request->data[$model])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
empty($request->data[$model][$fields['username']]) ||
|
||||||
|
empty($request->data[$model][$fields['password']])
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticates the identity contained in a request. Will use the `settings.userModel`, and `settings.fields`
|
* Authenticates the identity contained in a request. Will use the `settings.userModel`, and `settings.fields`
|
||||||
* to find POST data that is used to find a matching record in the `settings.userModel`. Will return false if
|
* to find POST data that is used to find a matching record in the `settings.userModel`. Will return false if
|
||||||
|
@ -50,13 +71,7 @@ class FormAuthenticate extends BaseAuthenticate {
|
||||||
list($plugin, $model) = pluginSplit($userModel);
|
list($plugin, $model) = pluginSplit($userModel);
|
||||||
|
|
||||||
$fields = $this->settings['fields'];
|
$fields = $this->settings['fields'];
|
||||||
if (empty($request->data[$model])) {
|
if (!$this->_checkFields($request, $model, $fields)) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
empty($request->data[$model][$fields['username']]) ||
|
|
||||||
empty($request->data[$model][$fields['password']])
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return $this->_findUser(
|
return $this->_findUser(
|
||||||
|
|
|
@ -211,6 +211,15 @@ class AuthComponent extends Component {
|
||||||
*/
|
*/
|
||||||
public $authError = null;
|
public $authError = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls handling of unauthorized access. By default unauthorized user is
|
||||||
|
* redirected to the referrer url or AuthComponent::$loginAction or '/'.
|
||||||
|
* If set to false a ForbiddenException exception is thrown instead of redirecting.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
public $unauthorizedRedirect = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller actions for which user validation is not required.
|
* Controller actions for which user validation is not required.
|
||||||
*
|
*
|
||||||
|
@ -289,13 +298,7 @@ class AuthComponent extends Component {
|
||||||
$url = Router::normalize($url);
|
$url = Router::normalize($url);
|
||||||
$loginAction = Router::normalize($this->loginAction);
|
$loginAction = Router::normalize($this->loginAction);
|
||||||
|
|
||||||
$allowedActions = $this->allowedActions;
|
if ($loginAction != $url && in_array($action, array_map('strtolower', $this->allowedActions))) {
|
||||||
$isAllowed = (
|
|
||||||
$this->allowedActions == array('*') ||
|
|
||||||
in_array($action, array_map('strtolower', $allowedActions))
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($loginAction != $url && $isAllowed) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,27 +309,43 @@ class AuthComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if (!$this->_getUser()) {
|
if (!$this->_getUser()) {
|
||||||
if (!$request->is('ajax')) {
|
if (!$request->is('ajax')) {
|
||||||
$this->flash($this->authError);
|
$this->flash($this->authError);
|
||||||
$this->Session->write('Auth.redirect', $request->here());
|
$this->Session->write('Auth.redirect', $request->here());
|
||||||
$controller->redirect($loginAction);
|
$controller->redirect($loginAction);
|
||||||
return false;
|
return false;
|
||||||
} elseif (!empty($this->ajaxLogin)) {
|
}
|
||||||
|
if (!empty($this->ajaxLogin)) {
|
||||||
$controller->viewPath = 'Elements';
|
$controller->viewPath = 'Elements';
|
||||||
echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
|
echo $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout);
|
||||||
$this->_stop();
|
$this->_stop();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
$controller->redirect(null, 403);
|
$controller->redirect(null, 403);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if (empty($this->authorize) || $this->isAuthorized($this->user())) {
|
if (empty($this->authorize) || $this->isAuthorized($this->user())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->_unauthorized($controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle unauthorized access attempt
|
||||||
|
*
|
||||||
|
* @param Controller $controller A reference to the controller object
|
||||||
|
* @return boolean Returns false
|
||||||
|
* @throws ForbiddenException
|
||||||
|
*/
|
||||||
|
protected function _unauthorized(Controller $controller) {
|
||||||
|
if (!$this->unauthorizedRedirect) {
|
||||||
|
throw new ForbiddenException($this->authError);
|
||||||
|
}
|
||||||
|
|
||||||
$this->flash($this->authError);
|
$this->flash($this->authError);
|
||||||
$default = '/';
|
$default = '/';
|
||||||
if (!empty($this->loginRedirect)) {
|
if (!empty($this->loginRedirect)) {
|
||||||
|
@ -366,7 +385,8 @@ class AuthComponent extends Component {
|
||||||
public function isAuthorized($user = null, $request = null) {
|
public function isAuthorized($user = null, $request = null) {
|
||||||
if (empty($user) && !$this->user()) {
|
if (empty($user) && !$this->user()) {
|
||||||
return false;
|
return false;
|
||||||
} elseif (empty($user)) {
|
}
|
||||||
|
if (empty($user)) {
|
||||||
$user = $this->user();
|
$user = $this->user();
|
||||||
}
|
}
|
||||||
if (empty($request)) {
|
if (empty($request)) {
|
||||||
|
@ -434,13 +454,13 @@ class AuthComponent extends Component {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
if (empty($args) || $action === null) {
|
if (empty($args) || $action === null) {
|
||||||
$this->allowedActions = $this->_methods;
|
$this->allowedActions = $this->_methods;
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
if (isset($args[0]) && is_array($args[0])) {
|
if (isset($args[0]) && is_array($args[0])) {
|
||||||
$args = $args[0];
|
$args = $args[0];
|
||||||
}
|
}
|
||||||
$this->allowedActions = array_merge($this->allowedActions, $args);
|
$this->allowedActions = array_merge($this->allowedActions, $args);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes items from the list of allowed/no authentication required actions.
|
* Removes items from the list of allowed/no authentication required actions.
|
||||||
|
@ -460,7 +480,8 @@ class AuthComponent extends Component {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
if (empty($args) || $action === null) {
|
if (empty($args) || $action === null) {
|
||||||
$this->allowedActions = array();
|
$this->allowedActions = array();
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
if (isset($args[0]) && is_array($args[0])) {
|
if (isset($args[0]) && is_array($args[0])) {
|
||||||
$args = $args[0];
|
$args = $args[0];
|
||||||
}
|
}
|
||||||
|
@ -472,7 +493,6 @@ class AuthComponent extends Component {
|
||||||
}
|
}
|
||||||
$this->allowedActions = array_values($this->allowedActions);
|
$this->allowedActions = array_values($this->allowedActions);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps action names to CRUD operations. Used for controller-based authentication. Make sure
|
* Maps action names to CRUD operations. Used for controller-based authentication. Make sure
|
||||||
|
|
|
@ -177,7 +177,7 @@ class CookieComponent extends Component {
|
||||||
if ($controller && isset($controller->response)) {
|
if ($controller && isset($controller->response)) {
|
||||||
$this->_response = $controller->response;
|
$this->_response = $controller->response;
|
||||||
} else {
|
} else {
|
||||||
$this->_response = new CakeResponse(array('charset' => Configure::read('App.encoding')));
|
$this->_response = new CakeResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,6 +278,19 @@ class CookieComponent extends Component {
|
||||||
return $this->_values[$this->name][$key];
|
return $this->_values[$this->name][$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if given variable is set in cookie.
|
||||||
|
*
|
||||||
|
* @param string $var Variable name to check for
|
||||||
|
* @return boolean True if variable is there
|
||||||
|
*/
|
||||||
|
public function check($key = null) {
|
||||||
|
if (empty($key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->read($key) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a cookie value
|
* Delete a cookie value
|
||||||
*
|
*
|
||||||
|
@ -378,11 +391,11 @@ class CookieComponent extends Component {
|
||||||
}
|
}
|
||||||
$this->_reset = $this->_expires;
|
$this->_reset = $this->_expires;
|
||||||
|
|
||||||
if ($expires == 0) {
|
if (!$expires) {
|
||||||
return $this->_expires = 0;
|
return $this->_expires = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_integer($expires) || is_numeric($expires)) {
|
if (is_int($expires) || is_numeric($expires)) {
|
||||||
return $this->_expires = $now + intval($expires);
|
return $this->_expires = $now + intval($expires);
|
||||||
}
|
}
|
||||||
return $this->_expires = strtotime($expires, $now);
|
return $this->_expires = strtotime($expires, $now);
|
||||||
|
@ -504,7 +517,7 @@ class CookieComponent extends Component {
|
||||||
$first = substr($string, 0, 1);
|
$first = substr($string, 0, 1);
|
||||||
if ($first === '{' || $first === '[') {
|
if ($first === '{' || $first === '[') {
|
||||||
$ret = json_decode($string, true);
|
$ret = json_decode($string, true);
|
||||||
return ($ret != null) ? $ret : $string;
|
return ($ret) ? $ret : $string;
|
||||||
}
|
}
|
||||||
$array = array();
|
$array = array();
|
||||||
foreach (explode(',', $string) as $pair) {
|
foreach (explode(',', $string) as $pair) {
|
||||||
|
|
|
@ -316,7 +316,7 @@ class EmailComponent extends Component {
|
||||||
foreach ($this->headers as $key => $value) {
|
foreach ($this->headers as $key => $value) {
|
||||||
$headers['X-' . $key] = $value;
|
$headers['X-' . $key] = $value;
|
||||||
}
|
}
|
||||||
if ($this->date != false) {
|
if ($this->date) {
|
||||||
$headers['Date'] = $this->date;
|
$headers['Date'] = $this->date;
|
||||||
}
|
}
|
||||||
$lib->setHeaders($headers);
|
$lib->setHeaders($headers);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
* @since CakePHP(tm) v 2.0
|
* @since CakePHP(tm) v 2.0
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('Component', 'Controller');
|
||||||
App::uses('Hash', 'Utility');
|
App::uses('Hash', 'Utility');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,6 +51,20 @@ App::uses('Hash', 'Utility');
|
||||||
*
|
*
|
||||||
* This would allow you to have different pagination settings for `Comment` and `Post` models.
|
* This would allow you to have different pagination settings for `Comment` and `Post` models.
|
||||||
*
|
*
|
||||||
|
* #### Paginating with custom finders
|
||||||
|
*
|
||||||
|
* You can paginate with any find type defined on your model using the `findType` option.
|
||||||
|
*
|
||||||
|
* {{{
|
||||||
|
* $this->Paginator->settings = array(
|
||||||
|
* 'Post' => array(
|
||||||
|
* 'findType' => 'popular'
|
||||||
|
* )
|
||||||
|
* );
|
||||||
|
* }}}
|
||||||
|
*
|
||||||
|
* Would paginate using the `find('popular')` method.
|
||||||
|
*
|
||||||
* @package Cake.Controller.Component
|
* @package Cake.Controller.Component
|
||||||
* @link http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html
|
* @link http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html
|
||||||
*/
|
*/
|
||||||
|
@ -152,6 +167,12 @@ class PaginatorComponent extends Component {
|
||||||
$extra = array_diff_key($options, compact(
|
$extra = array_diff_key($options, compact(
|
||||||
'conditions', 'fields', 'order', 'limit', 'page', 'recursive'
|
'conditions', 'fields', 'order', 'limit', 'page', 'recursive'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if (!empty($extra['findType'])) {
|
||||||
|
$type = $extra['findType'];
|
||||||
|
unset($extra['findType']);
|
||||||
|
}
|
||||||
|
|
||||||
if ($type !== 'all') {
|
if ($type !== 'all') {
|
||||||
$extra['type'] = $type;
|
$extra['type'] = $type;
|
||||||
}
|
}
|
||||||
|
@ -228,36 +249,34 @@ class PaginatorComponent extends Component {
|
||||||
if (strpos($object, '.') !== false) {
|
if (strpos($object, '.') !== false) {
|
||||||
list($object, $assoc) = pluginSplit($object);
|
list($object, $assoc) = pluginSplit($object);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($assoc && isset($this->Controller->{$object}->{$assoc})) {
|
if ($assoc && isset($this->Controller->{$object}->{$assoc})) {
|
||||||
$object = $this->Controller->{$object}->{$assoc};
|
return $this->Controller->{$object}->{$assoc};
|
||||||
} elseif (
|
|
||||||
$assoc && isset($this->Controller->{$this->Controller->modelClass}) &&
|
|
||||||
isset($this->Controller->{$this->Controller->modelClass}->{$assoc}
|
|
||||||
)) {
|
|
||||||
$object = $this->Controller->{$this->Controller->modelClass}->{$assoc};
|
|
||||||
} elseif (isset($this->Controller->{$object})) {
|
|
||||||
$object = $this->Controller->{$object};
|
|
||||||
} elseif (
|
|
||||||
isset($this->Controller->{$this->Controller->modelClass}) && isset($this->Controller->{$this->Controller->modelClass}->{$object}
|
|
||||||
)) {
|
|
||||||
$object = $this->Controller->{$this->Controller->modelClass}->{$object};
|
|
||||||
}
|
}
|
||||||
} elseif (empty($object) || $object === null) {
|
if ($assoc && isset($this->Controller->{$this->Controller->modelClass}->{$assoc})) {
|
||||||
|
return $this->Controller->{$this->Controller->modelClass}->{$assoc};
|
||||||
|
}
|
||||||
|
if (isset($this->Controller->{$object})) {
|
||||||
|
return $this->Controller->{$object};
|
||||||
|
}
|
||||||
|
if (isset($this->Controller->{$this->Controller->modelClass}->{$object})) {
|
||||||
|
return $this->Controller->{$this->Controller->modelClass}->{$object};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty($object) || $object === null) {
|
||||||
if (isset($this->Controller->{$this->Controller->modelClass})) {
|
if (isset($this->Controller->{$this->Controller->modelClass})) {
|
||||||
$object = $this->Controller->{$this->Controller->modelClass};
|
return $this->Controller->{$this->Controller->modelClass};
|
||||||
} else {
|
}
|
||||||
|
|
||||||
$className = null;
|
$className = null;
|
||||||
$name = $this->Controller->uses[0];
|
$name = $this->Controller->uses[0];
|
||||||
if (strpos($this->Controller->uses[0], '.') !== false) {
|
if (strpos($this->Controller->uses[0], '.') !== false) {
|
||||||
list($name, $className) = explode('.', $this->Controller->uses[0]);
|
list($name, $className) = explode('.', $this->Controller->uses[0]);
|
||||||
}
|
}
|
||||||
if ($className) {
|
if ($className) {
|
||||||
$object = $this->Controller->{$className};
|
return $this->Controller->{$className};
|
||||||
} else {
|
|
||||||
$object = $this->Controller->{$name};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->Controller->{$name};
|
||||||
}
|
}
|
||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
|
@ -299,10 +318,9 @@ class PaginatorComponent extends Component {
|
||||||
* @return array An array of pagination defaults for a model, or the general settings.
|
* @return array An array of pagination defaults for a model, or the general settings.
|
||||||
*/
|
*/
|
||||||
public function getDefaults($alias) {
|
public function getDefaults($alias) {
|
||||||
|
$defaults = $this->settings;
|
||||||
if (isset($this->settings[$alias])) {
|
if (isset($this->settings[$alias])) {
|
||||||
$defaults = $this->settings[$alias];
|
$defaults = $this->settings[$alias];
|
||||||
} else {
|
|
||||||
$defaults = $this->settings;
|
|
||||||
}
|
}
|
||||||
return array_merge(
|
return array_merge(
|
||||||
array('page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named'),
|
array('page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named'),
|
||||||
|
@ -323,13 +341,13 @@ class PaginatorComponent extends Component {
|
||||||
* @param array $whitelist The list of columns that can be used for sorting. If empty all keys are allowed.
|
* @param array $whitelist The list of columns that can be used for sorting. If empty all keys are allowed.
|
||||||
* @return array An array of options with sort + direction removed and replaced with order if possible.
|
* @return array An array of options with sort + direction removed and replaced with order if possible.
|
||||||
*/
|
*/
|
||||||
public function validateSort($object, $options, $whitelist = array()) {
|
public function validateSort(Model $object, array $options, array $whitelist = array()) {
|
||||||
if (isset($options['sort'])) {
|
if (isset($options['sort'])) {
|
||||||
$direction = null;
|
$direction = null;
|
||||||
if (isset($options['direction'])) {
|
if (isset($options['direction'])) {
|
||||||
$direction = strtolower($options['direction']);
|
$direction = strtolower($options['direction']);
|
||||||
}
|
}
|
||||||
if ($direction != 'asc' && $direction != 'desc') {
|
if (!in_array($direction, array('asc', 'desc'))) {
|
||||||
$direction = 'asc';
|
$direction = 'asc';
|
||||||
}
|
}
|
||||||
$options['order'] = array($options['sort'] => $direction);
|
$options['order'] = array($options['sort'] => $direction);
|
||||||
|
@ -371,7 +389,7 @@ class PaginatorComponent extends Component {
|
||||||
* @param array $options An array of options with a limit key to be checked.
|
* @param array $options An array of options with a limit key to be checked.
|
||||||
* @return array An array of options for pagination
|
* @return array An array of options for pagination
|
||||||
*/
|
*/
|
||||||
public function checkLimit($options) {
|
public function checkLimit(array $options) {
|
||||||
$options['limit'] = (int)$options['limit'];
|
$options['limit'] = (int)$options['limit'];
|
||||||
if (empty($options['limit']) || $options['limit'] < 1) {
|
if (empty($options['limit']) || $options['limit'] < 1) {
|
||||||
$options['limit'] = 1;
|
$options['limit'] = 1;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
App::uses('Component', 'Controller');
|
||||||
App::uses('Xml', 'Utility');
|
App::uses('Xml', 'Utility');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +89,17 @@ class RequestHandlerComponent extends Component {
|
||||||
'json' => array('json_decode', true)
|
'json' => array('json_decode', true)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping between type and viewClass
|
||||||
|
* By default only JSON and XML are mapped, use RequestHandlerComponent::viewClassMap()
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_viewClassMap = array(
|
||||||
|
'json' => 'Json',
|
||||||
|
'xml' => 'Xml'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
|
* Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
|
||||||
*
|
*
|
||||||
|
@ -95,8 +107,7 @@ class RequestHandlerComponent extends Component {
|
||||||
* @param array $settings Array of settings.
|
* @param array $settings Array of settings.
|
||||||
*/
|
*/
|
||||||
public function __construct(ComponentCollection $collection, $settings = array()) {
|
public function __construct(ComponentCollection $collection, $settings = array()) {
|
||||||
$default = array('checkHttpCache' => true);
|
parent::__construct($collection, $settings + array('checkHttpCache' => true));
|
||||||
parent::__construct($collection, $settings + $default);
|
|
||||||
$this->addInputType('xml', array(array($this, 'convertXml')));
|
$this->addInputType('xml', array(array($this, 'convertXml')));
|
||||||
|
|
||||||
$Controller = $collection->getController();
|
$Controller = $collection->getController();
|
||||||
|
@ -111,11 +122,10 @@ class RequestHandlerComponent extends Component {
|
||||||
* and the requested mime-types, RequestHandler::$ext is set to that value.
|
* and the requested mime-types, RequestHandler::$ext is set to that value.
|
||||||
*
|
*
|
||||||
* @param Controller $controller A reference to the controller
|
* @param Controller $controller A reference to the controller
|
||||||
* @param array $settings Array of settings to _set().
|
|
||||||
* @return void
|
* @return void
|
||||||
* @see Router::parseExtensions()
|
* @see Router::parseExtensions()
|
||||||
*/
|
*/
|
||||||
public function initialize(Controller $controller, $settings = array()) {
|
public function initialize(Controller $controller) {
|
||||||
if (isset($this->request->params['ext'])) {
|
if (isset($this->request->params['ext'])) {
|
||||||
$this->ext = $this->request->params['ext'];
|
$this->ext = $this->request->params['ext'];
|
||||||
}
|
}
|
||||||
|
@ -123,7 +133,9 @@ class RequestHandlerComponent extends Component {
|
||||||
$this->_setExtension();
|
$this->_setExtension();
|
||||||
}
|
}
|
||||||
$this->params = $controller->params;
|
$this->params = $controller->params;
|
||||||
$this->_set($settings);
|
if (!empty($this->settings['viewClassMap'])) {
|
||||||
|
$this->viewClassMap($this->settings['viewClassMap']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,11 +157,13 @@ class RequestHandlerComponent extends Component {
|
||||||
$extensions = Router::extensions();
|
$extensions = Router::extensions();
|
||||||
$preferred = array_shift($accept);
|
$preferred = array_shift($accept);
|
||||||
$preferredTypes = $this->response->mapType($preferred);
|
$preferredTypes = $this->response->mapType($preferred);
|
||||||
|
if (!in_array('xhtml', $preferredTypes) && !in_array('html', $preferredTypes)) {
|
||||||
$similarTypes = array_intersect($extensions, $preferredTypes);
|
$similarTypes = array_intersect($extensions, $preferredTypes);
|
||||||
if (count($similarTypes) === 1 && !in_array('xhtml', $preferredTypes) && !in_array('html', $preferredTypes)) {
|
if (count($similarTypes) === 1) {
|
||||||
$this->ext = array_shift($similarTypes);
|
$this->ext = array_shift($similarTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The startup method of the RequestHandler enables several automatic behaviors
|
* The startup method of the RequestHandler enables several automatic behaviors
|
||||||
|
@ -256,8 +270,7 @@ class RequestHandlerComponent extends Component {
|
||||||
* @return boolean false if the render process should be aborted
|
* @return boolean false if the render process should be aborted
|
||||||
**/
|
**/
|
||||||
public function beforeRender(Controller $controller) {
|
public function beforeRender(Controller $controller) {
|
||||||
$shouldCheck = $this->settings['checkHttpCache'];
|
if ($this->settings['checkHttpCache'] && $this->response->checkNotModified($this->request)) {
|
||||||
if ($shouldCheck && $this->response->checkNotModified($this->request)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,13 +395,11 @@ class RequestHandlerComponent extends Component {
|
||||||
* Gets Prototype version if call is Ajax, otherwise empty string.
|
* Gets Prototype version if call is Ajax, otherwise empty string.
|
||||||
* The Prototype library sets a special "Prototype version" HTTP header.
|
* The Prototype library sets a special "Prototype version" HTTP header.
|
||||||
*
|
*
|
||||||
* @return string Prototype version of component making Ajax call
|
* @return string|boolean When Ajax the prototype version of component making the call otherwise false
|
||||||
*/
|
*/
|
||||||
public function getAjaxVersion() {
|
public function getAjaxVersion() {
|
||||||
if (env('HTTP_X_PROTOTYPE_VERSION') != null) {
|
$httpX = env('HTTP_X_PROTOTYPE_VERSION');
|
||||||
return env('HTTP_X_PROTOTYPE_VERSION');
|
return ($httpX === null) ? false : $httpX;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,9 +465,10 @@ class RequestHandlerComponent extends Component {
|
||||||
public function accepts($type = null) {
|
public function accepts($type = null) {
|
||||||
$accepted = $this->request->accepts();
|
$accepted = $this->request->accepts();
|
||||||
|
|
||||||
if ($type == null) {
|
if (!$type) {
|
||||||
return $this->mapType($accepted);
|
return $this->mapType($accepted);
|
||||||
} elseif (is_array($type)) {
|
}
|
||||||
|
if (is_array($type)) {
|
||||||
foreach ($type as $t) {
|
foreach ($type as $t) {
|
||||||
$t = $this->mapAlias($t);
|
$t = $this->mapAlias($t);
|
||||||
if (in_array($t, $accepted)) {
|
if (in_array($t, $accepted)) {
|
||||||
|
@ -464,9 +476,9 @@ class RequestHandlerComponent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} elseif (is_string($type)) {
|
}
|
||||||
$type = $this->mapAlias($type);
|
if (is_string($type)) {
|
||||||
return in_array($type, $accepted);
|
return in_array($this->mapAlias($type), $accepted);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -483,18 +495,20 @@ class RequestHandlerComponent extends Component {
|
||||||
if (!$this->request->is('post') && !$this->request->is('put')) {
|
if (!$this->request->is('post') && !$this->request->is('put')) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (is_array($type)) {
|
||||||
list($contentType) = explode(';', env('CONTENT_TYPE'));
|
|
||||||
if ($type == null) {
|
|
||||||
return $this->mapType($contentType);
|
|
||||||
} elseif (is_array($type)) {
|
|
||||||
foreach ($type as $t) {
|
foreach ($type as $t) {
|
||||||
if ($this->requestedWith($t)) {
|
if ($this->requestedWith($t)) {
|
||||||
return $t;
|
return $t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} elseif (is_string($type)) {
|
}
|
||||||
|
|
||||||
|
list($contentType) = explode(';', env('CONTENT_TYPE'));
|
||||||
|
if (!$type) {
|
||||||
|
return $this->mapType($contentType);
|
||||||
|
}
|
||||||
|
if (is_string($type)) {
|
||||||
return ($type == $this->mapType($contentType));
|
return ($type == $this->mapType($contentType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,10 +536,9 @@ class RequestHandlerComponent extends Component {
|
||||||
if (empty($acceptRaw)) {
|
if (empty($acceptRaw)) {
|
||||||
return $this->ext;
|
return $this->ext;
|
||||||
}
|
}
|
||||||
$accepts = array_shift($acceptRaw);
|
$accepts = $this->mapType(array_shift($acceptRaw));
|
||||||
$accepts = $this->mapType($accepts);
|
|
||||||
|
|
||||||
if ($type == null) {
|
if (!$type) {
|
||||||
if (empty($this->ext) && !empty($accepts)) {
|
if (empty($this->ext) && !empty($accepts)) {
|
||||||
return $accepts[0];
|
return $accepts[0];
|
||||||
}
|
}
|
||||||
|
@ -582,18 +595,27 @@ class RequestHandlerComponent extends Component {
|
||||||
}
|
}
|
||||||
$controller->ext = '.ctp';
|
$controller->ext = '.ctp';
|
||||||
|
|
||||||
|
$pluginDot = null;
|
||||||
|
$viewClassMap = $this->viewClassMap();
|
||||||
|
if (array_key_exists($type, $viewClassMap)) {
|
||||||
|
list($pluginDot, $viewClass) = pluginSplit($viewClassMap[$type], true);
|
||||||
|
} else {
|
||||||
$viewClass = Inflector::classify($type);
|
$viewClass = Inflector::classify($type);
|
||||||
|
}
|
||||||
$viewName = $viewClass . 'View';
|
$viewName = $viewClass . 'View';
|
||||||
if (!class_exists($viewName)) {
|
if (!class_exists($viewName)) {
|
||||||
App::uses($viewName, 'View');
|
App::uses($viewName, $pluginDot . 'View');
|
||||||
}
|
}
|
||||||
if (class_exists($viewName)) {
|
if (class_exists($viewName)) {
|
||||||
$controller->viewClass = $viewClass;
|
$controller->viewClass = $viewClass;
|
||||||
} elseif (empty($this->_renderType)) {
|
} elseif (empty($this->_renderType)) {
|
||||||
$controller->viewPath .= DS . $type;
|
$controller->viewPath .= DS . $type;
|
||||||
} else {
|
} else {
|
||||||
$remove = preg_replace("/([\/\\\\]{$this->_renderType})$/", DS . $type, $controller->viewPath);
|
$controller->viewPath = preg_replace(
|
||||||
$controller->viewPath = $remove;
|
"/([\/\\\\]{$this->_renderType})$/",
|
||||||
|
DS . $type,
|
||||||
|
$controller->viewPath
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$this->_renderType = $type;
|
$this->_renderType = $type;
|
||||||
$controller->layoutPath = $type;
|
$controller->layoutPath = $type;
|
||||||
|
@ -603,12 +625,8 @@ class RequestHandlerComponent extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
$helper = ucfirst($type);
|
$helper = ucfirst($type);
|
||||||
$isAdded = (
|
|
||||||
in_array($helper, $controller->helpers) ||
|
|
||||||
array_key_exists($helper, $controller->helpers)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$isAdded) {
|
if (!in_array($helper, $controller->helpers) && empty($controller->helpers[$helper])) {
|
||||||
App::uses('AppHelper', 'View/Helper');
|
App::uses('AppHelper', 'View/Helper');
|
||||||
App::uses($helper . 'Helper', 'View/Helper');
|
App::uses($helper . 'Helper', 'View/Helper');
|
||||||
if (class_exists($helper . 'Helper')) {
|
if (class_exists($helper . 'Helper')) {
|
||||||
|
@ -634,30 +652,28 @@ class RequestHandlerComponent extends Component {
|
||||||
$defaults = array('index' => null, 'charset' => null, 'attachment' => false);
|
$defaults = array('index' => null, 'charset' => null, 'attachment' => false);
|
||||||
$options = $options + $defaults;
|
$options = $options + $defaults;
|
||||||
|
|
||||||
|
$cType = $type;
|
||||||
if (strpos($type, '/') === false) {
|
if (strpos($type, '/') === false) {
|
||||||
$cType = $this->response->getMimeType($type);
|
$cType = $this->response->getMimeType($type);
|
||||||
if ($cType === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (is_array($cType) && isset($cType[$options['index']])) {
|
|
||||||
$cType = $cType[$options['index']];
|
|
||||||
}
|
}
|
||||||
if (is_array($cType)) {
|
if (is_array($cType)) {
|
||||||
|
if (isset($cType[$options['index']])) {
|
||||||
|
$cType = $cType[$options['index']];
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->prefers($cType)) {
|
if ($this->prefers($cType)) {
|
||||||
$cType = $this->prefers($cType);
|
$cType = $this->prefers($cType);
|
||||||
} else {
|
} else {
|
||||||
$cType = $cType[0];
|
$cType = $cType[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$cType = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cType != null) {
|
if (!$type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (empty($this->request->params['requested'])) {
|
if (empty($this->request->params['requested'])) {
|
||||||
$this->response->type($cType);
|
$this->response->type($cType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($options['charset'])) {
|
if (!empty($options['charset'])) {
|
||||||
$this->response->charset($options['charset']);
|
$this->response->charset($options['charset']);
|
||||||
}
|
}
|
||||||
|
@ -666,8 +682,6 @@ class RequestHandlerComponent extends Component {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current response type (Content-type header), or null if not alias exists
|
* Returns the current response type (Content-type header), or null if not alias exists
|
||||||
|
@ -729,4 +743,25 @@ class RequestHandlerComponent extends Component {
|
||||||
$this->_inputTypeMap[$type] = $handler;
|
$this->_inputTypeMap[$type] = $handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter/setter for viewClassMap
|
||||||
|
*
|
||||||
|
* @param array|string $type The type string or array with format `array('type' => 'viewClass')` to map one or more
|
||||||
|
* @param array $viewClass The viewClass to be used for the type without `View` appended
|
||||||
|
* @return array]string Returns viewClass when only string $type is set, else array with viewClassMap
|
||||||
|
*/
|
||||||
|
public function viewClassMap($type = null, $viewClass = null) {
|
||||||
|
if (!$viewClass && is_string($type) && isset($this->_viewClassMap[$type])) {
|
||||||
|
return $this->_viewClassMap[$type];
|
||||||
|
}
|
||||||
|
if (is_string($type)) {
|
||||||
|
$this->_viewClassMap[$type] = $viewClass;
|
||||||
|
} elseif (is_array($type)) {
|
||||||
|
foreach ($type as $key => $value) {
|
||||||
|
$this->viewClassMap($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->_viewClassMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,13 @@ class SecurityComponent extends Component {
|
||||||
*/
|
*/
|
||||||
public $unlockedFields = array();
|
public $unlockedFields = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions to exclude from any security checks
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $unlockedActions = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to validate POST data. Set to false to disable for data coming from 3rd party
|
* Whether to validate POST data. Set to false to disable for data coming from 3rd party
|
||||||
* services, etc.
|
* services, etc.
|
||||||
|
@ -218,13 +225,11 @@ class SecurityComponent extends Component {
|
||||||
$controller->request->params['requested'] != 1
|
$controller->request->params['requested'] != 1
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($isPost && $isNotRequestAction && $this->validatePost) {
|
if (!in_array($this->_action, (array)$this->unlockedActions) && $isPost && $isNotRequestAction) {
|
||||||
if ($this->_validatePost($controller) === false) {
|
if ($this->validatePost && $this->_validatePost($controller) === false) {
|
||||||
return $this->blackHole($controller, 'auth');
|
return $this->blackHole($controller, 'auth');
|
||||||
}
|
}
|
||||||
}
|
if ($this->csrfCheck && $this->_validateCsrf($controller) === false) {
|
||||||
if ($isPost && $isNotRequestAction && $this->csrfCheck) {
|
|
||||||
if ($this->_validateCsrf($controller) === false) {
|
|
||||||
return $this->blackHole($controller, 'csrf');
|
return $this->blackHole($controller, 'csrf');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,11 +314,10 @@ class SecurityComponent extends Component {
|
||||||
* @throws BadRequestException
|
* @throws BadRequestException
|
||||||
*/
|
*/
|
||||||
public function blackHole(Controller $controller, $error = '') {
|
public function blackHole(Controller $controller, $error = '') {
|
||||||
if ($this->blackHoleCallback == null) {
|
if (!$this->blackHoleCallback) {
|
||||||
throw new BadRequestException(__d('cake_dev', 'The request has been black-holed'));
|
throw new BadRequestException(__d('cake_dev', 'The request has been black-holed'));
|
||||||
} else {
|
|
||||||
return $this->_callback($controller, $this->blackHoleCallback, array($error));
|
|
||||||
}
|
}
|
||||||
|
return $this->_callback($controller, $this->blackHoleCallback, array($error));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -489,7 +493,7 @@ class SecurityComponent extends Component {
|
||||||
|
|
||||||
$fieldList += $lockedFields;
|
$fieldList += $lockedFields;
|
||||||
$unlocked = implode('|', $unlocked);
|
$unlocked = implode('|', $unlocked);
|
||||||
$check = Security::hash(serialize($fieldList) . $unlocked . Configure::read('Security.salt'));
|
$check = Security::hash(serialize($fieldList) . $unlocked . Configure::read('Security.salt'), 'sha1');
|
||||||
return ($token === $check);
|
return ($token === $check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,11 +592,10 @@ class SecurityComponent extends Component {
|
||||||
* @throws BadRequestException When a the blackholeCallback is not callable.
|
* @throws BadRequestException When a the blackholeCallback is not callable.
|
||||||
*/
|
*/
|
||||||
protected function _callback(Controller $controller, $method, $params = array()) {
|
protected function _callback(Controller $controller, $method, $params = array()) {
|
||||||
if (is_callable(array($controller, $method))) {
|
if (!is_callable(array($controller, $method))) {
|
||||||
return call_user_func_array(array(&$controller, $method), empty($params) ? null : $params);
|
|
||||||
} else {
|
|
||||||
throw new BadRequestException(__d('cake_dev', 'The request has been black-holed'));
|
throw new BadRequestException(__d('cake_dev', 'The request has been black-holed'));
|
||||||
}
|
}
|
||||||
|
return call_user_func_array(array(&$controller, $method), empty($params) ? null : $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,7 +319,7 @@ class Controller extends Object implements CakeEventListener {
|
||||||
$this->name = substr(get_class($this), 0, -10);
|
$this->name = substr(get_class($this), 0, -10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->viewPath == null) {
|
if (!$this->viewPath) {
|
||||||
$this->viewPath = $this->name;
|
$this->viewPath = $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +454,7 @@ class Controller extends Object implements CakeEventListener {
|
||||||
$this->passedArgs = array_merge($request->params['pass'], $request->params['named']);
|
$this->passedArgs = array_merge($request->params['pass'], $request->params['named']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('return', $request->params) && $request->params['return'] == 1) {
|
if (!empty($request->params['return']) && $request->params['return'] == 1) {
|
||||||
$this->autoRender = false;
|
$this->autoRender = false;
|
||||||
}
|
}
|
||||||
if (!empty($request->params['bare'])) {
|
if (!empty($request->params['bare'])) {
|
||||||
|
@ -966,15 +966,16 @@ class Controller extends Object implements CakeEventListener {
|
||||||
* @link http://book.cakephp.org/2.0/en/controllers.html#Controller::referer
|
* @link http://book.cakephp.org/2.0/en/controllers.html#Controller::referer
|
||||||
*/
|
*/
|
||||||
public function referer($default = null, $local = false) {
|
public function referer($default = null, $local = false) {
|
||||||
if ($this->request) {
|
if (!$this->request) {
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
$referer = $this->request->referer($local);
|
$referer = $this->request->referer($local);
|
||||||
if ($referer == '/' && $default != null) {
|
if ($referer == '/' && $default) {
|
||||||
return Router::url($default, true);
|
return Router::url($default, true);
|
||||||
}
|
}
|
||||||
return $referer;
|
return $referer;
|
||||||
}
|
}
|
||||||
return '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces the user's browser not to cache the results of the current request.
|
* Forces the user's browser not to cache the results of the current request.
|
||||||
|
@ -1061,7 +1062,7 @@ class Controller extends Object implements CakeEventListener {
|
||||||
$cond[$key] = $value;
|
$cond[$key] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($bool != null && strtoupper($bool) != 'AND') {
|
if ($bool && strtoupper($bool) != 'AND') {
|
||||||
$cond = array($bool => $cond);
|
$cond = array($bool => $cond);
|
||||||
}
|
}
|
||||||
return $cond;
|
return $cond;
|
||||||
|
|
|
@ -146,7 +146,7 @@ class Scaffold {
|
||||||
$this->controller->viewClass = 'Scaffold';
|
$this->controller->viewClass = 'Scaffold';
|
||||||
}
|
}
|
||||||
$this->_validSession = (
|
$this->_validSession = (
|
||||||
isset($this->controller->Session) && $this->controller->Session->valid() != false
|
isset($this->controller->Session) && $this->controller->Session->valid()
|
||||||
);
|
);
|
||||||
$this->_scaffold($request);
|
$this->_scaffold($request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,7 +607,7 @@ class App {
|
||||||
extract($parent, EXTR_OVERWRITE);
|
extract($parent, EXTR_OVERWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($name == null && $file == null) {
|
if (!$name && !$file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,19 @@ class Configure {
|
||||||
return Hash::get(self::$_values, $var);
|
return Hash::get(self::$_values, $var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if given variable is set in Configure.
|
||||||
|
*
|
||||||
|
* @param string $var Variable name to check for
|
||||||
|
* @return boolean True if variable is there
|
||||||
|
*/
|
||||||
|
public static function check($var = null) {
|
||||||
|
if (empty($var)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Hash::get(self::$_values, $var) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to delete a variable from Configure.
|
* Used to delete a variable from Configure.
|
||||||
*
|
*
|
||||||
|
@ -306,10 +319,10 @@ class Configure {
|
||||||
public static function dump($key, $config = 'default', $keys = array()) {
|
public static function dump($key, $config = 'default', $keys = array()) {
|
||||||
$reader = self::_getReader($config);
|
$reader = self::_getReader($config);
|
||||||
if (!$reader) {
|
if (!$reader) {
|
||||||
throw new ConfigureException(__d('cake', 'There is no "%s" adapter.', $config));
|
throw new ConfigureException(__d('cake_dev', 'There is no "%s" adapter.', $config));
|
||||||
}
|
}
|
||||||
if (!method_exists($reader, 'dump')) {
|
if (!method_exists($reader, 'dump')) {
|
||||||
throw new ConfigureException(__d('cake', 'The "%s" adapter, does not have a dump() method.', $config));
|
throw new ConfigureException(__d('cake_dev', 'The "%s" adapter, does not have a dump() method.', $config));
|
||||||
}
|
}
|
||||||
$values = self::$_values;
|
$values = self::$_values;
|
||||||
if (!empty($keys) && is_array($keys)) {
|
if (!empty($keys) && is_array($keys)) {
|
||||||
|
|
|
@ -102,10 +102,7 @@ class ExceptionRenderer {
|
||||||
|
|
||||||
if ($exception instanceof CakeException && !$methodExists) {
|
if ($exception instanceof CakeException && !$methodExists) {
|
||||||
$method = '_cakeError';
|
$method = '_cakeError';
|
||||||
if (empty($template)) {
|
if (empty($template) || $template == 'internalError') {
|
||||||
$template = 'error500';
|
|
||||||
}
|
|
||||||
if ($template == 'internalError') {
|
|
||||||
$template = 'error500';
|
$template = 'error500';
|
||||||
}
|
}
|
||||||
} elseif ($exception instanceof PDOException) {
|
} elseif ($exception instanceof PDOException) {
|
||||||
|
@ -119,14 +116,13 @@ class ExceptionRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Configure::read('debug') == 0) {
|
$isNotDebug = !Configure::read('debug');
|
||||||
if ($method == '_cakeError') {
|
if ($isNotDebug && $method == '_cakeError') {
|
||||||
$method = 'error400';
|
$method = 'error400';
|
||||||
}
|
}
|
||||||
if ($code == 500) {
|
if ($isNotDebug && $code == 500) {
|
||||||
$method = 'error500';
|
$method = 'error500';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
$this->template = $template;
|
$this->template = $template;
|
||||||
$this->method = $method;
|
$this->method = $method;
|
||||||
$this->error = $exception;
|
$this->error = $exception;
|
||||||
|
@ -147,7 +143,12 @@ class ExceptionRenderer {
|
||||||
if (!$request = Router::getRequest(true)) {
|
if (!$request = Router::getRequest(true)) {
|
||||||
$request = new CakeRequest();
|
$request = new CakeRequest();
|
||||||
}
|
}
|
||||||
$response = new CakeResponse(array('charset' => Configure::read('App.encoding')));
|
$response = new CakeResponse();
|
||||||
|
|
||||||
|
if (method_exists($exception, 'responseHeader')) {
|
||||||
|
$response->header($exception->responseHeader());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$controller = new CakeErrorController($request, $response);
|
$controller = new CakeErrorController($request, $response);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
@ -183,7 +184,7 @@ class ExceptionRenderer {
|
||||||
$this->controller->set(array(
|
$this->controller->set(array(
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
'url' => h($url),
|
'url' => h($url),
|
||||||
'name' => $error->getMessage(),
|
'name' => h($error->getMessage()),
|
||||||
'error' => $error,
|
'error' => $error,
|
||||||
'_serialize' => array('code', 'url', 'name')
|
'_serialize' => array('code', 'url', 'name')
|
||||||
));
|
));
|
||||||
|
@ -199,13 +200,13 @@ class ExceptionRenderer {
|
||||||
*/
|
*/
|
||||||
public function error400($error) {
|
public function error400($error) {
|
||||||
$message = $error->getMessage();
|
$message = $error->getMessage();
|
||||||
if (Configure::read('debug') == 0 && $error instanceof CakeException) {
|
if (!Configure::read('debug') && $error instanceof CakeException) {
|
||||||
$message = __d('cake', 'Not Found');
|
$message = __d('cake', 'Not Found');
|
||||||
}
|
}
|
||||||
$url = $this->controller->request->here();
|
$url = $this->controller->request->here();
|
||||||
$this->controller->response->statusCode($error->getCode());
|
$this->controller->response->statusCode($error->getCode());
|
||||||
$this->controller->set(array(
|
$this->controller->set(array(
|
||||||
'name' => $message,
|
'name' => h($message),
|
||||||
'url' => h($url),
|
'url' => h($url),
|
||||||
'error' => $error,
|
'error' => $error,
|
||||||
'_serialize' => array('name', 'url')
|
'_serialize' => array('name', 'url')
|
||||||
|
@ -221,14 +222,14 @@ class ExceptionRenderer {
|
||||||
*/
|
*/
|
||||||
public function error500($error) {
|
public function error500($error) {
|
||||||
$message = $error->getMessage();
|
$message = $error->getMessage();
|
||||||
if (Configure::read('debug') == 0) {
|
if (!Configure::read('debug')) {
|
||||||
$message = __d('cake', 'An Internal Error Has Occurred.');
|
$message = __d('cake', 'An Internal Error Has Occurred.');
|
||||||
}
|
}
|
||||||
$url = $this->controller->request->here();
|
$url = $this->controller->request->here();
|
||||||
$code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500;
|
$code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500;
|
||||||
$this->controller->response->statusCode($code);
|
$this->controller->response->statusCode($code);
|
||||||
$this->controller->set(array(
|
$this->controller->set(array(
|
||||||
'name' => $message,
|
'name' => h($message),
|
||||||
'message' => h($url),
|
'message' => h($url),
|
||||||
'error' => $error,
|
'error' => $error,
|
||||||
'_serialize' => array('name', 'message')
|
'_serialize' => array('name', 'message')
|
||||||
|
@ -249,7 +250,7 @@ class ExceptionRenderer {
|
||||||
$this->controller->set(array(
|
$this->controller->set(array(
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
'url' => h($url),
|
'url' => h($url),
|
||||||
'name' => $error->getMessage(),
|
'name' => h($error->getMessage()),
|
||||||
'error' => $error,
|
'error' => $error,
|
||||||
'_serialize' => array('code', 'url', 'name', 'error')
|
'_serialize' => array('code', 'url', 'name', 'error')
|
||||||
));
|
));
|
||||||
|
|
|
@ -18,6 +18,43 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class that all Exceptions extend.
|
||||||
|
*
|
||||||
|
* @package Cake.Error
|
||||||
|
*/
|
||||||
|
class CakeBaseException extends RuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of headers to be passed to CakeResponse::header()
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_responseHeaders = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get/set the response header to be used
|
||||||
|
*
|
||||||
|
* See also CakeResponse::header()
|
||||||
|
*
|
||||||
|
* @param string|array $header. An array of header strings or a single header string
|
||||||
|
* - an associative array of "header name" => "header value"
|
||||||
|
* - an array of string headers is also accepted
|
||||||
|
* @param string $value. The header value.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function responseHeader($header = null, $value = null) {
|
||||||
|
if ($header) {
|
||||||
|
if (is_array($header)) {
|
||||||
|
return $this->_responseHeaders = $header;
|
||||||
|
}
|
||||||
|
$this->_responseHeaders = array($header => $value);
|
||||||
|
}
|
||||||
|
return $this->_responseHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent class for all of the HTTP related exceptions in CakePHP.
|
* Parent class for all of the HTTP related exceptions in CakePHP.
|
||||||
* All HTTP status/error related exceptions should extend this class so
|
* All HTTP status/error related exceptions should extend this class so
|
||||||
|
@ -26,7 +63,7 @@
|
||||||
* @package Cake.Error
|
* @package Cake.Error
|
||||||
*/
|
*/
|
||||||
if (!class_exists('HttpException')) {
|
if (!class_exists('HttpException')) {
|
||||||
class HttpException extends RuntimeException {
|
class HttpException extends CakeBaseException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +205,7 @@ class InternalErrorException extends HttpException {
|
||||||
*
|
*
|
||||||
* @package Cake.Error
|
* @package Cake.Error
|
||||||
*/
|
*/
|
||||||
class CakeException extends RuntimeException {
|
class CakeException extends CakeBaseException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of attributes that are passed in from the constructor, and
|
* Array of attributes that are passed in from the constructor, and
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent the transport class of events across the system, it receives a name, and subject and an optional
|
* Represents the transport class of events across the system, it receives a name, and subject and an optional
|
||||||
* payload. The name can be any string that uniquely identifies the event across the application, while the subject
|
* payload. The name can be any string that uniquely identifies the event across the application, while the subject
|
||||||
* represents the object that the event is applying to.
|
* represents the object that the event applies to.
|
||||||
*
|
*
|
||||||
* @package Cake.Event
|
* @package Cake.Event
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,15 +18,15 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Objects implementing this interface should declare the `implementedEvents` function
|
* Objects implementing this interface should declare the `implementedEvents` function
|
||||||
* to hint the event manager what methods should be called when an event is triggered.
|
* to notify the event manager what methods should be called when an event is triggered.
|
||||||
*
|
*
|
||||||
* @package Cake.Event
|
* @package Cake.Event
|
||||||
*/
|
*/
|
||||||
interface CakeEventListener {
|
interface CakeEventListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of events this object is implementing, when the class is registered
|
* Returns a list of events this object is implementing. When the class is registered
|
||||||
* in an event manager, each individual method will be associated to the respective event.
|
* in an event manager, each individual method will be associated with the respective event.
|
||||||
*
|
*
|
||||||
* ## Example:
|
* ## Example:
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
App::uses('CakeEventListener', 'Event');
|
App::uses('CakeEventListener', 'Event');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event manager is responsible for keeping track of event listeners and pass the correct
|
* The event manager is responsible for keeping track of event listeners, passing the correct
|
||||||
* data to them, and fire them in the correct order, when associated events are triggered. You
|
* data to them, and firing them in the correct order, when associated events are triggered. You
|
||||||
* can create multiple instances of this objects to manage local events or keep a single instance
|
* can create multiple instances of this object to manage local events or keep a single instance
|
||||||
* and pass it around to manage all events in your app.
|
* and pass it around to manage all events in your app.
|
||||||
*
|
*
|
||||||
* @package Cake.Event
|
* @package Cake.Event
|
||||||
|
@ -29,7 +29,7 @@ App::uses('CakeEventListener', 'Event');
|
||||||
class CakeEventManager {
|
class CakeEventManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default priority queue value for new attached listeners
|
* The default priority queue value for new, attached listeners
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
|
@ -50,7 +50,7 @@ class CakeEventManager {
|
||||||
protected $_listeners = array();
|
protected $_listeners = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal flag to distinguish a common manager from the sigleton
|
* Internal flag to distinguish a common manager from the singleton
|
||||||
*
|
*
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
|
@ -62,7 +62,7 @@ class CakeEventManager {
|
||||||
* other managers were created. Usually for creating hook systems or inter-class
|
* other managers were created. Usually for creating hook systems or inter-class
|
||||||
* communication
|
* communication
|
||||||
*
|
*
|
||||||
* If called with a first params, it will be set as the globally available instance
|
* If called with the first parameter, it will be set as the globally available instance
|
||||||
*
|
*
|
||||||
* @param CakeEventManager $manager
|
* @param CakeEventManager $manager
|
||||||
* @return CakeEventManager the global event manager
|
* @return CakeEventManager the global event manager
|
||||||
|
@ -83,15 +83,15 @@ class CakeEventManager {
|
||||||
* Adds a new listener to an event. Listeners
|
* Adds a new listener to an event. Listeners
|
||||||
*
|
*
|
||||||
* @param callback|CakeEventListener $callable PHP valid callback type or instance of CakeEventListener to be called
|
* @param callback|CakeEventListener $callable PHP valid callback type or instance of CakeEventListener to be called
|
||||||
* when the event named with $eventKey is triggered. If a CakeEventListener instances is passed, then the `implementedEvents`
|
* when the event named with $eventKey is triggered. If a CakeEventListener instance is passed, then the `implementedEvents`
|
||||||
* method will be called on the object to register the declared events individually as methods to be managed by this class.
|
* method will be called on the object to register the declared events individually as methods to be managed by this class.
|
||||||
* It is possible to define multiple event handlers per event name.
|
* It is possible to define multiple event handlers per event name.
|
||||||
*
|
*
|
||||||
* @param string $eventKey The event unique identifier name to with the callback will be associated. If $callable
|
* @param string $eventKey The event unique identifier name with which the callback will be associated. If $callable
|
||||||
* is an instance of CakeEventListener this argument will be ignored
|
* is an instance of CakeEventListener this argument will be ignored
|
||||||
*
|
*
|
||||||
* @param array $options used to set the `priority` and `passParams` flags to the listener.
|
* @param array $options used to set the `priority` and `passParams` flags to the listener.
|
||||||
* Priorities are handled like queues, and multiple attachments into the same priority queue will be treated in
|
* Priorities are handled like queues, and multiple attachments added to the same priority queue will be treated in
|
||||||
* the order of insertion. `passParams` means that the event data property will be converted to function arguments
|
* the order of insertion. `passParams` means that the event data property will be converted to function arguments
|
||||||
* when the listener is called. If $called is an instance of CakeEventListener, this parameter will be ignored
|
* when the listener is called. If $called is an instance of CakeEventListener, this parameter will be ignored
|
||||||
*
|
*
|
||||||
|
@ -145,7 +145,7 @@ class CakeEventManager {
|
||||||
* Auxiliary function to extract and return a PHP callback type out of the callable definition
|
* Auxiliary function to extract and return a PHP callback type out of the callable definition
|
||||||
* from the return value of the `implementedEvents` method on a CakeEventListener
|
* from the return value of the `implementedEvents` method on a CakeEventListener
|
||||||
*
|
*
|
||||||
* @param array $function the array taken from a handler definition for a event
|
* @param array $function the array taken from a handler definition for an event
|
||||||
* @param CakeEventListener $object The handler object
|
* @param CakeEventListener $object The handler object
|
||||||
* @return callback
|
* @return callback
|
||||||
*/
|
*/
|
||||||
|
@ -256,7 +256,7 @@ class CakeEventManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all listeners for a eventKey in the order they should be called
|
* Returns a list of all listeners for an eventKey in the order they should be called
|
||||||
*
|
*
|
||||||
* @param string $eventKey
|
* @param string $eventKey
|
||||||
* @return array
|
* @return array
|
||||||
|
|
|
@ -405,7 +405,7 @@ class I18n {
|
||||||
$header = unpack("L1magic/L1version/L1count/L1o_msg/L1o_trn", $header);
|
$header = unpack("L1magic/L1version/L1count/L1o_msg/L1o_trn", $header);
|
||||||
extract($header);
|
extract($header);
|
||||||
|
|
||||||
if ((dechex($magic) == '950412de' || dechex($magic) == 'ffffffff950412de') && $version == 0) {
|
if ((dechex($magic) == '950412de' || dechex($magic) == 'ffffffff950412de') && !$version) {
|
||||||
for ($n = 0; $n < $count; $n++) {
|
for ($n = 0; $n < $count; $n++) {
|
||||||
$r = unpack("L1len/L1offs", substr($data, $o_msg + $n * 8, 8));
|
$r = unpack("L1len/L1offs", substr($data, $o_msg + $n * 8, 8));
|
||||||
$msgid = substr($data, $r["offs"], $r["len"]);
|
$msgid = substr($data, $r["offs"], $r["len"]);
|
||||||
|
@ -585,19 +585,19 @@ class I18n {
|
||||||
$string = $string[1];
|
$string = $string[1];
|
||||||
if (substr($string, 0, 2) === $this->_escape . 'x') {
|
if (substr($string, 0, 2) === $this->_escape . 'x') {
|
||||||
$delimiter = $this->_escape . 'x';
|
$delimiter = $this->_escape . 'x';
|
||||||
return join('', array_map('chr', array_map('hexdec',array_filter(explode($delimiter, $string)))));
|
return implode('', array_map('chr', array_map('hexdec',array_filter(explode($delimiter, $string)))));
|
||||||
}
|
}
|
||||||
if (substr($string, 0, 2) === $this->_escape . 'd') {
|
if (substr($string, 0, 2) === $this->_escape . 'd') {
|
||||||
$delimiter = $this->_escape . 'd';
|
$delimiter = $this->_escape . 'd';
|
||||||
return join('', array_map('chr', array_filter(explode($delimiter, $string))));
|
return implode('', array_map('chr', array_filter(explode($delimiter, $string))));
|
||||||
}
|
}
|
||||||
if ($string[0] === $this->_escape && isset($string[1]) && is_numeric($string[1])) {
|
if ($string[0] === $this->_escape && isset($string[1]) && is_numeric($string[1])) {
|
||||||
$delimiter = $this->_escape;
|
$delimiter = $this->_escape;
|
||||||
return join('', array_map('chr', array_filter(explode($delimiter, $string))));
|
return implode('', array_map('chr', array_filter(explode($delimiter, $string))));
|
||||||
}
|
}
|
||||||
if (substr($string, 0, 3) === 'U00') {
|
if (substr($string, 0, 3) === 'U00') {
|
||||||
$delimiter = 'U00';
|
$delimiter = 'U00';
|
||||||
return join('', array_map('chr', array_map('hexdec', array_filter(explode($delimiter, $string)))));
|
return implode('', array_map('chr', array_map('hexdec', array_filter(explode($delimiter, $string)))));
|
||||||
}
|
}
|
||||||
if (preg_match('/U([0-9a-fA-F]{4})/', $string, $match)) {
|
if (preg_match('/U([0-9a-fA-F]{4})/', $string, $match)) {
|
||||||
return Multibyte::ascii(array(hexdec($match[1])));
|
return Multibyte::ascii(array(hexdec($match[1])));
|
||||||
|
|
|
@ -85,47 +85,53 @@ class L10n {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps ISO 639-3 to I10n::_l10nCatalog
|
* Maps ISO 639-3 to I10n::_l10nCatalog
|
||||||
|
* The terminological codes (first one per language) should be used if possible.
|
||||||
|
* They are the ones building the path in `/APP/Locale/[code]/`
|
||||||
|
* The bibliographic codes are aliases.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $_l10nMap = array(
|
protected $_l10nMap = array(
|
||||||
/* Afrikaans */ 'afr' => 'af',
|
/* Afrikaans */ 'afr' => 'af',
|
||||||
/* Albanian */ 'alb' => 'sq',
|
/* Albanian */ 'sqi' => 'sq',
|
||||||
|
/* Albanian - bibliographic */ 'alb' => 'sq',
|
||||||
/* Arabic */ 'ara' => 'ar',
|
/* Arabic */ 'ara' => 'ar',
|
||||||
/* Armenian - Armenia */ 'hye' => 'hy',
|
/* Armenian/Armenia */ 'hye' => 'hy',
|
||||||
|
/* Basque */ 'eus' => 'eu',
|
||||||
/* Basque */ 'baq' => 'eu',
|
/* Basque */ 'baq' => 'eu',
|
||||||
/* Tibetan */ 'bod' => 'bo',
|
/* Tibetan */ 'bod' => 'bo',
|
||||||
|
/* Tibetan - bibliographic */ 'tib' => 'bo',
|
||||||
/* Bosnian */ 'bos' => 'bs',
|
/* Bosnian */ 'bos' => 'bs',
|
||||||
/* Bulgarian */ 'bul' => 'bg',
|
/* Bulgarian */ 'bul' => 'bg',
|
||||||
/* Byelorussian */ 'bel' => 'be',
|
/* Byelorussian */ 'bel' => 'be',
|
||||||
/* Catalan */ 'cat' => 'ca',
|
/* Catalan */ 'cat' => 'ca',
|
||||||
/* Chinese */ 'chi' => 'zh',
|
|
||||||
/* Chinese */ 'zho' => 'zh',
|
/* Chinese */ 'zho' => 'zh',
|
||||||
|
/* Chinese - bibliographic */ 'chi' => 'zh',
|
||||||
/* Croatian */ 'hrv' => 'hr',
|
/* Croatian */ 'hrv' => 'hr',
|
||||||
/* Czech */ 'cze' => 'cs',
|
|
||||||
/* Czech */ 'ces' => 'cs',
|
/* Czech */ 'ces' => 'cs',
|
||||||
|
/* Czech - bibliographic */ 'cze' => 'cs',
|
||||||
/* Danish */ 'dan' => 'da',
|
/* Danish */ 'dan' => 'da',
|
||||||
/* Dutch (Standard) */ 'dut' => 'nl',
|
|
||||||
/* Dutch (Standard) */ 'nld' => 'nl',
|
/* Dutch (Standard) */ 'nld' => 'nl',
|
||||||
|
/* Dutch (Standard) - bibliographic */ 'dut' => 'nl',
|
||||||
/* English */ 'eng' => 'en',
|
/* English */ 'eng' => 'en',
|
||||||
/* Estonian */ 'est' => 'et',
|
/* Estonian */ 'est' => 'et',
|
||||||
/* Faeroese */ 'fao' => 'fo',
|
/* Faeroese */ 'fao' => 'fo',
|
||||||
/* Farsi */ 'fas' => 'fa',
|
/* Farsi/Persian */ 'fas' => 'fa',
|
||||||
/* Farsi */ 'per' => 'fa',
|
/* Farsi/Persian - bibliographic */ 'per' => 'fa',
|
||||||
/* Finnish */ 'fin' => 'fi',
|
/* Finnish */ 'fin' => 'fi',
|
||||||
/* French (Standard) */ 'fre' => 'fr',
|
|
||||||
/* French (Standard) */ 'fra' => 'fr',
|
/* French (Standard) */ 'fra' => 'fr',
|
||||||
|
/* French (Standard) - bibliographic */ 'fre' => 'fr',
|
||||||
/* Gaelic (Scots) */ 'gla' => 'gd',
|
/* Gaelic (Scots) */ 'gla' => 'gd',
|
||||||
/* Galician */ 'glg' => 'gl',
|
/* Galician */ 'glg' => 'gl',
|
||||||
/* German (Standard) */ 'deu' => 'de',
|
/* German (Standard) */ 'deu' => 'de',
|
||||||
/* German (Standard) */ 'ger' => 'de',
|
/* German (Standard) - bibliographic */ 'ger' => 'de',
|
||||||
/* Greek */ 'gre' => 'el',
|
/* Greek */ 'gre' => 'el',
|
||||||
/* Greek */ 'ell' => 'el',
|
/* Greek */ 'ell' => 'el',
|
||||||
/* Hebrew */ 'heb' => 'he',
|
/* Hebrew */ 'heb' => 'he',
|
||||||
/* Hindi */ 'hin' => 'hi',
|
/* Hindi */ 'hin' => 'hi',
|
||||||
/* Hungarian */ 'hun' => 'hu',
|
/* Hungarian */ 'hun' => 'hu',
|
||||||
/* Icelandic */ 'ice' => 'is',
|
|
||||||
/* Icelandic */ 'isl' => 'is',
|
/* Icelandic */ 'isl' => 'is',
|
||||||
|
/* Icelandic - bibliographic */ 'ice' => 'is',
|
||||||
/* Indonesian */ 'ind' => 'id',
|
/* Indonesian */ 'ind' => 'id',
|
||||||
/* Irish */ 'gle' => 'ga',
|
/* Irish */ 'gle' => 'ga',
|
||||||
/* Italian */ 'ita' => 'it',
|
/* Italian */ 'ita' => 'it',
|
||||||
|
@ -133,10 +139,10 @@ class L10n {
|
||||||
/* Korean */ 'kor' => 'ko',
|
/* Korean */ 'kor' => 'ko',
|
||||||
/* Latvian */ 'lav' => 'lv',
|
/* Latvian */ 'lav' => 'lv',
|
||||||
/* Lithuanian */ 'lit' => 'lt',
|
/* Lithuanian */ 'lit' => 'lt',
|
||||||
/* Macedonian */ 'mac' => 'mk',
|
|
||||||
/* Macedonian */ 'mkd' => 'mk',
|
/* Macedonian */ 'mkd' => 'mk',
|
||||||
/* Malaysian */ 'may' => 'ms',
|
/* Macedonian - bibliographic */ 'mac' => 'mk',
|
||||||
/* Malaysian */ 'msa' => 'ms',
|
/* Malaysian */ 'msa' => 'ms',
|
||||||
|
/* Malaysian - bibliographic */ 'may' => 'ms',
|
||||||
/* Maltese */ 'mlt' => 'mt',
|
/* Maltese */ 'mlt' => 'mt',
|
||||||
/* Norwegian */ 'nor' => 'no',
|
/* Norwegian */ 'nor' => 'no',
|
||||||
/* Norwegian Bokmal */ 'nob' => 'nb',
|
/* Norwegian Bokmal */ 'nob' => 'nb',
|
||||||
|
@ -144,14 +150,13 @@ class L10n {
|
||||||
/* Polish */ 'pol' => 'pl',
|
/* Polish */ 'pol' => 'pl',
|
||||||
/* Portuguese (Portugal) */ 'por' => 'pt',
|
/* Portuguese (Portugal) */ 'por' => 'pt',
|
||||||
/* Rhaeto-Romanic */ 'roh' => 'rm',
|
/* Rhaeto-Romanic */ 'roh' => 'rm',
|
||||||
/* Romanian */ 'rum' => 'ro',
|
|
||||||
/* Romanian */ 'ron' => 'ro',
|
/* Romanian */ 'ron' => 'ro',
|
||||||
|
/* Romanian - bibliographic */ 'rum' => 'ro',
|
||||||
/* Russian */ 'rus' => 'ru',
|
/* Russian */ 'rus' => 'ru',
|
||||||
/* Sami (Lappish) */ 'smi' => 'sz',
|
/* Sami (Lappish) */ 'smi' => 'sz',
|
||||||
/* Serbian */ 'scc' => 'sr',
|
|
||||||
/* Serbian */ 'srp' => 'sr',
|
/* Serbian */ 'srp' => 'sr',
|
||||||
/* Slovak */ 'slo' => 'sk',
|
|
||||||
/* Slovak */ 'slk' => 'sk',
|
/* Slovak */ 'slk' => 'sk',
|
||||||
|
/* Slovak - bibliographic */ 'slo' => 'sk',
|
||||||
/* Slovenian */ 'slv' => 'sl',
|
/* Slovenian */ 'slv' => 'sl',
|
||||||
/* Sorbian */ 'wen' => 'sb',
|
/* Sorbian */ 'wen' => 'sb',
|
||||||
/* Spanish (Spain - Traditional) */ 'spa' => 'es',
|
/* Spanish (Spain - Traditional) */ 'spa' => 'es',
|
||||||
|
@ -165,6 +170,7 @@ class L10n {
|
||||||
/* Venda */ 'ven' => 've',
|
/* Venda */ 'ven' => 've',
|
||||||
/* Vietnamese */ 'vie' => 'vi',
|
/* Vietnamese */ 'vie' => 'vi',
|
||||||
/* Welsh */ 'cym' => 'cy',
|
/* Welsh */ 'cym' => 'cy',
|
||||||
|
/* Welsh - bibliographic */ 'wel' => 'cy',
|
||||||
/* Xhosa */ 'xho' => 'xh',
|
/* Xhosa */ 'xho' => 'xh',
|
||||||
/* Yiddish */ 'yid' => 'yi',
|
/* Yiddish */ 'yid' => 'yi',
|
||||||
/* Zulu */ 'zul' => 'zu'
|
/* Zulu */ 'zul' => 'zu'
|
||||||
|
@ -203,7 +209,7 @@ class L10n {
|
||||||
'bo-in' => array('language' => 'Tibetan (India)', 'locale' => 'bo_in', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'bo-in' => array('language' => 'Tibetan (India)', 'locale' => 'bo_in', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'cs' => array('language' => 'Czech', 'locale' => 'cze', 'localeFallback' => 'cze', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'cs' => array('language' => 'Czech', 'locale' => 'ces', 'localeFallback' => 'ces', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'da' => array('language' => 'Danish', 'locale' => 'dan', 'localeFallback' => 'dan', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'da' => array('language' => 'Danish', 'locale' => 'dan', 'localeFallback' => 'dan', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'de' => array('language' => 'German (Standard)', 'locale' => 'deu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'de' => array('language' => 'German (Standard)', 'locale' => 'deu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'de-at' => array('language' => 'German (Austria)', 'locale' => 'de_at', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'de-at' => array('language' => 'German (Austria)', 'locale' => 'de_at', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
|
@ -245,16 +251,16 @@ class L10n {
|
||||||
'es-uy' => array('language' => 'Spanish (Uruguay)', 'locale' => 'es_uy', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'es-uy' => array('language' => 'Spanish (Uruguay)', 'locale' => 'es_uy', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'es-ve' => array('language' => 'Spanish (Venezuela)', 'locale' => 'es_ve', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'es-ve' => array('language' => 'Spanish (Venezuela)', 'locale' => 'es_ve', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'et' => array('language' => 'Estonian', 'locale' => 'est', 'localeFallback' => 'est', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'et' => array('language' => 'Estonian', 'locale' => 'est', 'localeFallback' => 'est', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'eu' => array('language' => 'Basque', 'locale' => 'baq', 'localeFallback' => 'baq', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'eu' => array('language' => 'Basque', 'locale' => 'eus', 'localeFallback' => 'eus', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fa' => array('language' => 'Farsi', 'locale' => 'per', 'localeFallback' => 'per', 'charset' => 'utf-8', 'direction' => 'rtl'),
|
'fa' => array('language' => 'Farsi', 'locale' => 'per', 'localeFallback' => 'per', 'charset' => 'utf-8', 'direction' => 'rtl'),
|
||||||
'fi' => array('language' => 'Finnish', 'locale' => 'fin', 'localeFallback' => 'fin', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fi' => array('language' => 'Finnish', 'locale' => 'fin', 'localeFallback' => 'fin', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fo' => array('language' => 'Faeroese', 'locale' => 'fao', 'localeFallback' => 'fao', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fo' => array('language' => 'Faeroese', 'locale' => 'fao', 'localeFallback' => 'fao', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr' => array('language' => 'French (Standard)', 'locale' => 'fre', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr' => array('language' => 'French (Standard)', 'locale' => 'fra', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr-be' => array('language' => 'French (Belgium)', 'locale' => 'fr_be', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr-be' => array('language' => 'French (Belgium)', 'locale' => 'fr_be', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr-ca' => array('language' => 'French (Canadian)', 'locale' => 'fr_ca', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr-ca' => array('language' => 'French (Canadian)', 'locale' => 'fr_ca', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr-ch' => array('language' => 'French (Swiss)', 'locale' => 'fr_ch', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr-ch' => array('language' => 'French (Swiss)', 'locale' => 'fr_ch', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr-fr' => array('language' => 'French (France)', 'locale' => 'fr_fr', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr-fr' => array('language' => 'French (France)', 'locale' => 'fr_fr', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'fr-lu' => array('language' => 'French (Luxembourg)', 'locale' => 'fr_lu', 'localeFallback' => 'fre', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'fr-lu' => array('language' => 'French (Luxembourg)', 'locale' => 'fr_lu', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ga' => array('language' => 'Irish', 'locale' => 'gle', 'localeFallback' => 'gle', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ga' => array('language' => 'Irish', 'locale' => 'gle', 'localeFallback' => 'gle', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'gd' => array('language' => 'Gaelic (Scots)', 'locale' => 'gla', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'gd' => array('language' => 'Gaelic (Scots)', 'locale' => 'gla', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'gd-ie' => array('language' => 'Gaelic (Irish)', 'locale' => 'gd_ie', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'gd-ie' => array('language' => 'Gaelic (Irish)', 'locale' => 'gd_ie', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
|
@ -266,7 +272,7 @@ class L10n {
|
||||||
'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'in' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'in' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'is' => array('language' => 'Icelandic', 'locale' => 'ice', 'localeFallback' => 'ice', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'is' => array('language' => 'Icelandic', 'locale' => 'isl', 'localeFallback' => 'isl', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'it' => array('language' => 'Italian', 'locale' => 'ita', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'it' => array('language' => 'Italian', 'locale' => 'ita', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'it-ch' => array('language' => 'Italian (Swiss) ', 'locale' => 'it_ch', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'it-ch' => array('language' => 'Italian (Swiss) ', 'locale' => 'it_ch', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ja' => array('language' => 'Japanese', 'locale' => 'jpn', 'localeFallback' => 'jpn', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ja' => array('language' => 'Japanese', 'locale' => 'jpn', 'localeFallback' => 'jpn', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
|
@ -276,14 +282,14 @@ class L10n {
|
||||||
'koi8-r' => array('language' => 'Russian', 'locale' => 'koi8_r', 'localeFallback' => 'rus', 'charset' => 'koi8-r', 'direction' => 'ltr'),
|
'koi8-r' => array('language' => 'Russian', 'locale' => 'koi8_r', 'localeFallback' => 'rus', 'charset' => 'koi8-r', 'direction' => 'ltr'),
|
||||||
'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mk', 'localeFallback' => 'mac', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mac', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ms' => array('language' => 'Malaysian', 'locale' => 'may', 'localeFallback' => 'may', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ms' => array('language' => 'Malaysian', 'locale' => 'msa', 'localeFallback' => 'msa', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'mt' => array('language' => 'Maltese', 'locale' => 'mlt', 'localeFallback' => 'mlt', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'mt' => array('language' => 'Maltese', 'locale' => 'mlt', 'localeFallback' => 'mlt', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'n' => array('language' => 'Dutch (Standard)', 'locale' => 'dut', 'localeFallback' => 'dut', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'n' => array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'nb' => array('language' => 'Norwegian Bokmal', 'locale' => 'nob', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'nb' => array('language' => 'Norwegian Bokmal', 'locale' => 'nob', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'nl' => array('language' => 'Dutch (Standard)', 'locale' => 'dut', 'localeFallback' => 'dut', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'nl' => array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'nl-be' => array('language' => 'Dutch (Belgium)', 'locale' => 'nl_be', 'localeFallback' => 'dut', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'nl-be' => array('language' => 'Dutch (Belgium)', 'locale' => 'nl_be', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'nn' => array('language' => 'Norwegian Nynorsk', 'locale' => 'nno', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'nn' => array('language' => 'Norwegian Nynorsk', 'locale' => 'nno', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'no' => array('language' => 'Norwegian', 'locale' => 'nor', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'no' => array('language' => 'Norwegian', 'locale' => 'nor', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'p' => array('language' => 'Polish', 'locale' => 'pol', 'localeFallback' => 'pol', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'p' => array('language' => 'Polish', 'locale' => 'pol', 'localeFallback' => 'pol', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
|
@ -291,15 +297,15 @@ class L10n {
|
||||||
'pt' => array('language' => 'Portuguese (Portugal)', 'locale' => 'por', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'pt' => array('language' => 'Portuguese (Portugal)', 'locale' => 'por', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'pt-br' => array('language' => 'Portuguese (Brazil)', 'locale' => 'pt_br', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'pt-br' => array('language' => 'Portuguese (Brazil)', 'locale' => 'pt_br', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'rm' => array('language' => 'Rhaeto-Romanic', 'locale' => 'roh', 'localeFallback' => 'roh', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'rm' => array('language' => 'Rhaeto-Romanic', 'locale' => 'roh', 'localeFallback' => 'roh', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ro' => array('language' => 'Romanian', 'locale' => 'rum', 'localeFallback' => 'rum', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ro' => array('language' => 'Romanian', 'locale' => 'ron', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ro-mo' => array('language' => 'Romanian (Moldavia)', 'locale' => 'ro_mo', 'localeFallback' => 'rum', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ro-mo' => array('language' => 'Romanian (Moldavia)', 'locale' => 'ro_mo', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ru' => array('language' => 'Russian', 'locale' => 'rus', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ru' => array('language' => 'Russian', 'locale' => 'rus', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'ru-mo' => array('language' => 'Russian (Moldavia)', 'locale' => 'ru_mo', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'ru-mo' => array('language' => 'Russian (Moldavia)', 'locale' => 'ru_mo', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sb' => array('language' => 'Sorbian', 'locale' => 'wen', 'localeFallback' => 'wen', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sb' => array('language' => 'Sorbian', 'locale' => 'wen', 'localeFallback' => 'wen', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sk' => array('language' => 'Slovak', 'locale' => 'slo', 'localeFallback' => 'slo', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sk' => array('language' => 'Slovak', 'locale' => 'slk', 'localeFallback' => 'slk', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sl' => array('language' => 'Slovenian', 'locale' => 'slv', 'localeFallback' => 'slv', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sl' => array('language' => 'Slovenian', 'locale' => 'slv', 'localeFallback' => 'slv', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sq' => array('language' => 'Albanian', 'locale' => 'alb', 'localeFallback' => 'alb', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sq' => array('language' => 'Albanian', 'locale' => 'sqi', 'localeFallback' => 'sqi', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sr' => array('language' => 'Serbian', 'locale' => 'scc', 'localeFallback' => 'scc', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sr' => array('language' => 'Serbian', 'locale' => 'srp', 'localeFallback' => 'srp', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sv' => array('language' => 'Swedish', 'locale' => 'swe', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sv' => array('language' => 'Swedish', 'locale' => 'swe', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sv-fi' => array('language' => 'Swedish (Finland)', 'locale' => 'sv_fi', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sv-fi' => array('language' => 'Swedish (Finland)', 'locale' => 'sv_fi', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'sx' => array('language' => 'Sutu', 'locale' => 'sx', 'localeFallback' => 'sx', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'sx' => array('language' => 'Sutu', 'locale' => 'sx', 'localeFallback' => 'sx', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
|
@ -315,11 +321,11 @@ class L10n {
|
||||||
'cy' => array('language' => 'Welsh', 'locale' => 'cym', 'localeFallback' => 'cym', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'cy' => array('language' => 'Welsh', 'locale' => 'cym', 'localeFallback' => 'cym', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'xh' => array('language' => 'Xhosa', 'locale' => 'xho', 'localeFallback' => 'xho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'xh' => array('language' => 'Xhosa', 'locale' => 'xho', 'localeFallback' => 'xho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'yi' => array('language' => 'Yiddish', 'locale' => 'yid', 'localeFallback' => 'yid', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'yi' => array('language' => 'Yiddish', 'locale' => 'yid', 'localeFallback' => 'yid', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'zh' => array('language' => 'Chinese', 'locale' => 'chi', 'localeFallback' => 'chi', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'zh' => array('language' => 'Chinese', 'locale' => 'zho', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'zh-cn' => array('language' => 'Chinese (PRC)', 'locale' => 'zh_cn', 'localeFallback' => 'chi', 'charset' => 'GB2312', 'direction' => 'ltr'),
|
'zh-cn' => array('language' => 'Chinese (PRC)', 'locale' => 'zh_cn', 'localeFallback' => 'zho', 'charset' => 'GB2312', 'direction' => 'ltr'),
|
||||||
'zh-hk' => array('language' => 'Chinese (Hong Kong)', 'locale' => 'zh_hk', 'localeFallback' => 'chi', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'zh-hk' => array('language' => 'Chinese (Hong Kong)', 'locale' => 'zh_hk', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'zh-sg' => array('language' => 'Chinese (Singapore)', 'locale' => 'zh_sg', 'localeFallback' => 'chi', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'zh-sg' => array('language' => 'Chinese (Singapore)', 'locale' => 'zh_sg', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'zh-tw' => array('language' => 'Chinese (Taiwan)', 'locale' => 'zh_tw', 'localeFallback' => 'chi', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
'zh-tw' => array('language' => 'Chinese (Taiwan)', 'locale' => 'zh_tw', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'),
|
||||||
'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8', 'direction' => 'ltr')
|
'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8', 'direction' => 'ltr')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -18,261 +18,6 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!function_exists('mb_stripos')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find position of first occurrence of a case-insensitive string.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the position of the first occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param integer $offset The position in $haystack to start searching.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string, or false
|
|
||||||
* if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) {
|
|
||||||
return Multibyte::stripos($haystack, $needle, $offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_stristr')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds first occurrence of a string within another, case insensitive.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the first occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param boolean $part Determines which portion of $haystack this function returns.
|
|
||||||
* If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
|
|
||||||
* If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
|
|
||||||
* Default value is false.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string|boolean The portion of $haystack, or false if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_stristr($haystack, $needle, $part = false, $encoding = null) {
|
|
||||||
return Multibyte::stristr($haystack, $needle, $part);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strlen')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get string length.
|
|
||||||
*
|
|
||||||
* @param string $string The string being checked for length.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer The number of characters in string $string having character encoding encoding.
|
|
||||||
* A multi-byte character is counted as 1.
|
|
||||||
*/
|
|
||||||
function mb_strlen($string, $encoding = null) {
|
|
||||||
return Multibyte::strlen($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strpos')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find position of first occurrence of a string.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string being checked.
|
|
||||||
* @param string $needle The position counted from the beginning of haystack.
|
|
||||||
* @param integer $offset The search offset. If it is not specified, 0 is used.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer|boolean The numeric position of the first occurrence of $needle in the $haystack string.
|
|
||||||
* If $needle is not found, it returns false.
|
|
||||||
*/
|
|
||||||
function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) {
|
|
||||||
return Multibyte::strpos($haystack, $needle, $offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strrchr')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the last occurrence of a character in a string within another.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the last occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param boolean $part Determines which portion of $haystack this function returns.
|
|
||||||
* If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
|
|
||||||
* If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
|
|
||||||
* Default value is false.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string|boolean The portion of $haystack. or false if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_strrchr($haystack, $needle, $part = false, $encoding = null) {
|
|
||||||
return Multibyte::strrchr($haystack, $needle, $part);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strrichr')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the last occurrence of a character in a string within another, case insensitive.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the last occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param boolean $part Determines which portion of $haystack this function returns.
|
|
||||||
* If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle.
|
|
||||||
* If set to false, it returns all of $haystack from the last occurrence of $needle to the end,
|
|
||||||
* Default value is false.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string|boolean The portion of $haystack. or false if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_strrichr($haystack, $needle, $part = false, $encoding = null) {
|
|
||||||
return Multibyte::strrichr($haystack, $needle, $part);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strripos')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds position of last occurrence of a string within another, case insensitive
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the position of the last occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param integer $offset The position in $haystack to start searching.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string,
|
|
||||||
* or false if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) {
|
|
||||||
return Multibyte::strripos($haystack, $needle, $offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strrpos')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find position of last occurrence of a string in a string.
|
|
||||||
*
|
|
||||||
* @param string $haystack The string being checked, for the last occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack.
|
|
||||||
* @param integer $offset May be specified to begin searching an arbitrary number of characters into the string.
|
|
||||||
* Negative values will stop searching at an arbitrary point prior to the end of the string.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer|boolean The numeric position of the last occurrence of $needle in the $haystack string.
|
|
||||||
* If $needle is not found, it returns false.
|
|
||||||
*/
|
|
||||||
function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) {
|
|
||||||
return Multibyte::strrpos($haystack, $needle, $offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strstr')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds first occurrence of a string within another
|
|
||||||
*
|
|
||||||
* @param string $haystack The string from which to get the first occurrence of $needle.
|
|
||||||
* @param string $needle The string to find in $haystack
|
|
||||||
* @param boolean $part Determines which portion of $haystack this function returns.
|
|
||||||
* If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle.
|
|
||||||
* If set to false, it returns all of $haystack from the first occurrence of $needle to the end,
|
|
||||||
* Default value is FALSE.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string|boolean The portion of $haystack, or true if $needle is not found.
|
|
||||||
*/
|
|
||||||
function mb_strstr($haystack, $needle, $part = false, $encoding = null) {
|
|
||||||
return Multibyte::strstr($haystack, $needle, $part);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strtolower')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a string lowercase
|
|
||||||
*
|
|
||||||
* @param string $string The string being lowercased.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string with all alphabetic characters converted to lowercase.
|
|
||||||
*/
|
|
||||||
function mb_strtolower($string, $encoding = null) {
|
|
||||||
return Multibyte::strtolower($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_strtoupper')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a string uppercase
|
|
||||||
*
|
|
||||||
* @param string $string The string being uppercased.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string with all alphabetic characters converted to uppercase.
|
|
||||||
*/
|
|
||||||
function mb_strtoupper($string, $encoding = null) {
|
|
||||||
return Multibyte::strtoupper($string);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_substr_count')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the number of substring occurrences
|
|
||||||
*
|
|
||||||
* @param string $haystack The string being checked.
|
|
||||||
* @param string $needle The string being found.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return integer The number of times the $needle substring occurs in the $haystack string.
|
|
||||||
*/
|
|
||||||
function mb_substr_count($haystack, $needle, $encoding = null) {
|
|
||||||
return Multibyte::substrCount($haystack, $needle);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_substr')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get part of string
|
|
||||||
*
|
|
||||||
* @param string $string The string being checked.
|
|
||||||
* @param integer $start The first position used in $string.
|
|
||||||
* @param integer $length The maximum length of the returned string.
|
|
||||||
* @param string $encoding Character encoding name to use. If it is omitted, internal character encoding is used.
|
|
||||||
* @return string The portion of $string specified by the $string and $length parameters.
|
|
||||||
*/
|
|
||||||
function mb_substr($string, $start, $length = null, $encoding = null) {
|
|
||||||
return Multibyte::substr($string, $start, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!function_exists('mb_encode_mimeheader')) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode string for MIME header
|
|
||||||
*
|
|
||||||
* @param string $str The string being encoded
|
|
||||||
* @param string $charset specifies the name of the character set in which str is represented in.
|
|
||||||
* The default value is determined by the current NLS setting (mbstring.language).
|
|
||||||
* @param string $transfer_encoding specifies the scheme of MIME encoding.
|
|
||||||
* It should be either "B" (Base64) or "Q" (Quoted-Printable). Falls back to "B" if not given.
|
|
||||||
* @param string $linefeed specifies the EOL (end-of-line) marker with which
|
|
||||||
* mb_encode_mimeheader() performs line-folding
|
|
||||||
* (a » RFC term, the act of breaking a line longer than a certain length into multiple lines.
|
|
||||||
* The length is currently hard-coded to 74 characters). Falls back to "\r\n" (CRLF) if not given.
|
|
||||||
* @param integer $indent [definition unknown and appears to have no affect]
|
|
||||||
* @return string A converted version of the string represented in ASCII.
|
|
||||||
*/
|
|
||||||
function mb_encode_mimeheader($str, $charset = 'UTF-8', $transferEncoding = 'B', $linefeed = "\r\n", $indent = 1) {
|
|
||||||
return Multibyte::mimeEncode($str, $charset, $linefeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multibyte handling methods.
|
* Multibyte handling methods.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
App::uses('BaseLog', 'Log/Engine');
|
App::uses('BaseLog', 'Log/Engine');
|
||||||
|
App::uses('Hash', 'Utility');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File Storage stream for Logging. Writes logs to different files
|
* File Storage stream for Logging. Writes logs to different files
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* @since CakePHP v 1.2.0.4487
|
* @since CakePHP v 1.2.0.4487
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('ModelBehavior', 'Model');
|
||||||
App::uses('AclNode', 'Model');
|
App::uses('AclNode', 'Model');
|
||||||
App::uses('Hash', 'Utility');
|
App::uses('Hash', 'Utility');
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* @since CakePHP(tm) v 1.2.0.5669
|
* @since CakePHP(tm) v 1.2.0.5669
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('ModelBehavior', 'Model');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Behavior to allow for dynamic and atomic manipulation of a Model's associations
|
* Behavior to allow for dynamic and atomic manipulation of a Model's associations
|
||||||
|
@ -174,7 +175,7 @@ class ContainableBehavior extends ModelBehavior {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->settings[$Model->alias]['recursive']) {
|
if ($this->settings[$Model->alias]['recursive']) {
|
||||||
$query['recursive'] = (isset($query['recursive'])) ? $query['recursive'] : $containments['depth'];
|
$query['recursive'] = (isset($query['recursive'])) ? max($query['recursive'], $containments['depth']) : $containments['depth'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$autoFields = ($this->settings[$Model->alias]['autoFields']
|
$autoFields = ($this->settings[$Model->alias]['autoFields']
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
App::uses('ModelBehavior', 'Model');
|
||||||
App::uses('I18n', 'I18n');
|
App::uses('I18n', 'I18n');
|
||||||
App::uses('I18nModel', 'Model');
|
App::uses('I18nModel', 'Model');
|
||||||
|
|
||||||
|
@ -337,7 +338,7 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
* @return boolean true.
|
* @return boolean true.
|
||||||
*/
|
*/
|
||||||
public function beforeSave(Model $Model, $options = array()) {
|
public function beforeSave(Model $Model, $options = array()) {
|
||||||
if (isset($options['validate']) && $options['validate'] == false) {
|
if (isset($options['validate']) && !$options['validate']) {
|
||||||
unset($this->runtime[$Model->alias]['beforeSave']);
|
unset($this->runtime[$Model->alias]['beforeSave']);
|
||||||
}
|
}
|
||||||
if (isset($this->runtime[$Model->alias]['beforeSave'])) {
|
if (isset($this->runtime[$Model->alias]['beforeSave'])) {
|
||||||
|
@ -409,7 +410,6 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
if (!isset($this->runtime[$Model->alias]['beforeValidate']) && !isset($this->runtime[$Model->alias]['beforeSave'])) {
|
if (!isset($this->runtime[$Model->alias]['beforeValidate']) && !isset($this->runtime[$Model->alias]['beforeSave'])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$locale = $this->_getLocale($Model);
|
|
||||||
if (isset($this->runtime[$Model->alias]['beforeValidate'])) {
|
if (isset($this->runtime[$Model->alias]['beforeValidate'])) {
|
||||||
$tempData = $this->runtime[$Model->alias]['beforeValidate'];
|
$tempData = $this->runtime[$Model->alias]['beforeValidate'];
|
||||||
} else {
|
} else {
|
||||||
|
@ -420,21 +420,10 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
$conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id);
|
$conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id);
|
||||||
$RuntimeModel = $this->translateModel($Model);
|
$RuntimeModel = $this->translateModel($Model);
|
||||||
|
|
||||||
$fields = array_merge(
|
|
||||||
$this->settings[$Model->alias],
|
|
||||||
$this->runtime[$Model->alias]['fields']
|
|
||||||
);
|
|
||||||
if ($created) {
|
if ($created) {
|
||||||
// set each field value to an empty string
|
$tempData = $this->_prepareTranslations($Model, $tempData);
|
||||||
foreach ($fields as $key => $field) {
|
|
||||||
if (!is_numeric($key)) {
|
|
||||||
$field = $key;
|
|
||||||
}
|
|
||||||
if (!isset($tempData[$field])) {
|
|
||||||
$tempData[$field] = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$locale = $this->_getLocale($Model);
|
||||||
|
|
||||||
foreach ($tempData as $field => $value) {
|
foreach ($tempData as $field => $value) {
|
||||||
unset($conditions['content']);
|
unset($conditions['content']);
|
||||||
|
@ -451,7 +440,10 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
}
|
}
|
||||||
$translations = $RuntimeModel->find('list', array(
|
$translations = $RuntimeModel->find('list', array(
|
||||||
'conditions' => $conditions,
|
'conditions' => $conditions,
|
||||||
'fields' => array($RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id')
|
'fields' => array(
|
||||||
|
$RuntimeModel->alias . '.locale',
|
||||||
|
$RuntimeModel->alias . '.id'
|
||||||
|
)
|
||||||
));
|
));
|
||||||
foreach ($value as $_locale => $_value) {
|
foreach ($value as $_locale => $_value) {
|
||||||
$RuntimeModel->create();
|
$RuntimeModel->create();
|
||||||
|
@ -470,6 +462,37 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the data to be saved for translated records.
|
||||||
|
* Add blank fields, and populates data for multi-locale saves.
|
||||||
|
*
|
||||||
|
* @param array $data The sparse data that was provided.
|
||||||
|
* @return array The fully populated data to save.
|
||||||
|
*/
|
||||||
|
protected function _prepareTranslations(Model $Model, $data) {
|
||||||
|
$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
|
||||||
|
$locales = array();
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$locales = array_merge($locales, array_keys($value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$locales = array_unique($locales);
|
||||||
|
$hasLocales = count($locales) > 0;
|
||||||
|
|
||||||
|
foreach ($fields as $key => $field) {
|
||||||
|
if (!is_numeric($key)) {
|
||||||
|
$field = $key;
|
||||||
|
}
|
||||||
|
if ($hasLocales && !isset($data[$field])) {
|
||||||
|
$data[$field] = array_fill_keys($locales, '');
|
||||||
|
} elseif (!isset($data[$field])) {
|
||||||
|
$data[$field] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* afterDelete Callback
|
* afterDelete Callback
|
||||||
*
|
*
|
||||||
|
@ -478,10 +501,7 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
*/
|
*/
|
||||||
public function afterDelete(Model $Model) {
|
public function afterDelete(Model $Model) {
|
||||||
$RuntimeModel = $this->translateModel($Model);
|
$RuntimeModel = $this->translateModel($Model);
|
||||||
$conditions = array(
|
$conditions = array('model' => $Model->alias, 'foreign_key' => $Model->id);
|
||||||
'model' => $Model->alias,
|
|
||||||
'foreign_key' => $Model->id
|
|
||||||
);
|
|
||||||
$RuntimeModel->deleteAll($conditions);
|
$RuntimeModel->deleteAll($conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,10 +569,7 @@ class TranslateBehavior extends ModelBehavior {
|
||||||
}
|
}
|
||||||
$associations = array();
|
$associations = array();
|
||||||
$RuntimeModel = $this->translateModel($Model);
|
$RuntimeModel = $this->translateModel($Model);
|
||||||
$default = array(
|
$default = array('className' => $RuntimeModel->alias, 'foreignKey' => 'foreign_key');
|
||||||
'className' => $RuntimeModel->alias,
|
|
||||||
'foreignKey' => 'foreign_key'
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($fields as $key => $value) {
|
foreach ($fields as $key => $value) {
|
||||||
if (is_numeric($key)) {
|
if (is_numeric($key)) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* @since CakePHP v 1.2.0.4487
|
* @since CakePHP v 1.2.0.4487
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('ModelBehavior', 'Model');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tree Behavior.
|
* Tree Behavior.
|
||||||
|
@ -354,17 +355,16 @@ class TreeBehavior extends ModelBehavior {
|
||||||
$recursive = $overrideRecursive;
|
$recursive = $overrideRecursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($keyPath == null && $valuePath == null && $Model->hasField($Model->displayField)) {
|
|
||||||
$fields = array($Model->primaryKey, $Model->displayField, $left, $right);
|
|
||||||
} else {
|
|
||||||
$fields = null;
|
$fields = null;
|
||||||
|
if (!$keyPath && !$valuePath && $Model->hasField($Model->displayField)) {
|
||||||
|
$fields = array($Model->primaryKey, $Model->displayField, $left, $right);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($keyPath == null) {
|
if (!$keyPath) {
|
||||||
$keyPath = '{n}.' . $Model->alias . '.' . $Model->primaryKey;
|
$keyPath = '{n}.' . $Model->alias . '.' . $Model->primaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($valuePath == null) {
|
if (!$valuePath) {
|
||||||
$valuePath = array('%s%s', '{n}.tree_prefix', '{n}.' . $Model->alias . '.' . $Model->displayField);
|
$valuePath = array('%s%s', '{n}.tree_prefix', '{n}.' . $Model->alias . '.' . $Model->displayField);
|
||||||
|
|
||||||
} elseif (is_string($valuePath)) {
|
} elseif (is_string($valuePath)) {
|
||||||
|
@ -644,9 +644,8 @@ class TreeBehavior extends ModelBehavior {
|
||||||
$db = ConnectionManager::getDataSource($Model->useDbConfig);
|
$db = ConnectionManager::getDataSource($Model->useDbConfig);
|
||||||
foreach ($Model->find('all', array('conditions' => $scope, 'fields' => array($Model->primaryKey, $parent), 'order' => $left)) as $array) {
|
foreach ($Model->find('all', array('conditions' => $scope, 'fields' => array($Model->primaryKey, $parent), 'order' => $left)) as $array) {
|
||||||
$path = $this->getPath($Model, $array[$Model->alias][$Model->primaryKey]);
|
$path = $this->getPath($Model, $array[$Model->alias][$Model->primaryKey]);
|
||||||
if ($path == null || count($path) < 2) {
|
|
||||||
$parentId = null;
|
$parentId = null;
|
||||||
} else {
|
if (count($path) > 1) {
|
||||||
$parentId = $path[count($path) - 2][$Model->alias][$Model->primaryKey];
|
$parentId = $path[count($path) - 2][$Model->alias][$Model->primaryKey];
|
||||||
}
|
}
|
||||||
$Model->updateAll(array($parent => $db->value($parentId, $parent)), array($Model->escapeField() => $array[$Model->alias][$Model->primaryKey]));
|
$Model->updateAll(array($parent => $db->value($parentId, $parent)), array($Model->escapeField() => $array[$Model->alias][$Model->primaryKey]));
|
||||||
|
@ -799,7 +798,7 @@ class TreeBehavior extends ModelBehavior {
|
||||||
$scope, 'OR' => array($Model->escapeField($left) => $i, $Model->escapeField($right) => $i)
|
$scope, 'OR' => array($Model->escapeField($left) => $i, $Model->escapeField($right) => $i)
|
||||||
)));
|
)));
|
||||||
if ($count != 1) {
|
if ($count != 1) {
|
||||||
if ($count == 0) {
|
if (!$count) {
|
||||||
$errors[] = array('index', $i, 'missing');
|
$errors[] = array('index', $i, 'missing');
|
||||||
} else {
|
} else {
|
||||||
$errors[] = array('index', $i, 'duplicate');
|
$errors[] = array('index', $i, 'duplicate');
|
||||||
|
|
|
@ -254,15 +254,21 @@ class CakeSchema extends Object {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_object($Object) || $Object->useTable === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$db = $Object->getDataSource();
|
$db = $Object->getDataSource();
|
||||||
if (is_object($Object) && $Object->useTable !== false) {
|
|
||||||
$fulltable = $table = $db->fullTableName($Object, false, false);
|
$fulltable = $table = $db->fullTableName($Object, false, false);
|
||||||
if ($prefix && strpos($table, $prefix) !== 0) {
|
if ($prefix && strpos($table, $prefix) !== 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!in_array($fulltable, $currentTables)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$table = $this->_noPrefixTable($prefix, $table);
|
$table = $this->_noPrefixTable($prefix, $table);
|
||||||
|
|
||||||
if (in_array($fulltable, $currentTables)) {
|
|
||||||
$key = array_search($fulltable, $currentTables);
|
$key = array_search($fulltable, $currentTables);
|
||||||
if (empty($tables[$table])) {
|
if (empty($tables[$table])) {
|
||||||
$tables[$table] = $this->_columns($Object);
|
$tables[$table] = $this->_columns($Object);
|
||||||
|
@ -270,12 +276,16 @@ class CakeSchema extends Object {
|
||||||
$tables[$table]['tableParameters'] = $db->readTableParameters($fulltable);
|
$tables[$table]['tableParameters'] = $db->readTableParameters($fulltable);
|
||||||
unset($currentTables[$key]);
|
unset($currentTables[$key]);
|
||||||
}
|
}
|
||||||
if (!empty($Object->hasAndBelongsToMany)) {
|
if (empty($Object->hasAndBelongsToMany)) {
|
||||||
foreach ($Object->hasAndBelongsToMany as $assocData) {
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($Object->hasAndBelongsToMany as $Assoc => $assocData) {
|
||||||
if (isset($assocData['with'])) {
|
if (isset($assocData['with'])) {
|
||||||
$class = $assocData['with'];
|
$class = $assocData['with'];
|
||||||
}
|
}
|
||||||
if (is_object($Object->$class)) {
|
if (!is_object($Object->$class)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$withTable = $db->fullTableName($Object->$class, false, false);
|
$withTable = $db->fullTableName($Object->$class, false, false);
|
||||||
if ($prefix && strpos($withTable, $prefix) !== 0) {
|
if ($prefix && strpos($withTable, $prefix) !== 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -292,10 +302,6 @@ class CakeSchema extends Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($currentTables)) {
|
if (!empty($currentTables)) {
|
||||||
foreach ($currentTables as $table) {
|
foreach ($currentTables as $table) {
|
||||||
|
@ -412,28 +418,28 @@ class CakeSchema extends Object {
|
||||||
}
|
}
|
||||||
$col = "\t\t'{$field}' => array('type' => '" . $value['type'] . "', ";
|
$col = "\t\t'{$field}' => array('type' => '" . $value['type'] . "', ";
|
||||||
unset($value['type']);
|
unset($value['type']);
|
||||||
$col .= join(', ', $this->_values($value));
|
$col .= implode(', ', $this->_values($value));
|
||||||
} elseif ($field == 'indexes') {
|
} elseif ($field == 'indexes') {
|
||||||
$col = "\t\t'indexes' => array(\n\t\t\t";
|
$col = "\t\t'indexes' => array(\n\t\t\t";
|
||||||
$props = array();
|
$props = array();
|
||||||
foreach ((array)$value as $key => $index) {
|
foreach ((array)$value as $key => $index) {
|
||||||
$props[] = "'{$key}' => array(" . join(', ', $this->_values($index)) . ")";
|
$props[] = "'{$key}' => array(" . implode(', ', $this->_values($index)) . ")";
|
||||||
}
|
}
|
||||||
$col .= join(",\n\t\t\t", $props) . "\n\t\t";
|
$col .= implode(",\n\t\t\t", $props) . "\n\t\t";
|
||||||
} elseif ($field == 'tableParameters') {
|
} elseif ($field == 'tableParameters') {
|
||||||
$col = "\t\t'tableParameters' => array(";
|
$col = "\t\t'tableParameters' => array(";
|
||||||
$props = array();
|
$props = array();
|
||||||
foreach ((array)$value as $key => $param) {
|
foreach ((array)$value as $key => $param) {
|
||||||
$props[] = "'{$key}' => '$param'";
|
$props[] = "'{$key}' => '$param'";
|
||||||
}
|
}
|
||||||
$col .= join(', ', $props);
|
$col .= implode(', ', $props);
|
||||||
}
|
}
|
||||||
$col .= ")";
|
$col .= ")";
|
||||||
$cols[] = $col;
|
$cols[] = $col;
|
||||||
}
|
}
|
||||||
$out .= join(",\n", $cols);
|
$out .= implode(",\n", $cols);
|
||||||
}
|
}
|
||||||
$out .= "\n\t);\n";
|
$out .= "\n\t);\n\n";
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +603,7 @@ class CakeSchema extends Object {
|
||||||
$db = $Obj->getDataSource();
|
$db = $Obj->getDataSource();
|
||||||
$fields = $Obj->schema(true);
|
$fields = $Obj->schema(true);
|
||||||
|
|
||||||
$columns = array();
|
$columns = $props = array();
|
||||||
foreach ($fields as $name => $value) {
|
foreach ($fields as $name => $value) {
|
||||||
if ($Obj->primaryKey == $name) {
|
if ($Obj->primaryKey == $name) {
|
||||||
$value['key'] = 'primary';
|
$value['key'] = 'primary';
|
||||||
|
|
|
@ -131,7 +131,7 @@ class CakeSession {
|
||||||
self::$time = time();
|
self::$time = time();
|
||||||
|
|
||||||
$checkAgent = Configure::read('Session.checkAgent');
|
$checkAgent = Configure::read('Session.checkAgent');
|
||||||
if (($checkAgent === true || $checkAgent === null) && env('HTTP_USER_AGENT') != null) {
|
if (($checkAgent === true || $checkAgent === null) && env('HTTP_USER_AGENT')) {
|
||||||
self::$_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt'));
|
self::$_userAgent = md5(env('HTTP_USER_AGENT') . Configure::read('Security.salt'));
|
||||||
}
|
}
|
||||||
self::_setPath($base);
|
self::_setPath($base);
|
||||||
|
@ -218,8 +218,7 @@ class CakeSession {
|
||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$result = Hash::get($_SESSION, $name);
|
return Hash::get($_SESSION, $name) !== null;
|
||||||
return isset($result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,7 +247,7 @@ class CakeSession {
|
||||||
public static function delete($name) {
|
public static function delete($name) {
|
||||||
if (self::check($name)) {
|
if (self::check($name)) {
|
||||||
self::_overwrite($_SESSION, Hash::remove($_SESSION, $name));
|
self::_overwrite($_SESSION, Hash::remove($_SESSION, $name));
|
||||||
return (self::check($name) == false);
|
return !self::check($name);
|
||||||
}
|
}
|
||||||
self::_setError(2, __d('cake_dev', "%s doesn't exist", $name));
|
self::_setError(2, __d('cake_dev', "%s doesn't exist", $name));
|
||||||
return false;
|
return false;
|
||||||
|
@ -283,9 +282,8 @@ class CakeSession {
|
||||||
protected static function _error($errorNumber) {
|
protected static function _error($errorNumber) {
|
||||||
if (!is_array(self::$error) || !array_key_exists($errorNumber, self::$error)) {
|
if (!is_array(self::$error) || !array_key_exists($errorNumber, self::$error)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return self::$error[$errorNumber];
|
|
||||||
}
|
}
|
||||||
|
return self::$error[$errorNumber];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -662,7 +660,7 @@ class CakeSession {
|
||||||
*/
|
*/
|
||||||
public static function renew() {
|
public static function renew() {
|
||||||
if (session_id()) {
|
if (session_id()) {
|
||||||
if (session_id() != '' || isset($_COOKIE[session_name()])) {
|
if (session_id() || isset($_COOKIE[session_name()])) {
|
||||||
setcookie(Configure::read('Session.cookie'), '', time() - 42000, self::$path);
|
setcookie(Configure::read('Session.cookie'), '', time() - 42000, self::$path);
|
||||||
}
|
}
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
|
|
|
@ -108,6 +108,7 @@ class Mysql extends DboSource {
|
||||||
'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
|
'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
|
||||||
'string' => array('name' => 'varchar', 'limit' => '255'),
|
'string' => array('name' => 'varchar', 'limit' => '255'),
|
||||||
'text' => array('name' => 'text'),
|
'text' => array('name' => 'text'),
|
||||||
|
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
|
||||||
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
|
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
|
||||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||||
|
@ -118,6 +119,13 @@ class Mysql extends DboSource {
|
||||||
'boolean' => array('name' => 'tinyint', 'limit' => '1')
|
'boolean' => array('name' => 'tinyint', 'limit' => '1')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of collation names to character set names
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_charsets = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to the database using options in the given configuration array.
|
* Connects to the database using options in the given configuration array.
|
||||||
*
|
*
|
||||||
|
@ -155,6 +163,7 @@ class Mysql extends DboSource {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->_charsets = array();
|
||||||
$this->_useAlias = (bool)version_compare($this->getVersion(), "4.1", ">=");
|
$this->_useAlias = (bool)version_compare($this->getVersion(), "4.1", ">=");
|
||||||
|
|
||||||
return $this->connected;
|
return $this->connected;
|
||||||
|
@ -177,7 +186,7 @@ class Mysql extends DboSource {
|
||||||
*/
|
*/
|
||||||
public function listSources($data = null) {
|
public function listSources($data = null) {
|
||||||
$cache = parent::listSources();
|
$cache = parent::listSources();
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
$result = $this->_execute('SHOW TABLES FROM ' . $this->name($this->config['database']));
|
$result = $this->_execute('SHOW TABLES FROM ' . $this->name($this->config['database']));
|
||||||
|
@ -261,15 +270,24 @@ class Mysql extends DboSource {
|
||||||
* @return string Character set name
|
* @return string Character set name
|
||||||
*/
|
*/
|
||||||
public function getCharsetName($name) {
|
public function getCharsetName($name) {
|
||||||
if ((bool)version_compare($this->getVersion(), "5", ">=")) {
|
if ((bool)version_compare($this->getVersion(), "5", "<")) {
|
||||||
$r = $this->_execute('SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS WHERE COLLATION_NAME = ?', array($name));
|
return false;
|
||||||
|
}
|
||||||
|
if (isset($this->_charsets[$name])) {
|
||||||
|
return $this->_charsets[$name];
|
||||||
|
}
|
||||||
|
$r = $this->_execute(
|
||||||
|
'SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS WHERE COLLATION_NAME = ?',
|
||||||
|
array($name)
|
||||||
|
);
|
||||||
$cols = $r->fetch(PDO::FETCH_ASSOC);
|
$cols = $r->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if (isset($cols['CHARACTER_SET_NAME'])) {
|
if (isset($cols['CHARACTER_SET_NAME'])) {
|
||||||
return $cols['CHARACTER_SET_NAME'];
|
$this->_charsets[$name] = $cols['CHARACTER_SET_NAME'];
|
||||||
|
} else {
|
||||||
|
$this->_charsets[$name] = false;
|
||||||
}
|
}
|
||||||
}
|
return $this->_charsets[$name];
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -282,7 +300,7 @@ class Mysql extends DboSource {
|
||||||
public function describe($model) {
|
public function describe($model) {
|
||||||
$key = $this->fullTableName($model, false);
|
$key = $this->fullTableName($model, false);
|
||||||
$cache = parent::describe($key);
|
$cache = parent::describe($key);
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
$table = $this->fullTableName($model);
|
$table = $this->fullTableName($model);
|
||||||
|
@ -334,7 +352,7 @@ class Mysql extends DboSource {
|
||||||
return parent::update($model, $fields, $values, $conditions);
|
return parent::update($model, $fields, $values, $conditions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($values == null) {
|
if (!$values) {
|
||||||
$combined = $fields;
|
$combined = $fields;
|
||||||
} else {
|
} else {
|
||||||
$combined = array_combine($fields, $values);
|
$combined = array_combine($fields, $values);
|
||||||
|
@ -425,17 +443,22 @@ class Mysql extends DboSource {
|
||||||
$table = $this->fullTableName($model);
|
$table = $this->fullTableName($model);
|
||||||
$old = version_compare($this->getVersion(), '4.1', '<=');
|
$old = version_compare($this->getVersion(), '4.1', '<=');
|
||||||
if ($table) {
|
if ($table) {
|
||||||
$indices = $this->_execute('SHOW INDEX FROM ' . $table);
|
$indexes = $this->_execute('SHOW INDEX FROM ' . $table);
|
||||||
// @codingStandardsIgnoreStart
|
// @codingStandardsIgnoreStart
|
||||||
// MySQL columns don't match the cakephp conventions.
|
// MySQL columns don't match the cakephp conventions.
|
||||||
while ($idx = $indices->fetch(PDO::FETCH_OBJ)) {
|
while ($idx = $indexes->fetch(PDO::FETCH_OBJ)) {
|
||||||
if ($old) {
|
if ($old) {
|
||||||
$idx = (object)current((array)$idx);
|
$idx = (object)current((array)$idx);
|
||||||
}
|
}
|
||||||
if (!isset($index[$idx->Key_name]['column'])) {
|
if (!isset($index[$idx->Key_name]['column'])) {
|
||||||
$col = array();
|
$col = array();
|
||||||
$index[$idx->Key_name]['column'] = $idx->Column_name;
|
$index[$idx->Key_name]['column'] = $idx->Column_name;
|
||||||
|
|
||||||
|
if ($idx->Index_type === 'FULLTEXT') {
|
||||||
|
$index[$idx->Key_name]['type'] = strtolower($idx->Index_type);
|
||||||
|
} else {
|
||||||
$index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0);
|
$index[$idx->Key_name]['unique'] = intval($idx->Non_unique == 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!empty($index[$idx->Key_name]['column']) && !is_array($index[$idx->Key_name]['column'])) {
|
if (!empty($index[$idx->Key_name]['column']) && !is_array($index[$idx->Key_name]['column'])) {
|
||||||
$col[] = $index[$idx->Key_name]['column'];
|
$col[] = $index[$idx->Key_name]['column'];
|
||||||
|
@ -445,7 +468,7 @@ class Mysql extends DboSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @codingStandardsIgnoreEnd
|
// @codingStandardsIgnoreEnd
|
||||||
$indices->closeCursor();
|
$indexes->closeCursor();
|
||||||
}
|
}
|
||||||
return $index;
|
return $index;
|
||||||
}
|
}
|
||||||
|
@ -555,31 +578,18 @@ class Mysql extends DboSource {
|
||||||
if (isset($indexes['drop'])) {
|
if (isset($indexes['drop'])) {
|
||||||
foreach ($indexes['drop'] as $name => $value) {
|
foreach ($indexes['drop'] as $name => $value) {
|
||||||
$out = 'DROP ';
|
$out = 'DROP ';
|
||||||
if ($name == 'PRIMARY') {
|
if ($name === 'PRIMARY') {
|
||||||
$out .= 'PRIMARY KEY';
|
$out .= 'PRIMARY KEY';
|
||||||
} else {
|
} else {
|
||||||
$out .= 'KEY ' . $name;
|
$out .= 'KEY ' . $this->startQuote . $name . $this->endQuote;
|
||||||
}
|
}
|
||||||
$alter[] = $out;
|
$alter[] = $out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($indexes['add'])) {
|
if (isset($indexes['add'])) {
|
||||||
foreach ($indexes['add'] as $name => $value) {
|
$add = $this->buildIndex($indexes['add']);
|
||||||
$out = 'ADD ';
|
foreach ($add as $index) {
|
||||||
if ($name == 'PRIMARY') {
|
$alter[] = 'ADD ' . $index;
|
||||||
$out .= 'PRIMARY ';
|
|
||||||
$name = null;
|
|
||||||
} else {
|
|
||||||
if (!empty($value['unique'])) {
|
|
||||||
$out .= 'UNIQUE ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (is_array($value['column'])) {
|
|
||||||
$out .= 'KEY ' . $name . ' (' . implode(', ', array_map(array(&$this, 'name'), $value['column'])) . ')';
|
|
||||||
} else {
|
|
||||||
$out .= 'KEY ' . $name . ' (' . $this->name($value['column']) . ')';
|
|
||||||
}
|
|
||||||
$alter[] = $out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $alter;
|
return $alter;
|
||||||
|
@ -645,9 +655,12 @@ class Mysql extends DboSource {
|
||||||
if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
|
if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) {
|
||||||
return $col;
|
return $col;
|
||||||
}
|
}
|
||||||
if (($col === 'tinyint' && $limit == 1) || $col === 'boolean') {
|
if (($col === 'tinyint' && $limit === 1) || $col === 'boolean') {
|
||||||
return 'boolean';
|
return 'boolean';
|
||||||
}
|
}
|
||||||
|
if (strpos($col, 'bigint') !== false || $col === 'bigint') {
|
||||||
|
return 'biginteger';
|
||||||
|
}
|
||||||
if (strpos($col, 'int') !== false) {
|
if (strpos($col, 'int') !== false) {
|
||||||
return 'integer';
|
return 'integer';
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ class Postgres extends DboSource {
|
||||||
'string' => array('name' => 'varchar', 'limit' => '255'),
|
'string' => array('name' => 'varchar', 'limit' => '255'),
|
||||||
'text' => array('name' => 'text'),
|
'text' => array('name' => 'text'),
|
||||||
'integer' => array('name' => 'integer', 'formatter' => 'intval'),
|
'integer' => array('name' => 'integer', 'formatter' => 'intval'),
|
||||||
|
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
|
||||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||||
'datetime' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
'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'),
|
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||||
|
@ -148,7 +149,7 @@ class Postgres extends DboSource {
|
||||||
public function listSources($data = null) {
|
public function listSources($data = null) {
|
||||||
$cache = parent::listSources();
|
$cache = parent::listSources();
|
||||||
|
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +159,8 @@ class Postgres extends DboSource {
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
return array();
|
return array();
|
||||||
} else {
|
}
|
||||||
|
|
||||||
$tables = array();
|
$tables = array();
|
||||||
|
|
||||||
foreach ($result as $item) {
|
foreach ($result as $item) {
|
||||||
|
@ -169,7 +171,6 @@ class Postgres extends DboSource {
|
||||||
parent::listSources($tables);
|
parent::listSources($tables);
|
||||||
return $tables;
|
return $tables;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of the fields in given table name.
|
* Returns an array of the fields in given table name.
|
||||||
|
@ -286,13 +287,34 @@ class Postgres extends DboSource {
|
||||||
if (is_object($table)) {
|
if (is_object($table)) {
|
||||||
$table = $this->fullTableName($table, false, false);
|
$table = $this->fullTableName($table, false, false);
|
||||||
}
|
}
|
||||||
if (isset($this->_sequenceMap[$table]) && isset($this->_sequenceMap[$table][$field])) {
|
if (!isset($this->_sequenceMap[$table])) {
|
||||||
|
$this->describe($table);
|
||||||
|
}
|
||||||
|
if (isset($this->_sequenceMap[$table][$field])) {
|
||||||
return $this->_sequenceMap[$table][$field];
|
return $this->_sequenceMap[$table][$field];
|
||||||
} else {
|
} else {
|
||||||
return "{$table}_{$field}_seq";
|
return "{$table}_{$field}_seq";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset a sequence based on the MAX() value of $column. Useful
|
||||||
|
* for resetting sequences after using insertMulti().
|
||||||
|
*
|
||||||
|
* @param string $table The name of the table to update.
|
||||||
|
* @param string $column The column to use when reseting the sequence value, the
|
||||||
|
* sequence name will be fetched using Postgres::getSequence();
|
||||||
|
* @return boolean success.
|
||||||
|
*/
|
||||||
|
public function resetSequence($table, $column) {
|
||||||
|
$tableName = $this->fullTableName($table, false, false);
|
||||||
|
$fullTable = $this->fullTableName($table);
|
||||||
|
|
||||||
|
$sequence = $this->value($this->getSequence($tableName, $column));
|
||||||
|
$this->execute("SELECT setval($sequence, (SELECT MAX(id) FROM $fullTable))");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all the records in a table and drops all associated auto-increment sequences
|
* Deletes all the records in a table and drops all associated auto-increment sequences
|
||||||
*
|
*
|
||||||
|
@ -640,6 +662,8 @@ class Postgres extends DboSource {
|
||||||
return 'datetime';
|
return 'datetime';
|
||||||
case (strpos($col, 'time') === 0):
|
case (strpos($col, 'time') === 0):
|
||||||
return 'time';
|
return 'time';
|
||||||
|
case ($col == 'bigint'):
|
||||||
|
return 'biginteger';
|
||||||
case (strpos($col, 'int') !== false && $col != 'interval'):
|
case (strpos($col, 'int') !== false && $col != 'interval'):
|
||||||
return 'integer';
|
return 'integer';
|
||||||
case (strpos($col, 'char') !== false || $col == 'uuid'):
|
case (strpos($col, 'char') !== false || $col == 'uuid'):
|
||||||
|
@ -671,7 +695,7 @@ class Postgres extends DboSource {
|
||||||
if ($col == 'uuid') {
|
if ($col == 'uuid') {
|
||||||
return 36;
|
return 36;
|
||||||
}
|
}
|
||||||
if ($limit != null) {
|
if ($limit) {
|
||||||
return intval($limit);
|
return intval($limit);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -801,7 +825,19 @@ class Postgres extends DboSource {
|
||||||
if (!isset($col['length']) && !isset($col['limit'])) {
|
if (!isset($col['length']) && !isset($col['limit'])) {
|
||||||
unset($column['length']);
|
unset($column['length']);
|
||||||
}
|
}
|
||||||
$out = preg_replace('/integer\([0-9]+\)/', 'integer', parent::buildColumn($column));
|
$out = parent::buildColumn($column);
|
||||||
|
|
||||||
|
$out = preg_replace(
|
||||||
|
'/integer\([0-9]+\)/',
|
||||||
|
'integer',
|
||||||
|
$out
|
||||||
|
);
|
||||||
|
$out = preg_replace(
|
||||||
|
'/bigint\([0-9]+\)/',
|
||||||
|
'bigint',
|
||||||
|
$out
|
||||||
|
);
|
||||||
|
|
||||||
$out = str_replace('integer serial', 'serial', $out);
|
$out = str_replace('integer serial', 'serial', $out);
|
||||||
if (strpos($out, 'timestamp DEFAULT')) {
|
if (strpos($out, 'timestamp DEFAULT')) {
|
||||||
if (isset($column['null']) && $column['null']) {
|
if (isset($column['null']) && $column['null']) {
|
||||||
|
|
|
@ -70,6 +70,7 @@ class Sqlite extends DboSource {
|
||||||
'string' => array('name' => 'varchar', 'limit' => '255'),
|
'string' => array('name' => 'varchar', 'limit' => '255'),
|
||||||
'text' => array('name' => 'text'),
|
'text' => array('name' => 'text'),
|
||||||
'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'),
|
'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'),
|
||||||
|
'biginteger' => array('name' => 'bigint', 'limit' => 20),
|
||||||
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
'float' => array('name' => 'float', 'formatter' => 'floatval'),
|
||||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
'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'),
|
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||||
|
@ -138,7 +139,7 @@ class Sqlite extends DboSource {
|
||||||
*/
|
*/
|
||||||
public function listSources($data = null) {
|
public function listSources($data = null) {
|
||||||
$cache = parent::listSources();
|
$cache = parent::listSources();
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +147,8 @@ class Sqlite extends DboSource {
|
||||||
|
|
||||||
if (!$result || empty($result)) {
|
if (!$result || empty($result)) {
|
||||||
return array();
|
return array();
|
||||||
} else {
|
}
|
||||||
|
|
||||||
$tables = array();
|
$tables = array();
|
||||||
foreach ($result as $table) {
|
foreach ($result as $table) {
|
||||||
$tables[] = $table[0]['name'];
|
$tables[] = $table[0]['name'];
|
||||||
|
@ -154,7 +156,6 @@ class Sqlite extends DboSource {
|
||||||
parent::listSources($tables);
|
parent::listSources($tables);
|
||||||
return $tables;
|
return $tables;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of the fields in given table name.
|
* Returns an array of the fields in given table name.
|
||||||
|
@ -165,7 +166,7 @@ class Sqlite extends DboSource {
|
||||||
public function describe($model) {
|
public function describe($model) {
|
||||||
$table = $this->fullTableName($model, false, false);
|
$table = $this->fullTableName($model, false, false);
|
||||||
$cache = parent::describe($table);
|
$cache = parent::describe($table);
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
$fields = array();
|
$fields = array();
|
||||||
|
@ -251,9 +252,22 @@ class Sqlite extends DboSource {
|
||||||
$limit = null;
|
$limit = null;
|
||||||
@list($col, $limit) = explode('(', $col);
|
@list($col, $limit) = explode('(', $col);
|
||||||
|
|
||||||
if (in_array($col, array('text', 'integer', 'float', 'boolean', 'timestamp', 'date', 'datetime', 'time'))) {
|
$standard = array(
|
||||||
|
'text',
|
||||||
|
'integer',
|
||||||
|
'float',
|
||||||
|
'boolean',
|
||||||
|
'timestamp',
|
||||||
|
'date',
|
||||||
|
'datetime',
|
||||||
|
'time'
|
||||||
|
);
|
||||||
|
if (in_array($col, $standard)) {
|
||||||
return $col;
|
return $col;
|
||||||
}
|
}
|
||||||
|
if ($col === 'bigint') {
|
||||||
|
return 'biginteger';
|
||||||
|
}
|
||||||
if (strpos($col, 'char') !== false) {
|
if (strpos($col, 'char') !== false) {
|
||||||
return 'string';
|
return 'string';
|
||||||
}
|
}
|
||||||
|
@ -448,7 +462,7 @@ class Sqlite extends DboSource {
|
||||||
$out .= 'UNIQUE ';
|
$out .= 'UNIQUE ';
|
||||||
}
|
}
|
||||||
if (is_array($value['column'])) {
|
if (is_array($value['column'])) {
|
||||||
$value['column'] = join(', ', array_map(array(&$this, 'name'), $value['column']));
|
$value['column'] = implode(', ', array_map(array(&$this, 'name'), $value['column']));
|
||||||
} else {
|
} else {
|
||||||
$value['column'] = $this->name($value['column']);
|
$value['column'] = $this->name($value['column']);
|
||||||
}
|
}
|
||||||
|
@ -513,10 +527,10 @@ class Sqlite extends DboSource {
|
||||||
case 'schema':
|
case 'schema':
|
||||||
extract($data);
|
extract($data);
|
||||||
if (is_array($columns)) {
|
if (is_array($columns)) {
|
||||||
$columns = "\t" . join(",\n\t", array_filter($columns));
|
$columns = "\t" . implode(",\n\t", array_filter($columns));
|
||||||
}
|
}
|
||||||
if (is_array($indexes)) {
|
if (is_array($indexes)) {
|
||||||
$indexes = "\t" . join("\n\t", array_filter($indexes));
|
$indexes = "\t" . implode("\n\t", array_filter($indexes));
|
||||||
}
|
}
|
||||||
return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
|
return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -89,6 +89,7 @@ class Sqlserver extends DboSource {
|
||||||
'string' => array('name' => 'nvarchar', 'limit' => '255'),
|
'string' => array('name' => 'nvarchar', 'limit' => '255'),
|
||||||
'text' => array('name' => 'nvarchar', 'limit' => 'MAX'),
|
'text' => array('name' => 'nvarchar', 'limit' => 'MAX'),
|
||||||
'integer' => array('name' => 'int', 'formatter' => 'intval'),
|
'integer' => array('name' => 'int', 'formatter' => 'intval'),
|
||||||
|
'biginteger' => array('name' => 'bigint'),
|
||||||
'float' => array('name' => 'numeric', 'formatter' => 'floatval'),
|
'float' => array('name' => 'numeric', 'formatter' => 'floatval'),
|
||||||
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
'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'),
|
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
|
||||||
|
@ -186,7 +187,7 @@ class Sqlserver extends DboSource {
|
||||||
public function describe($model) {
|
public function describe($model) {
|
||||||
$table = $this->fullTableName($model, false);
|
$table = $this->fullTableName($model, false);
|
||||||
$cache = parent::describe($table);
|
$cache = parent::describe($table);
|
||||||
if ($cache != null) {
|
if ($cache) {
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
$fields = array();
|
$fields = array();
|
||||||
|
@ -402,6 +403,9 @@ class Sqlserver extends DboSource {
|
||||||
if ($col == 'bit') {
|
if ($col == 'bit') {
|
||||||
return 'boolean';
|
return 'boolean';
|
||||||
}
|
}
|
||||||
|
if (strpos($col, 'bigint') !== false) {
|
||||||
|
return 'biginteger';
|
||||||
|
}
|
||||||
if (strpos($col, 'int') !== false) {
|
if (strpos($col, 'int') !== false) {
|
||||||
return 'integer';
|
return 'integer';
|
||||||
}
|
}
|
||||||
|
@ -618,7 +622,7 @@ class Sqlserver extends DboSource {
|
||||||
*/
|
*/
|
||||||
public function insertMulti($table, $fields, $values) {
|
public function insertMulti($table, $fields, $values) {
|
||||||
$primaryKey = $this->_getPrimaryKey($table);
|
$primaryKey = $this->_getPrimaryKey($table);
|
||||||
$hasPrimaryKey = $primaryKey != null && (
|
$hasPrimaryKey = $primaryKey && (
|
||||||
(is_array($fields) && in_array($primaryKey, $fields)
|
(is_array($fields) && in_array($primaryKey, $fields)
|
||||||
|| (is_string($fields) && strpos($fields, $this->startQuote . $primaryKey . $this->endQuote) !== false))
|
|| (is_string($fields) && strpos($fields, $this->startQuote . $primaryKey . $this->endQuote) !== false))
|
||||||
);
|
);
|
||||||
|
@ -644,7 +648,7 @@ class Sqlserver extends DboSource {
|
||||||
*/
|
*/
|
||||||
public function buildColumn($column) {
|
public function buildColumn($column) {
|
||||||
$result = parent::buildColumn($column);
|
$result = parent::buildColumn($column);
|
||||||
$result = preg_replace('/(int|integer)\([0-9]+\)/i', '$1', $result);
|
$result = preg_replace('/(bigint|int|integer)\([0-9]+\)/i', '$1', $result);
|
||||||
$result = preg_replace('/(bit)\([0-9]+\)/i', '$1', $result);
|
$result = preg_replace('/(bit)\([0-9]+\)/i', '$1', $result);
|
||||||
if (strpos($result, 'DEFAULT NULL') !== false) {
|
if (strpos($result, 'DEFAULT NULL') !== false) {
|
||||||
if (isset($column['default']) && $column['default'] === '') {
|
if (isset($column['default']) && $column['default'] === '') {
|
||||||
|
@ -731,7 +735,7 @@ class Sqlserver extends DboSource {
|
||||||
*/
|
*/
|
||||||
protected function _execute($sql, $params = array(), $prepareOptions = array()) {
|
protected function _execute($sql, $params = array(), $prepareOptions = array()) {
|
||||||
$this->_lastAffected = false;
|
$this->_lastAffected = false;
|
||||||
if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UTE)?\s/mi', $sql) > 0) {
|
if (strncasecmp($sql, 'SELECT', 6) === 0 || preg_match('/^EXEC(?:UTE)?\s/mi', $sql) > 0) {
|
||||||
$prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
|
$prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
|
||||||
return parent::_execute($sql, $params, $prepareOptions);
|
return parent::_execute($sql, $params, $prepareOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,7 +671,7 @@ class DboSource extends DataSource {
|
||||||
|
|
||||||
if ($this->hasResult()) {
|
if ($this->hasResult()) {
|
||||||
$first = $this->fetchRow();
|
$first = $this->fetchRow();
|
||||||
if ($first != null) {
|
if ($first) {
|
||||||
$out[] = $first;
|
$out[] = $first;
|
||||||
}
|
}
|
||||||
while ($item = $this->fetchResult()) {
|
while ($item = $this->fetchResult()) {
|
||||||
|
@ -984,7 +984,7 @@ class DboSource extends DataSource {
|
||||||
public function create(Model $model, $fields = null, $values = null) {
|
public function create(Model $model, $fields = null, $values = null) {
|
||||||
$id = null;
|
$id = null;
|
||||||
|
|
||||||
if ($fields == null) {
|
if (!$fields) {
|
||||||
unset($fields, $values);
|
unset($fields, $values);
|
||||||
$fields = array_keys($model->data);
|
$fields = array_keys($model->data);
|
||||||
$values = array_values($model->data);
|
$values = array_values($model->data);
|
||||||
|
@ -1054,7 +1054,7 @@ class DboSource extends DataSource {
|
||||||
|
|
||||||
if ($model->recursive == -1) {
|
if ($model->recursive == -1) {
|
||||||
$_associations = array();
|
$_associations = array();
|
||||||
} elseif ($model->recursive == 0) {
|
} elseif ($model->recursive === 0) {
|
||||||
unset($_associations[2], $_associations[3]);
|
unset($_associations[2], $_associations[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1408,10 +1408,9 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isset($data[$association])) {
|
if (!isset($data[$association])) {
|
||||||
if ($merge[0][$association] != null) {
|
|
||||||
$data[$association] = $merge[0][$association];
|
|
||||||
} else {
|
|
||||||
$data[$association] = array();
|
$data[$association] = array();
|
||||||
|
if ($merge[0][$association]) {
|
||||||
|
$data[$association] = $merge[0][$association];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (is_array($merge[0][$association])) {
|
if (is_array($merge[0][$association])) {
|
||||||
|
@ -1767,7 +1766,7 @@ class DboSource extends DataSource {
|
||||||
case 'schema':
|
case 'schema':
|
||||||
foreach (array('columns', 'indexes', 'tableParameters') as $var) {
|
foreach (array('columns', 'indexes', 'tableParameters') as $var) {
|
||||||
if (is_array(${$var})) {
|
if (is_array(${$var})) {
|
||||||
${$var} = "\t" . join(",\n\t", array_filter(${$var}));
|
${$var} = "\t" . implode(",\n\t", array_filter(${$var}));
|
||||||
} else {
|
} else {
|
||||||
${$var} = '';
|
${$var} = '';
|
||||||
}
|
}
|
||||||
|
@ -1821,7 +1820,7 @@ class DboSource extends DataSource {
|
||||||
* @return boolean Success
|
* @return boolean Success
|
||||||
*/
|
*/
|
||||||
public function update(Model $model, $fields = array(), $values = null, $conditions = null) {
|
public function update(Model $model, $fields = array(), $values = null, $conditions = null) {
|
||||||
if ($values == null) {
|
if (!$values) {
|
||||||
$combined = $fields;
|
$combined = $fields;
|
||||||
} else {
|
} else {
|
||||||
$combined = array_combine($fields, $values);
|
$combined = array_combine($fields, $values);
|
||||||
|
@ -2514,7 +2513,7 @@ class DboSource extends DataSource {
|
||||||
$data = $this->_parseKey($model, trim($key), $value);
|
$data = $this->_parseKey($model, trim($key), $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data != null) {
|
if ($data) {
|
||||||
$out[] = $data;
|
$out[] = $data;
|
||||||
$data = null;
|
$data = null;
|
||||||
}
|
}
|
||||||
|
@ -2925,6 +2924,19 @@ class DboSource extends DataSource {
|
||||||
return $this->commit();
|
return $this->commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset a sequence based on the MAX() value of $column. Useful
|
||||||
|
* for resetting sequences after using insertMulti().
|
||||||
|
*
|
||||||
|
* This method should be implemented by datasources that require sequences to be used.
|
||||||
|
*
|
||||||
|
* @param string $table The name of the table to update.
|
||||||
|
* @param string $column The column to use when reseting the sequence value.
|
||||||
|
* @return boolean success.
|
||||||
|
*/
|
||||||
|
public function resetSequence($table, $column) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of the indexes in given datasource name.
|
* Returns an array of the indexes in given datasource name.
|
||||||
*
|
*
|
||||||
|
@ -3071,7 +3083,7 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
$out = $this->_buildFieldParameters($out, $column, 'beforeDefault');
|
$out = $this->_buildFieldParameters($out, $column, 'beforeDefault');
|
||||||
|
|
||||||
if (isset($column['key']) && $column['key'] === 'primary' && $type === 'integer') {
|
if (isset($column['key']) && $column['key'] === 'primary' && ($type === 'integer' || $type === 'biginteger')) {
|
||||||
$out .= ' ' . $this->columns['primary_key']['name'];
|
$out .= ' ' . $this->columns['primary_key']['name'];
|
||||||
} elseif (isset($column['key']) && $column['key'] === 'primary') {
|
} elseif (isset($column['key']) && $column['key'] === 'primary') {
|
||||||
$out .= ' NOT NULL';
|
$out .= ' NOT NULL';
|
||||||
|
@ -3117,7 +3129,7 @@ class DboSource extends DataSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format indexes for create table
|
* Format indexes for create table.
|
||||||
*
|
*
|
||||||
* @param array $indexes
|
* @param array $indexes
|
||||||
* @param string $table
|
* @param string $table
|
||||||
|
@ -3133,6 +3145,8 @@ class DboSource extends DataSource {
|
||||||
} else {
|
} else {
|
||||||
if (!empty($value['unique'])) {
|
if (!empty($value['unique'])) {
|
||||||
$out .= 'UNIQUE ';
|
$out .= 'UNIQUE ';
|
||||||
|
} elseif (!empty($value['type']) && strtoupper($value['type']) === 'FULLTEXT') {
|
||||||
|
$out .= 'FULLTEXT ';
|
||||||
}
|
}
|
||||||
$name = $this->startQuote . $name . $this->endQuote;
|
$name = $this->startQuote . $name . $this->endQuote;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
* @since CakePHP(tm) v 1.2.0.4525
|
* @since CakePHP(tm) v 1.2.0.4525
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('AppModel', 'Model');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A model used by TranslateBehavior to access the translation tables.
|
* A model used by TranslateBehavior to access the translation tables.
|
||||||
|
|
|
@ -235,6 +235,13 @@ class Model extends Object implements CakeEventListener {
|
||||||
*/
|
*/
|
||||||
public $tablePrefix = null;
|
public $tablePrefix = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin model belongs to.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $plugin = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the model.
|
* Name of the model.
|
||||||
*
|
*
|
||||||
|
@ -669,12 +676,16 @@ class Model extends Object implements CakeEventListener {
|
||||||
extract(array_merge(
|
extract(array_merge(
|
||||||
array(
|
array(
|
||||||
'id' => $this->id, 'table' => $this->useTable, 'ds' => $this->useDbConfig,
|
'id' => $this->id, 'table' => $this->useTable, 'ds' => $this->useDbConfig,
|
||||||
'name' => $this->name, 'alias' => $this->alias
|
'name' => $this->name, 'alias' => $this->alias, 'plugin' => $this->plugin
|
||||||
),
|
),
|
||||||
$id
|
$id
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->plugin === null) {
|
||||||
|
$this->plugin = (isset($plugin) ? $plugin : $this->plugin);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->name === null) {
|
if ($this->name === null) {
|
||||||
$this->name = (isset($name) ? $name : get_class($this));
|
$this->name = (isset($name) ? $name : get_class($this));
|
||||||
}
|
}
|
||||||
|
@ -720,7 +731,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
$this->useTable = Inflector::tableize($this->name);
|
$this->useTable = Inflector::tableize($this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->displayField == null) {
|
if (!$this->displayField) {
|
||||||
unset($this->displayField);
|
unset($this->displayField);
|
||||||
}
|
}
|
||||||
$this->table = $this->useTable;
|
$this->table = $this->useTable;
|
||||||
|
@ -1393,7 +1404,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
$this->schema();
|
$this->schema();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->_schema != null) {
|
if ($this->_schema) {
|
||||||
return isset($this->_schema[$name]);
|
return isset($this->_schema[$name]);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1447,7 +1458,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
* or false if none $field exist.
|
* or false if none $field exist.
|
||||||
*/
|
*/
|
||||||
public function getVirtualField($field = null) {
|
public function getVirtualField($field = null) {
|
||||||
if ($field == null) {
|
if (!$field) {
|
||||||
return empty($this->virtualFields) ? false : $this->virtualFields;
|
return empty($this->virtualFields) ? false : $this->virtualFields;
|
||||||
}
|
}
|
||||||
if ($this->isVirtualField($field)) {
|
if ($this->isVirtualField($field)) {
|
||||||
|
@ -1503,7 +1514,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
public function read($fields = null, $id = null) {
|
public function read($fields = null, $id = null) {
|
||||||
$this->validationErrors = array();
|
$this->validationErrors = array();
|
||||||
|
|
||||||
if ($id != null) {
|
if ($id) {
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1519,9 +1530,8 @@ class Model extends Object implements CakeEventListener {
|
||||||
'fields' => $fields
|
'fields' => $fields
|
||||||
));
|
));
|
||||||
return $this->data;
|
return $this->data;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2220,6 +2230,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
} else {
|
} else {
|
||||||
$data = array_merge(array($key => $this->{$association}->id), $data, array($key => $this->{$association}->id));
|
$data = array_merge(array($key => $this->{$association}->id), $data, array($key => $this->{$association}->id));
|
||||||
}
|
}
|
||||||
|
$options = $this->_addToWhiteList($key, $options);
|
||||||
} else {
|
} else {
|
||||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||||
}
|
}
|
||||||
|
@ -2250,6 +2261,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
$validates = $this->{$association}->create(null) !== null;
|
$validates = $this->{$association}->create(null) !== null;
|
||||||
$saved = false;
|
$saved = false;
|
||||||
if ($validates) {
|
if ($validates) {
|
||||||
|
$options = $this->{$association}->_addToWhiteList($key, $options);
|
||||||
if ($options['deep']) {
|
if ($options['deep']) {
|
||||||
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2270,6 +2282,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
$values[$i] = array_merge(array($key => $this->id), $value, array($key => $this->id));
|
$values[$i] = array_merge(array($key => $this->id), $value, array($key => $this->id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$options = $this->{$association}->_addToWhiteList($key, $options);
|
||||||
$_return = $this->{$association}->saveMany($values, array_merge($options, array('atomic' => false)));
|
$_return = $this->{$association}->saveMany($values, array_merge($options, array('atomic' => false)));
|
||||||
if (in_array(false, $_return, true)) {
|
if (in_array(false, $_return, true)) {
|
||||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||||
|
@ -2302,6 +2315,29 @@ class Model extends Object implements CakeEventListener {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for saveAll() and friends, to add foreign key to fieldlist
|
||||||
|
*
|
||||||
|
* @param string $key fieldname to be added to list
|
||||||
|
* @param array $options
|
||||||
|
* @return array $options
|
||||||
|
*/
|
||||||
|
protected function _addToWhiteList($key, $options) {
|
||||||
|
if (empty($options['fieldList']) && $this->whitelist && !in_array($key, $this->whitelist)) {
|
||||||
|
$options['fieldList'][$this->alias] = $this->whitelist;
|
||||||
|
$options['fieldList'][$this->alias][] = $key;
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
if (!empty($options['fieldList'][$this->alias]) && is_array($options['fieldList'][$this->alias])) {
|
||||||
|
$options['fieldList'][$this->alias][] = $key;
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
if (!empty($options['fieldList']) && is_array($options['fieldList'])) {
|
||||||
|
$options['fieldList'][] = $key;
|
||||||
|
}
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates a single record, as well as all its directly associated records.
|
* Validates a single record, as well as all its directly associated records.
|
||||||
*
|
*
|
||||||
|
@ -2566,7 +2602,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
* @return boolean True if such a record exists
|
* @return boolean True if such a record exists
|
||||||
*/
|
*/
|
||||||
public function hasAny($conditions = null) {
|
public function hasAny($conditions = null) {
|
||||||
return ($this->find('count', array('conditions' => $conditions, 'recursive' => -1)) != false);
|
return (bool)$this->find('count', array('conditions' => $conditions, 'recursive' => -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2987,7 +3023,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
if (!empty($this->id)) {
|
if (!empty($this->id)) {
|
||||||
$fields[$this->alias . '.' . $this->primaryKey . ' !='] = $this->id;
|
$fields[$this->alias . '.' . $this->primaryKey . ' !='] = $this->id;
|
||||||
}
|
}
|
||||||
return ($this->find('count', array('conditions' => $fields, 'recursive' => -1)) == 0);
|
return !$this->find('count', array('conditions' => $fields, 'recursive' => -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3158,7 +3194,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
public function setDataSource($dataSource = null) {
|
public function setDataSource($dataSource = null) {
|
||||||
$oldConfig = $this->useDbConfig;
|
$oldConfig = $this->useDbConfig;
|
||||||
|
|
||||||
if ($dataSource != null) {
|
if ($dataSource) {
|
||||||
$this->useDbConfig = $dataSource;
|
$this->useDbConfig = $dataSource;
|
||||||
}
|
}
|
||||||
$db = ConnectionManager::getDataSource($this->useDbConfig);
|
$db = ConnectionManager::getDataSource($this->useDbConfig);
|
||||||
|
@ -3204,7 +3240,7 @@ class Model extends Object implements CakeEventListener {
|
||||||
* @return array Associations
|
* @return array Associations
|
||||||
*/
|
*/
|
||||||
public function getAssociated($type = null) {
|
public function getAssociated($type = null) {
|
||||||
if ($type == null) {
|
if (!$type) {
|
||||||
$associated = array();
|
$associated = array();
|
||||||
foreach ($this->_associations as $assoc) {
|
foreach ($this->_associations as $assoc) {
|
||||||
if (!empty($this->{$assoc})) {
|
if (!empty($this->{$assoc})) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Permission extends AppModel {
|
||||||
* @return boolean Success (true if ARO has access to action in ACO, false otherwise)
|
* @return boolean Success (true if ARO has access to action in ACO, false otherwise)
|
||||||
*/
|
*/
|
||||||
public function check($aro, $aco, $action = "*") {
|
public function check($aro, $aco, $action = "*") {
|
||||||
if ($aro == null || $aco == null) {
|
if (!$aro || !$aco) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +89,12 @@ class Permission extends AppModel {
|
||||||
$aroPath = $this->Aro->node($aro);
|
$aroPath = $this->Aro->node($aro);
|
||||||
$acoPath = $this->Aco->node($aco);
|
$acoPath = $this->Aco->node($aco);
|
||||||
|
|
||||||
if (empty($aroPath) || empty($acoPath)) {
|
if (!$aroPath || !$acoPath) {
|
||||||
trigger_error(__d('cake_dev', "DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
trigger_error(__d('cake_dev', "DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($acoPath == null || $acoPath == array()) {
|
if (!$acoPath) {
|
||||||
trigger_error(__d('cake_dev', "DbAcl::check() - Failed ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
trigger_error(__d('cake_dev', "DbAcl::check() - Failed ACO node lookup in permissions check. Node references:\nAro: ") . print_r($aro, true) . "\nAco: " . print_r($aco, true), E_USER_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,6 @@ class Permission extends AppModel {
|
||||||
return false;
|
return false;
|
||||||
case 0:
|
case 0:
|
||||||
continue;
|
continue;
|
||||||
break;
|
|
||||||
case 1:
|
case 1:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +170,7 @@ class Permission extends AppModel {
|
||||||
$permKeys = $this->getAcoKeys($this->schema());
|
$permKeys = $this->getAcoKeys($this->schema());
|
||||||
$save = array();
|
$save = array();
|
||||||
|
|
||||||
if ($perms == false) {
|
if (!$perms) {
|
||||||
trigger_error(__d('cake_dev', 'DbAcl::allow() - Invalid node'), E_USER_WARNING);
|
trigger_error(__d('cake_dev', 'DbAcl::allow() - Invalid node'), E_USER_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +197,7 @@ class Permission extends AppModel {
|
||||||
}
|
}
|
||||||
list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']);
|
list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']);
|
||||||
|
|
||||||
if ($perms['link'] != null && !empty($perms['link'])) {
|
if ($perms['link'] && !empty($perms['link'])) {
|
||||||
$save['id'] = $perms['link'][0][$this->alias]['id'];
|
$save['id'] = $perms['link'][0][$this->alias]['id'];
|
||||||
} else {
|
} else {
|
||||||
unset($save['id']);
|
unset($save['id']);
|
||||||
|
|
|
@ -273,7 +273,7 @@ class CakeValidationRule {
|
||||||
$this->_valid = call_user_func_array(array('Validation', $this->_rule), $this->_ruleParams);
|
$this->_valid = call_user_func_array(array('Validation', $this->_rule), $this->_ruleParams);
|
||||||
} elseif (is_string($validator['rule'])) {
|
} elseif (is_string($validator['rule'])) {
|
||||||
$this->_valid = preg_match($this->_rule, $data[$field]);
|
$this->_valid = preg_match($this->_rule, $data[$field]);
|
||||||
} elseif (Configure::read('debug') > 0) {
|
} else {
|
||||||
trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $this->_rule, $field), E_USER_WARNING);
|
trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $this->_rule, $field), E_USER_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,17 +366,17 @@ class CakeRequest implements ArrayAccess {
|
||||||
* @return string The client IP.
|
* @return string The client IP.
|
||||||
*/
|
*/
|
||||||
public function clientIp($safe = true) {
|
public function clientIp($safe = true) {
|
||||||
if (!$safe && env('HTTP_X_FORWARDED_FOR') != null) {
|
if (!$safe && env('HTTP_X_FORWARDED_FOR')) {
|
||||||
$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
|
$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
|
||||||
} else {
|
} else {
|
||||||
if (env('HTTP_CLIENT_IP') != null) {
|
if (env('HTTP_CLIENT_IP')) {
|
||||||
$ipaddr = env('HTTP_CLIENT_IP');
|
$ipaddr = env('HTTP_CLIENT_IP');
|
||||||
} else {
|
} else {
|
||||||
$ipaddr = env('REMOTE_ADDR');
|
$ipaddr = env('REMOTE_ADDR');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env('HTTP_CLIENTADDRESS') != null) {
|
if (env('HTTP_CLIENTADDRESS')) {
|
||||||
$tmpipaddr = env('HTTP_CLIENTADDRESS');
|
$tmpipaddr = env('HTTP_CLIENTADDRESS');
|
||||||
|
|
||||||
if (!empty($tmpipaddr)) {
|
if (!empty($tmpipaddr)) {
|
||||||
|
@ -696,8 +696,50 @@ class CakeRequest implements ArrayAccess {
|
||||||
* @return array An array of prefValue => array(content/types)
|
* @return array An array of prefValue => array(content/types)
|
||||||
*/
|
*/
|
||||||
public function parseAccept() {
|
public function parseAccept() {
|
||||||
|
return $this->_parseAcceptWithQualifier($this->header('accept'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the languages accepted by the client, or check if a specific language is accepted.
|
||||||
|
*
|
||||||
|
* Get the list of accepted languages:
|
||||||
|
*
|
||||||
|
* {{{ CakeRequest::acceptLanguage(); }}}
|
||||||
|
*
|
||||||
|
* Check if a specific language is accepted:
|
||||||
|
*
|
||||||
|
* {{{ CakeRequest::acceptLanguage('es-es'); }}}
|
||||||
|
*
|
||||||
|
* @param string $language The language to test.
|
||||||
|
* @return If a $language is provided, a boolean. Otherwise the array of accepted languages.
|
||||||
|
*/
|
||||||
|
public static function acceptLanguage($language = null) {
|
||||||
|
$raw = self::_parseAcceptWithQualifier(self::header('Accept-Language'));
|
||||||
$accept = array();
|
$accept = array();
|
||||||
$header = explode(',', $this->header('accept'));
|
foreach ($raw as $qualifier => $languages) {
|
||||||
|
foreach ($languages as &$lang) {
|
||||||
|
if (strpos($lang, '_')) {
|
||||||
|
$lang = str_replace('_', '-', $lang);
|
||||||
|
}
|
||||||
|
$lang = strtolower($lang);
|
||||||
|
}
|
||||||
|
$accept = array_merge($accept, $languages);
|
||||||
|
}
|
||||||
|
if ($language === null) {
|
||||||
|
return $accept;
|
||||||
|
}
|
||||||
|
return in_array(strtolower($language), $accept);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse Accept* headers with qualifier options
|
||||||
|
*
|
||||||
|
* @param string $header
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected static function _parseAcceptWithQualifier($header) {
|
||||||
|
$accept = array();
|
||||||
|
$header = explode(',', $header);
|
||||||
foreach (array_filter($header) as $value) {
|
foreach (array_filter($header) as $value) {
|
||||||
$prefPos = strpos($value, ';');
|
$prefPos = strpos($value, ';');
|
||||||
if ($prefPos !== false) {
|
if ($prefPos !== false) {
|
||||||
|
@ -719,31 +761,13 @@ class CakeRequest implements ArrayAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the languages accepted by the client, or check if a specific language is accepted.
|
* Provides a read accessor for `$this->query`. Allows you
|
||||||
|
* to use a syntax similar to `CakeSession` for reading url query data.
|
||||||
*
|
*
|
||||||
* Get the list of accepted languages:
|
* @return mixed The value being read
|
||||||
*
|
|
||||||
* {{{ CakeRequest::acceptLanguage(); }}}
|
|
||||||
*
|
|
||||||
* Check if a specific language is accepted:
|
|
||||||
*
|
|
||||||
* {{{ CakeRequest::acceptLanguage('es-es'); }}}
|
|
||||||
*
|
|
||||||
* @param string $language The language to test.
|
|
||||||
* @return If a $language is provided, a boolean. Otherwise the array of accepted languages.
|
|
||||||
*/
|
*/
|
||||||
public static function acceptLanguage($language = null) {
|
public function query($name) {
|
||||||
$accepts = preg_split('/[;,]/', self::header('Accept-Language'));
|
return Hash::get($this->query, $name);
|
||||||
foreach ($accepts as &$accept) {
|
|
||||||
$accept = strtolower($accept);
|
|
||||||
if (strpos($accept, '_') !== false) {
|
|
||||||
$accept = str_replace('_', '-', $accept);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($language === null) {
|
|
||||||
return $accepts;
|
|
||||||
}
|
|
||||||
return in_array($language, $accepts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -805,6 +829,38 @@ class CakeRequest implements ArrayAccess {
|
||||||
return $input;
|
return $input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only allow 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');
|
||||||
|
* or
|
||||||
|
* $this->request->onlyAllow(array('post', 'delete'));
|
||||||
|
*
|
||||||
|
* If the request would be GET, response header "Allow: POST, DELETE" will be set
|
||||||
|
* and a 405 error will be returned
|
||||||
|
*
|
||||||
|
* @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();
|
||||||
|
}
|
||||||
|
foreach ($methods as $method) {
|
||||||
|
if ($this->is($method)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$allowed = strtoupper(implode(', ', $methods));
|
||||||
|
$e = new MethodNotAllowedException();
|
||||||
|
$e->responseHeader('Allow', $allowed);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read data from php://input, mocked in tests.
|
* Read data from php://input, mocked in tests.
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
App::uses('File', 'Utility');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CakeResponse is responsible for managing the response text, status and headers of a HTTP response.
|
* CakeResponse is responsible for managing the response text, status and headers of a HTTP response.
|
||||||
*
|
*
|
||||||
|
@ -115,10 +117,10 @@ class CakeResponse {
|
||||||
'7z' => 'application/x-7z-compressed',
|
'7z' => 'application/x-7z-compressed',
|
||||||
'hdf' => 'application/x-hdf',
|
'hdf' => 'application/x-hdf',
|
||||||
'hqx' => 'application/mac-binhex40',
|
'hqx' => 'application/mac-binhex40',
|
||||||
'ico' => 'image/vnd.microsoft.icon',
|
'ico' => 'image/x-icon',
|
||||||
'ips' => 'application/x-ipscript',
|
'ips' => 'application/x-ipscript',
|
||||||
'ipx' => 'application/x-ipix',
|
'ipx' => 'application/x-ipix',
|
||||||
'js' => 'text/javascript',
|
'js' => 'application/javascript',
|
||||||
'latex' => 'application/x-latex',
|
'latex' => 'application/x-latex',
|
||||||
'lha' => 'application/octet-stream',
|
'lha' => 'application/octet-stream',
|
||||||
'lsp' => 'application/x-lisp',
|
'lsp' => 'application/x-lisp',
|
||||||
|
@ -171,6 +173,7 @@ class CakeResponse {
|
||||||
'texinfo' => 'application/x-texinfo',
|
'texinfo' => 'application/x-texinfo',
|
||||||
'tr' => 'application/x-troff',
|
'tr' => 'application/x-troff',
|
||||||
'tsp' => 'application/dsptype',
|
'tsp' => 'application/dsptype',
|
||||||
|
'ttc' => 'font/ttf',
|
||||||
'ttf' => 'font/ttf',
|
'ttf' => 'font/ttf',
|
||||||
'unv' => 'application/i-deas',
|
'unv' => 'application/i-deas',
|
||||||
'ustar' => 'application/x-ustar',
|
'ustar' => 'application/x-ustar',
|
||||||
|
@ -237,6 +240,12 @@ class CakeResponse {
|
||||||
'ogv' => 'video/ogg',
|
'ogv' => 'video/ogg',
|
||||||
'webm' => 'video/webm',
|
'webm' => 'video/webm',
|
||||||
'mp4' => 'video/mp4',
|
'mp4' => 'video/mp4',
|
||||||
|
'm4v' => 'video/mp4',
|
||||||
|
'f4v' => 'video/mp4',
|
||||||
|
'f4p' => 'video/mp4',
|
||||||
|
'm4a' => 'audio/mp4',
|
||||||
|
'f4a' => 'audio/mp4',
|
||||||
|
'f4b' => 'audio/mp4',
|
||||||
'gif' => 'image/gif',
|
'gif' => 'image/gif',
|
||||||
'ief' => 'image/ief',
|
'ief' => 'image/ief',
|
||||||
'jpe' => 'image/jpeg',
|
'jpe' => 'image/jpeg',
|
||||||
|
@ -265,7 +274,7 @@ class CakeResponse {
|
||||||
'mime' => 'www/mime',
|
'mime' => 'www/mime',
|
||||||
'pdb' => 'chemical/x-pdb',
|
'pdb' => 'chemical/x-pdb',
|
||||||
'xyz' => 'chemical/x-pdb',
|
'xyz' => 'chemical/x-pdb',
|
||||||
'javascript' => 'text/javascript',
|
'javascript' => 'application/javascript',
|
||||||
'form' => 'application/x-www-form-urlencoded',
|
'form' => 'application/x-www-form-urlencoded',
|
||||||
'file' => 'multipart/form-data',
|
'file' => 'multipart/form-data',
|
||||||
'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
|
'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
|
||||||
|
@ -276,6 +285,19 @@ class CakeResponse {
|
||||||
'wml' => 'text/vnd.wap.wml',
|
'wml' => 'text/vnd.wap.wml',
|
||||||
'wmlscript' => 'text/vnd.wap.wmlscript',
|
'wmlscript' => 'text/vnd.wap.wmlscript',
|
||||||
'wbmp' => 'image/vnd.wap.wbmp',
|
'wbmp' => 'image/vnd.wap.wbmp',
|
||||||
|
'woff' => 'application/x-font-woff',
|
||||||
|
'webp' => 'image/webp',
|
||||||
|
'appcache' => 'text/cache-manifest',
|
||||||
|
'manifest' => 'text/cache-manifest',
|
||||||
|
'htc' => 'text/x-component',
|
||||||
|
'rdf' => 'application/xml',
|
||||||
|
'crx' => 'application/x-chrome-extension',
|
||||||
|
'oex' => 'application/x-opera-extension',
|
||||||
|
'xpi' => 'application/x-xpinstall',
|
||||||
|
'safariextz' => 'application/octet-stream',
|
||||||
|
'webapp' => 'application/x-web-app-manifest+json',
|
||||||
|
'vcf' => 'text/x-vcard',
|
||||||
|
'vtt' => 'text/vtt',
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -314,6 +336,13 @@ class CakeResponse {
|
||||||
*/
|
*/
|
||||||
protected $_body = null;
|
protected $_body = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File object for file to be read out as response
|
||||||
|
*
|
||||||
|
* @var File
|
||||||
|
*/
|
||||||
|
protected $_file = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The charset the response body is encoded with
|
* The charset the response body is encoded with
|
||||||
*
|
*
|
||||||
|
@ -355,9 +384,10 @@ class CakeResponse {
|
||||||
if (isset($options['type'])) {
|
if (isset($options['type'])) {
|
||||||
$this->type($options['type']);
|
$this->type($options['type']);
|
||||||
}
|
}
|
||||||
if (isset($options['charset'])) {
|
if (!isset($options['charset'])) {
|
||||||
$this->charset($options['charset']);
|
$options['charset'] = Configure::read('App.encoding');
|
||||||
}
|
}
|
||||||
|
$this->charset($options['charset']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -380,8 +410,13 @@ class CakeResponse {
|
||||||
foreach ($this->_headers as $header => $value) {
|
foreach ($this->_headers as $header => $value) {
|
||||||
$this->_sendHeader($header, $value);
|
$this->_sendHeader($header, $value);
|
||||||
}
|
}
|
||||||
|
if ($this->_file) {
|
||||||
|
$this->_sendFile($this->_file);
|
||||||
|
$this->_file = null;
|
||||||
|
} else {
|
||||||
$this->_sendContent($this->_body);
|
$this->_sendContent($this->_body);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the cookies that have been added via static method CakeResponse::addCookie()
|
* Sets the cookies that have been added via static method CakeResponse::addCookie()
|
||||||
|
@ -712,7 +747,7 @@ class CakeResponse {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function cache($since, $time = '+1 day') {
|
public function cache($since, $time = '+1 day') {
|
||||||
if (!is_integer($time)) {
|
if (!is_int($time)) {
|
||||||
$time = strtotime($time);
|
$time = strtotime($time);
|
||||||
}
|
}
|
||||||
$this->header(array(
|
$this->header(array(
|
||||||
|
@ -755,7 +790,7 @@ class CakeResponse {
|
||||||
unset($this->_cacheDirectives['public']);
|
unset($this->_cacheDirectives['public']);
|
||||||
$this->maxAge($time);
|
$this->maxAge($time);
|
||||||
}
|
}
|
||||||
if ($time == null) {
|
if (!$time) {
|
||||||
$this->_setCacheControl();
|
$this->_setCacheControl();
|
||||||
}
|
}
|
||||||
return (bool)$public;
|
return (bool)$public;
|
||||||
|
@ -974,7 +1009,7 @@ class CakeResponse {
|
||||||
protected function _getUTCDate($time = null) {
|
protected function _getUTCDate($time = null) {
|
||||||
if ($time instanceof DateTime) {
|
if ($time instanceof DateTime) {
|
||||||
$result = clone $time;
|
$result = clone $time;
|
||||||
} elseif (is_integer($time)) {
|
} elseif (is_int($time)) {
|
||||||
$result = new DateTime(date('Y-m-d H:i:s', $time));
|
$result = new DateTime(date('Y-m-d H:i:s', $time));
|
||||||
} else {
|
} else {
|
||||||
$result = new DateTime($time);
|
$result = new DateTime($time);
|
||||||
|
@ -1052,12 +1087,11 @@ class CakeResponse {
|
||||||
* is marked as so accordingly so the client can be informed of that.
|
* is marked as so accordingly so the client can be informed of that.
|
||||||
*
|
*
|
||||||
* In order to mark a response as not modified, you need to set at least
|
* In order to mark a response as not modified, you need to set at least
|
||||||
* the Last-Modified response header or a response etag to be compared
|
* the Last-Modified etag response header before calling this method. Otherwise
|
||||||
* with the request itself
|
* a comparison will not be possible.
|
||||||
*
|
*
|
||||||
* @return boolean whether the response was marked as not modified or
|
* @return boolean whether the response was marked as not modified or not.
|
||||||
* not
|
*/
|
||||||
**/
|
|
||||||
public function checkNotModified(CakeRequest $request) {
|
public function checkNotModified(CakeRequest $request) {
|
||||||
$etags = preg_split('/\s*,\s*/', $request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY);
|
$etags = preg_split('/\s*,\s*/', $request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY);
|
||||||
$modifiedSince = $request->header('If-Modified-Since');
|
$modifiedSince = $request->header('If-Modified-Since');
|
||||||
|
@ -1154,4 +1188,138 @@ class CakeResponse {
|
||||||
$this->_cookies[$options['name']] = $options;
|
$this->_cookies[$options['name']] = $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup for display or download the given file
|
||||||
|
*
|
||||||
|
* @param string $path Path to file
|
||||||
|
* @param array $options Options
|
||||||
|
* ### Options keys
|
||||||
|
* - name: Alternate download name
|
||||||
|
* - download: If `true` sets download header and forces file to be downloaded rather than displayed in browser
|
||||||
|
* @return void
|
||||||
|
* @throws NotFoundException
|
||||||
|
*/
|
||||||
|
public function file($path, $options = array()) {
|
||||||
|
$options += array(
|
||||||
|
'name' => null,
|
||||||
|
'download' => null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!is_file($path)) {
|
||||||
|
$path = APP . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = new File($path);
|
||||||
|
if (!$file->exists() || !$file->readable()) {
|
||||||
|
if (Configure::read('debug')) {
|
||||||
|
throw new NotFoundException(__d('cake_dev', 'The requested file %s was not found or not readable', $path));
|
||||||
|
}
|
||||||
|
throw new NotFoundException(__d('cake', 'The requested file was not found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$extension = strtolower($file->ext());
|
||||||
|
$download = $options['download'];
|
||||||
|
if ((!$extension || $this->type($extension) === false) && is_null($download)) {
|
||||||
|
$download = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileSize = $file->size();
|
||||||
|
if ($download) {
|
||||||
|
$agent = env('HTTP_USER_AGENT');
|
||||||
|
|
||||||
|
if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) {
|
||||||
|
$contentType = 'application/octetstream';
|
||||||
|
} elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) {
|
||||||
|
$contentType = 'application/force-download';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($contentType)) {
|
||||||
|
$this->type($contentType);
|
||||||
|
}
|
||||||
|
if (is_null($options['name'])) {
|
||||||
|
$name = $file->name;
|
||||||
|
} else {
|
||||||
|
$name = $options['name'];
|
||||||
|
}
|
||||||
|
$this->download($name);
|
||||||
|
$this->header('Accept-Ranges', 'bytes');
|
||||||
|
|
||||||
|
$httpRange = env('HTTP_RANGE');
|
||||||
|
if (isset($httpRange)) {
|
||||||
|
list($toss, $range) = explode('=', $httpRange);
|
||||||
|
|
||||||
|
$size = $fileSize - 1;
|
||||||
|
$length = $fileSize - $range;
|
||||||
|
|
||||||
|
$this->header(array(
|
||||||
|
'Content-Length' => $length,
|
||||||
|
'Content-Range' => 'bytes ' . $range . $size . '/' . $fileSize
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->statusCode(206);
|
||||||
|
$file->open('rb', true);
|
||||||
|
$file->offset($range);
|
||||||
|
} else {
|
||||||
|
$this->header('Content-Length', $fileSize);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->header('Content-Length', $fileSize);
|
||||||
|
}
|
||||||
|
$this->_clearBuffer();
|
||||||
|
|
||||||
|
$this->_file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads out a file, and echos the content to the client.
|
||||||
|
*
|
||||||
|
* @param File $file File object
|
||||||
|
* @return boolean True is whole file is echoed successfully or false if client connection is lost in between
|
||||||
|
*/
|
||||||
|
protected function _sendFile($file) {
|
||||||
|
$compress = $this->outputCompressed();
|
||||||
|
$file->open('rb');
|
||||||
|
while (!feof($file->handle)) {
|
||||||
|
if (!$this->_isActive()) {
|
||||||
|
$file->close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
set_time_limit(0);
|
||||||
|
echo fread($file->handle, 8192);
|
||||||
|
if (!$compress) {
|
||||||
|
$this->_flushBuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$file->close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if connection is still active
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function _isActive() {
|
||||||
|
return connection_status() === CONNECTION_NORMAL && !connection_aborted();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the contents of the topmost output buffer and discards them
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function _clearBuffer() {
|
||||||
|
return @ob_end_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the contents of the output buffer
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function _flushBuffer() {
|
||||||
|
@flush();
|
||||||
|
@ob_flush();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,39 @@ class CakeSocket {
|
||||||
*/
|
*/
|
||||||
public $lastError = array();
|
public $lastError = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the socket stream is encrypted after a CakeSocket::enableCrypto() call
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
public $encrypted = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all the encryption methods available
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_encryptMethods = array(
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
|
'sslv2_client' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT,
|
||||||
|
'sslv3_client' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
|
||||||
|
'sslv23_client' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
|
||||||
|
'tls_client' => STREAM_CRYPTO_METHOD_TLS_CLIENT,
|
||||||
|
'sslv2_server' => STREAM_CRYPTO_METHOD_SSLv2_SERVER,
|
||||||
|
'sslv3_server' => STREAM_CRYPTO_METHOD_SSLv3_SERVER,
|
||||||
|
'sslv23_server' => STREAM_CRYPTO_METHOD_SSLv23_SERVER,
|
||||||
|
'tls_server' => STREAM_CRYPTO_METHOD_TLS_SERVER
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to capture connection warnings which can happen when there are
|
||||||
|
* SSL errors for example.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_connectionErrors = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
@ -96,26 +129,47 @@ class CakeSocket {
|
||||||
* @throws SocketException
|
* @throws SocketException
|
||||||
*/
|
*/
|
||||||
public function connect() {
|
public function connect() {
|
||||||
if ($this->connection != null) {
|
if ($this->connection) {
|
||||||
$this->disconnect();
|
$this->disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scheme = null;
|
$scheme = null;
|
||||||
if (isset($this->config['request']) && $this->config['request']['uri']['scheme'] == 'https') {
|
if (isset($this->config['request']['uri']) && $this->config['request']['uri']['scheme'] == 'https') {
|
||||||
$scheme = 'ssl://';
|
$scheme = 'ssl://';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->config['persistent'] == true) {
|
if (!empty($this->config['context'])) {
|
||||||
$this->connection = @pfsockopen($scheme . $this->config['host'], $this->config['port'], $errNum, $errStr, $this->config['timeout']);
|
$context = stream_context_create($this->config['context']);
|
||||||
} else {
|
} else {
|
||||||
$this->connection = @fsockopen($scheme . $this->config['host'], $this->config['port'], $errNum, $errStr, $this->config['timeout']);
|
$context = stream_context_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$connectAs = STREAM_CLIENT_CONNECT;
|
||||||
|
if ($this->config['persistent']) {
|
||||||
|
$connectAs |= STREAM_CLIENT_PERSISTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_error_handler(array($this, '_connectionErrorHandler'));
|
||||||
|
$this->connection = stream_socket_client(
|
||||||
|
$scheme . $this->config['host'] . ':' . $this->config['port'],
|
||||||
|
$errNum,
|
||||||
|
$errStr,
|
||||||
|
$this->config['timeout'],
|
||||||
|
$connectAs,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
if (!empty($errNum) || !empty($errStr)) {
|
if (!empty($errNum) || !empty($errStr)) {
|
||||||
$this->setLastError($errNum, $errStr);
|
$this->setLastError($errNum, $errStr);
|
||||||
throw new SocketException($errStr, $errNum);
|
throw new SocketException($errStr, $errNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->connection && $this->_connectionErrors) {
|
||||||
|
$message = implode("\n", $this->_connectionErrors);
|
||||||
|
throw new SocketException($message, E_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
$this->connected = is_resource($this->connection);
|
$this->connected = is_resource($this->connection);
|
||||||
if ($this->connected) {
|
if ($this->connected) {
|
||||||
stream_set_timeout($this->connection, $this->config['timeout']);
|
stream_set_timeout($this->connection, $this->config['timeout']);
|
||||||
|
@ -123,6 +177,31 @@ class CakeSocket {
|
||||||
return $this->connected;
|
return $this->connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* socket_stream_client() does not populate errNum, or $errStr when there are
|
||||||
|
* connection errors, as in the case of SSL verification failure.
|
||||||
|
*
|
||||||
|
* Instead we need to handle those errors manually.
|
||||||
|
*
|
||||||
|
* @param int $code
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
protected function _connectionErrorHandler($code, $message) {
|
||||||
|
$this->_connectionErrors[] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the connection context.
|
||||||
|
*
|
||||||
|
* @return null|array Null when there is no connnection, an array when there is.
|
||||||
|
*/
|
||||||
|
public function context() {
|
||||||
|
if (!$this->connection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return stream_context_get_options($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the host name of the current connection.
|
* Get the host name of the current connection.
|
||||||
*
|
*
|
||||||
|
@ -277,4 +356,36 @@ class CakeSocket {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts current stream socket, using one of the defined encryption methods
|
||||||
|
*
|
||||||
|
* @param string $type can be one of 'ssl2', 'ssl3', 'ssl23' or 'tls'
|
||||||
|
* @param string $clientOrServer can be one of 'client', 'server'. Default is 'client'
|
||||||
|
* @param boolean $enable enable or disable encryption. Default is true (enable)
|
||||||
|
* @return boolean True on success
|
||||||
|
* @throws InvalidArgumentException When an invalid encryption scheme is chosen.
|
||||||
|
* @throws SocketException When attempting to enable SSL/TLS fails
|
||||||
|
* @see stream_socket_enable_crypto
|
||||||
|
*/
|
||||||
|
public function enableCrypto($type, $clientOrServer = 'client', $enable = true) {
|
||||||
|
if (!array_key_exists($type . '_' . $clientOrServer, $this->_encryptMethods)) {
|
||||||
|
throw new InvalidArgumentException(__d('cake_dev', 'Invalid encryption scheme chosen'));
|
||||||
|
}
|
||||||
|
$enableCryptoResult = false;
|
||||||
|
try {
|
||||||
|
$enableCryptoResult = stream_socket_enable_crypto($this->connection, $enable, $this->_encryptMethods[$type . '_' . $clientOrServer]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->setLastError(null, $e->getMessage());
|
||||||
|
throw new SocketException($e->getMessage());
|
||||||
|
}
|
||||||
|
if ($enableCryptoResult === true) {
|
||||||
|
$this->encrypted = $enable;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$errorMessage = __d('cake_dev', 'Unable to perform enableCrypto operation on CakeSocket');
|
||||||
|
$this->setLastError(null, $errorMessage);
|
||||||
|
throw new SocketException($errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -946,13 +946,17 @@ class CakeEmail {
|
||||||
* $email->attachments(array('custom_name.png' => array(
|
* $email->attachments(array('custom_name.png' => array(
|
||||||
* 'file' => 'path/to/file',
|
* 'file' => 'path/to/file',
|
||||||
* 'mimetype' => 'image/png',
|
* 'mimetype' => 'image/png',
|
||||||
* 'contentId' => 'abc123'
|
* 'contentId' => 'abc123',
|
||||||
|
* 'contentDisposition' => false
|
||||||
* ));
|
* ));
|
||||||
* }}}
|
* }}}
|
||||||
*
|
*
|
||||||
* The `contentId` key allows you to specify an inline attachment. In your email text, you
|
* The `contentId` key allows you to specify an inline attachment. In your email text, you
|
||||||
* can use `<img src="cid:abc123" />` to display the image inline.
|
* can use `<img src="cid:abc123" />` to display the image inline.
|
||||||
*
|
*
|
||||||
|
* The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve
|
||||||
|
* attachment compatibility with outlook email clients.
|
||||||
|
*
|
||||||
* @param string|array $attachments String with the filename or array with filenames
|
* @param string|array $attachments String with the filename or array with filenames
|
||||||
* @return array|CakeEmail Either the array of attachments when getting or $this when setting.
|
* @return array|CakeEmail Either the array of attachments when getting or $this when setting.
|
||||||
* @throws SocketException
|
* @throws SocketException
|
||||||
|
@ -991,6 +995,7 @@ class CakeEmail {
|
||||||
* @param string|array $attachments String with the filename or array with filenames
|
* @param string|array $attachments String with the filename or array with filenames
|
||||||
* @return CakeEmail $this
|
* @return CakeEmail $this
|
||||||
* @throws SocketException
|
* @throws SocketException
|
||||||
|
* @see CakeEmail::attachments()
|
||||||
*/
|
*/
|
||||||
public function addAttachments($attachments) {
|
public function addAttachments($attachments) {
|
||||||
$current = $this->_attachments;
|
$current = $this->_attachments;
|
||||||
|
@ -1355,7 +1360,12 @@ class CakeEmail {
|
||||||
$msg[] = '--' . $boundary;
|
$msg[] = '--' . $boundary;
|
||||||
$msg[] = 'Content-Type: ' . $fileInfo['mimetype'];
|
$msg[] = 'Content-Type: ' . $fileInfo['mimetype'];
|
||||||
$msg[] = 'Content-Transfer-Encoding: base64';
|
$msg[] = 'Content-Transfer-Encoding: base64';
|
||||||
|
if (
|
||||||
|
!isset($fileInfo['contentDisposition']) ||
|
||||||
|
$fileInfo['contentDisposition']
|
||||||
|
) {
|
||||||
$msg[] = 'Content-Disposition: attachment; filename="' . $filename . '"';
|
$msg[] = 'Content-Disposition: attachment; filename="' . $filename . '"';
|
||||||
|
}
|
||||||
$msg[] = '';
|
$msg[] = '';
|
||||||
$msg[] = $data;
|
$msg[] = $data;
|
||||||
$msg[] = '';
|
$msg[] = '';
|
||||||
|
|
|
@ -79,7 +79,8 @@ class SmtpTransport extends AbstractTransport {
|
||||||
'timeout' => 30,
|
'timeout' => 30,
|
||||||
'username' => null,
|
'username' => null,
|
||||||
'password' => null,
|
'password' => null,
|
||||||
'client' => null
|
'client' => null,
|
||||||
|
'tls' => false
|
||||||
);
|
);
|
||||||
$this->_config = $config + $default;
|
$this->_config = $config + $default;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +108,15 @@ class SmtpTransport extends AbstractTransport {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->_smtpSend("EHLO {$host}", '250');
|
$this->_smtpSend("EHLO {$host}", '250');
|
||||||
|
if ($this->_config['tls']) {
|
||||||
|
$this->_smtpSend("STARTTLS", '220');
|
||||||
|
$this->_socket->enableCrypto('tls');
|
||||||
|
$this->_smtpSend("EHLO {$host}", '250');
|
||||||
|
}
|
||||||
} catch (SocketException $e) {
|
} catch (SocketException $e) {
|
||||||
|
if ($this->_config['tls']) {
|
||||||
|
throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.'));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
$this->_smtpSend("HELO {$host}", '250');
|
$this->_smtpSend("HELO {$host}", '250');
|
||||||
} catch (SocketException $e2) {
|
} catch (SocketException $e2) {
|
||||||
|
@ -132,6 +141,8 @@ class SmtpTransport extends AbstractTransport {
|
||||||
if (!$this->_smtpSend(base64_encode($this->_config['password']), '235')) {
|
if (!$this->_smtpSend(base64_encode($this->_config['password']), '235')) {
|
||||||
throw new SocketException(__d('cake_dev', 'SMTP server did not accept the password.'));
|
throw new SocketException(__d('cake_dev', 'SMTP server did not accept the password.'));
|
||||||
}
|
}
|
||||||
|
} elseif ($authRequired == '504') {
|
||||||
|
throw new SocketException(__d('cake_dev', 'SMTP authentication method not allowed, check if SMTP server requires TLS'));
|
||||||
} elseif ($authRequired != '503') {
|
} elseif ($authRequired != '503') {
|
||||||
throw new SocketException(__d('cake_dev', 'SMTP does not require authentication.'));
|
throw new SocketException(__d('cake_dev', 'SMTP does not require authentication.'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,437 +12,24 @@
|
||||||
*
|
*
|
||||||
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
* @link http://cakephp.org CakePHP(tm) Project
|
* @link http://cakephp.org CakePHP(tm) Project
|
||||||
* @package Cake.Network.Http
|
|
||||||
* @since CakePHP(tm) v 2.0.0
|
* @since CakePHP(tm) v 2.0.0
|
||||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
*/
|
*/
|
||||||
|
App::uses('HttpSocketResponse', 'Network/Http');
|
||||||
|
|
||||||
|
if (class_exists('HttpResponse')) {
|
||||||
|
trigger_error(__d(
|
||||||
|
'cake_dev',
|
||||||
|
"HttpResponse is deprecated due to naming conflicts. Use HttpSocketResponse instead."
|
||||||
|
), E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP Response from HttpSocket.
|
* HTTP Response from HttpSocket.
|
||||||
*
|
*
|
||||||
* @package Cake.Network.Http
|
* @package Cake.Network.Http
|
||||||
|
* @deprecated This class is deprecated as it has naming conflicts with pecl/http
|
||||||
*/
|
*/
|
||||||
class HttpResponse implements ArrayAccess {
|
class HttpResponse extends HttpSocketResponse {
|
||||||
|
|
||||||
/**
|
|
||||||
* Body content
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $body = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Headers
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $headers = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cookies
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $cookies = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP version
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $httpVersion = 'HTTP/1.1';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response code
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
public $code = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reason phrase
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $reasonPhrase = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pure raw content
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $raw = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param string $message
|
|
||||||
*/
|
|
||||||
public function __construct($message = null) {
|
|
||||||
if ($message !== null) {
|
|
||||||
$this->parseResponse($message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Body content
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function body() {
|
|
||||||
return (string)$this->body;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get header in case insensitive
|
|
||||||
*
|
|
||||||
* @param string $name Header name
|
|
||||||
* @param array $headers
|
|
||||||
* @return mixed String if header exists or null
|
|
||||||
*/
|
|
||||||
public function getHeader($name, $headers = null) {
|
|
||||||
if (!is_array($headers)) {
|
|
||||||
$headers =& $this->headers;
|
|
||||||
}
|
|
||||||
if (isset($headers[$name])) {
|
|
||||||
return $headers[$name];
|
|
||||||
}
|
|
||||||
foreach ($headers as $key => $value) {
|
|
||||||
if (strcasecmp($key, $name) == 0) {
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If return is 200 (OK)
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function isOk() {
|
|
||||||
return $this->code == 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If return is a valid 3xx (Redirection)
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function isRedirect() {
|
|
||||||
return in_array($this->code, array(301, 302, 303, 307)) && !is_null($this->getHeader('Location'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the given message and breaks it down in parts.
|
|
||||||
*
|
|
||||||
* @param string $message Message to parse
|
|
||||||
* @return void
|
|
||||||
* @throws SocketException
|
|
||||||
*/
|
|
||||||
public function parseResponse($message) {
|
|
||||||
if (!is_string($message)) {
|
|
||||||
throw new SocketException(__d('cake_dev', 'Invalid response.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) {
|
|
||||||
throw new SocketException(__d('cake_dev', 'Invalid HTTP response.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
list(, $statusLine, $header) = $match;
|
|
||||||
$this->raw = $message;
|
|
||||||
$this->body = (string)substr($message, strlen($match[0]));
|
|
||||||
|
|
||||||
if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) {
|
|
||||||
$this->httpVersion = $match[1];
|
|
||||||
$this->code = $match[2];
|
|
||||||
$this->reasonPhrase = $match[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->headers = $this->_parseHeader($header);
|
|
||||||
$transferEncoding = $this->getHeader('Transfer-Encoding');
|
|
||||||
$decoded = $this->_decodeBody($this->body, $transferEncoding);
|
|
||||||
$this->body = $decoded['body'];
|
|
||||||
|
|
||||||
if (!empty($decoded['header'])) {
|
|
||||||
$this->headers = $this->_parseHeader($this->_buildHeader($this->headers) . $this->_buildHeader($decoded['header']));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($this->headers)) {
|
|
||||||
$this->cookies = $this->parseCookies($this->headers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic function to decode a $body with a given $encoding. Returns either an array with the keys
|
|
||||||
* 'body' and 'header' or false on failure.
|
|
||||||
*
|
|
||||||
* @param string $body A string containing the body to decode.
|
|
||||||
* @param string|boolean $encoding Can be false in case no encoding is being used, or a string representing the encoding.
|
|
||||||
* @return mixed Array of response headers and body or false.
|
|
||||||
*/
|
|
||||||
protected function _decodeBody($body, $encoding = 'chunked') {
|
|
||||||
if (!is_string($body)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (empty($encoding)) {
|
|
||||||
return array('body' => $body, 'header' => false);
|
|
||||||
}
|
|
||||||
$decodeMethod = '_decode' . Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body';
|
|
||||||
|
|
||||||
if (!is_callable(array(&$this, $decodeMethod))) {
|
|
||||||
return array('body' => $body, 'header' => false);
|
|
||||||
}
|
|
||||||
return $this->{$decodeMethod}($body);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as
|
|
||||||
* a result.
|
|
||||||
*
|
|
||||||
* @param string $body A string containing the chunked body to decode.
|
|
||||||
* @return mixed Array of response headers and body or false.
|
|
||||||
* @throws SocketException
|
|
||||||
*/
|
|
||||||
protected function _decodeChunkedBody($body) {
|
|
||||||
if (!is_string($body)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$decodedBody = null;
|
|
||||||
$chunkLength = null;
|
|
||||||
|
|
||||||
while ($chunkLength !== 0) {
|
|
||||||
if (!preg_match('/^([0-9a-f]+) *(?:;(.+)=(.+))?(?:\r\n|\n)/iU', $body, $match)) {
|
|
||||||
throw new SocketException(__d('cake_dev', 'HttpSocket::_decodeChunkedBody - Could not parse malformed chunk.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$chunkSize = 0;
|
|
||||||
$hexLength = 0;
|
|
||||||
$chunkExtensionName = '';
|
|
||||||
$chunkExtensionValue = '';
|
|
||||||
if (isset($match[0])) {
|
|
||||||
$chunkSize = $match[0];
|
|
||||||
}
|
|
||||||
if (isset($match[1])) {
|
|
||||||
$hexLength = $match[1];
|
|
||||||
}
|
|
||||||
if (isset($match[2])) {
|
|
||||||
$chunkExtensionName = $match[2];
|
|
||||||
}
|
|
||||||
if (isset($match[3])) {
|
|
||||||
$chunkExtensionValue = $match[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = substr($body, strlen($chunkSize));
|
|
||||||
$chunkLength = hexdec($hexLength);
|
|
||||||
$chunk = substr($body, 0, $chunkLength);
|
|
||||||
if (!empty($chunkExtensionName)) {
|
|
||||||
// @todo See if there are popular chunk extensions we should implement
|
|
||||||
}
|
|
||||||
$decodedBody .= $chunk;
|
|
||||||
if ($chunkLength !== 0) {
|
|
||||||
$body = substr($body, $chunkLength + strlen("\r\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$entityHeader = false;
|
|
||||||
if (!empty($body)) {
|
|
||||||
$entityHeader = $this->_parseHeader($body);
|
|
||||||
}
|
|
||||||
return array('body' => $decodedBody, 'header' => $entityHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses an array based header.
|
|
||||||
*
|
|
||||||
* @param array $header Header as an indexed array (field => value)
|
|
||||||
* @return array Parsed header
|
|
||||||
*/
|
|
||||||
protected function _parseHeader($header) {
|
|
||||||
if (is_array($header)) {
|
|
||||||
return $header;
|
|
||||||
} elseif (!is_string($header)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
preg_match_all("/(.+):(.+)(?:(?<![\t ])\r\n|\$)/Uis", $header, $matches, PREG_SET_ORDER);
|
|
||||||
|
|
||||||
$header = array();
|
|
||||||
foreach ($matches as $match) {
|
|
||||||
list(, $field, $value) = $match;
|
|
||||||
|
|
||||||
$value = trim($value);
|
|
||||||
$value = preg_replace("/[\t ]\r\n/", "\r\n", $value);
|
|
||||||
|
|
||||||
$field = $this->_unescapeToken($field);
|
|
||||||
|
|
||||||
if (!isset($header[$field])) {
|
|
||||||
$header[$field] = $value;
|
|
||||||
} else {
|
|
||||||
$header[$field] = array_merge((array)$header[$field], (array)$value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $header;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses cookies in response headers.
|
|
||||||
*
|
|
||||||
* @param array $header Header array containing one ore more 'Set-Cookie' headers.
|
|
||||||
* @return mixed Either false on no cookies, or an array of cookies received.
|
|
||||||
* @todo Make this 100% RFC 2965 confirm
|
|
||||||
*/
|
|
||||||
public function parseCookies($header) {
|
|
||||||
$cookieHeader = $this->getHeader('Set-Cookie', $header);
|
|
||||||
if (!$cookieHeader) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$cookies = array();
|
|
||||||
foreach ((array)$cookieHeader as $cookie) {
|
|
||||||
if (strpos($cookie, '";"') !== false) {
|
|
||||||
$cookie = str_replace('";"', "{__cookie_replace__}", $cookie);
|
|
||||||
$parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie));
|
|
||||||
} else {
|
|
||||||
$parts = preg_split('/\;[ \t]*/', $cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
list($name, $value) = explode('=', array_shift($parts), 2);
|
|
||||||
$cookies[$name] = compact('value');
|
|
||||||
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if (strpos($part, '=') !== false) {
|
|
||||||
list($key, $value) = explode('=', $part);
|
|
||||||
} else {
|
|
||||||
$key = $part;
|
|
||||||
$value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$key = strtolower($key);
|
|
||||||
if (!isset($cookies[$name][$key])) {
|
|
||||||
$cookies[$name][$key] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs)
|
|
||||||
*
|
|
||||||
* @param string $token Token to unescape
|
|
||||||
* @param array $chars
|
|
||||||
* @return string Unescaped token
|
|
||||||
* @todo Test $chars parameter
|
|
||||||
*/
|
|
||||||
protected function _unescapeToken($token, $chars = null) {
|
|
||||||
$regex = '/"([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])"/';
|
|
||||||
$token = preg_replace($regex, '\\1', $token);
|
|
||||||
return $token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets escape chars according to RFC 2616 (HTTP 1.1 specs).
|
|
||||||
*
|
|
||||||
* @param boolean $hex true to get them as HEX values, false otherwise
|
|
||||||
* @param array $chars
|
|
||||||
* @return array Escape chars
|
|
||||||
* @todo Test $chars parameter
|
|
||||||
*/
|
|
||||||
protected function _tokenEscapeChars($hex = true, $chars = null) {
|
|
||||||
if (!empty($chars)) {
|
|
||||||
$escape = $chars;
|
|
||||||
} else {
|
|
||||||
$escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
|
|
||||||
for ($i = 0; $i <= 31; $i++) {
|
|
||||||
$escape[] = chr($i);
|
|
||||||
}
|
|
||||||
$escape[] = chr(127);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($hex == false) {
|
|
||||||
return $escape;
|
|
||||||
}
|
|
||||||
foreach ($escape as $key => $char) {
|
|
||||||
$escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
|
|
||||||
}
|
|
||||||
return $escape;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ArrayAccess - Offset Exists
|
|
||||||
*
|
|
||||||
* @param string $offset
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function offsetExists($offset) {
|
|
||||||
return in_array($offset, array('raw', 'status', 'header', 'body', 'cookies'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ArrayAccess - Offset Get
|
|
||||||
*
|
|
||||||
* @param string $offset
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function offsetGet($offset) {
|
|
||||||
switch ($offset) {
|
|
||||||
case 'raw':
|
|
||||||
$firstLineLength = strpos($this->raw, "\r\n") + 2;
|
|
||||||
if ($this->raw[$firstLineLength] === "\r") {
|
|
||||||
$header = null;
|
|
||||||
} else {
|
|
||||||
$header = substr($this->raw, $firstLineLength, strpos($this->raw, "\r\n\r\n") - $firstLineLength) . "\r\n";
|
|
||||||
}
|
|
||||||
return array(
|
|
||||||
'status-line' => $this->httpVersion . ' ' . $this->code . ' ' . $this->reasonPhrase . "\r\n",
|
|
||||||
'header' => $header,
|
|
||||||
'body' => $this->body,
|
|
||||||
'response' => $this->raw
|
|
||||||
);
|
|
||||||
case 'status':
|
|
||||||
return array(
|
|
||||||
'http-version' => $this->httpVersion,
|
|
||||||
'code' => $this->code,
|
|
||||||
'reason-phrase' => $this->reasonPhrase
|
|
||||||
);
|
|
||||||
case 'header':
|
|
||||||
return $this->headers;
|
|
||||||
case 'body':
|
|
||||||
return $this->body;
|
|
||||||
case 'cookies':
|
|
||||||
return $this->cookies;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ArrayAccess - Offset Set
|
|
||||||
*
|
|
||||||
* @param string $offset
|
|
||||||
* @param mixed $value
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function offsetSet($offset, $value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ArrayAccess - Offset Unset
|
|
||||||
*
|
|
||||||
* @param string $offset
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function offsetUnset($offset) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance as string
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function __toString() {
|
|
||||||
return $this->body();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
App::uses('CakeSocket', 'Network');
|
App::uses('CakeSocket', 'Network');
|
||||||
App::uses('Router', 'Routing');
|
App::uses('Router', 'Routing');
|
||||||
|
App::uses('Hash', 'Utility');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cake network socket connection class.
|
* Cake network socket connection class.
|
||||||
|
@ -64,7 +65,7 @@ class HttpSocket extends CakeSocket {
|
||||||
),
|
),
|
||||||
'raw' => null,
|
'raw' => null,
|
||||||
'redirect' => false,
|
'redirect' => false,
|
||||||
'cookies' => array()
|
'cookies' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +80,7 @@ class HttpSocket extends CakeSocket {
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $responseClass = 'HttpResponse';
|
public $responseClass = 'HttpSocketResponse';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration settings for the HttpSocket and the requests
|
* Configuration settings for the HttpSocket and the requests
|
||||||
|
@ -92,6 +93,9 @@ class HttpSocket extends CakeSocket {
|
||||||
'protocol' => 'tcp',
|
'protocol' => 'tcp',
|
||||||
'port' => 80,
|
'port' => 80,
|
||||||
'timeout' => 30,
|
'timeout' => 30,
|
||||||
|
'ssl_verify_peer' => true,
|
||||||
|
'ssl_verify_depth' => 5,
|
||||||
|
'ssl_verify_host' => true,
|
||||||
'request' => array(
|
'request' => array(
|
||||||
'uri' => array(
|
'uri' => array(
|
||||||
'scheme' => array('http', 'https'),
|
'scheme' => array('http', 'https'),
|
||||||
|
@ -99,7 +103,7 @@ class HttpSocket extends CakeSocket {
|
||||||
'port' => array(80, 443)
|
'port' => array(80, 443)
|
||||||
),
|
),
|
||||||
'redirect' => false,
|
'redirect' => false,
|
||||||
'cookies' => array()
|
'cookies' => array(),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -246,7 +250,7 @@ class HttpSocket extends CakeSocket {
|
||||||
* method and provide a more granular interface.
|
* method and provide a more granular interface.
|
||||||
*
|
*
|
||||||
* @param string|array $request Either an URI string, or an array defining host/uri
|
* @param string|array $request Either an URI string, or an array defining host/uri
|
||||||
* @return mixed false on error, HttpResponse on success
|
* @return mixed false on error, HttpSocketResponse on success
|
||||||
* @throws SocketException
|
* @throws SocketException
|
||||||
*/
|
*/
|
||||||
public function request($request = array()) {
|
public function request($request = array()) {
|
||||||
|
@ -348,6 +352,8 @@ class HttpSocket extends CakeSocket {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->_configContext($this->request['uri']['host']);
|
||||||
|
|
||||||
$this->request['raw'] = '';
|
$this->request['raw'] = '';
|
||||||
if ($this->request['line'] !== false) {
|
if ($this->request['line'] !== false) {
|
||||||
$this->request['raw'] = $this->request['line'];
|
$this->request['raw'] = $this->request['line'];
|
||||||
|
@ -395,6 +401,7 @@ class HttpSocket extends CakeSocket {
|
||||||
throw new SocketException(__d('cake_dev', 'Class %s not found.', $this->responseClass));
|
throw new SocketException(__d('cake_dev', 'Class %s not found.', $this->responseClass));
|
||||||
}
|
}
|
||||||
$this->response = new $responseClass($response);
|
$this->response = new $responseClass($response);
|
||||||
|
|
||||||
if (!empty($this->response->cookies)) {
|
if (!empty($this->response->cookies)) {
|
||||||
if (!isset($this->config['request']['cookies'][$Host])) {
|
if (!isset($this->config['request']['cookies'][$Host])) {
|
||||||
$this->config['request']['cookies'][$Host] = array();
|
$this->config['request']['cookies'][$Host] = array();
|
||||||
|
@ -643,6 +650,33 @@ class HttpSocket extends CakeSocket {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the socket's context. Adds in configuration
|
||||||
|
* that can not be declared in the class definition.
|
||||||
|
*
|
||||||
|
* @param string $host The host you're connecting to.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function _configContext($host) {
|
||||||
|
foreach ($this->config as $key => $value) {
|
||||||
|
if (substr($key, 0, 4) !== 'ssl_') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$contextKey = substr($key, 4);
|
||||||
|
if (empty($this->config['context']['ssl'][$contextKey])) {
|
||||||
|
$this->config['context']['ssl'][$contextKey] = $value;
|
||||||
|
}
|
||||||
|
unset($this->config[$key]);
|
||||||
|
}
|
||||||
|
if (empty($this->_context['ssl']['cafile'])) {
|
||||||
|
$this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem';
|
||||||
|
}
|
||||||
|
if (!empty($this->config['context']['ssl']['verify_host'])) {
|
||||||
|
$this->config['context']['ssl']['CN_match'] = $host;
|
||||||
|
unset($this->config['context']['ssl']['verify_host']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a $uri array and turns it into a fully qualified URL string
|
* Takes a $uri array and turns it into a fully qualified URL string
|
||||||
*
|
*
|
||||||
|
@ -944,7 +978,7 @@ class HttpSocket extends CakeSocket {
|
||||||
$escape[] = chr(127);
|
$escape[] = chr(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hex == false) {
|
if (!$hex) {
|
||||||
return $escape;
|
return $escape;
|
||||||
}
|
}
|
||||||
foreach ($escape as $key => $char) {
|
foreach ($escape as $key => $char) {
|
||||||
|
|
455
lib/Cake/Network/Http/HttpSocketResponse.php
Normal file
455
lib/Cake/Network/Http/HttpSocketResponse.php
Normal file
|
@ -0,0 +1,455 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* HTTP Response from HttpSocket.
|
||||||
|
*
|
||||||
|
* PHP 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||||||
|
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||||||
|
* @link http://cakephp.org CakePHP(tm) Project
|
||||||
|
* @since CakePHP(tm) v 2.0.0
|
||||||
|
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP Response from HttpSocket.
|
||||||
|
*
|
||||||
|
* @package Cake.Network.Http
|
||||||
|
*/
|
||||||
|
class HttpSocketResponse implements ArrayAccess {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Body content
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $body = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Headers
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $headers = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cookies
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $cookies = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP version
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $httpVersion = 'HTTP/1.1';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response code
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public $code = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reason phrase
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $reasonPhrase = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pure raw content
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $raw = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context data in the response.
|
||||||
|
* Contains SSL certificates for example.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $context = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
public function __construct($message = null) {
|
||||||
|
if ($message !== null) {
|
||||||
|
$this->parseResponse($message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Body content
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function body() {
|
||||||
|
return (string)$this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get header in case insensitive
|
||||||
|
*
|
||||||
|
* @param string $name Header name
|
||||||
|
* @param array $headers
|
||||||
|
* @return mixed String if header exists or null
|
||||||
|
*/
|
||||||
|
public function getHeader($name, $headers = null) {
|
||||||
|
if (!is_array($headers)) {
|
||||||
|
$headers =& $this->headers;
|
||||||
|
}
|
||||||
|
if (isset($headers[$name])) {
|
||||||
|
return $headers[$name];
|
||||||
|
}
|
||||||
|
foreach ($headers as $key => $value) {
|
||||||
|
if (strcasecmp($key, $name) === 0) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If return is 200 (OK)
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isOk() {
|
||||||
|
return $this->code == 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If return is a valid 3xx (Redirection)
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isRedirect() {
|
||||||
|
return in_array($this->code, array(301, 302, 303, 307)) && !is_null($this->getHeader('Location'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given message and breaks it down in parts.
|
||||||
|
*
|
||||||
|
* @param string $message Message to parse
|
||||||
|
* @return void
|
||||||
|
* @throws SocketException
|
||||||
|
*/
|
||||||
|
public function parseResponse($message) {
|
||||||
|
if (!is_string($message)) {
|
||||||
|
throw new SocketException(__d('cake_dev', 'Invalid response.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) {
|
||||||
|
throw new SocketException(__d('cake_dev', 'Invalid HTTP response.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
list(, $statusLine, $header) = $match;
|
||||||
|
$this->raw = $message;
|
||||||
|
$this->body = (string)substr($message, strlen($match[0]));
|
||||||
|
|
||||||
|
if (preg_match("/(.+) ([0-9]{3}) (.+)\r\n/DU", $statusLine, $match)) {
|
||||||
|
$this->httpVersion = $match[1];
|
||||||
|
$this->code = $match[2];
|
||||||
|
$this->reasonPhrase = $match[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->headers = $this->_parseHeader($header);
|
||||||
|
$transferEncoding = $this->getHeader('Transfer-Encoding');
|
||||||
|
$decoded = $this->_decodeBody($this->body, $transferEncoding);
|
||||||
|
$this->body = $decoded['body'];
|
||||||
|
|
||||||
|
if (!empty($decoded['header'])) {
|
||||||
|
$this->headers = $this->_parseHeader($this->_buildHeader($this->headers) . $this->_buildHeader($decoded['header']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($this->headers)) {
|
||||||
|
$this->cookies = $this->parseCookies($this->headers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic function to decode a $body with a given $encoding. Returns either an array with the keys
|
||||||
|
* 'body' and 'header' or false on failure.
|
||||||
|
*
|
||||||
|
* @param string $body A string containing the body to decode.
|
||||||
|
* @param string|boolean $encoding Can be false in case no encoding is being used, or a string representing the encoding.
|
||||||
|
* @return mixed Array of response headers and body or false.
|
||||||
|
*/
|
||||||
|
protected function _decodeBody($body, $encoding = 'chunked') {
|
||||||
|
if (!is_string($body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (empty($encoding)) {
|
||||||
|
return array('body' => $body, 'header' => false);
|
||||||
|
}
|
||||||
|
$decodeMethod = '_decode' . Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body';
|
||||||
|
|
||||||
|
if (!is_callable(array(&$this, $decodeMethod))) {
|
||||||
|
return array('body' => $body, 'header' => false);
|
||||||
|
}
|
||||||
|
return $this->{$decodeMethod}($body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as
|
||||||
|
* a result.
|
||||||
|
*
|
||||||
|
* @param string $body A string containing the chunked body to decode.
|
||||||
|
* @return mixed Array of response headers and body or false.
|
||||||
|
* @throws SocketException
|
||||||
|
*/
|
||||||
|
protected function _decodeChunkedBody($body) {
|
||||||
|
if (!is_string($body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$decodedBody = null;
|
||||||
|
$chunkLength = null;
|
||||||
|
|
||||||
|
while ($chunkLength !== 0) {
|
||||||
|
if (!preg_match('/^([0-9a-f]+) *(?:;(.+)=(.+))?(?:\r\n|\n)/iU', $body, $match)) {
|
||||||
|
throw new SocketException(__d('cake_dev', 'HttpSocket::_decodeChunkedBody - Could not parse malformed chunk.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$chunkSize = 0;
|
||||||
|
$hexLength = 0;
|
||||||
|
$chunkExtensionName = '';
|
||||||
|
$chunkExtensionValue = '';
|
||||||
|
if (isset($match[0])) {
|
||||||
|
$chunkSize = $match[0];
|
||||||
|
}
|
||||||
|
if (isset($match[1])) {
|
||||||
|
$hexLength = $match[1];
|
||||||
|
}
|
||||||
|
if (isset($match[2])) {
|
||||||
|
$chunkExtensionName = $match[2];
|
||||||
|
}
|
||||||
|
if (isset($match[3])) {
|
||||||
|
$chunkExtensionValue = $match[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = substr($body, strlen($chunkSize));
|
||||||
|
$chunkLength = hexdec($hexLength);
|
||||||
|
$chunk = substr($body, 0, $chunkLength);
|
||||||
|
if (!empty($chunkExtensionName)) {
|
||||||
|
// @todo See if there are popular chunk extensions we should implement
|
||||||
|
}
|
||||||
|
$decodedBody .= $chunk;
|
||||||
|
if ($chunkLength !== 0) {
|
||||||
|
$body = substr($body, $chunkLength + strlen("\r\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityHeader = false;
|
||||||
|
if (!empty($body)) {
|
||||||
|
$entityHeader = $this->_parseHeader($body);
|
||||||
|
}
|
||||||
|
return array('body' => $decodedBody, 'header' => $entityHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an array based header.
|
||||||
|
*
|
||||||
|
* @param array $header Header as an indexed array (field => value)
|
||||||
|
* @return array Parsed header
|
||||||
|
*/
|
||||||
|
protected function _parseHeader($header) {
|
||||||
|
if (is_array($header)) {
|
||||||
|
return $header;
|
||||||
|
} elseif (!is_string($header)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match_all("/(.+):(.+)(?:(?<![\t ])\r\n|\$)/Uis", $header, $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
|
$header = array();
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
list(, $field, $value) = $match;
|
||||||
|
|
||||||
|
$value = trim($value);
|
||||||
|
$value = preg_replace("/[\t ]\r\n/", "\r\n", $value);
|
||||||
|
|
||||||
|
$field = $this->_unescapeToken($field);
|
||||||
|
|
||||||
|
if (!isset($header[$field])) {
|
||||||
|
$header[$field] = $value;
|
||||||
|
} else {
|
||||||
|
$header[$field] = array_merge((array)$header[$field], (array)$value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses cookies in response headers.
|
||||||
|
*
|
||||||
|
* @param array $header Header array containing one ore more 'Set-Cookie' headers.
|
||||||
|
* @return mixed Either false on no cookies, or an array of cookies received.
|
||||||
|
* @todo Make this 100% RFC 2965 confirm
|
||||||
|
*/
|
||||||
|
public function parseCookies($header) {
|
||||||
|
$cookieHeader = $this->getHeader('Set-Cookie', $header);
|
||||||
|
if (!$cookieHeader) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cookies = array();
|
||||||
|
foreach ((array)$cookieHeader as $cookie) {
|
||||||
|
if (strpos($cookie, '";"') !== false) {
|
||||||
|
$cookie = str_replace('";"', "{__cookie_replace__}", $cookie);
|
||||||
|
$parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie));
|
||||||
|
} else {
|
||||||
|
$parts = preg_split('/\;[ \t]*/', $cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
list($name, $value) = explode('=', array_shift($parts), 2);
|
||||||
|
$cookies[$name] = compact('value');
|
||||||
|
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if (strpos($part, '=') !== false) {
|
||||||
|
list($key, $value) = explode('=', $part);
|
||||||
|
} else {
|
||||||
|
$key = $part;
|
||||||
|
$value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = strtolower($key);
|
||||||
|
if (!isset($cookies[$name][$key])) {
|
||||||
|
$cookies[$name][$key] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $cookies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs)
|
||||||
|
*
|
||||||
|
* @param string $token Token to unescape
|
||||||
|
* @param array $chars
|
||||||
|
* @return string Unescaped token
|
||||||
|
* @todo Test $chars parameter
|
||||||
|
*/
|
||||||
|
protected function _unescapeToken($token, $chars = null) {
|
||||||
|
$regex = '/"([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])"/';
|
||||||
|
$token = preg_replace($regex, '\\1', $token);
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets escape chars according to RFC 2616 (HTTP 1.1 specs).
|
||||||
|
*
|
||||||
|
* @param boolean $hex true to get them as HEX values, false otherwise
|
||||||
|
* @param array $chars
|
||||||
|
* @return array Escape chars
|
||||||
|
* @todo Test $chars parameter
|
||||||
|
*/
|
||||||
|
protected function _tokenEscapeChars($hex = true, $chars = null) {
|
||||||
|
if (!empty($chars)) {
|
||||||
|
$escape = $chars;
|
||||||
|
} else {
|
||||||
|
$escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " ");
|
||||||
|
for ($i = 0; $i <= 31; $i++) {
|
||||||
|
$escape[] = chr($i);
|
||||||
|
}
|
||||||
|
$escape[] = chr(127);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$hex) {
|
||||||
|
return $escape;
|
||||||
|
}
|
||||||
|
foreach ($escape as $key => $char) {
|
||||||
|
$escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
return $escape;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArrayAccess - Offset Exists
|
||||||
|
*
|
||||||
|
* @param string $offset
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function offsetExists($offset) {
|
||||||
|
return in_array($offset, array('raw', 'status', 'header', 'body', 'cookies'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArrayAccess - Offset Get
|
||||||
|
*
|
||||||
|
* @param string $offset
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function offsetGet($offset) {
|
||||||
|
switch ($offset) {
|
||||||
|
case 'raw':
|
||||||
|
$firstLineLength = strpos($this->raw, "\r\n") + 2;
|
||||||
|
if ($this->raw[$firstLineLength] === "\r") {
|
||||||
|
$header = null;
|
||||||
|
} else {
|
||||||
|
$header = substr($this->raw, $firstLineLength, strpos($this->raw, "\r\n\r\n") - $firstLineLength) . "\r\n";
|
||||||
|
}
|
||||||
|
return array(
|
||||||
|
'status-line' => $this->httpVersion . ' ' . $this->code . ' ' . $this->reasonPhrase . "\r\n",
|
||||||
|
'header' => $header,
|
||||||
|
'body' => $this->body,
|
||||||
|
'response' => $this->raw
|
||||||
|
);
|
||||||
|
case 'status':
|
||||||
|
return array(
|
||||||
|
'http-version' => $this->httpVersion,
|
||||||
|
'code' => $this->code,
|
||||||
|
'reason-phrase' => $this->reasonPhrase
|
||||||
|
);
|
||||||
|
case 'header':
|
||||||
|
return $this->headers;
|
||||||
|
case 'body':
|
||||||
|
return $this->body;
|
||||||
|
case 'cookies':
|
||||||
|
return $this->cookies;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArrayAccess - Offset Set
|
||||||
|
*
|
||||||
|
* @param string $offset
|
||||||
|
* @param mixed $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function offsetSet($offset, $value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArrayAccess - Offset Unset
|
||||||
|
*
|
||||||
|
* @param string $offset
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function offsetUnset($offset) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance as string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString() {
|
||||||
|
return $this->body();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -209,12 +209,6 @@ class Dispatcher implements CakeEventListener {
|
||||||
public function parseParams($event) {
|
public function parseParams($event) {
|
||||||
$request = $event->data['request'];
|
$request = $event->data['request'];
|
||||||
Router::setRequestInfo($request);
|
Router::setRequestInfo($request);
|
||||||
if (count(Router::$routes) == 0) {
|
|
||||||
$namedExpressions = Router::getNamedExpressions();
|
|
||||||
extract($namedExpressions);
|
|
||||||
$this->_loadRoutes();
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = Router::parse($request->url);
|
$params = Router::parse($request->url);
|
||||||
$request->addParams($params);
|
$request->addParams($params);
|
||||||
|
|
||||||
|
@ -269,13 +263,4 @@ class Dispatcher implements CakeEventListener {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads route configuration
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function _loadRoutes() {
|
|
||||||
include APP . 'Config' . DS . 'routes.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,6 @@ class AssetDispatcher extends DispatcherFilter {
|
||||||
*/
|
*/
|
||||||
public function beforeDispatch($event) {
|
public function beforeDispatch($event) {
|
||||||
$url = $event->data['request']->url;
|
$url = $event->data['request']->url;
|
||||||
$response = $event->data['response'];
|
|
||||||
|
|
||||||
if (strpos($url, '..') !== false || strpos($url, '.') === false) {
|
if (strpos($url, '..') !== false || strpos($url, '.') === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -53,43 +51,27 @@ class AssetDispatcher extends DispatcherFilter {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pathSegments = explode('.', $url);
|
$assetFile = $this->_getAssetFile($url);
|
||||||
$ext = array_pop($pathSegments);
|
if ($assetFile === null || !file_exists($assetFile)) {
|
||||||
$parts = explode('/', $url);
|
return null;
|
||||||
$assetFile = null;
|
|
||||||
|
|
||||||
if ($parts[0] === 'theme') {
|
|
||||||
$themeName = $parts[1];
|
|
||||||
unset($parts[0], $parts[1]);
|
|
||||||
$fileFragment = urldecode(implode(DS, $parts));
|
|
||||||
$path = App::themePath($themeName) . 'webroot' . DS;
|
|
||||||
if (file_exists($path . $fileFragment)) {
|
|
||||||
$assetFile = $path . $fileFragment;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$plugin = Inflector::camelize($parts[0]);
|
|
||||||
if (CakePlugin::loaded($plugin)) {
|
|
||||||
unset($parts[0]);
|
|
||||||
$fileFragment = urldecode(implode(DS, $parts));
|
|
||||||
$pluginWebroot = CakePlugin::path($plugin) . 'webroot' . DS;
|
|
||||||
if (file_exists($pluginWebroot . $fileFragment)) {
|
|
||||||
$assetFile = $pluginWebroot . $fileFragment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($assetFile !== null) {
|
$response = $event->data['response'];
|
||||||
$event->stopPropagation();
|
$event->stopPropagation();
|
||||||
|
|
||||||
$response->modified(filemtime($assetFile));
|
$response->modified(filemtime($assetFile));
|
||||||
if (!$response->checkNotModified($event->data['request'])) {
|
if ($response->checkNotModified($event->data['request'])) {
|
||||||
$this->_deliverAsset($response, $assetFile, $ext);
|
|
||||||
}
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$pathSegments = explode('.', $url);
|
||||||
|
$ext = array_pop($pathSegments);
|
||||||
|
$this->_deliverAsset($response, $assetFile, $ext);
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the client is requeting a filtered asset and runs the corresponding
|
* Checks if the client is requesting a filtered asset and runs the corresponding
|
||||||
* filter if any is configured
|
* filter if any is configured
|
||||||
*
|
*
|
||||||
* @param CakeEvent $event containing the request and response object
|
* @param CakeEvent $event containing the request and response object
|
||||||
|
@ -111,15 +93,44 @@ class AssetDispatcher extends DispatcherFilter {
|
||||||
if (($isCss && empty($filters['css'])) || ($isJs && empty($filters['js']))) {
|
if (($isCss && empty($filters['css'])) || ($isJs && empty($filters['js']))) {
|
||||||
$response->statusCode(404);
|
$response->statusCode(404);
|
||||||
return $response;
|
return $response;
|
||||||
} elseif ($isCss) {
|
}
|
||||||
|
|
||||||
|
if ($isCss) {
|
||||||
include WWW_ROOT . DS . $filters['css'];
|
include WWW_ROOT . DS . $filters['css'];
|
||||||
return $response;
|
return $response;
|
||||||
} elseif ($isJs) {
|
}
|
||||||
|
|
||||||
|
if ($isJs) {
|
||||||
include WWW_ROOT . DS . $filters['js'];
|
include WWW_ROOT . DS . $filters['js'];
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds asset file path based off url
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return string Absolute path for asset file
|
||||||
|
*/
|
||||||
|
protected function _getAssetFile($url) {
|
||||||
|
$parts = explode('/', $url);
|
||||||
|
if ($parts[0] === 'theme') {
|
||||||
|
$themeName = $parts[1];
|
||||||
|
unset($parts[0], $parts[1]);
|
||||||
|
$fileFragment = urldecode(implode(DS, $parts));
|
||||||
|
$path = App::themePath($themeName) . 'webroot' . DS;
|
||||||
|
return $path . $fileFragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plugin = Inflector::camelize($parts[0]);
|
||||||
|
if (CakePlugin::loaded($plugin)) {
|
||||||
|
unset($parts[0]);
|
||||||
|
$fileFragment = urldecode(implode(DS, $parts));
|
||||||
|
$pluginWebroot = CakePlugin::path($plugin) . 'webroot' . DS;
|
||||||
|
return $pluginWebroot . $fileFragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an asset file to the client
|
* Sends an asset file to the client
|
||||||
*
|
*
|
||||||
|
|
|
@ -154,7 +154,8 @@ class CakeRoute {
|
||||||
if (preg_match('#\/\*\*$#', $route)) {
|
if (preg_match('#\/\*\*$#', $route)) {
|
||||||
$parsed = preg_replace('#/\\\\\*\\\\\*$#', '(?:/(?P<_trailing_>.*))?', $parsed);
|
$parsed = preg_replace('#/\\\\\*\\\\\*$#', '(?:/(?P<_trailing_>.*))?', $parsed);
|
||||||
$this->_greedy = true;
|
$this->_greedy = true;
|
||||||
} elseif (preg_match('#\/\*$#', $route)) {
|
}
|
||||||
|
if (preg_match('#\/\*$#', $route)) {
|
||||||
$parsed = preg_replace('#/\\\\\*$#', '(?:/(?P<_args_>.*))?', $parsed);
|
$parsed = preg_replace('#/\\\\\*$#', '(?:/(?P<_args_>.*))?', $parsed);
|
||||||
$this->_greedy = true;
|
$this->_greedy = true;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +164,7 @@ class CakeRoute {
|
||||||
$this->_compiledRoute = '#^' . $parsed . '[/]*$#';
|
$this->_compiledRoute = '#^' . $parsed . '[/]*$#';
|
||||||
$this->keys = $names;
|
$this->keys = $names;
|
||||||
|
|
||||||
//remove defaults that are also keys. They can cause match failures
|
// Remove defaults that are also keys. They can cause match failures
|
||||||
foreach ($this->keys as $key) {
|
foreach ($this->keys as $key) {
|
||||||
unset($this->defaults[$key]);
|
unset($this->defaults[$key]);
|
||||||
}
|
}
|
||||||
|
@ -219,7 +220,7 @@ class CakeRoute {
|
||||||
if (isset($route[$key])) {
|
if (isset($route[$key])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_integer($key)) {
|
if (is_int($key)) {
|
||||||
$route['pass'][] = $value;
|
$route['pass'][] = $value;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ class RedirectRoute extends CakeRoute {
|
||||||
$this->response = new CakeResponse();
|
$this->response = new CakeResponse();
|
||||||
}
|
}
|
||||||
$redirect = $this->redirect;
|
$redirect = $this->redirect;
|
||||||
if (count($this->redirect) == 1 && !isset($this->redirect['controller'])) {
|
if (count($this->redirect) === 1 && !isset($this->redirect['controller'])) {
|
||||||
$redirect = $this->redirect[0];
|
$redirect = $this->redirect[0];
|
||||||
}
|
}
|
||||||
if (isset($this->options['persist']) && is_array($redirect)) {
|
if (isset($this->options['persist']) && is_array($redirect)) {
|
||||||
|
|
|
@ -48,6 +48,13 @@ class Router {
|
||||||
*/
|
*/
|
||||||
public static $routes = array();
|
public static $routes = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Have routes been loaded
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
public static $initialized = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of action prefixes used in connected routes.
|
* List of action prefixes used in connected routes.
|
||||||
* Includes admin prefix
|
* Includes admin prefix
|
||||||
|
@ -284,6 +291,8 @@ class Router {
|
||||||
* @throws RouterException
|
* @throws RouterException
|
||||||
*/
|
*/
|
||||||
public static function connect($route, $defaults = array(), $options = array()) {
|
public static function connect($route, $defaults = array(), $options = array()) {
|
||||||
|
self::$initialized = true;
|
||||||
|
|
||||||
foreach (self::$_prefixes as $prefix) {
|
foreach (self::$_prefixes as $prefix) {
|
||||||
if (isset($defaults[$prefix])) {
|
if (isset($defaults[$prefix])) {
|
||||||
if ($defaults[$prefix]) {
|
if ($defaults[$prefix]) {
|
||||||
|
@ -304,7 +313,12 @@ class Router {
|
||||||
}
|
}
|
||||||
$routeClass = self::$_routeClass;
|
$routeClass = self::$_routeClass;
|
||||||
if (isset($options['routeClass'])) {
|
if (isset($options['routeClass'])) {
|
||||||
$routeClass = self::_validateRouteClass($options['routeClass']);
|
if (strpos($options['routeClass'], '.') === false) {
|
||||||
|
$routeClass = $options['routeClass'];
|
||||||
|
} else {
|
||||||
|
list($plugin, $routeClass) = pluginSplit($options['routeClass'], true);
|
||||||
|
}
|
||||||
|
$routeClass = self::_validateRouteClass($routeClass);
|
||||||
unset($options['routeClass']);
|
unset($options['routeClass']);
|
||||||
}
|
}
|
||||||
if ($routeClass == 'RedirectRoute' && isset($defaults['redirect'])) {
|
if ($routeClass == 'RedirectRoute' && isset($defaults['redirect'])) {
|
||||||
|
@ -420,7 +434,7 @@ class Router {
|
||||||
$options = array_merge(array('default' => false, 'reset' => false, 'greedy' => true), $options);
|
$options = array_merge(array('default' => false, 'reset' => false, 'greedy' => true), $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options['reset'] == true || self::$_namedConfig['rules'] === false) {
|
if ($options['reset'] || self::$_namedConfig['rules'] === false) {
|
||||||
self::$_namedConfig['rules'] = array();
|
self::$_namedConfig['rules'] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,6 +529,10 @@ class Router {
|
||||||
* @return array Parsed elements from URL
|
* @return array Parsed elements from URL
|
||||||
*/
|
*/
|
||||||
public static function parse($url) {
|
public static function parse($url) {
|
||||||
|
if (!self::$initialized) {
|
||||||
|
self::_loadRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
$ext = null;
|
$ext = null;
|
||||||
$out = array();
|
$out = array();
|
||||||
|
|
||||||
|
@ -743,6 +761,10 @@ class Router {
|
||||||
* @return string Full translated URL with base path.
|
* @return string Full translated URL with base path.
|
||||||
*/
|
*/
|
||||||
public static function url($url = null, $full = false) {
|
public static function url($url = null, $full = false) {
|
||||||
|
if (!self::$initialized) {
|
||||||
|
self::_loadRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
$params = array('plugin' => null, 'controller' => null, 'action' => 'index');
|
$params = array('plugin' => null, 'controller' => null, 'action' => 'index');
|
||||||
|
|
||||||
if (is_bool($full)) {
|
if (is_bool($full)) {
|
||||||
|
@ -829,12 +851,7 @@ class Router {
|
||||||
$output = self::_handleNoRoute($url);
|
$output = self::_handleNoRoute($url);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (preg_match('/:\/\/|^(javascript|mailto|tel|sms):|\#/i', $url)) {
|
||||||
(strpos($url, '://') !== false ||
|
|
||||||
(strpos($url, 'javascript:') === 0) ||
|
|
||||||
(strpos($url, 'mailto:') === 0)) ||
|
|
||||||
(!strncmp($url, '#', 1))
|
|
||||||
) {
|
|
||||||
return $url;
|
return $url;
|
||||||
}
|
}
|
||||||
if (substr($url, 0, 1) === '/') {
|
if (substr($url, 0, 1) === '/') {
|
||||||
|
@ -928,9 +945,9 @@ class Router {
|
||||||
if (!empty($named)) {
|
if (!empty($named)) {
|
||||||
foreach ($named as $name => $value) {
|
foreach ($named as $name => $value) {
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$flattend = Hash::flatten($value, '][');
|
$flattend = Hash::flatten($value, '%5D%5B');
|
||||||
foreach ($flattend as $namedKey => $namedValue) {
|
foreach ($flattend as $namedKey => $namedValue) {
|
||||||
$output .= '/' . $name . "[$namedKey]" . self::$_namedConfig['separator'] . rawurlencode($namedValue);
|
$output .= '/' . $name . "%5B{$namedKey}%5D" . self::$_namedConfig['separator'] . rawurlencode($namedValue);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$output .= '/' . $name . self::$_namedConfig['separator'] . rawurlencode($value);
|
$output .= '/' . $name . self::$_namedConfig['separator'] . rawurlencode($value);
|
||||||
|
@ -1073,7 +1090,7 @@ class Router {
|
||||||
* @return string base url with plugin name removed if present
|
* @return string base url with plugin name removed if present
|
||||||
*/
|
*/
|
||||||
public static function stripPlugin($base, $plugin = null) {
|
public static function stripPlugin($base, $plugin = null) {
|
||||||
if ($plugin != null) {
|
if ($plugin) {
|
||||||
$base = preg_replace('/(?:' . $plugin . ')/', '', $base);
|
$base = preg_replace('/(?:' . $plugin . ')/', '', $base);
|
||||||
$base = str_replace('//', '', $base);
|
$base = str_replace('//', '', $base);
|
||||||
$pos1 = strrpos($base, '/');
|
$pos1 = strrpos($base, '/');
|
||||||
|
@ -1117,6 +1134,10 @@ class Router {
|
||||||
* @return array Array of extensions Router is configured to parse.
|
* @return array Array of extensions Router is configured to parse.
|
||||||
*/
|
*/
|
||||||
public static function extensions() {
|
public static function extensions() {
|
||||||
|
if (!self::$initialized) {
|
||||||
|
self::_loadRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
return self::$_validExtensions;
|
return self::$_validExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1138,6 +1159,16 @@ class Router {
|
||||||
return self::$_validExtensions = array_merge(self::$_validExtensions, $extensions);
|
return self::$_validExtensions = array_merge(self::$_validExtensions, $extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads route configuration
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected static function _loadRoutes() {
|
||||||
|
self::$initialized = true;
|
||||||
|
include APP . 'Config' . DS . 'routes.php';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Save the initial state
|
//Save the initial state
|
||||||
|
|
|
@ -825,6 +825,18 @@ EXPECTED;
|
||||||
########## DEBUG ##########
|
########## DEBUG ##########
|
||||||
'<div>this-is-a-test</div>'
|
'<div>this-is-a-test</div>'
|
||||||
###########################
|
###########################
|
||||||
|
EXPECTED;
|
||||||
|
$expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 8);
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
debug(false, false, false);
|
||||||
|
$result = ob_get_clean();
|
||||||
|
$expected = <<<EXPECTED
|
||||||
|
|
||||||
|
########## DEBUG ##########
|
||||||
|
false
|
||||||
|
###########################
|
||||||
EXPECTED;
|
EXPECTED;
|
||||||
$expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 8);
|
$expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 8);
|
||||||
$this->assertEquals($expected, $result);
|
$this->assertEquals($expected, $result);
|
||||||
|
|
|
@ -73,7 +73,8 @@ class RegisEngineTest extends CakeTestCase {
|
||||||
'server' => '127.0.0.1',
|
'server' => '127.0.0.1',
|
||||||
'port' => 6379,
|
'port' => 6379,
|
||||||
'timeout' => 0,
|
'timeout' => 0,
|
||||||
'persistent' => true
|
'persistent' => true,
|
||||||
|
'password' => false,
|
||||||
);
|
);
|
||||||
$this->assertEquals($expecting, $settings);
|
$this->assertEquals($expecting, $settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,7 @@ three.four = value four
|
||||||
is_null = null
|
is_null = null
|
||||||
bool_false = false
|
bool_false = false
|
||||||
bool_true = true
|
bool_true = true
|
||||||
|
|
||||||
[Asset]
|
[Asset]
|
||||||
timestamp = force
|
timestamp = force
|
||||||
INI;
|
INI;
|
||||||
|
|
|
@ -88,7 +88,7 @@ class CommandListShellTest extends CakeTestCase {
|
||||||
$expected = "/\[.*TestPluginTwo.*\] example, welcome/";
|
$expected = "/\[.*TestPluginTwo.*\] example, welcome/";
|
||||||
$this->assertRegExp($expected, $output);
|
$this->assertRegExp($expected, $output);
|
||||||
|
|
||||||
$expected = "/\[.*CORE.*\] acl, api, bake, command_list, console, i18n, schema, test, testsuite, upgrade/";
|
$expected = "/\[.*CORE.*\] acl, api, bake, command_list, console, i18n, schema, server, test, testsuite, upgrade/";
|
||||||
$this->assertRegExp($expected, $output);
|
$this->assertRegExp($expected, $output);
|
||||||
|
|
||||||
$expected = "/\[.*app.*\] sample/";
|
$expected = "/\[.*app.*\] sample/";
|
||||||
|
|
|
@ -362,6 +362,40 @@ class SchemaShellTest extends CakeTestCase {
|
||||||
CakePlugin::unload();
|
CakePlugin::unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test generate with specific models
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testGenerateModels() {
|
||||||
|
App::build(array(
|
||||||
|
'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
|
||||||
|
), App::RESET);
|
||||||
|
CakePlugin::load('TestPlugin');
|
||||||
|
|
||||||
|
$this->db->cacheSources = false;
|
||||||
|
$this->Shell->params = array(
|
||||||
|
'plugin' => 'TestPlugin',
|
||||||
|
'connection' => 'test',
|
||||||
|
'models' => 'TestPluginComment',
|
||||||
|
'force' => false,
|
||||||
|
'overwrite' => true
|
||||||
|
);
|
||||||
|
$this->Shell->startup();
|
||||||
|
$this->Shell->Schema->path = TMP . 'tests' . DS;
|
||||||
|
|
||||||
|
$this->Shell->generate();
|
||||||
|
$this->file = new File(TMP . 'tests' . DS . 'schema.php');
|
||||||
|
$contents = $this->file->read();
|
||||||
|
|
||||||
|
$this->assertRegExp('/class TestPluginSchema/', $contents);
|
||||||
|
$this->assertRegExp('/public \$test_plugin_comments/', $contents);
|
||||||
|
$this->assertNotRegExp('/public \$authors/', $contents);
|
||||||
|
$this->assertNotRegExp('/public \$auth_users/', $contents);
|
||||||
|
$this->assertNotRegExp('/public \$posts/', $contents);
|
||||||
|
CakePlugin::unload();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test schema run create with no table args.
|
* Test schema run create with no table args.
|
||||||
*
|
*
|
||||||
|
@ -463,6 +497,35 @@ class SchemaShellTest extends CakeTestCase {
|
||||||
CakePlugin::unload();
|
CakePlugin::unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test that underscored names also result in CamelCased class names
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testName() {
|
||||||
|
App::build(array(
|
||||||
|
'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
|
||||||
|
));
|
||||||
|
CakePlugin::load('TestPlugin');
|
||||||
|
$this->Shell->params = array(
|
||||||
|
'plugin' => 'TestPlugin',
|
||||||
|
'connection' => 'test',
|
||||||
|
'name' => 'custom_name',
|
||||||
|
'force' => false,
|
||||||
|
'overwrite' => true,
|
||||||
|
);
|
||||||
|
$this->Shell->startup();
|
||||||
|
if (file_exists($this->Shell->Schema->path . DS . 'custom_name.php')) {
|
||||||
|
unlink($this->Shell->Schema->path . DS . 'custom_name.php');
|
||||||
|
}
|
||||||
|
$this->Shell->generate();
|
||||||
|
|
||||||
|
$contents = file_get_contents($this->Shell->Schema->path . DS . 'custom_name.php');
|
||||||
|
$this->assertRegExp('/class CustomNameSchema/', $contents);
|
||||||
|
unlink($this->Shell->Schema->path . DS . 'custom_name.php');
|
||||||
|
CakePlugin::unload();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test that using Plugin.name with write.
|
* test that using Plugin.name with write.
|
||||||
*
|
*
|
||||||
|
|
|
@ -191,9 +191,9 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
*/
|
*/
|
||||||
public function testDoHelpersTrailingSpace() {
|
public function testDoHelpersTrailingSpace() {
|
||||||
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
|
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
|
||||||
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Javascript, Ajax, CustomOne '));
|
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Text, Number, CustomOne '));
|
||||||
$result = $this->Task->doHelpers();
|
$result = $this->Task->doHelpers();
|
||||||
$expected = array('Javascript', 'Ajax', 'CustomOne');
|
$expected = array('Text', 'Number', 'CustomOne');
|
||||||
$this->assertEquals($expected, $result);
|
$this->assertEquals($expected, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,9 +204,9 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
*/
|
*/
|
||||||
public function testDoHelpersTrailingCommas() {
|
public function testDoHelpersTrailingCommas() {
|
||||||
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
|
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
|
||||||
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Javascript, Ajax, CustomOne, , '));
|
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Text, Number, CustomOne, , '));
|
||||||
$result = $this->Task->doHelpers();
|
$result = $this->Task->doHelpers();
|
||||||
$expected = array('Javascript', 'Ajax', 'CustomOne');
|
$expected = array('Text', 'Number', 'CustomOne');
|
||||||
$this->assertEquals($expected, $result);
|
$this->assertEquals($expected, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,11 +257,11 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
public function testConfirmController() {
|
public function testConfirmController() {
|
||||||
$controller = 'Posts';
|
$controller = 'Posts';
|
||||||
$scaffold = false;
|
$scaffold = false;
|
||||||
$helpers = array('Ajax', 'Time');
|
$helpers = array('Js', 'Time');
|
||||||
$components = array('Acl', 'Auth');
|
$components = array('Acl', 'Auth');
|
||||||
|
|
||||||
$this->Task->expects($this->at(4))->method('out')->with("Controller Name:\n\t$controller");
|
$this->Task->expects($this->at(4))->method('out')->with("Controller Name:\n\t$controller");
|
||||||
$this->Task->expects($this->at(5))->method('out')->with("Helpers:\n\tAjax, Time");
|
$this->Task->expects($this->at(5))->method('out')->with("Helpers:\n\tJs, Time");
|
||||||
$this->Task->expects($this->at(6))->method('out')->with("Components:\n\tAcl, Auth");
|
$this->Task->expects($this->at(6))->method('out')->with("Components:\n\tAcl, Auth");
|
||||||
$this->Task->confirmController($controller, $scaffold, $helpers, $components);
|
$this->Task->confirmController($controller, $scaffold, $helpers, $components);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function testBake() {
|
public function testBake() {
|
||||||
$helpers = array('Ajax', 'Time');
|
$helpers = array('Js', 'Time');
|
||||||
$components = array('Acl', 'Auth');
|
$components = array('Acl', 'Auth');
|
||||||
$this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true));
|
$this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true));
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
$this->assertContains(' * @property AuthComponent $Auth', $result);
|
$this->assertContains(' * @property AuthComponent $Auth', $result);
|
||||||
$this->assertContains('class ArticlesController extends AppController', $result);
|
$this->assertContains('class ArticlesController extends AppController', $result);
|
||||||
$this->assertContains("public \$components = array('Acl', 'Auth')", $result);
|
$this->assertContains("public \$components = array('Acl', 'Auth')", $result);
|
||||||
$this->assertContains("public \$helpers = array('Ajax', 'Time')", $result);
|
$this->assertContains("public \$helpers = array('Js', 'Time')", $result);
|
||||||
$this->assertContains("--actions--", $result);
|
$this->assertContains("--actions--", $result);
|
||||||
|
|
||||||
$result = $this->Task->bake('Articles', 'scaffold', $helpers, $components);
|
$result = $this->Task->bake('Articles', 'scaffold', $helpers, $components);
|
||||||
|
@ -350,7 +350,8 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
|
|
||||||
$this->assertContains('function view($id = null)', $result);
|
$this->assertContains('function view($id = null)', $result);
|
||||||
$this->assertContains("throw new NotFoundException(__('Invalid bake article'));", $result);
|
$this->assertContains("throw new NotFoundException(__('Invalid bake article'));", $result);
|
||||||
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
|
$this->assertContains("\$options = array('conditions' => array('BakeArticle.' . \$this->BakeArticle->primaryKey => \$id));", $result);
|
||||||
|
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->find('first', \$options));", $result);
|
||||||
|
|
||||||
$this->assertContains('function add()', $result);
|
$this->assertContains('function add()', $result);
|
||||||
$this->assertContains("if (\$this->request->is('post'))", $result);
|
$this->assertContains("if (\$this->request->is('post'))", $result);
|
||||||
|
@ -389,7 +390,7 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
|
|
||||||
$this->assertContains('function view($id = null)', $result);
|
$this->assertContains('function view($id = null)', $result);
|
||||||
$this->assertContains("throw new NotFoundException(__('Invalid bake article'));", $result);
|
$this->assertContains("throw new NotFoundException(__('Invalid bake article'));", $result);
|
||||||
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
|
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->find('first', \$options));", $result);
|
||||||
|
|
||||||
$this->assertContains('function add()', $result);
|
$this->assertContains('function add()', $result);
|
||||||
$this->assertContains("if (\$this->request->is('post'))", $result);
|
$this->assertContains("if (\$this->request->is('post'))", $result);
|
||||||
|
@ -402,6 +403,7 @@ class ControllerTaskTest extends CakeTestCase {
|
||||||
$this->assertContains("\$this->set(compact('bakeTags'))", $result);
|
$this->assertContains("\$this->set(compact('bakeTags'))", $result);
|
||||||
|
|
||||||
$this->assertContains('function delete($id = null)', $result);
|
$this->assertContains('function delete($id = null)', $result);
|
||||||
|
$this->assertContains("\$this->request->onlyAllow('post', 'delete')", $result);
|
||||||
$this->assertContains('if ($this->BakeArticle->delete())', $result);
|
$this->assertContains('if ($this->BakeArticle->delete())', $result);
|
||||||
$this->assertContains("\$this->flash(__('Bake article deleted'), array('action' => 'index'))", $result);
|
$this->assertContains("\$this->flash(__('Bake article deleted'), array('action' => 'index'))", $result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,10 +308,10 @@ class ExtractTaskTest extends CakeTestCase {
|
||||||
$this->Task->execute();
|
$this->Task->execute();
|
||||||
$result = file_get_contents($this->path . DS . 'default.pot');
|
$result = file_get_contents($this->path . DS . 'default.pot');
|
||||||
|
|
||||||
$pattern = preg_quote('#Model' . DS . 'PersisterOne.php:validation for field title#', '\\');
|
$pattern = preg_quote('#Model/PersisterOne.php:validation for field title#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = preg_quote('#Model' . DS . 'PersisterOne.php:validation for field body#', '\\');
|
$pattern = preg_quote('#Model/PersisterOne.php:validation for field body#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = '#msgid "Post title is required"#';
|
$pattern = '#msgid "Post title is required"#';
|
||||||
|
@ -354,10 +354,10 @@ class ExtractTaskTest extends CakeTestCase {
|
||||||
$this->Task->execute();
|
$this->Task->execute();
|
||||||
$result = file_get_contents($this->path . DS . 'test_plugin.pot');
|
$result = file_get_contents($this->path . DS . 'test_plugin.pot');
|
||||||
|
|
||||||
$pattern = preg_quote('#Plugin' . DS . 'TestPlugin' . DS . 'Model' . DS . 'TestPluginPost.php:validation for field title#', '\\');
|
$pattern = preg_quote('#Plugin/TestPlugin/Model/TestPluginPost.php:validation for field title#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = preg_quote('#Plugin' . DS . 'TestPlugin' . DS . 'Model' . DS . 'TestPluginPost.php:validation for field body#', '\\');
|
$pattern = preg_quote('#Plugin/TestPlugin/Model/TestPluginPost.php:validation for field body#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = '#msgid "Post title is required"#';
|
$pattern = '#msgid "Post title is required"#';
|
||||||
|
@ -393,10 +393,10 @@ class ExtractTaskTest extends CakeTestCase {
|
||||||
$this->Task->execute();
|
$this->Task->execute();
|
||||||
$result = file_get_contents($this->path . DS . 'test_plugin.pot');
|
$result = file_get_contents($this->path . DS . 'test_plugin.pot');
|
||||||
|
|
||||||
$pattern = preg_quote('#Model' . DS . 'TestPluginPost.php:validation for field title#', '\\');
|
$pattern = preg_quote('#Model/TestPluginPost.php:validation for field title#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = preg_quote('#Model' . DS . 'TestPluginPost.php:validation for field body#', '\\');
|
$pattern = preg_quote('#Model/TestPluginPost.php:validation for field body#', '\\');
|
||||||
$this->assertRegExp($pattern, $result);
|
$this->assertRegExp($pattern, $result);
|
||||||
|
|
||||||
$pattern = '#msgid "Post title is required"#';
|
$pattern = '#msgid "Post title is required"#';
|
||||||
|
|
|
@ -315,7 +315,7 @@ class ModelTaskTest extends CakeTestCase {
|
||||||
$this->Task->initValidations();
|
$this->Task->initValidations();
|
||||||
$this->Task->interactive = true;
|
$this->Task->interactive = true;
|
||||||
$this->Task->expects($this->any())->method('in')
|
$this->Task->expects($this->any())->method('in')
|
||||||
->will($this->onConsecutiveCalls('23', 'y', '17', 'n'));
|
->will($this->onConsecutiveCalls('24', 'y', '18', 'n'));
|
||||||
|
|
||||||
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
|
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
|
||||||
$expected = array('notempty' => 'notempty', 'maxlength' => 'maxlength');
|
$expected = array('notempty' => 'notempty', 'maxlength' => 'maxlength');
|
||||||
|
@ -333,7 +333,7 @@ class ModelTaskTest extends CakeTestCase {
|
||||||
$this->Task->interactive = true;
|
$this->Task->interactive = true;
|
||||||
|
|
||||||
$this->Task->expects($this->any())->method('in')
|
$this->Task->expects($this->any())->method('in')
|
||||||
->will($this->onConsecutiveCalls('999999', '23', 'n'));
|
->will($this->onConsecutiveCalls('999999', '24', 'n'));
|
||||||
|
|
||||||
$this->Task->expects($this->at(10))->method('out')
|
$this->Task->expects($this->at(10))->method('out')
|
||||||
->with($this->stringContains('make a valid'));
|
->with($this->stringContains('make a valid'));
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue