1
0
mirror of synced 2025-01-18 06:21:40 +03:00

DDC-2931 - Safe comparison between proxies and entities when refreshing objects

This commit is contained in:
Marco Pivetta 2014-02-01 01:57:51 +01:00
parent 8c92e0f19f
commit 7a32eca039

View File

@ -2514,14 +2514,14 @@ class UnitOfWork implements PropertyChangedListener
&& isset($hints[Query::HINT_REFRESH_ENTITY]) && isset($hints[Query::HINT_REFRESH_ENTITY])
&& ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity && ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity
&& $unmanagedProxy instanceof Proxy && $unmanagedProxy instanceof Proxy
&& (($unmanagedProxyClass = $this->em->getClassMetadata(get_class($unmanagedProxy))) === $class) && $this->isIdentifierEquals($unmanagedProxy, $entity)
) { ) {
// DDC-1238 - we have a managed instance, but it isn't the provided one. // DDC-1238 - we have a managed instance, but it isn't the provided one.
// Therefore we clear its identifier. Also, we must re-fetch metadata since the // Therefore we clear its identifier. Also, we must re-fetch metadata since the
// refreshed object may be anything // refreshed object may be anything
foreach ($unmanagedProxyClass->identifier as $fieldName) { foreach ($class->identifier as $fieldName) {
$unmanagedProxyClass->reflFields[$fieldName]->setValue($unmanagedProxy, null); $class->reflFields[$fieldName]->setValue($unmanagedProxy, null);
} }
return $unmanagedProxy; return $unmanagedProxy;
@ -3320,4 +3320,37 @@ class UnitOfWork implements PropertyChangedListener
$this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em)); $this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em));
} }
} }
/**
* Verifies if two given entities actually are the same based on identifier comparison
*
* @param object $entity1
* @param object $entity2
*
* @return bool
*/
private function isIdentifierEquals($entity1, $entity2)
{
if ($entity1 === $entity2) {
return true;
}
$class = $this->em->getClassMetadata(get_class($entity1));
if ($class !== $this->em->getClassMetadata(get_class($entity2))) {
return false;
}
$oid1 = spl_object_hash($entity1);
$oid2 = spl_object_hash($entity2);
$id1 = isset($this->entityIdentifiers[$oid1])
? $this->entityIdentifiers[$oid1]
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity1));
$id2 = isset($this->entityIdentifiers[$oid2])
? $this->entityIdentifiers[$oid2]
: $this->flattenIdentifier($class, $class->getIdentifierValues($entity2));
return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2);
}
} }