mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 03:18:26 +00:00
Merge branch 'master' into 2.6
Conflicts: lib/Cake/Model/Model.php
This commit is contained in:
commit
051d78c1a5
8 changed files with 172 additions and 9 deletions
|
@ -33,14 +33,14 @@ chance of keeping on top of things.
|
|||
* Core test cases should continue to pass. You can run tests locally or enable
|
||||
[travis-ci](https://travis-ci.org/) for your fork, so all tests and codesniffs
|
||||
will be executed.
|
||||
* Your work should apply the CakePHP coding standards.
|
||||
* Your work should apply the [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html).
|
||||
|
||||
## Which branch to base the work
|
||||
|
||||
* Bugfix branches will be based on master.
|
||||
* New features that are backwards compatible will be based on next minor release
|
||||
branch.
|
||||
* New features or other non-BC changes will go in the next major release branch.
|
||||
* New features or other non backwards compatible changes will go in the next major release branch.
|
||||
|
||||
## Submitting Changes
|
||||
|
||||
|
@ -51,7 +51,7 @@ chance of keeping on top of things.
|
|||
## Test cases and codesniffer
|
||||
|
||||
CakePHP tests requires [PHPUnit](http://www.phpunit.de/manual/current/en/installation.html)
|
||||
3.5 or higher. To run the test cases locally use the following command:
|
||||
3.7, version 4 is not compatible. To run the test cases locally use the following command:
|
||||
|
||||
./lib/Cake/Console/cake test core AllTests --stderr
|
||||
|
||||
|
@ -60,7 +60,7 @@ To run the sniffs for CakePHP coding standards:
|
|||
phpcs -p --extensions=php --standard=CakePHP ./lib/Cake
|
||||
|
||||
Check the [cakephp-codesniffer](https://github.com/cakephp/cakephp-codesniffer)
|
||||
repository to setup the CakePHP standard. The README contains installation info
|
||||
repository to setup the CakePHP standard. The [README](https://github.com/cakephp/cakephp-codesniffer/blob/master/README.mdown) contains installation info
|
||||
for the sniff and phpcs.
|
||||
|
||||
# Additional Resources
|
||||
|
|
|
@ -261,6 +261,9 @@ class Postgres extends DboSource {
|
|||
$this->_sequenceMap[$table][$c->name] = $sequenceName;
|
||||
}
|
||||
}
|
||||
if ($fields[$c->name]['type'] === 'timestamp' && $fields[$c->name]['default'] === '') {
|
||||
$fields[$c->name]['default'] = null;
|
||||
}
|
||||
if ($fields[$c->name]['type'] === 'boolean' && !empty($fields[$c->name]['default'])) {
|
||||
$fields[$c->name]['default'] = constant($fields[$c->name]['default']);
|
||||
}
|
||||
|
|
|
@ -2399,7 +2399,7 @@ class DboSource extends DataSource {
|
|||
return $conditions;
|
||||
}
|
||||
$exists = $Model->exists();
|
||||
if (!$exists && $conditions !== null) {
|
||||
if (!$exists && ($conditions !== null || !empty($Model->__safeUpdateMode))) {
|
||||
return false;
|
||||
} elseif (!$exists) {
|
||||
return null;
|
||||
|
|
|
@ -593,6 +593,14 @@ class Model extends Object implements CakeEventListener {
|
|||
*/
|
||||
public $__backContainableAssociation = array();
|
||||
|
||||
/**
|
||||
* Safe update mode
|
||||
* If true, this prevents Model::save() from generating a query with WHERE 1 = 1 on race condition.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $__safeUpdateMode = false;
|
||||
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
/**
|
||||
|
@ -1689,6 +1697,7 @@ class Model extends Object implements CakeEventListener {
|
|||
* @param array $fieldList List of fields to allow to be saved
|
||||
* @return mixed On success Model::$data if its not empty or true, false on failure
|
||||
* @throws Exception
|
||||
* @throws PDOException
|
||||
* @link http://book.cakephp.org/2.0/en/models/saving-your-data.html
|
||||
*/
|
||||
public function save($data = null, $validate = true, $fieldList = array()) {
|
||||
|
@ -1869,7 +1878,14 @@ class Model extends Object implements CakeEventListener {
|
|||
$cache = $this->_prepareUpdateFields(array_combine($fields, $values));
|
||||
|
||||
if (!empty($this->id)) {
|
||||
$success = (bool)$db->update($this, $fields, $values);
|
||||
$this->__safeUpdateMode = true;
|
||||
try {
|
||||
$success = (bool)$db->update($this, $fields, $values);
|
||||
} catch (Exception $e) {
|
||||
$this->__safeUpdateMode = false;
|
||||
throw $e;
|
||||
}
|
||||
$this->__safeUpdateMode = false;
|
||||
} else {
|
||||
if (empty($this->data[$this->alias][$this->primaryKey]) && $this->_isUUIDField($this->primaryKey)) {
|
||||
if (array_key_exists($this->primaryKey, $this->data[$this->alias])) {
|
||||
|
|
|
@ -162,8 +162,8 @@ class PostgresClientTestModel extends Model {
|
|||
'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'),
|
||||
'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'),
|
||||
'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'),
|
||||
'created' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''),
|
||||
'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null)
|
||||
'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'length' => ''),
|
||||
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null, 'length' => null)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -551,6 +551,7 @@ class PostgresTest extends CakeTestCase {
|
|||
'connection' => 'test',
|
||||
'models' => array('DatatypeTest')
|
||||
));
|
||||
|
||||
$schema->tables = array(
|
||||
'datatype_tests' => $result['tables']['missing']['datatype_tests']
|
||||
);
|
||||
|
@ -1098,4 +1099,49 @@ class PostgresTest extends CakeTestCase {
|
|||
$this->assertNotContains($scientificNotation, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test describe() behavior for timestamp columns.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDescribeTimestamp() {
|
||||
$this->loadFixtures('User');
|
||||
$model = ClassRegistry::init('User');
|
||||
$result = $this->Dbo->describe($model);
|
||||
$expected = array(
|
||||
'id' => array(
|
||||
'type' => 'integer',
|
||||
'null' => false,
|
||||
'default' => null,
|
||||
'length' => 11,
|
||||
'key' => 'primary'
|
||||
),
|
||||
'user' => array(
|
||||
'type' => 'string',
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'length' => 255
|
||||
),
|
||||
'password' => array(
|
||||
'type' => 'string',
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'length' => 255
|
||||
),
|
||||
'created' => array(
|
||||
'type' => 'datetime',
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'length' => null
|
||||
),
|
||||
'updated' => array(
|
||||
'type' => 'datetime',
|
||||
'null' => true,
|
||||
'default' => null,
|
||||
'length' => null
|
||||
)
|
||||
);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ require_once dirname(dirname(__FILE__)) . DS . 'models.php';
|
|||
*/
|
||||
class MockPDO extends PDO {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
|
@ -1412,4 +1415,45 @@ class DboSourceTest extends CakeTestCase {
|
|||
$result = $db->insertMulti('articles', array_keys($data[0]), $data);
|
||||
$this->assertTrue($result, 'Data was saved');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test defaultConditions()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDefaultConditions() {
|
||||
$this->loadFixtures('Article');
|
||||
$Article = ClassRegistry::init('Article');
|
||||
$db = $Article->getDataSource();
|
||||
|
||||
// Creates a default set of conditions from the model if $conditions is null/empty.
|
||||
$Article->id = 1;
|
||||
$result = $db->defaultConditions($Article, null);
|
||||
$this->assertEquals(array('Article.id' => 1), $result);
|
||||
|
||||
// $useAlias == false
|
||||
$Article->id = 1;
|
||||
$result = $db->defaultConditions($Article, null, false);
|
||||
$this->assertEquals(array($db->fullTableName($Article, false) . '.id' => 1), $result);
|
||||
|
||||
// If conditions are supplied then they will be returned.
|
||||
$Article->id = 1;
|
||||
$result = $db->defaultConditions($Article, array('Article.title' => 'First article'));
|
||||
$this->assertEquals(array('Article.title' => 'First article'), $result);
|
||||
|
||||
// If a model doesn't exist and no conditions were provided either null or false will be returned based on what was input.
|
||||
$Article->id = 1000000;
|
||||
$result = $db->defaultConditions($Article, null);
|
||||
$this->assertNull($result);
|
||||
|
||||
$Article->id = 1000000;
|
||||
$result = $db->defaultConditions($Article, false);
|
||||
$this->assertFalse($result);
|
||||
|
||||
// Safe update mode
|
||||
$Article->id = 1000000;
|
||||
$Article->__safeUpdateMode = true;
|
||||
$result = $db->defaultConditions($Article, null);
|
||||
$this->assertFalse($result);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6625,6 +6625,11 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$this->assertEquals(array(6, 4, 5, 2), $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* testToggleBoolFields method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testToggleBoolFields() {
|
||||
$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
|
||||
$Post = new CounterCachePost();
|
||||
|
@ -7515,4 +7520,53 @@ class ModelWriteTest extends BaseModelTest {
|
|||
$this->assertFalse(isset($model->data['Bid']['name']));
|
||||
$this->assertFalse(isset($model->data['Bid']['message_id']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that Model::save() doesn't generate a query with WHERE 1 = 1 on race condition.
|
||||
*
|
||||
* @link https://github.com/cakephp/cakephp/issues/3857
|
||||
* @return void
|
||||
*/
|
||||
public function testSafeUpdateMode() {
|
||||
$this->loadFixtures('User');
|
||||
|
||||
$User = ClassRegistry::init('User');
|
||||
$this->assertFalse($User->__safeUpdateMode);
|
||||
|
||||
$User->getEventManager()->attach(array($this, 'deleteMe'), 'Model.beforeSave');
|
||||
|
||||
$User->id = 1;
|
||||
$User->set(array('user' => 'nobody'));
|
||||
$User->save();
|
||||
|
||||
$users = $User->find('list', array('fields' => 'User.user'));
|
||||
|
||||
$expected = array(
|
||||
2 => 'nate',
|
||||
3 => 'larry',
|
||||
4 => 'garrett',
|
||||
);
|
||||
$this->assertEquals($expected, $users);
|
||||
$this->assertFalse($User->__safeUpdateMode);
|
||||
|
||||
$User->id = 2;
|
||||
$User->set(array('user' => $User->getDataSource()->expression('PDO_EXCEPTION()')));
|
||||
try {
|
||||
$User->save(null, false);
|
||||
$this->fail('No exception thrown');
|
||||
} catch (PDOException $e) {
|
||||
$this->assertFalse($User->__safeUpdateMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulates race condition
|
||||
*
|
||||
* @param CakeEvent $event containing the Model
|
||||
* @return void
|
||||
*/
|
||||
public function deleteMe($event) {
|
||||
$Model = $event->subject;
|
||||
$Model->getDataSource()->delete($Model, array($Model->alias . '.' . $Model->primaryKey => $Model->id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,7 +289,7 @@ class CakeTestFixture {
|
|||
foreach ($this->records as $record) {
|
||||
$merge = array_values(array_merge($default, $record));
|
||||
if (count($fields) !== count($merge)) {
|
||||
throw new CakeException('Fixture invalid: Count of fields does not match count of values');
|
||||
throw new CakeException('Fixture invalid: Count of fields does not match count of values in ' . get_class($this));
|
||||
}
|
||||
$values[] = $merge;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue