|
|
@@ -1974,6 +1974,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
* 'AssociatedModel' => array('field', 'otherfield')
|
|
|
* )
|
|
|
* }}}
|
|
|
+ * - deep: see saveMany/saveAssociated
|
|
|
*
|
|
|
* @param array $data Record data to save. This can be either a numerically-indexed array (for saving multiple
|
|
|
* records of the same type), or an array indexed by association name.
|
|
|
@@ -1993,11 +1994,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
return $this->saveMany($data, $options);
|
|
|
}
|
|
|
if ($options['validate'] === 'only') {
|
|
|
- $validatesAssoc = $this->validateAssociated($data, $options);
|
|
|
- if (isset($this->validationErrors[$this->alias]) && $this->validationErrors[$this->alias] === false) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- return $validatesAssoc;
|
|
|
+ return $this->validateAssociated($data, $options);
|
|
|
}
|
|
|
return $this->saveAssociated($data, $options);
|
|
|
}
|
|
|
@@ -2012,6 +2009,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
* - 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()
|
|
|
+ * - deep: If set to true, all associated data will be saved as well.
|
|
|
*
|
|
|
* @param array $data Record data to save. This should be a numerically-indexed array
|
|
|
* @param array $options Options to use when saving record data, See $options above.
|
|
|
@@ -2025,7 +2023,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
$data = $this->data;
|
|
|
}
|
|
|
|
|
|
- $options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
|
|
|
+ $options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
|
|
|
$this->validationErrors = $validationErrors = array();
|
|
|
|
|
|
if (empty($data) && $options['validate'] !== false) {
|
|
|
@@ -2046,12 +2044,21 @@ class Model extends Object implements CakeEventListener {
|
|
|
}
|
|
|
$return = array();
|
|
|
foreach ($data as $key => $record) {
|
|
|
- $validates = ($this->create(null) !== null && $this->save($record, $options));
|
|
|
+ $validates = $this->create(null) !== null;
|
|
|
+ $saved = false;
|
|
|
+ if ($validates) {
|
|
|
+ if ($options['deep']) {
|
|
|
+ $saved = $this->saveAssociated($record, array_merge($options, array('atomic' => false)));
|
|
|
+ } else {
|
|
|
+ $saved = $this->save($record, $options);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true))));
|
|
|
if (!$validates) {
|
|
|
$validationErrors[$key] = $this->validationErrors;
|
|
|
}
|
|
|
if (!$options['atomic']) {
|
|
|
- $return[] = $validates;
|
|
|
+ $return[$key] = $validates;
|
|
|
} elseif (!$validates) {
|
|
|
break;
|
|
|
}
|
|
|
@@ -2079,6 +2086,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
*
|
|
|
* - atomic: If true (default), returns boolean. If false returns array.
|
|
|
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
|
|
+ * - deep: If set to true, all associated data will be validated as well.
|
|
|
*
|
|
|
* @param array $data Record data to validate. This should be a numerically-indexed array
|
|
|
* @param array $options Options to use when validating record data (see above), See also $options of validates().
|
|
|
@@ -2088,14 +2096,21 @@ class Model extends Object implements CakeEventListener {
|
|
|
* depending on whether each record validated successfully.
|
|
|
*/
|
|
|
public function validateMany($data, $options = array()) {
|
|
|
- $options = array_merge(array('atomic' => true), $options);
|
|
|
+ $options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
|
|
$this->validationErrors = $validationErrors = $return = array();
|
|
|
foreach ($data as $key => $record) {
|
|
|
- $validates = $this->create($record) && $this->validates($options);
|
|
|
- if (!$validates) {
|
|
|
+ if ($options['deep']) {
|
|
|
+ $validates = $this->validateAssociated($record, $options);
|
|
|
+ } else {
|
|
|
+ $validates = $this->create($record) && $this->validates($options);
|
|
|
+ }
|
|
|
+ if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) {
|
|
|
$validationErrors[$key] = $this->validationErrors;
|
|
|
+ $validates = false;
|
|
|
+ } else {
|
|
|
+ $validates = true;
|
|
|
}
|
|
|
- $return[] = $validates;
|
|
|
+ $return[$key] = $validates;
|
|
|
}
|
|
|
$this->validationErrors = $validationErrors;
|
|
|
if (!$options['atomic']) {
|
|
|
@@ -2124,6 +2139,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
* 'AssociatedModel' => array('field', 'otherfield')
|
|
|
* )
|
|
|
* }}}
|
|
|
+ * - deep: If set to true, not only directly associated data is saved, but deeper nested associated data as well.
|
|
|
*
|
|
|
* @param array $data Record data to save. This should be an array indexed by association name.
|
|
|
* @param array $options Options to use when saving record data, See $options above.
|
|
|
@@ -2137,7 +2153,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
$data = $this->data;
|
|
|
}
|
|
|
|
|
|
- $options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
|
|
|
+ $options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
|
|
|
$this->validationErrors = $validationErrors = array();
|
|
|
|
|
|
if (empty($data) && $options['validate'] !== false) {
|
|
|
@@ -2160,13 +2176,26 @@ class Model extends Object implements CakeEventListener {
|
|
|
$validates = true;
|
|
|
foreach ($data as $association => $values) {
|
|
|
if (isset($associations[$association]) && $associations[$association] === 'belongsTo') {
|
|
|
- if ($this->{$association}->create(null) !== null && $this->{$association}->save($values, $options)) {
|
|
|
- $data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
|
|
|
+ $validates = $this->{$association}->create(null) !== null;
|
|
|
+ $saved = false;
|
|
|
+ if ($validates) {
|
|
|
+ if ($options['deep']) {
|
|
|
+ $saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
|
|
+ } else {
|
|
|
+ $saved = $this->{$association}->save($values, array_merge($options, array('atomic' => false)));
|
|
|
+ }
|
|
|
+ $validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
|
|
|
+ }
|
|
|
+ if ($validates) {
|
|
|
+ if (!empty($data[$this->alias])) {
|
|
|
+ $data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
|
|
|
+ } else {
|
|
|
+ $data[$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
|
|
|
+ }
|
|
|
} else {
|
|
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
|
|
- $validates = false;
|
|
|
}
|
|
|
- $return[$association][] = $validates;
|
|
|
+ $return[$association] = $validates;
|
|
|
}
|
|
|
}
|
|
|
if ($validates && !($this->create(null) !== null && $this->save($data, $options))) {
|
|
|
@@ -2184,11 +2213,20 @@ class Model extends Object implements CakeEventListener {
|
|
|
switch ($type) {
|
|
|
case 'hasOne':
|
|
|
$values[$this->{$type}[$association]['foreignKey']] = $this->id;
|
|
|
- if (!($this->{$association}->create(null) !== null && $this->{$association}->save($values, $options))) {
|
|
|
+ $validates = $this->{$association}->create(null) !== null;
|
|
|
+ $saved = false;
|
|
|
+ if ($validates) {
|
|
|
+ if ($options['deep']) {
|
|
|
+ $saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
|
|
|
+ } else {
|
|
|
+ $saved = $this->{$association}->save($values, $options);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true))));
|
|
|
+ if (!$validates) {
|
|
|
$validationErrors[$association] = $this->{$association}->validationErrors;
|
|
|
- $validates = false;
|
|
|
}
|
|
|
- $return[$association][] = $validates;
|
|
|
+ $return[$association] = $validates;
|
|
|
break;
|
|
|
case 'hasMany':
|
|
|
foreach ($values as $i => $value) {
|
|
|
@@ -2231,6 +2269,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
*
|
|
|
* - atomic: If true (default), returns boolean. If false returns array.
|
|
|
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
|
|
|
+ * - deep: If set to true, not only directly associated data , but deeper nested associated data is validated as well.
|
|
|
*
|
|
|
* @param array $data Record data to validate. This should be an array indexed by association name.
|
|
|
* @param array $options Options to use when validating record data (see above), See also $options of validates().
|
|
|
@@ -2239,7 +2278,7 @@ class Model extends Object implements CakeEventListener {
|
|
|
* depending on whether each record validated successfully.
|
|
|
*/
|
|
|
public function validateAssociated($data, $options = array()) {
|
|
|
- $options = array_merge(array('atomic' => true), $options);
|
|
|
+ $options = array_merge(array('atomic' => true, 'deep' => false), $options);
|
|
|
$this->validationErrors = $validationErrors = $return = array();
|
|
|
if (!($this->create($data) && $this->validates($options))) {
|
|
|
$validationErrors[$this->alias] = $this->validationErrors;
|
|
|
@@ -2248,12 +2287,23 @@ class Model extends Object implements CakeEventListener {
|
|
|
$return[$this->alias] = true;
|
|
|
}
|
|
|
$associations = $this->getAssociated();
|
|
|
- $validates = true;
|
|
|
foreach ($data as $association => $values) {
|
|
|
+ $validates = true;
|
|
|
if (isset($associations[$association])) {
|
|
|
if (in_array($associations[$association], array('belongsTo', 'hasOne'))) {
|
|
|
- $validates = $this->{$association}->create($values) && $this->{$association}->validates($options);
|
|
|
- $return[$association][] = $validates;
|
|
|
+ if ($options['deep']) {
|
|
|
+ $validates = $this->{$association}->validateAssociated($values, $options);
|
|
|
+ } else {
|
|
|
+ $validates = $this->{$association}->create($values) !== null && $this->{$association}->validates($options);
|
|
|
+ }
|
|
|
+ if (is_array($validates)) {
|
|
|
+ if (in_array(false, $validates, true)) {
|
|
|
+ $validates = false;
|
|
|
+ } else {
|
|
|
+ $validates = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $return[$association] = $validates;
|
|
|
} elseif ($associations[$association] === 'hasMany') {
|
|
|
$validates = $this->{$association}->validateMany($values, $options);
|
|
|
$return[$association] = $validates;
|