Merge branch '2.x' into 2.next

This commit is contained in:
mark_story 2016-06-27 21:47:47 -04:00
commit 432eb9c432
28 changed files with 370 additions and 57 deletions

View file

@ -41,6 +41,8 @@ before_script:
- sh -c "if [ '$PHPCS' = '1' ]; then composer global require 'cakephp/cakephp-codesniffer:1.*'; fi" - sh -c "if [ '$PHPCS' = '1' ]; then composer global require 'cakephp/cakephp-codesniffer:1.*'; fi"
- sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/cakephp/cakephp-codesniffer; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/cakephp/cakephp-codesniffer; fi"
- echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- if [[ ${TRAVIS_PHP_VERSION:0:3} == "7.0" ]] ; then print "yes" | pecl install apcu-5.1.3; else print "yes" | pecl install apcu-4.0.11; fi
- echo -e "extension = apcu.so\napc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- phpenv rehash - phpenv rehash
- set +H - set +H
- echo "<?php - echo "<?php

View file

@ -5,8 +5,6 @@
[![Bake Status](https://secure.travis-ci.org/cakephp/cakephp.png?branch=master)](http://travis-ci.org/cakephp/cakephp) [![Bake Status](https://secure.travis-ci.org/cakephp/cakephp.png?branch=master)](http://travis-ci.org/cakephp/cakephp)
[![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/) [![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/)
[![CakePHP](http://cakephp.org/img/cake-logo.png)](http://www.cakephp.org)
CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC. CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.
Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility. Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility.

View file

@ -94,7 +94,7 @@ if (isset($filePresent)):
$errorMsg = $connectionError->getMessage(); $errorMsg = $connectionError->getMessage();
if (method_exists($connectionError, 'getAttributes')): if (method_exists($connectionError, 'getAttributes')):
$attributes = $connectionError->getAttributes(); $attributes = $connectionError->getAttributes();
if (isset($errorMsg['message'])): if (isset($attributes['message'])):
$errorMsg .= '<br />' . $attributes['message']; $errorMsg .= '<br />' . $attributes['message'];
endif; endif;
endif; endif;
@ -209,8 +209,10 @@ You can also add some CSS styles for your pages at: %s.',
<ul><li><?php echo __d('cake_dev', 'A comprehensive list of all CakePHP plugins created by the community'); ?></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://community.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Community Center'); ?> </a> <li><a href="http://community.cakephp.org"><?php echo __d('cake_dev', 'CakePHP Community Center'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li>
<li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a> <li><a href="http://discourse.cakephp.org/">CakePHP Official Forum </a>
<ul><li><?php echo __d('cake_dev', 'Community mailing list'); ?></li></ul></li> <ul><li>CakePHP discussion forum</li></ul></li>
<li><a href="http://discourse.cakephp.org/"><?php echo __d('cake_dev', 'CakePHP Official Forum'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP discussion forum'); ?></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>
<ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a> <li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a>

37
app/composer.json Normal file
View file

@ -0,0 +1,37 @@
{
"name": "cakephp/app",
"description": "CakePHP Application skeleton",
"type": "library",
"keywords": ["application", "cakephp"],
"homepage": "http://cakephp.org",
"license": "MIT",
"authors": [
{
"name": "CakePHP Community",
"homepage": "https://github.com/cakephp/cakephp/graphs/contributors"
}
],
"support": {
"issues": "https://github.com/cakephp/cakephp/issues",
"forum": "http://stackoverflow.com/tags/cakephp",
"irc": "irc://irc.freenode.org/cakephp",
"source": "https://github.com/cakephp/cakephp"
},
"require": {
"php": ">=5.3.0",
"ext-mcrypt": "*"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
"cakephp/cakephp": "~2.8"
},
"suggest": {
"cakephp/cakephp-codesniffer": "Easily check code formatting against the CakePHP coding standards."
},
"bin": [
"lib/Cake/Console/cake"
],
"config": {
"vendor-dir": "Vendor/"
}
}

View file

@ -213,10 +213,10 @@
--> -->
<target name="distribute" depends="prepare" description="Upload pear packages to pear.cakephp.org"> <target name="distribute" depends="prepare" description="Upload pear packages to pear.cakephp.org">
<echo msg="Uploading tgz file to cakephp.org" /> <echo msg="Uploading tgz file to cakephp.org" />
<exec command="scp ${dist.dir}/${pear.package}.tgz cakephp@cakephp.org:${pirum.dir}" dir="." checkreturn="true" /> <exec command="scp ${dist.dir}/${pear.package}.tgz cakephp@pear.cakephp.org:${pirum.dir}" dir="." checkreturn="true" />
<echo msg="Adding new release to pirum" /> <echo msg="Adding new release to pirum" />
<exec command="ssh cakephp@cakephp.org pirum add ${pirum.dir} ${pirum.dir}/${pear.package}.tgz" checkreturn="true" /> <exec command="ssh cakephp@pear.cakephp.org pirum add ${pirum.dir} ${pirum.dir}/${pear.package}.tgz" checkreturn="true" />
</target> </target>
<target name="codestyle" description="Check codestyle (human readable format)"> <target name="codestyle" description="Check codestyle (human readable format)">

View file

@ -23,9 +23,11 @@
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "3.7.*", "phpunit/phpunit": "3.7.*",
"cakephp/debug_kit" : "^2.2.0",
"cakephp/cakephp-codesniffer": "^1.0.0" "cakephp/cakephp-codesniffer": "^1.0.0"
}, },
"config": {
"vendor-dir": "vendors/"
},
"bin": [ "bin": [
"lib/Cake/Console/cake" "lib/Cake/Console/cake"
] ]

View file

@ -31,6 +31,13 @@ class ApcEngine extends CacheEngine {
*/ */
protected $_compiledGroupNames = array(); protected $_compiledGroupNames = array();
/**
* APC or APCu extension
*
* @var string
*/
protected $_apcExtension = 'apc';
/** /**
* Initialize the Cache Engine * Initialize the Cache Engine
* *
@ -47,6 +54,10 @@ class ApcEngine extends CacheEngine {
} }
$settings += array('engine' => 'Apc'); $settings += array('engine' => 'Apc');
parent::init($settings); parent::init($settings);
if (function_exists('apcu_dec')) {
$this->_apcExtension = 'apcu';
return true;
}
return function_exists('apc_dec'); return function_exists('apc_dec');
} }
@ -63,8 +74,9 @@ class ApcEngine extends CacheEngine {
if ($duration) { if ($duration) {
$expires = time() + $duration; $expires = time() + $duration;
} }
apc_store($key . '_expires', $expires, $duration); $func = $this->_apcExtension . '_store';
return apc_store($key, $value, $duration); $func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
} }
/** /**
@ -75,11 +87,12 @@ class ApcEngine extends CacheEngine {
*/ */
public function read($key) { public function read($key) {
$time = time(); $time = time();
$cachetime = (int)apc_fetch($key . '_expires'); $func = $this->_apcExtension . '_fetch';
$cachetime = (int)$func($key . '_expires');
if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) { if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
return false; return false;
} }
return apc_fetch($key); return $func($key);
} }
/** /**
@ -90,7 +103,8 @@ class ApcEngine extends CacheEngine {
* @return New incremented value, false otherwise * @return New incremented value, false otherwise
*/ */
public function increment($key, $offset = 1) { public function increment($key, $offset = 1) {
return apc_inc($key, $offset); $func = $this->_apcExtension . '_inc';
return $func($key, $offset);
} }
/** /**
@ -101,7 +115,8 @@ class ApcEngine extends CacheEngine {
* @return New decremented value, false otherwise * @return New decremented value, false otherwise
*/ */
public function decrement($key, $offset = 1) { public function decrement($key, $offset = 1) {
return apc_dec($key, $offset); $func = $this->_apcExtension . '_dec';
return $func($key, $offset);
} }
/** /**
@ -111,7 +126,8 @@ class ApcEngine extends CacheEngine {
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/ */
public function delete($key) { public function delete($key) {
return apc_delete($key); $func = $this->_apcExtension . '_delete';
return $func($key);
} }
/** /**
@ -125,19 +141,20 @@ class ApcEngine extends CacheEngine {
if ($check) { if ($check) {
return true; return true;
} }
$func = $this->_apcExtension . '_delete';
if (class_exists('APCIterator', false)) { if (class_exists('APCIterator', false)) {
$iterator = new APCIterator( $iterator = new APCIterator(
'user', 'user',
'/^' . preg_quote($this->settings['prefix'], '/') . '/', '/^' . preg_quote($this->settings['prefix'], '/') . '/',
APC_ITER_NONE APC_ITER_NONE
); );
apc_delete($iterator); $func($iterator);
return true; return true;
} }
$cache = apc_cache_info('user'); $cache = $this->_apcExtension === 'apc' ? apc_cache_info('user') : apcu_cache_info();
foreach ($cache['cache_list'] as $key) { foreach ($cache['cache_list'] as $key) {
if (strpos($key['info'], $this->settings['prefix']) === 0) { if (strpos($key['info'], $this->settings['prefix']) === 0) {
apc_delete($key['info']); $func($key['info']);
} }
} }
return true; return true;
@ -157,11 +174,13 @@ class ApcEngine extends CacheEngine {
} }
} }
$groups = apc_fetch($this->_compiledGroupNames); $fetchFunc = $this->_apcExtension . '_fetch';
$storeFunc = $this->_apcExtension . '_store';
$groups = $fetchFunc($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) { if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) { foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) { if (!isset($groups[$group])) {
apc_store($group, 1); $storeFunc($group, 1);
$groups[$group] = 1; $groups[$group] = 1;
} }
} }
@ -184,7 +203,8 @@ class ApcEngine extends CacheEngine {
* @return bool success * @return bool success
*/ */
public function clearGroup($group) { public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success); $func = $this->_apcExtension . '_inc';
$func($this->settings['prefix'] . $group, 1, $success);
return $success; return $success;
} }
@ -203,7 +223,8 @@ class ApcEngine extends CacheEngine {
if ($duration) { if ($duration) {
$expires = time() + $duration; $expires = time() + $duration;
} }
apc_add($key . '_expires', $expires, $duration); $func = $this->_apcExtension . '_add';
return apc_add($key, $value, $duration); $func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
} }
} }

View file

@ -182,11 +182,11 @@ class ControllerTask extends BakeTask {
$components = $this->doComponents(); $components = $this->doComponents();
$wannaUseSession = $this->in( $wannaUseSession = $this->in(
__d('cake_console', "Would you like to use Session flash messages?"), array('y', 'n'), 'y' __d('cake_console', "Would you like to use the FlashComponent to display flash messages?"), array('y', 'n'), 'y'
); );
if (strtolower($wannaUseSession) === 'y') { if (strtolower($wannaUseSession) === 'y') {
array_push($components, 'Session'); array_push($components, 'Session', 'Flash');
} }
array_unique($components); array_unique($components);
} }
@ -384,9 +384,9 @@ class ControllerTask extends BakeTask {
* @return array Components the user wants to use. * @return array Components the user wants to use.
*/ */
public function doComponents() { public function doComponents() {
$components = array('Paginator', 'Flash'); $components = array('Paginator');
return array_merge($components, $this->_doPropertyChoices( return array_merge($components, $this->_doPropertyChoices(
__d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent and FlashComponent?"), __d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent?"),
__d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'") __d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'")
)); ));
} }

View file

@ -214,6 +214,8 @@ You can also add some CSS styles for your pages at: %s.',
<ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Everything related to the CakePHP community in one place'); ?></li></ul></li>
<li><a href="https://groups.google.com/group/cake-php"><?php echo __d('cake_dev', 'CakePHP Google Group'); ?> </a> <li><a href="https://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="http://discourse.cakephp.org/"><?php echo __d('cake_dev', 'CakePHP Official Forum'); ?> </a>
<ul><li><?php echo __d('cake_dev', 'CakePHP discussion forum'); ?></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>
<ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li> <ul><li><?php echo __d('cake_dev', 'Live chat about CakePHP'); ?></li></ul></li>
<li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a> <li><a href="https://github.com/cakephp/"><?php echo __d('cake_dev', 'CakePHP Code'); ?> </a>

View file

@ -505,7 +505,12 @@ class RequestHandlerComponent extends Component {
* in the request content type will be returned. * in the request content type will be returned.
*/ */
public function requestedWith($type = null) { public function requestedWith($type = null) {
if (!$this->request->is('post') && !$this->request->is('put') && !$this->request->is('delete')) { if (
!$this->request->is('patch') &&
!$this->request->is('post') &&
!$this->request->is('put') &&
!$this->request->is('delete')
) {
return null; return null;
} }
if (is_array($type)) { if (is_array($type)) {

View file

@ -185,6 +185,9 @@ class Sqlite extends DboSource {
'default' => $default, 'default' => $default,
'length' => $this->length($column['type']) 'length' => $this->length($column['type'])
); );
if (in_array($fields[$column['name']]['type'], array('timestamp', 'datetime')) && strtoupper($fields[$column['name']]['default']) === 'CURRENT_TIMESTAMP') {
$fields[$column['name']]['default'] = null;
}
if ($column['pk'] == 1) { if ($column['pk'] == 1) {
$fields[$column['name']]['key'] = $this->index['PRI']; $fields[$column['name']]['key'] = $this->index['PRI'];
$fields[$column['name']]['null'] = false; $fields[$column['name']]['null'] = false;

View file

@ -2302,6 +2302,7 @@ class DboSource extends DataSource {
$this->_transactionNesting = 0; $this->_transactionNesting = 0;
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery('BEGIN'); $this->logQuery('BEGIN');
} }
return $this->_transactionStarted = $this->_connection->beginTransaction(); return $this->_transactionStarted = $this->_connection->beginTransaction();
@ -2315,6 +2316,7 @@ class DboSource extends DataSource {
protected function _beginNested() { protected function _beginNested() {
$query = 'SAVEPOINT LEVEL' . ++$this->_transactionNesting; $query = 'SAVEPOINT LEVEL' . ++$this->_transactionNesting;
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery($query); $this->logQuery($query);
} }
$this->_connection->exec($query); $this->_connection->exec($query);
@ -2335,6 +2337,7 @@ class DboSource extends DataSource {
if ($this->_transactionNesting === 0) { if ($this->_transactionNesting === 0) {
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery('COMMIT'); $this->logQuery('COMMIT');
} }
$this->_transactionStarted = false; $this->_transactionStarted = false;
@ -2357,6 +2360,7 @@ class DboSource extends DataSource {
protected function _commitNested() { protected function _commitNested() {
$query = 'RELEASE SAVEPOINT LEVEL' . $this->_transactionNesting--; $query = 'RELEASE SAVEPOINT LEVEL' . $this->_transactionNesting--;
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery($query); $this->logQuery($query);
} }
$this->_connection->exec($query); $this->_connection->exec($query);
@ -2377,6 +2381,7 @@ class DboSource extends DataSource {
if ($this->_transactionNesting === 0) { if ($this->_transactionNesting === 0) {
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery('ROLLBACK'); $this->logQuery('ROLLBACK');
} }
$this->_transactionStarted = false; $this->_transactionStarted = false;
@ -2399,6 +2404,7 @@ class DboSource extends DataSource {
protected function _rollbackNested() { protected function _rollbackNested() {
$query = 'ROLLBACK TO SAVEPOINT LEVEL' . $this->_transactionNesting--; $query = 'ROLLBACK TO SAVEPOINT LEVEL' . $this->_transactionNesting--;
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = $this->numRows = $this->affected = false;
$this->logQuery($query); $this->logQuery($query);
} }
$this->_connection->exec($query); $this->_connection->exec($query);
@ -3190,10 +3196,13 @@ class DboSource extends DataSource {
$statement->bindValue($i, $val, $columnMap[$col]); $statement->bindValue($i, $val, $columnMap[$col]);
$i += 1; $i += 1;
} }
$t = microtime(true);
$statement->execute(); $statement->execute();
$statement->closeCursor(); $statement->closeCursor();
if ($this->fullDebug) { if ($this->fullDebug) {
$this->took = round((microtime(true) - $t) * 1000, 0);
$this->numRows = $this->affected = $statement->rowCount();
$this->logQuery($sql, $value); $this->logQuery($sql, $value);
} }
} }

View file

@ -97,6 +97,7 @@ class CakeRequest implements ArrayAccess {
*/ */
protected $_detectors = array( protected $_detectors = array(
'get' => array('env' => 'REQUEST_METHOD', 'value' => 'GET'), 'get' => array('env' => 'REQUEST_METHOD', 'value' => 'GET'),
'patch' => array('env' => 'REQUEST_METHOD', 'value' => 'PATCH'),
'post' => array('env' => 'REQUEST_METHOD', 'value' => 'POST'), 'post' => array('env' => 'REQUEST_METHOD', 'value' => 'POST'),
'put' => array('env' => 'REQUEST_METHOD', 'value' => 'PUT'), 'put' => array('env' => 'REQUEST_METHOD', 'value' => 'PUT'),
'delete' => array('env' => 'REQUEST_METHOD', 'value' => 'DELETE'), 'delete' => array('env' => 'REQUEST_METHOD', 'value' => 'DELETE'),
@ -1124,6 +1125,9 @@ class CakeRequest implements ArrayAccess {
* @return bool * @return bool
*/ */
public function offsetExists($name) { public function offsetExists($name) {
if ($name === 'url' || $name === 'data') {
return true;
}
return isset($this->params[$name]); return isset($this->params[$name]);
} }

View file

@ -1203,7 +1203,7 @@ class CakeEmail {
* @throws SocketException * @throws SocketException
*/ */
public static function deliver($to = null, $subject = null, $message = null, $transportConfig = 'fast', $send = true) { public static function deliver($to = null, $subject = null, $message = null, $transportConfig = 'fast', $send = true) {
$class = __CLASS__; $class = get_called_class();
/** @var CakeEmail $instance */ /** @var CakeEmail $instance */
$instance = new $class($transportConfig); $instance = new $class($transportConfig);
if ($to !== null) { if ($to !== null) {

View file

@ -15,6 +15,7 @@
* @since CakePHP(tm) v 2.0.0 * @since CakePHP(tm) v 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
App::uses('AbstractTransport', 'Network/Email');
/** /**
* Debug Transport class, useful for emulate the email sending process and inspect the resulted * Debug Transport class, useful for emulate the email sending process and inspect the resulted

View file

@ -15,6 +15,7 @@
* @since CakePHP(tm) v 2.0.0 * @since CakePHP(tm) v 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
App::uses('AbstractTransport', 'Network/Email');
/** /**
* Send mail using mail() function * Send mail using mail() function

View file

@ -15,7 +15,7 @@
* @since CakePHP(tm) v 2.0.0 * @since CakePHP(tm) v 2.0.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
App::uses('AbstractTransport', 'Network/Email');
App::uses('CakeSocket', 'Network'); App::uses('CakeSocket', 'Network');
/** /**

View file

@ -25,6 +25,13 @@ App::uses('Cache', 'Cache');
*/ */
class ApcEngineTest extends CakeTestCase { class ApcEngineTest extends CakeTestCase {
/**
* APC extension to be used
*
* @var string
*/
protected $_apcExtension = 'apc';
/** /**
* setUp method * setUp method
* *
@ -32,12 +39,17 @@ class ApcEngineTest extends CakeTestCase {
*/ */
public function setUp() { public function setUp() {
parent::setUp(); parent::setUp();
$this->skipIf(!function_exists('apc_store'), 'Apc is not installed or configured properly.'); $hasApc = extension_loaded('apc') || extension_loaded('apcu');
$this->skipIf(!$hasApc, 'Apc is not installed or configured properly.');
if (PHP_SAPI === 'cli') { if (PHP_SAPI === 'cli') {
$this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.'); $this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.');
} }
if (extension_loaded('apcu')) {
$this->_apcExtension = 'apcu';
}
$this->_cacheDisable = Configure::read('Cache.disable'); $this->_cacheDisable = Configure::read('Cache.disable');
Configure::write('Cache.disable', false); Configure::write('Cache.disable', false);
Cache::config('apc', array('engine' => 'Apc', 'prefix' => 'cake_')); Cache::config('apc', array('engine' => 'Apc', 'prefix' => 'cake_'));
@ -147,7 +159,8 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDecrement() { public function testDecrement() {
$this->skipIf(!function_exists('apc_dec'), 'No apc_dec() function, cannot test decrement().'); $hasSupport = function_exists('apc_dec') || function_exists('apcu_dec');
$this->skipIf(!$hasSupport, 'No apc_dec()/apcu_dec() function, cannot test decrement().');
$result = Cache::write('test_decrement', 5, 'apc'); $result = Cache::write('test_decrement', 5, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
@ -171,7 +184,8 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testIncrement() { public function testIncrement() {
$this->skipIf(!function_exists('apc_inc'), 'No apc_inc() function, cannot test increment().'); $hasSupport = function_exists('apc_inc') || function_exists('apcu_inc');
$this->skipIf(!function_exists('apc_inc'), 'No apc_inc()/apcu_inc() function, cannot test increment().');
$result = Cache::write('test_increment', 5, 'apc'); $result = Cache::write('test_increment', 5, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
@ -195,14 +209,18 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testClear() { public function testClear() {
apc_store('not_cake', 'survive'); $storeFunc = $this->_apcExtension . '_store';
$fetchFunc = $this->_apcExtension . '_fetch';
$deleteFunc = $this->_apcExtension . '_delete';
$storeFunc('not_cake', 'survive');
Cache::write('some_value', 'value', 'apc'); Cache::write('some_value', 'value', 'apc');
$result = Cache::clear(false, 'apc'); $result = Cache::clear(false, 'apc');
$this->assertTrue($result); $this->assertTrue($result);
$this->assertFalse(Cache::read('some_value', 'apc')); $this->assertFalse(Cache::read('some_value', 'apc'));
$this->assertEquals('survive', apc_fetch('not_cake')); $this->assertEquals('survive', $fetchFunc('not_cake'));
apc_delete('not_cake'); $deleteFunc('not_cake');
} }
/** /**
@ -213,6 +231,7 @@ class ApcEngineTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testGroupsReadWrite() { public function testGroupsReadWrite() {
$incFunc = $this->_apcExtension . '_inc';
Cache::config('apc_groups', array( Cache::config('apc_groups', array(
'engine' => 'Apc', 'engine' => 'Apc',
'duration' => 0, 'duration' => 0,
@ -222,12 +241,12 @@ class ApcEngineTest extends CakeTestCase {
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_a'); $incFunc('test_group_a');
$this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_b'); $incFunc('test_group_b');
$this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'apc_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'apc_groups'));

View file

@ -222,7 +222,7 @@ class ControllerTaskTest extends CakeTestCase {
public function testDoComponentsNo() { public function testDoComponentsNo() {
$this->Task->expects($this->any())->method('in')->will($this->returnValue('n')); $this->Task->expects($this->any())->method('in')->will($this->returnValue('n'));
$result = $this->Task->doComponents(); $result = $this->Task->doComponents();
$this->assertSame(array('Paginator', 'Flash'), $result); $this->assertSame(array('Paginator'), $result);
} }
/** /**
@ -235,7 +235,7 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security ')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security '));
$result = $this->Task->doComponents(); $result = $this->Task->doComponents();
$expected = array('Paginator', 'Flash', 'RequestHandler', 'Security'); $expected = array('Paginator', 'RequestHandler', 'Security');
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
@ -249,7 +249,7 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security, , ')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security, , '));
$result = $this->Task->doComponents(); $result = $this->Task->doComponents();
$expected = array('Paginator', 'Flash', 'RequestHandler', 'Security'); $expected = array('Paginator', 'RequestHandler', 'Security');
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }

View file

@ -618,6 +618,9 @@ class RequestHandlerComponentTest extends CakeTestCase {
$_SERVER['REQUEST_METHOD'] = 'DELETE'; $_SERVER['REQUEST_METHOD'] = 'DELETE';
$this->assertEquals('json', $this->RequestHandler->requestedWith()); $this->assertEquals('json', $this->RequestHandler->requestedWith());
$_SERVER['REQUEST_METHOD'] = 'PATCH';
$this->assertEquals('json', $this->RequestHandler->requestedWith());
$_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['REQUEST_METHOD'] = 'POST';
unset($_SERVER['CONTENT_TYPE']); unset($_SERVER['CONTENT_TYPE']);
$_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json';

View file

@ -168,7 +168,13 @@ class SqliteTest extends CakeTestCase {
$dbName = 'db' . rand() . '$(*%&).db'; $dbName = 'db' . rand() . '$(*%&).db';
$this->assertFalse(file_exists(TMP . $dbName)); $this->assertFalse(file_exists(TMP . $dbName));
$db = new Sqlite(array_merge($this->Dbo->config, array('database' => TMP . $dbName))); try {
$db = new Sqlite(array_merge($this->Dbo->config, array('database' => TMP . $dbName)));
} catch (MissingConnectionException $e) {
// This might be caused by NTFS file systems, where '*' is a forbidden character. Repeat without this character.
$dbName = str_replace('*', '', $dbName);
$db = new Sqlite(array_merge($this->Dbo->config, array('database' => TMP . $dbName)));
}
$this->assertTrue(file_exists(TMP . $dbName)); $this->assertTrue(file_exists(TMP . $dbName));
$db->execute("CREATE TABLE test_list (id VARCHAR(255));"); $db->execute("CREATE TABLE test_list (id VARCHAR(255));");
@ -422,6 +428,40 @@ class SqliteTest extends CakeTestCase {
$this->Dbo->query('DROP TABLE ' . $tableName); $this->Dbo->query('DROP TABLE ' . $tableName);
} }
/**
* Test that describe ignores `default current_timestamp` in timestamp columns.
*
* @return void
*/
public function testDescribeHandleCurrentTimestamp() {
$name = $this->Dbo->fullTableName('timestamp_default_values');
$sql = <<<SQL
CREATE TABLE $name (
id INT NOT NULL,
phone VARCHAR(10),
limit_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
SQL;
$this->Dbo->execute($sql);
$model = new Model(array(
'table' => 'timestamp_default_values',
'ds' => 'test',
'alias' => 'TimestampDefaultValue'
));
$result = $this->Dbo->describe($model);
$this->Dbo->execute('DROP TABLE ' . $name);
$this->assertNull($result['limit_date']['default']);
$schema = new CakeSchema(array(
'connection' => 'test',
'testdescribes' => $result
));
$result = $this->Dbo->createSchema($schema);
$this->assertContains('"limit_date" timestamp NOT NULL', $result);
}
/** /**
* Test virtualFields with functions. * Test virtualFields with functions.
* *
@ -466,6 +506,7 @@ class SqliteTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testNestedTransaction() { public function testNestedTransaction() {
$this->Dbo->useNestedTransactions = true;
$this->skipIf($this->Dbo->nestedTransactionSupported() === false, 'The Sqlite version do not support nested transaction'); $this->skipIf($this->Dbo->nestedTransactionSupported() === false, 'The Sqlite version do not support nested transaction');
$this->loadFixtures('User'); $this->loadFixtures('User');

View file

@ -318,11 +318,6 @@ class CakeSocketTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testEnableCrypto() { public function testEnableCrypto() {
// testing on ssl server
$this->_connectSocketToSslTls();
$this->assertTrue($this->Socket->enableCrypto('sslv3', 'client'));
$this->Socket->disconnect();
// testing on tls server // testing on tls server
$this->_connectSocketToSslTls(); $this->_connectSocketToSslTls();
$this->assertTrue($this->Socket->enableCrypto('tls', 'client')); $this->assertTrue($this->Socket->enableCrypto('tls', 'client'));

View file

@ -1227,4 +1227,85 @@ class FolderTest extends CakeTestCase {
$Folder->delete(); $Folder->delete();
} }
/**
* testSortByTime method
*
* Verify that the order using modified time is correct.
*
* @return void
*/
public function testSortByTime() {
$Folder = new Folder(TMP . 'test_sort_by_time', true);
$file2 = new File($Folder->pwd() . DS . 'file_2.tmp');
$file2->create();
sleep(1);
$file1 = new File($Folder->pwd() . DS . 'file_1.tmp');
$file1->create();
$expected = array('file_2.tmp', 'file_1.tmp');
$result = $Folder->find('.*', Folder::SORT_TIME);
$this->assertSame($expected, $result);
$Folder->delete();
}
/**
* testSortByTime2 method
*
* Verify that the sort order using modified time is correct.
*
* @return void
*/
public function testSortByTime2() {
$Folder = new Folder(TMP . 'test_sort_by_time2', true);
$fileC = new File($Folder->pwd() . DS . 'c.txt');
$fileC->create();
sleep(1);
$fileA = new File($Folder->pwd() . DS . 'a.txt');
$fileA->create();
sleep(1);
$fileB = new File($Folder->pwd() . DS . 'b.txt');
$fileB->create();
$expected = array('c.txt', 'a.txt', 'b.txt');
$result = $Folder->find('.*', Folder::SORT_TIME);
$this->assertSame($expected, $result);
$Folder->delete();
}
/**
* Verify that the sort order using name is correct.
*
* @return void
*/
public function testSortByName() {
$Folder = new Folder(TMP . 'test_sort_by_name', true);
$fileA = new File($Folder->pwd() . DS . 'a.txt');
$fileA->create();
$fileC = new File($Folder->pwd() . DS . 'c.txt');
$fileC->create();
sleep(1);
$fileB = new File($Folder->pwd() . DS . 'b.txt');
$fileB->create();
$expected = array('a.txt', 'b.txt', 'c.txt');
$result = $Folder->find('.*', Folder::SORT_NAME);
$this->assertSame($expected, $result);
$Folder->delete();
}
} }

View file

@ -1599,6 +1599,28 @@ class FormHelperTest extends CakeTestCase {
$this->assertEquals(array(), $this->Form->fields); $this->assertEquals(array(), $this->Form->fields);
} }
/**
* test reset unlockFields, when create new form.
*
* @return void
*/
public function testResetUnlockFields() {
$this->Form->request['_Token'] = array(
'key' => 'testKey',
'unlockedFields' => array()
);
$this->Form->unlockField('Contact.id');
$this->Form->create('Contact');
$this->Form->hidden('Contact.id', array('value' => 1));
$this->assertEmpty($this->Form->fields, 'Field should be unlocked');
$this->Form->end();
$this->Form->create('Contact');
$this->Form->hidden('Contact.id', array('value' => 1));
$this->assertEquals(1, $this->Form->fields['Contact.id'], 'Hidden input should be secured.');
}
/** /**
* testTagIsInvalid method * testTagIsInvalid method
* *
@ -3940,6 +3962,25 @@ class FormHelperTest extends CakeTestCase {
); );
$this->assertTags($result, $expected); $this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('option A', 'option B'), array('fieldset' => 'classy-stuff'));
$expected = array(
'fieldset' => array('class' => 'classy-stuff'),
'legend' => array(),
'Field',
'/legend',
'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'),
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')),
array('label' => array('for' => 'ModelField0')),
'option A',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'option B',
'/label',
'/fieldset'
);
$this->assertTags($result, $expected);
$result = $this->Form->radio( $result = $this->Form->radio(
'Employee.gender', 'Employee.gender',
array('male' => 'Male', 'female' => 'Female'), array('male' => 'Male', 'female' => 'Female'),

View file

@ -46,6 +46,16 @@ class Folder {
*/ */
const SKIP = 'skip'; const SKIP = 'skip';
/**
* Sort mode by name
*/
const SORT_NAME = 'name';
/**
* Sort mode by time
*/
const SORT_TIME = 'time';
/** /**
* Path to Folder. * Path to Folder.
* *
@ -71,6 +81,14 @@ class Folder {
*/ */
public $mode = 0755; public $mode = 0755;
/**
* Functions array to be called depending on the sort type chosen.
*/
protected $_fsorts = array(
self::SORT_NAME => 'getPathname',
self::SORT_TIME => 'getCTime'
);
/** /**
* Holds messages from last method. * Holds messages from last method.
* *
@ -155,14 +173,14 @@ class Folder {
* Returns an array of the contents of the current directory. * Returns an array of the contents of the current directory.
* The returned array holds two arrays: One of directories and one of files. * The returned array holds two arrays: One of directories and one of files.
* *
* @param bool $sort Whether you want the results sorted, set this and the sort property * @param string|bool $sort Whether you want the results sorted, set this and the sort property
* to false to get unsorted results. * to false to get unsorted results.
* @param array|bool $exceptions Either an array or boolean true will not grab dot files * @param array|bool $exceptions Either an array or boolean true will not grab dot files
* @param bool $fullPath True returns the full path * @param bool $fullPath True returns the full path
* @return mixed Contents of current directory as an array, an empty array on failure * @return mixed Contents of current directory as an array, an empty array on failure
* @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::read * @link http://book.cakephp.org/2.0/en/core-utility-libraries/file-folder.html#Folder::read
*/ */
public function read($sort = true, $exceptions = false, $fullPath = false) { public function read($sort = self::SORT_NAME, $exceptions = false, $fullPath = false) {
$dirs = $files = array(); $dirs = $files = array();
if (!$this->pwd()) { if (!$this->pwd()) {
@ -178,6 +196,11 @@ class Folder {
} catch (Exception $e) { } catch (Exception $e) {
return array($dirs, $files); return array($dirs, $files);
} }
if (!is_bool($sort) && isset($this->_fsorts[$sort])) {
$methodName = $this->_fsorts[$sort];
} else {
$methodName = $this->_fsorts[self::SORT_NAME];
}
foreach ($iterator as $item) { foreach ($iterator as $item) {
if ($item->isDot()) { if ($item->isDot()) {
@ -191,14 +214,22 @@ class Folder {
$name = $item->getPathName(); $name = $item->getPathName();
} }
if ($item->isDir()) { if ($item->isDir()) {
$dirs[] = $name; $dirs[$item->{$methodName}()][] = $name;
} else { } else {
$files[] = $name; $files[$item->{$methodName}()][] = $name;
} }
} }
if ($sort || $this->sort) { if ($sort || $this->sort) {
sort($dirs); ksort($dirs);
sort($files); ksort($files);
}
if ($dirs) {
$dirs = call_user_func_array('array_merge', $dirs);
}
if ($files) {
$files = call_user_func_array('array_merge', $files);
} }
return array($dirs, $files); return array($dirs, $files);
} }

View file

@ -191,8 +191,10 @@ class Security {
E_USER_WARNING E_USER_WARNING
); );
$bytes = ''; $bytes = '';
while ($bytes < $length) { $byteLength = 0;
while ($byteLength < $length) {
$bytes .= static::hash(CakeText::uuid() . uniqid(mt_rand(), true), 'sha512', true); $bytes .= static::hash(CakeText::uuid() . uniqid(mt_rand(), true), 'sha512', true);
$byteLength = strlen($bytes);
} }
return substr($bytes, 0, $length); return substr($bytes, 0, $length);
} }

View file

@ -17,4 +17,4 @@
// @license http://www.opensource.org/licenses/mit-license.php MIT License // @license http://www.opensource.org/licenses/mit-license.php MIT License
// +--------------------------------------------------------------------------------------------+ // // +--------------------------------------------------------------------------------------------+ //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
2.8.3 2.8.5

View file

@ -560,6 +560,7 @@ class FormHelper extends AppHelper {
$this->setEntity(null); $this->setEntity(null);
$out .= $this->Html->useTag('formend'); $out .= $this->Html->useTag('formend');
$this->_unlockedFields = array();
$this->_View->modelScope = false; $this->_View->modelScope = false;
$this->requestType = null; $this->requestType = null;
return $out; return $out;
@ -932,9 +933,12 @@ class FormHelper extends AppHelper {
if (isset($options['legend'])) { if (isset($options['legend'])) {
$legend = $options['legend']; $legend = $options['legend'];
unset($options['legend']);
} }
if (isset($options['fieldset'])) { if (isset($options['fieldset'])) {
$fieldset = $options['fieldset']; $fieldset = $options['fieldset'];
unset($options['fieldset']);
} }
if (empty($fields)) { if (empty($fields)) {
@ -972,7 +976,7 @@ class FormHelper extends AppHelper {
} }
if (is_string($fieldset)) { if (is_string($fieldset)) {
$fieldsetClass = sprintf(' class="%s"', $fieldset); $fieldsetClass = array('class' => $fieldset);
} else { } else {
$fieldsetClass = ''; $fieldsetClass = '';
} }
@ -1512,6 +1516,7 @@ class FormHelper extends AppHelper {
* - `between` - the string between legend and input set or array of strings to insert * - `between` - the string between legend and input set or array of strings to insert
* strings between each input block * strings between each input block
* - `legend` - control whether or not the widget set has a fieldset & legend * - `legend` - control whether or not the widget set has a fieldset & legend
* - `fieldset` - sets the class of the fieldset. Fieldset is only generated if legend attribute is provided
* - `value` - indicate a value that is should be checked * - `value` - indicate a value that is should be checked
* - `label` - boolean to indicate whether or not labels for widgets show be displayed * - `label` - boolean to indicate whether or not labels for widgets show be displayed
* - `hiddenField` - boolean to indicate if you want the results of radio() to include * - `hiddenField` - boolean to indicate if you want the results of radio() to include
@ -1546,6 +1551,12 @@ class FormHelper extends AppHelper {
$legend = __(Inflector::humanize($this->field())); $legend = __(Inflector::humanize($this->field()));
} }
$fieldsetAttrs = '';
if (isset($attributes['fieldset'])) {
$fieldsetAttrs = array('class' => $attributes['fieldset']);
unset($attributes['fieldset']);
}
$label = true; $label = true;
if (isset($attributes['label'])) { if (isset($attributes['label'])) {
$label = $attributes['label']; $label = $attributes['label'];
@ -1639,8 +1650,10 @@ class FormHelper extends AppHelper {
if (is_array($between)) { if (is_array($between)) {
$between = ''; $between = '';
} }
if ($legend) { if ($legend) {
$out = $this->Html->useTag('fieldset', '', $this->Html->useTag('legend', $legend) . $between . $out); $out = $this->Html->useTag('legend', $legend) . $between . $out;
$out = $this->Html->useTag('fieldset', $fieldsetAttrs, $out);
} }
return $out; return $out;
} }