Using Doctrine\Common\Util\ClassUtil for class_name resolutionThis avoids exceptions when passing a Proxy instance to the public API of the EntityManager, ClassMetadataFactory or UnitOfWork when the Proxy itself isn't generated by the EntityManager itself, while discovering the correct ClassMetadata instance for the proxy
This commit is contained in:
parent
022d27e4e9
commit
cbe4987e18
@ -22,7 +22,7 @@ namespace Doctrine\ORM;
|
||||
use Doctrine\DBAL\Types\Type,
|
||||
Doctrine\DBAL\Cache\QueryCacheProfile,
|
||||
Doctrine\ORM\Query\QueryException,
|
||||
Doctrine\ORM\Internal\Hydration\CacheHydrator;
|
||||
Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* Base contract for ORM queries. Base class for Query and NativeQuery.
|
||||
@ -241,7 +241,7 @@ abstract class AbstractQuery
|
||||
|
||||
return $value;
|
||||
|
||||
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)):
|
||||
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value)):
|
||||
return $this->convertObjectParameterToScalarValue($value);
|
||||
|
||||
default:
|
||||
|
@ -22,6 +22,7 @@ namespace Doctrine\ORM\Id;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\ORM\ORMException;
|
||||
use Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* Special generator for application-assigned identifiers (doesnt really generate anything).
|
||||
@ -43,7 +44,7 @@ class AssignedGenerator extends AbstractIdGenerator
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
$class = $em->getClassMetadata(get_class($entity));
|
||||
$class = $em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
$idFields = $class->getIdentifierFieldNames();
|
||||
$identifier = array();
|
||||
|
||||
|
@ -22,7 +22,8 @@ namespace Doctrine\ORM;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\Common\Collections\Collection,
|
||||
Doctrine\Common\Collections\ArrayCollection,
|
||||
Closure;
|
||||
Closure,
|
||||
Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* A PersistentCollection represents a collection of elements that have persistent state.
|
||||
@ -306,7 +307,7 @@ final class PersistentCollection implements Collection
|
||||
$this->association['isOwningSide'] &&
|
||||
$this->association['type'] === ClassMetadata::MANY_TO_MANY &&
|
||||
$this->owner &&
|
||||
$this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) {
|
||||
$this->em->getClassMetadata(ClassUtils::getClass($this->owner))->isChangeTrackingNotify()) {
|
||||
$this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ use PDO,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Events,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* A BasicEntityPersiter maps an entity to a single table in a relational database.
|
||||
@ -1499,11 +1500,11 @@ class BasicEntityPersister
|
||||
*/
|
||||
private function getIndividualValue($value)
|
||||
{
|
||||
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
|
||||
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) {
|
||||
if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
|
||||
$idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
|
||||
} else {
|
||||
$class = $this->_em->getClassMetadata(get_class($value));
|
||||
$class = $this->_em->getClassMetadata(ClassUtils::getClass($value));
|
||||
$idValues = $class->getIdentifierValues($value);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@ namespace Doctrine\ORM\Persisters;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\UnitOfWork;
|
||||
Doctrine\ORM\UnitOfWork,
|
||||
Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* Persister for many-to-many collections.
|
||||
@ -43,7 +44,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
protected function _getDeleteRowSQL(PersistentCollection $coll)
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||
$class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner()));
|
||||
|
||||
return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform())
|
||||
. ' WHERE ' . implode(' = ? AND ', $mapping['joinTableColumns']) . ' = ?';
|
||||
@ -80,7 +81,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
{
|
||||
$mapping = $coll->getMapping();
|
||||
$columns = $mapping['joinTableColumns'];
|
||||
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||
$class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner()));
|
||||
|
||||
$joinTable = $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform());
|
||||
|
||||
@ -118,7 +119,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
$identifier2 = $this->_uow->getEntityIdentifier($element);
|
||||
|
||||
if ($isComposite) {
|
||||
$class1 = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||
$class1 = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner()));
|
||||
$class2 = $coll->getTypeClass();
|
||||
}
|
||||
|
||||
@ -150,7 +151,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
*/
|
||||
protected function _getDeleteSQL(PersistentCollection $coll)
|
||||
{
|
||||
$class = $this->_em->getClassMetadata(get_class($coll->getOwner()));
|
||||
$class = $this->_em->getClassMetadata(ClassUtils::getClass($coll->getOwner()));
|
||||
$mapping = $coll->getMapping();
|
||||
|
||||
return 'DELETE FROM ' . $class->getQuotedJoinTableName($mapping, $this->_conn->getDatabasePlatform())
|
||||
@ -178,7 +179,7 @@ class ManyToManyPersister extends AbstractCollectionPersister
|
||||
}
|
||||
|
||||
// Composite identifier
|
||||
$sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
|
||||
$sourceClass = $this->_em->getClassMetadata(ClassUtils::getClass($mapping->getOwner()));
|
||||
|
||||
foreach ($mapping['relationToSourceKeyColumns'] as $srcColumn) {
|
||||
$params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
|
||||
|
@ -27,7 +27,8 @@ use Exception, InvalidArgumentException, UnexpectedValueException,
|
||||
Doctrine\Common\Persistence\ObjectManagerAware,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Proxy\Proxy;
|
||||
Doctrine\ORM\Proxy\Proxy,
|
||||
Doctrine\Common\Util\ClassUtils;
|
||||
|
||||
/**
|
||||
* The UnitOfWork is responsible for tracking changes to objects during an
|
||||
@ -375,7 +376,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
private function computeScheduleInsertsChangeSets()
|
||||
{
|
||||
foreach ($this->entityInsertions as $entity) {
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$this->computeChangeSet($class, $entity);
|
||||
}
|
||||
@ -398,7 +399,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
throw new \InvalidArgumentException("Entity has to be managed for single computation " . self::objToStr($entity));
|
||||
}
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
if ($class->isChangeTrackingDeferredImplicit()) {
|
||||
$this->persist($entity);
|
||||
@ -433,7 +434,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
list ($entity, $changeset) = $update;
|
||||
|
||||
$this->entityChangeSets[$oid] = $changeset;
|
||||
$this->getEntityPersister(get_class($entity))->update($entity);
|
||||
$this->getEntityPersister(ClassUtils::getClass($entity))->update($entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -838,7 +839,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
if ( ! $class->isInheritanceTypeNone()) {
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
}
|
||||
|
||||
$actualData = array();
|
||||
@ -886,7 +887,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$hasListeners = $this->evm->hasListeners(Events::postPersist);
|
||||
|
||||
foreach ($this->entityInsertions as $oid => $entity) {
|
||||
if (get_class($entity) !== $className) {
|
||||
if (ClassUtils::getClass($entity) !== $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -945,7 +946,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
|
||||
|
||||
foreach ($this->entityUpdates as $oid => $entity) {
|
||||
if ( ! (get_class($entity) === $className || $entity instanceof Proxy && get_parent_class($entity) === $className)) {
|
||||
if (ClassUtils::getClass($entity) !== $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -992,7 +993,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$hasListeners = $this->evm->hasListeners(Events::postRemove);
|
||||
|
||||
foreach ($this->entityDeletions as $oid => $entity) {
|
||||
if ( ! (get_class($entity) == $className || $entity instanceof Proxy && get_parent_class($entity) == $className)) {
|
||||
if (ClassUtils::getClass($entity) !== $className) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1043,7 +1044,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$newNodes = array();
|
||||
|
||||
foreach ($entityChangeSet as $entity) {
|
||||
$className = get_class($entity);
|
||||
$className = ClassUtils::getClass($entity);
|
||||
|
||||
if ($calc->hasClass($className)) {
|
||||
continue;
|
||||
@ -1206,7 +1207,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
public function isScheduledForDirtyCheck($entity)
|
||||
{
|
||||
$rootEntityName = $this->em->getClassMetadata(get_class($entity))->rootEntityName;
|
||||
$rootEntityName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName;
|
||||
|
||||
return isset($this->scheduledForDirtyCheck[$rootEntityName][spl_object_hash($entity)]);
|
||||
}
|
||||
@ -1287,7 +1288,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
public function addToIdentityMap($entity)
|
||||
{
|
||||
$classMetadata = $this->em->getClassMetadata(get_class($entity));
|
||||
$classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
$idHash = implode(' ', $this->entityIdentifiers[spl_object_hash($entity)]);
|
||||
|
||||
if ($idHash === '') {
|
||||
@ -1335,7 +1336,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
// Note that you can not remember the NEW or DETACHED state in _entityStates since
|
||||
// the UoW does not hold references to such objects and the object hash can be reused.
|
||||
// More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it.
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
$id = $class->getIdentifierValues($entity);
|
||||
|
||||
if ( ! $id) {
|
||||
@ -1357,7 +1358,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
// db lookup
|
||||
if ($this->getEntityPersister(get_class($entity))->exists($entity)) {
|
||||
if ($this->getEntityPersister($class->name)->exists($entity)) {
|
||||
return self::STATE_DETACHED;
|
||||
}
|
||||
|
||||
@ -1374,7 +1375,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
// db lookup
|
||||
if ($this->getEntityPersister(get_class($entity))->exists($entity)) {
|
||||
if ($this->getEntityPersister($class->name)->exists($entity)) {
|
||||
return self::STATE_DETACHED;
|
||||
}
|
||||
|
||||
@ -1465,7 +1466,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
return false;
|
||||
}
|
||||
|
||||
$classMetadata = $this->em->getClassMetadata(get_class($entity));
|
||||
$classMetadata = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
$idHash = implode(' ', $this->entityIdentifiers[$oid]);
|
||||
|
||||
if ($idHash === '') {
|
||||
@ -1520,7 +1521,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$visited[$oid] = $entity; // Mark visited
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($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
|
||||
@ -1594,7 +1595,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
// can cause problems when a lazy proxy has to be initialized for the cascade operation.
|
||||
$this->cascadeRemove($entity, $visited);
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
$entityState = $this->getEntityState($entity);
|
||||
|
||||
switch ($entityState) {
|
||||
@ -1660,7 +1661,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
// First we assume DETACHED, although it can still be NEW but we can avoid
|
||||
// an extra db-roundtrip this way. If it is not MANAGED but has an identity,
|
||||
@ -1814,7 +1815,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
if ($prevManagedCopy !== null) {
|
||||
$assocField = $assoc['fieldName'];
|
||||
$prevClass = $this->em->getClassMetadata(get_class($prevManagedCopy));
|
||||
$prevClass = $this->em->getClassMetadata(ClassUtils::getClass($prevManagedCopy));
|
||||
|
||||
if ($assoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$prevClass->reflFields[$assocField]->setValue($prevManagedCopy, $managedCopy);
|
||||
@ -1921,7 +1922,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
|
||||
$visited[$oid] = $entity; // mark visited
|
||||
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
if ($this->getEntityState($entity) !== self::STATE_MANAGED) {
|
||||
throw ORMInvalidArgumentException::entityNotManaged($entity);
|
||||
@ -1943,7 +1944,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function cascadeRefresh($entity, array &$visited)
|
||||
{
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
@ -1984,7 +1985,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function cascadeDetach($entity, array &$visited)
|
||||
{
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
@ -2026,7 +2027,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function cascadeMerge($entity, $managedCopy, array &$visited)
|
||||
{
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
@ -2064,7 +2065,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function cascadePersist($entity, array &$visited)
|
||||
{
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
@ -2105,7 +2106,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
private function cascadeRemove($entity, array &$visited)
|
||||
{
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$associationMappings = array_filter(
|
||||
$class->associationMappings,
|
||||
@ -2151,13 +2152,12 @@ class UnitOfWork implements PropertyChangedListener
|
||||
throw ORMInvalidArgumentException::entityNotManaged($entity);
|
||||
}
|
||||
|
||||
$entityName = get_class($entity);
|
||||
$class = $this->em->getClassMetadata($entityName);
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
switch ($lockMode) {
|
||||
case \Doctrine\DBAL\LockMode::OPTIMISTIC;
|
||||
if ( ! $class->isVersioned) {
|
||||
throw OptimisticLockException::notVersioned($entityName);
|
||||
throw OptimisticLockException::notVersioned($class->name);
|
||||
}
|
||||
|
||||
if ($lockVersion === null) {
|
||||
@ -2689,7 +2689,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
*/
|
||||
public function scheduleForDirtyCheck($entity)
|
||||
{
|
||||
$rootClassName = $this->em->getClassMetadata(get_class($entity))->rootEntityName;
|
||||
$rootClassName = $this->em->getClassMetadata(ClassUtils::getClass($entity))->rootEntityName;
|
||||
|
||||
$this->scheduledForDirtyCheck[$rootClassName][spl_object_hash($entity)] = $entity;
|
||||
}
|
||||
@ -2827,7 +2827,7 @@ class UnitOfWork implements PropertyChangedListener
|
||||
public function propertyChanged($entity, $propertyName, $oldValue, $newValue)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
$class = $this->em->getClassMetadata(get_class($entity));
|
||||
$class = $this->em->getClassMetadata(ClassUtils::getClass($entity));
|
||||
|
||||
$isAssocField = isset($class->associationMappings[$propertyName]);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user