From 2be32f249c4e7df7ee9b9046c8950f217408c04e Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Tue, 22 Aug 2017 09:57:57 +0200 Subject: [PATCH] #1521 DDC-2922 adapting UoW and exception implementation to the new specification --- .../ORM/ORMInvalidArgumentException.php | 62 +++++++++++++++---- lib/Doctrine/ORM/UnitOfWork.php | 14 ++--- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/lib/Doctrine/ORM/ORMInvalidArgumentException.php b/lib/Doctrine/ORM/ORMInvalidArgumentException.php index 6aa270c78..796d2c5a5 100644 --- a/lib/Doctrine/ORM/ORMInvalidArgumentException.php +++ b/lib/Doctrine/ORM/ORMInvalidArgumentException.php @@ -82,21 +82,42 @@ class ORMInvalidArgumentException extends \InvalidArgumentException } /** - * @param array $assoc + * @param array[][]|object[][] $newEntitiesWithAssociations non-empty an array + * of [array $associationMapping, object $entity] pairs + * + * @return ORMInvalidArgumentException + */ + static public function newEntitiesFoundThroughRelationships($newEntitiesWithAssociations) + { + $errorMessages = array_map( + function (array $newEntityWithAssociation) : string { + [$associationMapping, $entity] = $newEntityWithAssociation; + + return self::newEntityFoundThroughRelationshipMessage($associationMapping, $entity); + }, + $newEntitiesWithAssociations + ); + + if (1 === count($errorMessages)) { + return new self(reset($errorMessages)); + } + + return new self( + 'Multiple non-persisted new entities were found through the given association graph:' + . "\n\n * " + . implode("\n * ", $errorMessages) + ); + } + + /** + * @param array $associationMapping * @param object $entry * * @return ORMInvalidArgumentException */ - static public function newEntityFoundThroughRelationship(array $assoc, $entry) + static public function newEntityFoundThroughRelationship(array $associationMapping, $entry) { - return new self("A new entity was found through the relationship '" - . $assoc['sourceEntity'] . "#" . $assoc['fieldName'] . "' that was not" - . " configured to cascade persist operations for entity: " . self::objToStr($entry) . "." - . " To solve this issue: Either explicitly call EntityManager#persist()" - . " on this unknown entity or configure cascade persist" - . " this association in the mapping for example @ManyToOne(..,cascade={\"persist\"})." - . (method_exists($entry, '__toString') ? "": " If you cannot find out which entity causes the problem" - . " implement '" . $assoc['targetEntity'] . "#__toString()' to get a clue.")); + return new self(self::newEntityFoundThroughRelationshipMessage($associationMapping, $entry)); } /** @@ -229,8 +250,27 @@ class ORMInvalidArgumentException extends \InvalidArgumentException * * @return string */ - private static function objToStr($obj) + private static function objToStr($obj) : string { return method_exists($obj, '__toString') ? (string) $obj : get_class($obj).'@'.spl_object_hash($obj); } + + /** + * @param array $associationMapping + * @param object $entity + */ + private static function newEntityFoundThroughRelationshipMessage(array $associationMapping, $entity) : string + { + return 'A new entity was found through the relationship \'' + . $associationMapping['sourceEntity'] . '#' . $associationMapping['fieldName'] . '\' that was not' + . ' configured to cascade persist operations for entity: ' . self::objToStr($entity) . '.' + . ' To solve this issue: Either explicitly call EntityManager#persist()' + . ' on this unknown entity or configure cascade persist' + . ' this association in the mapping for example @ManyToOne(..,cascade={"persist"}).' + . (method_exists($entity, '__toString') + ? '' + : ' If you cannot find out which entity causes the problem implement \'' + . $associationMapping['targetEntity'] . '#__toString()\' to get a clue.' + ); + } } diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 5efb01b3b..0edd756f0 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -347,9 +347,6 @@ class UnitOfWork implements PropertyChangedListener } } - // @TODO move this further down - $this->assertThatThereAreNoUnintentionallyNonPersistedAssociations(); - if ( ! ($this->entityInsertions || $this->entityDeletions || $this->entityUpdates || @@ -362,6 +359,8 @@ class UnitOfWork implements PropertyChangedListener return; // Nothing to do. } + $this->assertThatThereAreNoUnintentionallyNonPersistedAssociations(); + if ($this->orphanRemovals) { foreach ($this->orphanRemovals as $orphan) { $this->remove($orphan); @@ -3398,11 +3397,12 @@ class UnitOfWork implements PropertyChangedListener { $entitiesNeedingCascadePersist = \array_diff_key($this->nonCascadedNewDetectedEntities, $this->entityInsertions); - if($entitiesNeedingCascadePersist){ - [$assoc, $entity] = \array_values($entitiesNeedingCascadePersist)[0]; + $this->nonCascadedNewDetectedEntities = []; - // @TODO internal clean up here - throw ORMInvalidArgumentException::newEntityFoundThroughRelationship($assoc, $entity); + if ($entitiesNeedingCascadePersist) { + throw ORMInvalidArgumentException::newEntitiesFoundThroughRelationships( + \array_values($entitiesNeedingCascadePersist) + ); } }