private function computeAssociationChanges($assoc, $value)
{
if ($value instanceof PersistentCollection && $value->isDirty()) {
if ($assoc['isOwningSide']) {
$this->collectionUpdates[] = $value;
}
$this->visitedCollections[] = $value;
}
// Look through the entities, and in any of their associations, for transient (new)
// enities, recursively. ("Persistence by reachability")
if ($assoc['type'] & ClassMetadata::TO_ONE) {
if ($value instanceof Proxy && ! $value->__isInitialized__) {
return; // Ignore uninitialized proxy objects
}
$value = array($value);
} else if ($value instanceof PersistentCollection) {
// Unwrap. Uninitialized collections will simply be empty.
$value = $value->unwrap();
}
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
foreach ($value as $entry) {
$state = $this->getEntityState($entry, self::STATE_NEW);
$oid = spl_object_hash($entry);
if ($state == self::STATE_NEW) {
if ( ! $assoc['isCascadePersist']) {
throw new InvalidArgumentException("A new entity was found through a relationship that was not"
. " configured to cascade persist operations: " . self::objToStr($entry) . "."
. " Explicitly persist the new entity or configure cascading persist operations"
. " on the relationship.");
}
$this->persistNew($targetClass, $entry);
$this->computeChangeSet($targetClass, $entry);
} else if ($state == self::STATE_REMOVED) {
return new InvalidArgumentException("Removed entity detected during flush: "
. self::objToStr($entry).". Remove deleted entities from associations.");
} else if ($state == self::STATE_DETACHED) {
// Can actually not happen right now as we assume STATE_NEW,
// so the exception will be raised from the DBAL layer (constraint violation).
throw new InvalidArgumentException("A detached entity was found through a "
. "relationship during cascading a persist operation.");
}
// MANAGED associated entities are already taken into account
// during changeset calculation anyway, since they are in the identity map.
}
}