mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Merge branch 'master' into 2.5
Conflicts: lib/Cake/VERSION.txt
This commit is contained in:
commit
3cee3b0e99
11 changed files with 320 additions and 14 deletions
31
composer.json
Normal file
31
composer.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "cakephp/cakephp",
|
||||
"description": "The CakePHP framework",
|
||||
"type": "library",
|
||||
"keywords": ["framework"],
|
||||
"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.2.8",
|
||||
"ext-mcrypt": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "3.7.*",
|
||||
"cakephp/debug_kit" : "2.2.*"
|
||||
},
|
||||
"bin": [
|
||||
"lib/Cake/Console/cake"
|
||||
]
|
||||
}
|
|
@ -29,7 +29,7 @@ App::uses('CakeEventManager', 'Event');
|
|||
*
|
||||
* Controllers should provide a number of 'action' methods. These are public methods on the controller
|
||||
* that are not prefixed with a '_' and not part of Controller. Each action serves as an endpoint for
|
||||
* performing a specific action on a resource or collection of resources. For example adding or editing a new
|
||||
* performing a specific action on a resource or collection of resources. For example: adding or editing a new
|
||||
* object, or listing a set of objects.
|
||||
*
|
||||
* You can access request parameters, using `$this->request`. The request object contains all the POST, GET and FILES
|
||||
|
@ -259,7 +259,7 @@ class Controller extends Object implements CakeEventListener {
|
|||
|
||||
/**
|
||||
* Holds current methods of the controller. This is a list of all the methods reachable
|
||||
* via URL. Modifying this array, will allow you to change which methods can be reached.
|
||||
* via URL. Modifying this array will allow you to change which methods can be reached.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
|
@ -285,7 +285,7 @@ class Controller extends Object implements CakeEventListener {
|
|||
public $modelKey = null;
|
||||
|
||||
/**
|
||||
* Holds any validation errors produced by the last call of the validateErrors() method/
|
||||
* Holds any validation errors produced by the last call of the validateErrors() method.
|
||||
*
|
||||
* @var array Validation errors, or false if none
|
||||
*/
|
||||
|
@ -610,7 +610,7 @@ class Controller extends Object implements CakeEventListener {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all events that will fire in the controller during it's lifecycle.
|
||||
* Returns a list of all events that will fire in the controller during its lifecycle.
|
||||
* You can override this function to add you own listener callbacks
|
||||
*
|
||||
* @return array
|
||||
|
|
|
@ -212,7 +212,7 @@ class TreeBehavior extends ModelBehavior {
|
|||
'fields' => array($Model->primaryKey, $parent, $left, $right), 'recursive' => $recursive)
|
||||
);
|
||||
|
||||
if ($values === false) {
|
||||
if (empty($values)) {
|
||||
return false;
|
||||
}
|
||||
list($node) = array_values($values);
|
||||
|
|
|
@ -129,7 +129,7 @@ class Postgres extends DboSource {
|
|||
$this->setEncoding($config['encoding']);
|
||||
}
|
||||
if (!empty($config['schema'])) {
|
||||
$this->_execute('SET search_path TO ' . $config['schema']);
|
||||
$this->_execute('SET search_path TO "' . $config['schema'] . '"');
|
||||
}
|
||||
if (!empty($config['settings'])) {
|
||||
foreach ($config['settings'] as $key => $value) {
|
||||
|
|
|
@ -299,6 +299,7 @@ class CakeResponse {
|
|||
'vcf' => 'text/x-vcard',
|
||||
'vtt' => 'text/vtt',
|
||||
'mkv' => 'video/x-matroska',
|
||||
'pkpass' => 'application/vnd.apple.pkpass'
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,6 +130,29 @@ class TreeBehaviorScopedTest extends CakeTestCase {
|
|||
$this->assertEquals(11, $this->Tree->find('count'));
|
||||
}
|
||||
|
||||
/**
|
||||
* testSaveWithParentAndInvalidScope method
|
||||
*
|
||||
* Attempting to save an invalid data should not trigger an `Undefined offset`
|
||||
* error
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSaveWithParentAndInvalidScope() {
|
||||
$this->Tree = new FlagTree();
|
||||
$this->Tree->order = null;
|
||||
$data = $this->Tree->create(array(
|
||||
'name' => 'Flag',
|
||||
));
|
||||
$tree = $this->Tree->save($data);
|
||||
$this->Tree->Behaviors->load('Tree', array(
|
||||
'scope' => array('FlagTree.flag' => 100)
|
||||
));
|
||||
$tree['FlagTree']['parent_id'] = 1;
|
||||
$result = $this->Tree->save($tree);
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testMoveUpWithScope method
|
||||
*
|
||||
|
|
|
@ -2464,6 +2464,25 @@ class MysqlTest extends CakeTestCase {
|
|||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test conditions() with replacements.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testConditionsWithReplacements() {
|
||||
$result = $this->Dbo->conditions(array(
|
||||
'score BETWEEN :0 AND :1' => array(90.1, 95.7)
|
||||
));
|
||||
$expected = " WHERE `score` BETWEEN 90.1 AND 95.7";
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$result = $this->Dbo->conditions(array(
|
||||
'score BETWEEN ? AND ?' => array(90.1, 95.7)
|
||||
));
|
||||
$expected = " WHERE `score` BETWEEN 90.1 AND 95.7";
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that array conditions with only one element work.
|
||||
*
|
||||
|
|
|
@ -3329,8 +3329,8 @@ class FormHelperTest extends CakeTestCase {
|
|||
$expected = array(
|
||||
'input' => array('type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'),
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array('type' => 'checkbox', 'name' => 'data[Model][multi_field][]', 'value' => '1/2', 'id' => 'ModelMultiField12')),
|
||||
array('label' => array('for' => 'ModelMultiField12')),
|
||||
array('input' => array('type' => 'checkbox', 'name' => 'data[Model][multi_field][]', 'value' => '1/2', 'id' => 'ModelMultiField1/2')),
|
||||
array('label' => array('for' => 'ModelMultiField1/2')),
|
||||
'half',
|
||||
'/label',
|
||||
'/div',
|
||||
|
@ -3610,8 +3610,8 @@ class FormHelperTest extends CakeTestCase {
|
|||
$result = $this->Form->radio('Model.field', array('1/2' => 'half'));
|
||||
$expected = array(
|
||||
'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'),
|
||||
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1/2', 'id' => 'ModelField12')),
|
||||
'label' => array('for' => 'ModelField12'),
|
||||
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1/2', 'id' => 'ModelField1/2')),
|
||||
'label' => array('for' => 'ModelField1/2'),
|
||||
'half',
|
||||
'/label'
|
||||
);
|
||||
|
@ -3738,6 +3738,38 @@ class FormHelperTest extends CakeTestCase {
|
|||
'/fieldset'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Form->radio(
|
||||
'Model.field',
|
||||
array('a>b' => 'first', 'a<b' => 'second', 'a"b' => 'third')
|
||||
);
|
||||
$expected = array(
|
||||
'fieldset' => array(),
|
||||
'legend' => array(),
|
||||
'Field',
|
||||
'/legend',
|
||||
'input' => array(
|
||||
'type' => 'hidden', 'name' => 'data[Model][field]',
|
||||
'id' => 'ModelField_', 'value' => '',
|
||||
),
|
||||
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
|
||||
'id' => 'ModelFieldAB', 'value' => 'a>b')),
|
||||
array('label' => array('for' => 'ModelFieldAB')),
|
||||
'first',
|
||||
'/label',
|
||||
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
|
||||
'id' => 'ModelFieldAB1', 'value' => 'a<b')),
|
||||
array('label' => array('for' => 'ModelFieldAB1')),
|
||||
'second',
|
||||
'/label',
|
||||
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]',
|
||||
'id' => 'ModelFieldAB2', 'value' => 'a"b')),
|
||||
array('label' => array('for' => 'ModelFieldAB2')),
|
||||
'third',
|
||||
'/label',
|
||||
'/fieldset'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4257,6 +4289,50 @@ class FormHelperTest extends CakeTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* testDomIdSuffix method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDomIdSuffix() {
|
||||
$result = $this->Form->domIdSuffix('1 string with 1$-dollar signs');
|
||||
$this->assertEquals('1StringWith1$-dollarSigns', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('<abc x="foo" y=\'bar\'>');
|
||||
$this->assertEquals('AbcX=FooY=Bar', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('1 string with 1$-dollar signs', 'xhtml');
|
||||
$this->assertEquals('1StringWith1-dollarSigns', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('<abc x="foo" y=\'bar\'>', 'xhtml');
|
||||
$this->assertEquals('AbcXFooYBar', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testDomIdSuffixCollisionResolvement()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDomIdSuffixCollisionResolvement() {
|
||||
$result = $this->Form->domIdSuffix('a>b');
|
||||
$this->assertEquals('AB', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('a<b');
|
||||
$this->assertEquals('AB1', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('a\'b');
|
||||
$this->assertEquals('AB2', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('1 string with 1$-dollar', 'xhtml');
|
||||
$this->assertEquals('1StringWith1-dollar', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('1 string with 1€-dollar', 'xhtml');
|
||||
$this->assertEquals('1StringWith1-dollar1', $result);
|
||||
|
||||
$result = $this->Form->domIdSuffix('1 string with 1$-dollar', 'xhtml');
|
||||
$this->assertEquals('1StringWith1-dollar2', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testSelect method
|
||||
*
|
||||
|
@ -4697,6 +4773,34 @@ class FormHelperTest extends CakeTestCase {
|
|||
'/select'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Form->select(
|
||||
'Model.multi_field',
|
||||
array('a>b' => 'first', 'a<b' => 'second', 'a"b' => 'third'),
|
||||
array('multiple' => true)
|
||||
);
|
||||
$expected = array(
|
||||
'input' => array(
|
||||
'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '',
|
||||
'id' => 'ModelMultiField_'
|
||||
),
|
||||
array('select' => array('name' => 'data[Model][multi_field][]',
|
||||
'multiple' => 'multiple', 'id' => 'ModelMultiField'
|
||||
)),
|
||||
array('option' => array('value' => 'a>b')),
|
||||
'first',
|
||||
'/option',
|
||||
array('option' => array('value' => 'a<b')),
|
||||
'second',
|
||||
'/option',
|
||||
array('option' => array(
|
||||
'value' => 'a"b'
|
||||
)),
|
||||
'third',
|
||||
'/option',
|
||||
'/select'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5105,6 +5209,84 @@ class FormHelperTest extends CakeTestCase {
|
|||
'/div'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Form->select(
|
||||
'Model.multi_field',
|
||||
array('a+' => 'first', 'a++' => 'second', 'a+++' => 'third'),
|
||||
array('multiple' => 'checkbox')
|
||||
);
|
||||
$expected = array(
|
||||
'input' => array(
|
||||
'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'
|
||||
),
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a+', 'id' => 'ModelMultiFieldA+'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldA+')),
|
||||
'first',
|
||||
'/label',
|
||||
'/div',
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a++', 'id' => 'ModelMultiFieldA++'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldA++')),
|
||||
'second',
|
||||
'/label',
|
||||
'/div',
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a+++', 'id' => 'ModelMultiFieldA+++'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldA+++')),
|
||||
'third',
|
||||
'/label',
|
||||
'/div'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Form->select(
|
||||
'Model.multi_field',
|
||||
array('a>b' => 'first', 'a<b' => 'second', 'a"b' => 'third'),
|
||||
array('multiple' => 'checkbox')
|
||||
);
|
||||
$expected = array(
|
||||
'input' => array(
|
||||
'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'
|
||||
),
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a>b', 'id' => 'ModelMultiFieldAB2'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldAB2')),
|
||||
'first',
|
||||
'/label',
|
||||
'/div',
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a<b', 'id' => 'ModelMultiFieldAB1'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldAB1')),
|
||||
'second',
|
||||
'/label',
|
||||
'/div',
|
||||
array('div' => array('class' => 'checkbox')),
|
||||
array('input' => array(
|
||||
'type' => 'checkbox', 'name' => 'data[Model][multi_field][]',
|
||||
'value' => 'a"b', 'id' => 'ModelMultiFieldAB'
|
||||
)),
|
||||
array('label' => array('for' => 'ModelMultiFieldAB')),
|
||||
'third',
|
||||
'/label',
|
||||
'/div'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -851,6 +851,16 @@ class HelperTest extends CakeTestCase {
|
|||
$this->assertEquals('&lt;script&gt;alert(document.cookie)&lt;/script&gt;', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testDomId method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDomId() {
|
||||
$result = $this->Helper->domId('Foo.bar');
|
||||
$this->assertEquals('FooBar', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testMultiDimensionalField method
|
||||
*
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
App::uses('Router', 'Routing');
|
||||
App::uses('Hash', 'Utility');
|
||||
App::uses('Inflector', 'Utility');
|
||||
|
||||
/**
|
||||
* Abstract base class for all other Helpers in CakePHP.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
App::uses('ClassRegistry', 'Utility');
|
||||
App::uses('AppHelper', 'View/Helper');
|
||||
App::uses('Hash', 'Utility');
|
||||
App::uses('Inflector', 'Utility');
|
||||
|
||||
/**
|
||||
* Form helper library.
|
||||
|
@ -109,6 +110,13 @@ class FormHelper extends AppHelper {
|
|||
*/
|
||||
public $validationErrors = array();
|
||||
|
||||
/**
|
||||
* Holds already used DOM ID suffixes to avoid collisions with multiple form field elements.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_domIdSuffixes = array();
|
||||
|
||||
/**
|
||||
* Copies the validationErrors variable from the View object into this instance
|
||||
*
|
||||
|
@ -1510,6 +1518,7 @@ class FormHelper extends AppHelper {
|
|||
$value = $value ? 1 : 0;
|
||||
}
|
||||
|
||||
$this->_domIdSuffixes = array();
|
||||
foreach ($options as $optValue => $optTitle) {
|
||||
$optionsHere = array('value' => $optValue, 'disabled' => false);
|
||||
|
||||
|
@ -1520,9 +1529,7 @@ class FormHelper extends AppHelper {
|
|||
if ($disabled && (!is_array($disabled) || in_array((string)$optValue, $disabled, !$isNumeric))) {
|
||||
$optionsHere['disabled'] = true;
|
||||
}
|
||||
$tagName = Inflector::camelize(
|
||||
$attributes['id'] . '_' . Inflector::slug($optValue)
|
||||
);
|
||||
$tagName = $attributes['id'] . $this->domIdSuffix($optValue);
|
||||
|
||||
if ($label) {
|
||||
$labelOpts = is_array($label) ? $label : array();
|
||||
|
@ -2086,6 +2093,34 @@ class FormHelper extends AppHelper {
|
|||
return implode("\n", $select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a valid DOM ID suffix from a string.
|
||||
* Also avoids collisions when multiple values are coverted to the same suffix by
|
||||
* appending a numeric value.
|
||||
*
|
||||
* For pre-HTML5 IDs only characters like a-z 0-9 - _ are valid. HTML5 doesn't have that
|
||||
* limitation, but to avoid layout issues it still filters out some sensitive chars.
|
||||
*
|
||||
* @param string $value The value that should be transferred into a DOM ID suffix.
|
||||
* @param string $type Doctype to use. Defaults to html5. Anything else will use limited chars.
|
||||
* @return string DOM ID
|
||||
*/
|
||||
public function domIdSuffix($value, $type = 'html5') {
|
||||
if ($type === 'html5') {
|
||||
$value = str_replace(array('<', '>', ' ', '"', '\''), '_', $value);
|
||||
} else {
|
||||
$value = preg_replace('~[^\\pL\d-_]+~u', '_', $value);
|
||||
}
|
||||
$value = Inflector::camelize($value);
|
||||
$count = 1;
|
||||
$suffix = $value;
|
||||
while (in_array($suffix, $this->_domIdSuffixes)) {
|
||||
$suffix = $value . $count++;
|
||||
}
|
||||
$this->_domIdSuffixes[] = $suffix;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SELECT element for days.
|
||||
*
|
||||
|
@ -2626,6 +2661,7 @@ class FormHelper extends AppHelper {
|
|||
$selectedIsEmpty = ($attributes['value'] === '' || $attributes['value'] === null);
|
||||
$selectedIsArray = is_array($attributes['value']);
|
||||
|
||||
$this->_domIdSuffixes = array();
|
||||
foreach ($elements as $name => $title) {
|
||||
$htmlOptions = array();
|
||||
if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) {
|
||||
|
@ -2694,7 +2730,7 @@ class FormHelper extends AppHelper {
|
|||
if ($attributes['style'] === 'checkbox') {
|
||||
$htmlOptions['value'] = $name;
|
||||
|
||||
$tagName = $attributes['id'] . Inflector::camelize(Inflector::slug($name));
|
||||
$tagName = $attributes['id'] . $this->domIdSuffix($name);
|
||||
$htmlOptions['id'] = $tagName;
|
||||
$label = array('for' => $tagName);
|
||||
|
||||
|
@ -2713,6 +2749,9 @@ class FormHelper extends AppHelper {
|
|||
$item = $this->Html->useTag('checkboxmultiple', $name, $htmlOptions);
|
||||
$select[] = $this->Html->div($attributes['class'], $item . $label);
|
||||
} else {
|
||||
if ($attributes['escape']) {
|
||||
$name = h($name);
|
||||
}
|
||||
$select[] = $this->Html->useTag('selectoption', $name, $htmlOptions, $title);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue