mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
Improving validation support in Model::saveAll(), adding tests for cross-database joins, disproves #4251
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6511 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
parent
33c0fec53a
commit
0ee0324e20
4 changed files with 313 additions and 141 deletions
|
@ -425,11 +425,12 @@ class DboSource extends DataSource {
|
||||||
function logQuery($sql) {
|
function logQuery($sql) {
|
||||||
$this->_queriesCnt++;
|
$this->_queriesCnt++;
|
||||||
$this->_queriesTime += $this->took;
|
$this->_queriesTime += $this->took;
|
||||||
$this->_queriesLog[] = array('query' => $sql,
|
$this->_queriesLog[] = array(
|
||||||
'error' => $this->error,
|
'query' => $sql,
|
||||||
'affected' => $this->affected,
|
'error' => $this->error,
|
||||||
'numRows' => $this->numRows,
|
'affected' => $this->affected,
|
||||||
'took' => $this->took
|
'numRows' => $this->numRows,
|
||||||
|
'took' => $this->took
|
||||||
);
|
);
|
||||||
if (count($this->_queriesLog) > $this->_queriesLogMax) {
|
if (count($this->_queriesLog) > $this->_queriesLogMax) {
|
||||||
array_pop($this->_queriesLog);
|
array_pop($this->_queriesLog);
|
||||||
|
|
|
@ -843,12 +843,11 @@ class Model extends Overloadable {
|
||||||
return $this->_schema;
|
return $this->_schema;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* See Model::schema
|
|
||||||
*
|
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @see Model::schema()
|
* @see Model::schema()
|
||||||
*/
|
*/
|
||||||
function loadInfo($clear = false) {
|
function loadInfo($clear = false) {
|
||||||
|
trigger_error(__('(Model::loadInfo) Deprecated - See Model::schema()', true), E_USER_WARNING);
|
||||||
$info = $this->schema($clear);
|
$info = $this->schema($clear);
|
||||||
if (is_array($info)) {
|
if (is_array($info)) {
|
||||||
$fields = array();
|
$fields = array();
|
||||||
|
@ -1040,11 +1039,18 @@ class Model extends Overloadable {
|
||||||
function save($data = null, $validate = true, $fieldList = array()) {
|
function save($data = null, $validate = true, $fieldList = array()) {
|
||||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||||
$_whitelist = $this->whitelist;
|
$_whitelist = $this->whitelist;
|
||||||
|
$defaults = array('validate' => true, 'fieldList' => array(), 'callbacks' => true);
|
||||||
$fields = array();
|
$fields = array();
|
||||||
|
|
||||||
if (!empty($fieldList)) {
|
if (!is_array($validate)) {
|
||||||
$this->whitelist = $fieldList;
|
$options = array_merge($defaults, compact('validate', 'fieldList', 'callbacks'));
|
||||||
} elseif ($fieldList === null) {
|
} else {
|
||||||
|
$options = array_merge($defaults, $validate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($options['fieldList'])) {
|
||||||
|
$this->whitelist = $options['fieldList'];
|
||||||
|
} elseif ($options['fieldList'] === null) {
|
||||||
$this->whitelist = array();
|
$this->whitelist = array();
|
||||||
}
|
}
|
||||||
$this->set($data);
|
$this->set($data);
|
||||||
|
@ -1059,17 +1065,15 @@ class Model extends Overloadable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$exists = $this->exists();
|
$exists = $this->exists();
|
||||||
|
|
||||||
$dateFields = array('modified', 'updated');
|
$dateFields = array('modified', 'updated');
|
||||||
|
|
||||||
if (!$exists) {
|
if (!$exists) {
|
||||||
$dateFields[] = 'created';
|
$dateFields[] = 'created';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->data[$this->alias])) {
|
if (isset($this->data[$this->alias])) {
|
||||||
$fields = array_keys($this->data[$this->alias]);
|
$fields = array_keys($this->data[$this->alias]);
|
||||||
}
|
}
|
||||||
|
if ($options['validate'] && !$this->validates()) {
|
||||||
if ($validate && !$this->validates()) {
|
|
||||||
$this->whitelist = $_whitelist;
|
$this->whitelist = $_whitelist;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1089,9 +1093,11 @@ class Model extends Overloadable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->Behaviors->trigger('beforeSave', array(), array('break' => true, 'breakOn' => false)) || !$this->beforeSave()) {
|
if ($options['callbacks'] === true || $options['callbacks'] == 'before') {
|
||||||
$this->whitelist = $_whitelist;
|
if (!$this->Behaviors->trigger('beforeSave', array(), array('break' => true, 'breakOn' => false)) || !$this->beforeSave()) {
|
||||||
return false;
|
$this->whitelist = $_whitelist;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$fields = $values = array();
|
$fields = $values = array();
|
||||||
|
|
||||||
|
@ -1164,8 +1170,10 @@ class Model extends Overloadable {
|
||||||
if (!empty($this->data)) {
|
if (!empty($this->data)) {
|
||||||
$success = $this->data;
|
$success = $this->data;
|
||||||
}
|
}
|
||||||
$this->Behaviors->trigger('afterSave', array($created));
|
if ($options['callbacks'] === true || $options['callbacks'] == 'after') {
|
||||||
$this->afterSave($created);
|
$this->Behaviors->trigger('afterSave', array($created));
|
||||||
|
$this->afterSave($created);
|
||||||
|
}
|
||||||
if (!empty($this->data)) {
|
if (!empty($this->data)) {
|
||||||
$success = Set::pushDiff($success, $this->data);
|
$success = Set::pushDiff($success, $this->data);
|
||||||
}
|
}
|
||||||
|
@ -1269,9 +1277,16 @@ class Model extends Overloadable {
|
||||||
* Saves (a) multiple individual records for a single model or (b) this record, as well as
|
* Saves (a) multiple individual records for a single model or (b) this record, as well as
|
||||||
* all associated records
|
* all associated records
|
||||||
*
|
*
|
||||||
* @param array $data Record data to save
|
* @param array $data Record data to save. This can be either a numerically-indexed array (for saving multiple
|
||||||
* @param array $options
|
* records of the same type), or an array indexed by association name.
|
||||||
* @return mixed True on success, or an array of validation errors on failure
|
* @param array $options Options to use when saving record data, which are as follows:
|
||||||
|
* - validate: Set to false to disable validation, true to validate each record before
|
||||||
|
* saving, 'first' to validate *all* records before any are saved, or 'only' to only
|
||||||
|
* validate the records, but not save them.
|
||||||
|
* - atomic: If true (default), will attempt to save all records in a single transaction.
|
||||||
|
* Should be set to false if database/table does not support transactions
|
||||||
|
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
||||||
|
* @return mixed True on success, or false on failure
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
function saveAll($data = null, $options = array()) {
|
function saveAll($data = null, $options = array()) {
|
||||||
|
@ -1280,138 +1295,130 @@ class Model extends Overloadable {
|
||||||
}
|
}
|
||||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||||
|
|
||||||
$options = array_merge(array('validate' => true, 'fieldList' => array(), 'atomic' => true), $options);
|
$options = array_merge(array('validate' => true, 'atomic' => true), $options);
|
||||||
$validationErrors = array();
|
$this->validationErrors = $validationErrors = array();
|
||||||
$validates = true;
|
$validates = true;
|
||||||
$return = array();
|
$return = array();
|
||||||
|
|
||||||
if ($options['atomic']) {
|
if ($options['atomic'] && $options['validate'] !== 'only') {
|
||||||
$db->begin($this);
|
$db->begin($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Set::numeric(array_keys($data))) {
|
if (Set::numeric(array_keys($data))) {
|
||||||
if ($options['validate'] === 'first' || $options['validate'] === 'only') {
|
while ($validates) {
|
||||||
$this->validationErrors = array();
|
|
||||||
|
|
||||||
foreach ($data as $record) {
|
foreach ($data as $record) {
|
||||||
if (!($this->create($record) && $this->validates())) {
|
if (!$validates = $this->__save($this, $record, $options)) {
|
||||||
$validationErrors[] = $this->validationErrors;
|
if (empty($this->id)) {
|
||||||
$validates = false;
|
$validationErrors[] = $this->validationErrors;
|
||||||
}
|
} else {
|
||||||
}
|
$validationErrors[$this->id] = $this->validationErrors;
|
||||||
if (!$validates) {
|
|
||||||
$this->validationErrors = $validationErrors;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($data as $record) {
|
|
||||||
if (!($this->create($record) && $result = $this->save(null, $options['validate'] !== false, $options['fieldList'])) && $options['atomic']) {
|
|
||||||
if ($options['atomic']) {
|
|
||||||
$db->rollback($this);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$return[] = $result[$this->alias];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$associations = $this->getAssociated();
|
|
||||||
|
|
||||||
if ($options['validate'] === 'first' || $options['validate'] === 'only') {
|
|
||||||
foreach ($data as $association => $values) {
|
|
||||||
if (isset($associations[$association]) && ($type = $associations[$association]) == 'belongsTo') {
|
|
||||||
if (!($this->{$association}->create($values) && $this->{$association}->validates())) {
|
|
||||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
|
||||||
$validates = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!($this->create($data[$this->alias]) && $this->validates())) {
|
$this->validationErrors = $validationErrors;
|
||||||
$validationErrors[$this->alias] = $this->validationErrors;
|
|
||||||
$validates = false;
|
|
||||||
}
|
|
||||||
foreach ($data as $association => $values) {
|
|
||||||
if (isset($associations[$association])) {
|
|
||||||
switch ($associations[$association]) {
|
|
||||||
case 'hasOne':
|
|
||||||
$type = $associations[$association];
|
|
||||||
$this->{$association}->set($this->{$type}[$association]['foreignKey'], $this->id);
|
|
||||||
if (!($this->{$association}->create($values) && $this->{$association}->validates())) {
|
|
||||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
|
||||||
$validates = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'hasMany':
|
|
||||||
if (!$this->{$association}->saveAll($values, array('validate' => 'only'))) {
|
|
||||||
$validationErrors[$association] = $this->{$association}->validationErrors;
|
|
||||||
$validates = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($options['validate'] === 'only') {
|
|
||||||
if (empty($validationErrors)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$this->validationErrors = $validationErrors;
|
|
||||||
return $validates;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($data as $association => $values) {
|
switch (true) {
|
||||||
if (isset($associations[$association]) && ($type = $associations[$association]) == 'belongsTo') {
|
case ($options['validate'] === 'only'):
|
||||||
$alias = $this->{$association}->alias;
|
return $validates;
|
||||||
$foreignKey = $this->{$type}[$association]['foreignKey'];
|
break;
|
||||||
|
case ($options['validate'] === 'first'):
|
||||||
if (!$result = $this->{$association}->save($values, ($options['validate'] !== false), $options['fieldList'])) {
|
$options['validate'] = true;
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
if ($options['atomic']) {
|
if ($options['atomic']) {
|
||||||
$db->rollback($this);
|
if ($validates) {
|
||||||
|
return ($db->commit($this) !== false);
|
||||||
|
} else {
|
||||||
|
$db->rollback($this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return $validates;
|
||||||
} elseif (!isset($data[$foreignKey]) || empty($data[$foreignKey])) {
|
break;
|
||||||
$data[$this->alias][$foreignKey] = $this->{$association}->id;
|
|
||||||
}
|
|
||||||
$return[$association] = $result[$association];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return $validates;
|
||||||
|
}
|
||||||
|
$associations = $this->getAssociated();
|
||||||
|
|
||||||
if (!$result = $this->save($data[$this->alias], ($options['validate'] !== false), $options['fieldList'])) {
|
while ($validates) {
|
||||||
if ($options['atomic']) {
|
|
||||||
$db->rollback($this);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($data as $association => $values) {
|
foreach ($data as $association => $values) {
|
||||||
if (isset($associations[$association])) {
|
if (isset($associations[$association])) {
|
||||||
switch ($associations[$association]) {
|
switch ($associations[$association]) {
|
||||||
case 'hasOne':
|
case 'belongsTo':
|
||||||
$type = $associations[$association];
|
if ($this->__save($this->{$association}, $values, $options)) {
|
||||||
$this->{$association}->set($this->{$type}[$association]['foreignKey'], $this->id);
|
$data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
|
||||||
if (!$result = $this->{$association}->save($values, ($options['validate'] !== false), $options['fieldList'])) {
|
} else {
|
||||||
if ($options['atomic']) {
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||||
$db->rollback($this);
|
$validates = false;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'hasMany':
|
|
||||||
if (!$result = $this->{$association}->saveAll($values, $options)) {
|
|
||||||
if ($options['atomic']) {
|
|
||||||
$db->rollback($this);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$return[$association] = $result[$association];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!$this->__save($this, $data[$this->alias], $options)) {
|
||||||
|
$validationErrors[$this->alias] = $this->validationErrors;
|
||||||
|
$validates = false;
|
||||||
|
}
|
||||||
|
foreach ($data as $association => $values) {
|
||||||
|
if (isset($associations[$association])) {
|
||||||
|
$type = $associations[$association];
|
||||||
|
switch ($type) {
|
||||||
|
case 'hasOne':
|
||||||
|
$values[$this->{$type}[$association]['foreignKey']] = $this->id;
|
||||||
|
if (!$this->__save($this->{$association}, $values, $options)) {
|
||||||
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||||
|
$validates = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'hasMany':
|
||||||
|
foreach ($values as $i => $value) {
|
||||||
|
$values[$i][$this->{$type}[$association]['foreignKey']] = $this->id;
|
||||||
|
}
|
||||||
|
if (!$this->{$association}->saveAll($values, array('validate' => 'only'))) {
|
||||||
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
||||||
|
$validates = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->validationErrors = $validationErrors;
|
||||||
|
|
||||||
if ($options['atomic']) {
|
switch (true) {
|
||||||
return ($db->commit($this) !== false);
|
case ($options['validate'] === 'only'):
|
||||||
|
return $validates;
|
||||||
|
break;
|
||||||
|
case ($options['validate'] === 'first'):
|
||||||
|
$options['validate'] = true;
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ($options['atomic']) {
|
||||||
|
if ($validates) {
|
||||||
|
return ($db->commit($this) !== false);
|
||||||
|
} else {
|
||||||
|
$db->rollback($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $validates;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Private helper method used by saveAll
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @see Model::saveAll()
|
||||||
|
*/
|
||||||
|
function __save(&$model, $data, $options) {
|
||||||
|
if ($options['validate'] === 'first' || $options['validate'] === 'only') {
|
||||||
|
if (!($model->create($data) && $this->validates())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} elseif (!($model->create($data) && $model->save(null, $options))) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1876,22 +1876,23 @@ class ModelTest extends CakeTestCase {
|
||||||
);
|
);
|
||||||
$this->assertEqual($result, $expected);
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
$data = array('Article' => array('id' => 10, 'user_id' => '2', 'title' => 'New Article With Tags and fieldList',
|
$data = array(
|
||||||
'body' => 'New Article Body with Tags and fieldList', 'created' => '2007-03-18 14:55:23',
|
'Article' => array('id' => 10, 'user_id' => '2', 'title' => 'New Article With Tags and fieldList', 'body' => 'New Article Body with Tags and fieldList', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31'),
|
||||||
'updated' => '2007-03-18 14:57:31'),
|
'Tag' => array('Tag' => array(1, 2, 3))
|
||||||
'Tag' => array('Tag' => array(1, 2, 3)));
|
);
|
||||||
$result = $this->model->create() && $this->model->save($data, true, array('user_id', 'title', 'published'));
|
$result = $this->model->create() && $this->model->save($data, true, array('user_id', 'title', 'published'));
|
||||||
$this->assertTrue($result);
|
$this->assertTrue($result);
|
||||||
|
|
||||||
$this->model->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')));
|
$this->model->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')));
|
||||||
$result = $this->model->read();
|
$result = $this->model->read();
|
||||||
$expected = array('Article' => array('id' => 4,
|
$expected = array(
|
||||||
'user_id' => 2, 'title' => 'New Article With Tags and fieldList',
|
'Article' => array('id' => 4, 'user_id' => 2, 'title' => 'New Article With Tags and fieldList', 'body' => '', 'published' => 'N', 'created' => '', 'updated' => ''),
|
||||||
'body' => '', 'published' => 'N', 'created' => '', 'updated' => ''),
|
'Tag' => array(
|
||||||
'Tag' => array(
|
0 => array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'),
|
||||||
0 => array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'),
|
1 => array('id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31'),
|
||||||
1 => array('id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31'),
|
2 => array('id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31')
|
||||||
2 => array('id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31')));
|
)
|
||||||
|
);
|
||||||
$this->assertEqual($result, $expected);
|
$this->assertEqual($result, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1956,6 +1957,59 @@ class ModelTest extends CakeTestCase {
|
||||||
$this->assertEqual($result[6]['Attachment'], $expected);
|
$this->assertEqual($result[6]['Attachment'], $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSaveAllValidation() {
|
||||||
|
$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
|
||||||
|
$this->model =& new Post();
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
array('id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N'),
|
||||||
|
array('id' => '2', 'title' => 'Just update the title'),
|
||||||
|
array('title' => 'Creating a fourth post', 'body' => 'Fourth post body')
|
||||||
|
);
|
||||||
|
$ts = date('Y-m-d H:i:s');
|
||||||
|
$this->assertTrue($this->model->saveAll($data));
|
||||||
|
|
||||||
|
$result = $this->model->find('all', array('recursive' => -1));
|
||||||
|
$expected = array(
|
||||||
|
array('Post' => array('id' => '1', 'author_id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N', 'created' => '2007-03-18 10:39:23', 'updated' => $ts)),
|
||||||
|
array('Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'N', 'created' => '2007-03-18 10:41:23', 'updated' => $ts)),
|
||||||
|
array('Post' => array('id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31')),
|
||||||
|
array('Post' => array('id' => '4', 'author_id' => '0', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N', 'created' => $ts, 'updated' => $ts))
|
||||||
|
);
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
|
||||||
|
$this->model->validate = array('title' => VALID_NOT_EMPTY, 'author_id' => 'numeric');
|
||||||
|
$data = array(
|
||||||
|
array('id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y'),
|
||||||
|
array('id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title'),
|
||||||
|
);
|
||||||
|
$ts = date('Y-m-d H:i:s');
|
||||||
|
$this->assertFalse($this->model->saveAll($data));
|
||||||
|
|
||||||
|
$expected[0]['Post'] = array_merge($expected[0]['Post'], $data[0], array('updated' => $ts));
|
||||||
|
$result = $this->model->find('all', array('recursive' => -1));
|
||||||
|
$errors = array(2 => array('title' => 'This field cannot be left blank'));
|
||||||
|
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
$this->assertEqual($this->model->validationErrors, $errors);
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
array('id' => '1', 'title' => 'Re-Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N'),
|
||||||
|
array('id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title'),
|
||||||
|
);
|
||||||
|
$this->assertFalse($this->model->saveAll($data, array('validate' => 'first')));
|
||||||
|
|
||||||
|
$result = $this->model->find('all', array('recursive' => -1));
|
||||||
|
$this->assertEqual($result, $expected);
|
||||||
|
$this->assertEqual($this->model->validationErrors, $errors);
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
array('title' => 'First new post', 'body' => 'Woohoo!', 'published' => 'Y'),
|
||||||
|
array('title' => 'Empty body', 'body' => '')
|
||||||
|
);
|
||||||
|
$this->model->validate['body'] = VALID_NOT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
function testSaveWithCounterCache() {
|
function testSaveWithCounterCache() {
|
||||||
$this->loadFixtures('Syfile', 'Item');
|
$this->loadFixtures('Syfile', 'Item');
|
||||||
$this->model =& new Syfile();
|
$this->model =& new Syfile();
|
||||||
|
@ -3049,6 +3103,116 @@ class ModelTest extends CakeTestCase {
|
||||||
$this->assertFalse(isset($this->model->Behaviors->Tree));
|
$this->assertFalse(isset($this->model->Behaviors->Tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests cross database joins. Requires $test and $test2 to both be set in DATABASE_CONFIG
|
||||||
|
* NOTE: When testing on MySQL, you must set 'persistent' => false on *both* database connections,
|
||||||
|
* or one connection will step on the other.
|
||||||
|
*/
|
||||||
|
function testCrossDatabaseJoins() {
|
||||||
|
$config = new DATABASE_CONFIG();
|
||||||
|
|
||||||
|
if (!isset($config->test) || !isset($config->test2)) {
|
||||||
|
echo "<br />Primary and secondary test databases not configured, skipping cross-database join tests<br />";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->loadFixtures('Article', 'Tag', 'ArticlesTag', 'User', 'Comment');
|
||||||
|
$this->model =& new Article();
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
array(
|
||||||
|
'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'),
|
||||||
|
'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'),
|
||||||
|
'Comment' => array(
|
||||||
|
array('id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'),
|
||||||
|
array('id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'),
|
||||||
|
array('id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31'),
|
||||||
|
array('id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31')
|
||||||
|
),
|
||||||
|
'Tag' => array(
|
||||||
|
array('id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'),
|
||||||
|
array('id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31')
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'),
|
||||||
|
'User' => array('id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31'),
|
||||||
|
'Comment' => array(
|
||||||
|
array('id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31'),
|
||||||
|
array('id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31')
|
||||||
|
),
|
||||||
|
'Tag' => array(
|
||||||
|
array('id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'),
|
||||||
|
array('id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31')
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'),
|
||||||
|
'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'),
|
||||||
|
'Comment' => array(),
|
||||||
|
'Tag' => array()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->model->find('all'), $expected);
|
||||||
|
|
||||||
|
$db2 =& ConnectionManager::getDataSource('test2');
|
||||||
|
|
||||||
|
foreach (array('User', 'Comment') as $class) {
|
||||||
|
$this->_fixtures[$this->_fixtureClassMap[$class]]->create($db2);
|
||||||
|
$this->_fixtures[$this->_fixtureClassMap[$class]]->insert($db2);
|
||||||
|
$this->db->truncate(Inflector::pluralize(Inflector::underscore($class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEqual($this->model->User->find('all'), array());
|
||||||
|
$this->assertEqual($this->model->Comment->find('all'), array());
|
||||||
|
$this->assertEqual($this->model->find('count'), 3);
|
||||||
|
|
||||||
|
$this->model->User->setDataSource('test2');
|
||||||
|
$this->model->Comment->setDataSource('test2');
|
||||||
|
|
||||||
|
$result = Set::extract($this->model->User->find('all'), '{n}.User.id');
|
||||||
|
$this->assertEqual($result, array('1', '2', '3', '4'));
|
||||||
|
$this->assertEqual($this->model->find('all'), $expected);
|
||||||
|
|
||||||
|
$this->model->Comment->unbindModel(array('hasOne' => array('Attachment')));
|
||||||
|
$expected = array(
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'),
|
||||||
|
'User' => array('id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31'),
|
||||||
|
'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31')
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'),
|
||||||
|
'User' => array('id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31'),
|
||||||
|
'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31')
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31'),
|
||||||
|
'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'),
|
||||||
|
'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31')
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31'),
|
||||||
|
'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'),
|
||||||
|
'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31')
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31'),
|
||||||
|
'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'),
|
||||||
|
'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31')
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Comment' => array('id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31'),
|
||||||
|
'User' => array('id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31'),
|
||||||
|
'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->assertEqual($this->model->Comment->find('all'), $expected);
|
||||||
|
|
||||||
|
foreach (array('User', 'Comment') as $class) {
|
||||||
|
$fixture =& $this->_fixtures[$this->_fixtureClassMap[$class]]->drop($db2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function endTest() {
|
function endTest() {
|
||||||
ClassRegistry::flush();
|
ClassRegistry::flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ class User extends CakeTestModel {
|
||||||
class Article extends CakeTestModel {
|
class Article extends CakeTestModel {
|
||||||
var $name = 'Article';
|
var $name = 'Article';
|
||||||
var $belongsTo = array('User');
|
var $belongsTo = array('User');
|
||||||
var $hasMany = array('Comment' => array('className'=>'Comment', 'dependent' => true));
|
var $hasMany = array('Comment' => array('dependent' => true));
|
||||||
var $hasAndBelongsToMany = array('Tag');
|
var $hasAndBelongsToMany = array('Tag');
|
||||||
var $validate = array('user_id' => VALID_NUMBER, 'title' => array('allowEmpty' => false, 'rule' => VALID_NOT_EMPTY), 'body' => VALID_NOT_EMPTY);
|
var $validate = array('user_id' => VALID_NUMBER, 'title' => array('allowEmpty' => false, 'rule' => VALID_NOT_EMPTY), 'body' => VALID_NOT_EMPTY);
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ class ArticleFeaturedsTag extends CakeTestModel {
|
||||||
class Comment extends CakeTestModel {
|
class Comment extends CakeTestModel {
|
||||||
var $name = 'Comment';
|
var $name = 'Comment';
|
||||||
var $belongsTo = array('Article', 'User');
|
var $belongsTo = array('Article', 'User');
|
||||||
var $hasOne = array('Attachment' => array('className'=>'Attachment', 'dependent' => true));
|
var $hasOne = array('Attachment' => array('dependent' => true));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Short description for class.
|
* Short description for class.
|
||||||
|
|
Loading…
Add table
Reference in a new issue