|
|
@@ -33,6 +33,7 @@ use Cake\ORM\Association\BelongsToMany;
|
|
|
use Cake\ORM\Association\HasMany;
|
|
|
use Cake\ORM\Association\HasOne;
|
|
|
use Cake\ORM\Exception\MissingEntityException;
|
|
|
+use Cake\ORM\Exception\RolledbackTransactionException;
|
|
|
use Cake\ORM\Rule\IsUnique;
|
|
|
use Cake\Utility\Inflector;
|
|
|
use Cake\Validation\Validation;
|
|
|
@@ -1436,6 +1437,8 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
|
|
|
* $articles->save($entity, ['associated' => false]);
|
|
|
* ```
|
|
|
*
|
|
|
+ * @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction
|
|
|
+ * is aborted in the afterSave event.
|
|
|
*/
|
|
|
public function save(EntityInterface $entity, $options = [])
|
|
|
{
|
|
|
@@ -1486,6 +1489,8 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
|
|
|
* @param \ArrayObject $options the options to use for the save operation
|
|
|
* @return \Cake\Datasource\EntityInterface|bool
|
|
|
* @throws \RuntimeException When an entity is missing some of the primary keys.
|
|
|
+ * @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction
|
|
|
+ * is aborted in the afterSave event.
|
|
|
*/
|
|
|
protected function _processSave($entity, $options)
|
|
|
{
|
|
|
@@ -1533,32 +1538,53 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
|
|
|
}
|
|
|
|
|
|
if ($success) {
|
|
|
- $success = $this->_associations->saveChildren(
|
|
|
- $this,
|
|
|
- $entity,
|
|
|
- $options['associated'],
|
|
|
- ['_primary' => false] + $options->getArrayCopy()
|
|
|
- );
|
|
|
- if ($success || !$options['atomic']) {
|
|
|
- $this->dispatchEvent('Model.afterSave', compact('entity', 'options'));
|
|
|
- $entity->clean();
|
|
|
- if (!$options['atomic'] && !$options['_primary']) {
|
|
|
- $entity->isNew(false);
|
|
|
- $entity->source($this->registryAlias());
|
|
|
- }
|
|
|
- $success = true;
|
|
|
- }
|
|
|
+ $success = $this->_onSaveSuccess($entity, $options);
|
|
|
}
|
|
|
|
|
|
if (!$success && $isNew) {
|
|
|
$entity->unsetProperty($this->primaryKey());
|
|
|
$entity->isNew(true);
|
|
|
}
|
|
|
- if ($success) {
|
|
|
- return $entity;
|
|
|
+
|
|
|
+ return $success ? $entity : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handles the saving of children associations and executing the afterSave logic
|
|
|
+ * once the entity for this table has been saved successfully.
|
|
|
+ *
|
|
|
+ * @param \Cake\Datasource\EntityInterface $entity the entity to be saved
|
|
|
+ * @param \ArrayObject $options the options to use for the save operation
|
|
|
+ * @return bool True on success
|
|
|
+ * @throws \Cake\ORM\Exception\RolledbackTransactionException If the transaction
|
|
|
+ * is aborted in the afterSave event.
|
|
|
+ */
|
|
|
+ protected function _onSaveSuccess($entity, $options)
|
|
|
+ {
|
|
|
+ $success = $this->_associations->saveChildren(
|
|
|
+ $this,
|
|
|
+ $entity,
|
|
|
+ $options['associated'],
|
|
|
+ ['_primary' => false] + $options->getArrayCopy()
|
|
|
+ );
|
|
|
+
|
|
|
+ if (!$success && $options['atomic']) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->dispatchEvent('Model.afterSave', compact('entity', 'options'));
|
|
|
+
|
|
|
+ if ($options['atomic'] && !$this->connection()->inTransaction()) {
|
|
|
+ throw new RolledbackTransactionException(['table' => get_class($this)]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $entity->clean();
|
|
|
+ if (!$options['atomic'] && !$options['_primary']) {
|
|
|
+ $entity->isNew(false);
|
|
|
+ $entity->source($this->registryAlias());
|
|
|
}
|
|
|
|
|
|
- return false;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
/**
|