private function doPersist($entity, array &$visited)
{
$oid = spl_object_hash($entity);
if (isset($visited[$oid])) {
return; // Prevent infinite recursion
}
$visited[$oid] = $entity; // Mark visited
$class = $this->em->getClassMetadata(get_class($entity));
// We assume NEW, so DETACHED entities result in an exception on flush (constraint violation).
// If we would detect DETACHED here we would throw an exception anyway with the same
// consequences (not recoverable/programming error), so just assuming NEW here
// lets us avoid some database lookups for entities with natural identifiers.
$entityState = $this->getEntityState($entity, self::STATE_NEW);
switch ($entityState) {
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
case self::STATE_NEW:
$this->persistNew($class, $entity);
break;
case self::STATE_REMOVED:
// Entity becomes managed again
unset($this->entityDeletions[$oid]);
$this->entityStates[$oid] = self::STATE_MANAGED;
break;
case self::STATE_DETACHED:
// Can actually not happen right now since we assume STATE_NEW.
throw new InvalidArgumentException("Detached entity passed to persist().");
default:
throw new UnexpectedValueException("Unexpected entity state: $entityState.");
}
$this->cascadePersist($entity, $visited);
}