Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a5d233c

Browse files
Decouple public API from Doctrine\Persistence\Proxy
1 parent 81ddeb4 commit a5d233c

48 files changed

Lines changed: 195 additions & 229 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/en/reference/unitofwork.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ will still end up with the same reference:
3737
public function testIdentityMapReference(): void
3838
{
3939
$objectA = $this->entityManager->getReference('EntityName', 1);
40-
// check for proxyinterface
41-
$this->assertInstanceOf('Doctrine\Persistence\Proxy', $objectA);
40+
// check entity is not initialized
41+
$this->assertTrue($this->entityManager->isUninitializedObject($objectA));
4242
4343
$objectB = $this->entityManager->find('EntityName', 1);
4444

lib/Doctrine/ORM/Cache/DefaultQueryCache.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Doctrine\ORM\Query;
1717
use Doctrine\ORM\Query\ResultSetMapping;
1818
use Doctrine\ORM\UnitOfWork;
19-
use Doctrine\Persistence\Proxy;
2019

2120
use function array_map;
2221
use function array_shift;
@@ -345,7 +344,7 @@ private function storeAssociationCache(QueryCacheKey $key, array $assoc, $assocV
345344
$assocIdentifier = $this->uow->getEntityIdentifier($assocValue);
346345
$entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier);
347346

348-
if (! $assocValue instanceof Proxy && ($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) {
347+
if (! $this->uow->isUninitializedObject($assocValue) && ($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) {
349348
// Entity put fail
350349
if (! $assocPersister->storeEntityCache($assocValue, $entityKey)) {
351350
return null;

lib/Doctrine/ORM/EntityManager.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,14 @@ public function initializeObject($obj)
953953
$this->unitOfWork->initializeObject($obj);
954954
}
955955

956+
/**
957+
* {@inheritDoc}
958+
*/
959+
public function isUninitializedObject($obj): bool
960+
{
961+
return $this->unitOfWork->isUninitializedObject($obj);
962+
}
963+
956964
/**
957965
* Factory method to create EntityManager instances.
958966
*

lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Doctrine\ORM\PersistentCollection;
1111
use Doctrine\ORM\Query;
1212
use Doctrine\ORM\UnitOfWork;
13-
use Doctrine\Persistence\Proxy;
1413

1514
use function array_fill_keys;
1615
use function array_keys;
@@ -439,7 +438,7 @@ protected function hydrateRowData(array $row, array &$result)
439438
// PATH B: Single-valued association
440439
$reflFieldValue = $reflField->getValue($parentObject);
441440

442-
if (! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && ! $reflFieldValue->__isInitialized())) {
441+
if (! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || $this->_uow->isUninitializedObject($reflFieldValue)) {
443442
// we only need to take action if this value is null,
444443
// we refresh the entity or its an uninitialized proxy.
445444
if (isset($nonemptyComponents[$dqlAlias])) {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\ORM\Proxy;
6+
7+
use Doctrine\Persistence\Proxy;
8+
9+
/**
10+
* @internal
11+
*
12+
* @template T of object
13+
* @template-extends Proxy<T>
14+
*
15+
* @method void __setInitialized(bool $initialized)
16+
*/
17+
interface InternalProxy extends Proxy
18+
{
19+
}

lib/Doctrine/ORM/Proxy/Proxy.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
* Interface for proxy classes.
1111
*
1212
* @deprecated 2.14. Use \Doctrine\Persistence\Proxy instead
13+
*
14+
* @template T of object
15+
* @template-extends BaseProxy<T>
16+
* @template-extends InternalProxy<T>
1317
*/
14-
interface Proxy extends BaseProxy
18+
interface Proxy extends BaseProxy, InternalProxy
1519
{
1620
}

lib/Doctrine/ORM/Proxy/ProxyFactory.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Doctrine\ORM\UnitOfWork;
1818
use Doctrine\ORM\Utility\IdentifierFlattener;
1919
use Doctrine\Persistence\Mapping\ClassMetadata;
20-
use Doctrine\Persistence\Proxy;
2120
use ReflectionProperty;
2221
use Symfony\Component\VarExporter\ProxyHelper;
2322
use Symfony\Component\VarExporter\VarExporter;
@@ -105,7 +104,7 @@ public function __construct(EntityManagerInterface $em, $proxyDir, $proxyNs, $au
105104
$proxyGenerator = new ProxyGenerator($proxyDir, $proxyNs);
106105

107106
if ($em->getConfiguration()->isLazyGhostObjectEnabled()) {
108-
$proxyGenerator->setPlaceholder('baseProxyInterface', Proxy::class);
107+
$proxyGenerator->setPlaceholder('baseProxyInterface', InternalProxy::class);
109108
$proxyGenerator->setPlaceholder('useLazyGhostTrait', Closure::fromCallable([$this, 'generateUseLazyGhostTrait']));
110109
$proxyGenerator->setPlaceholder('skippedProperties', Closure::fromCallable([$this, 'generateSkippedProperties']));
111110
$proxyGenerator->setPlaceholder('serializeImpl', Closure::fromCallable([$this, 'generateSerializeImpl']));
@@ -135,7 +134,7 @@ public function getProxy($className, array $identifier)
135134

136135
$initializer = $this->definitions[$className]->initializer;
137136

138-
$proxy->__construct(static function (Proxy $object) use ($initializer, $proxy): void {
137+
$proxy->__construct(static function (InternalProxy $object) use ($initializer, $proxy): void {
139138
$initializer($object, $proxy);
140139
});
141140

@@ -242,13 +241,13 @@ private function createInitializer(ClassMetadata $classMetadata, EntityPersister
242241
/**
243242
* Creates a closure capable of initializing a proxy
244243
*
245-
* @return Closure(Proxy, Proxy):void
244+
* @return Closure(InternalProxy, InternalProxy):void
246245
*
247246
* @throws EntityNotFoundException
248247
*/
249248
private function createLazyInitializer(ClassMetadata $classMetadata, EntityPersister $entityPersister): Closure
250249
{
251-
return function (Proxy $proxy, Proxy $original) use ($entityPersister, $classMetadata): void {
250+
return function (InternalProxy $proxy, InternalProxy $original) use ($entityPersister, $classMetadata): void {
252251
$identifier = $classMetadata->getIdentifierValues($original);
253252
$entity = $entityPersister->loadById($identifier, $original);
254253

lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use Doctrine\ORM\Mapping\ClassMetadata;
1010
use Doctrine\ORM\PersistentCollection;
1111
use Doctrine\ORM\UnitOfWork;
12-
use Doctrine\Persistence\Proxy;
1312
use ReflectionObject;
1413

1514
use function count;
@@ -87,7 +86,7 @@ public function dumpIdentityMap(EntityManagerInterface $em)
8786
if ($value === null) {
8887
fwrite($fh, " NULL\n");
8988
} else {
90-
if ($value instanceof Proxy && ! $value->__isInitialized()) {
89+
if ($uow->isUninitializedObject($value)) {
9190
fwrite($fh, '[PROXY] ');
9291
}
9392

lib/Doctrine/ORM/UnitOfWork.php

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
use Doctrine\ORM\Persisters\Entity\EntityPersister;
3939
use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister;
4040
use Doctrine\ORM\Persisters\Entity\SingleTablePersister;
41+
use Doctrine\ORM\Proxy\InternalProxy;
4142
use Doctrine\ORM\Utility\IdentifierFlattener;
4243
use Doctrine\Persistence\Mapping\RuntimeReflectionService;
4344
use Doctrine\Persistence\NotifyPropertyChanged;
4445
use Doctrine\Persistence\ObjectManagerAware;
4546
use Doctrine\Persistence\PropertyChangedListener;
46-
use Doctrine\Persistence\Proxy;
4747
use Exception;
4848
use InvalidArgumentException;
4949
use RuntimeException;
@@ -581,7 +581,7 @@ private function computeSingleEntityChangeSet($entity): void
581581
}
582582

583583
// Ignore uninitialized proxy objects
584-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
584+
if ($this->isUninitializedObject($entity)) {
585585
return;
586586
}
587587

@@ -906,7 +906,7 @@ public function computeChangeSets()
906906

907907
foreach ($entitiesToProcess as $entity) {
908908
// Ignore uninitialized proxy objects
909-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
909+
if ($this->isUninitializedObject($entity)) {
910910
continue;
911911
}
912912

@@ -931,7 +931,7 @@ public function computeChangeSets()
931931
*/
932932
private function computeAssociationChanges(array $assoc, $value): void
933933
{
934-
if ($value instanceof Proxy && ! $value->__isInitialized()) {
934+
if ($this->isUninitializedObject($value)) {
935935
return;
936936
}
937937

@@ -2172,7 +2172,7 @@ private function ensureVersionMatch(
21722172
$entity,
21732173
$managedCopy
21742174
): void {
2175-
if (! ($class->isVersioned && $this->isLoaded($managedCopy) && $this->isLoaded($entity))) {
2175+
if (! ($class->isVersioned && ! $this->isUninitializedObject($managedCopy) && ! $this->isUninitializedObject($entity))) {
21762176
return;
21772177
}
21782178

@@ -2190,16 +2190,6 @@ private function ensureVersionMatch(
21902190
throw OptimisticLockException::lockFailedVersionMismatch($entity, $entityVersion, $managedCopyVersion);
21912191
}
21922192

2193-
/**
2194-
* Tests if an entity is loaded - must either be a loaded proxy or not a proxy
2195-
*
2196-
* @param object $entity
2197-
*/
2198-
private function isLoaded($entity): bool
2199-
{
2200-
return ! ($entity instanceof Proxy) || $entity->__isInitialized();
2201-
}
2202-
22032193
/**
22042194
* Sets/adds associated managed copies into the previous entity's association field
22052195
*
@@ -2495,7 +2485,7 @@ static function ($assoc) {
24952485
*/
24962486
private function cascadePersist($entity, array &$visited): void
24972487
{
2498-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
2488+
if ($this->isUninitializedObject($entity)) {
24992489
// nothing to do - proxy is not initialized, therefore we don't do anything with it
25002490
return;
25012491
}
@@ -2569,13 +2559,13 @@ static function ($assoc) {
25692559
}
25702560
);
25712561

2562+
if ($associationMappings) {
2563+
$this->initializeObject($entity);
2564+
}
2565+
25722566
$entitiesToCascade = [];
25732567

25742568
foreach ($associationMappings as $assoc) {
2575-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
2576-
$entity->__load();
2577-
}
2578-
25792569
$relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity);
25802570

25812571
switch (true) {
@@ -2631,9 +2621,7 @@ public function lock($entity, int $lockMode, $lockVersion = null): void
26312621
return;
26322622
}
26332623

2634-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
2635-
$entity->__load();
2636-
}
2624+
$this->initializeObject($entity);
26372625

26382626
assert($class->versionField !== null);
26392627
$entityVersion = $class->reflFields[$class->versionField]->getValue($entity);
@@ -2823,7 +2811,6 @@ public function createEntity($className, array $data, &$hints = [])
28232811
$unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY];
28242812
if (
28252813
$unmanagedProxy !== $entity
2826-
&& $unmanagedProxy instanceof Proxy
28272814
&& $this->isIdentifierEquals($unmanagedProxy, $entity)
28282815
) {
28292816
// We will hydrate the given un-managed proxy anyway:
@@ -2832,7 +2819,8 @@ public function createEntity($className, array $data, &$hints = [])
28322819
}
28332820
}
28342821

2835-
if ($entity instanceof Proxy && ! $entity->__isInitialized()) {
2822+
if ($this->isUninitializedObject($entity)) {
2823+
assert($entity instanceof InternalProxy);
28362824
$entity->__setInitialized(true);
28372825
} else {
28382826
if (
@@ -2978,8 +2966,7 @@ public function createEntity($className, array $data, &$hints = [])
29782966
$hints['fetchMode'][$class->name][$field] === ClassMetadata::FETCH_EAGER &&
29792967
isset($hints[self::HINT_DEFEREAGERLOAD]) &&
29802968
! $targetClass->isIdentifierComposite &&
2981-
$newValue instanceof Proxy &&
2982-
$newValue->__isInitialized() === false
2969+
$this->isUninitializedObject($newValue)
29832970
) {
29842971
$this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId);
29852972
}
@@ -3377,7 +3364,7 @@ public function registerManaged($entity, array $id, array $data)
33773364

33783365
$this->addToIdentityMap($entity);
33793366

3380-
if ($entity instanceof NotifyPropertyChanged && ( ! $entity instanceof Proxy || $entity->__isInitialized())) {
3367+
if ($entity instanceof NotifyPropertyChanged && ! $this->isUninitializedObject($entity)) {
33813368
$entity->addPropertyChangedListener($this);
33823369
}
33833370
}
@@ -3485,7 +3472,7 @@ public function getScheduledCollectionUpdates()
34853472
*/
34863473
public function initializeObject($obj)
34873474
{
3488-
if ($obj instanceof Proxy) {
3475+
if ($obj instanceof InternalProxy) {
34893476
$obj->__load();
34903477

34913478
return;
@@ -3496,6 +3483,16 @@ public function initializeObject($obj)
34963483
}
34973484
}
34983485

3486+
/**
3487+
* Tests if a value is an uninitialized entity.
3488+
*
3489+
* @param mixed $obj
3490+
*/
3491+
public function isUninitializedObject($obj): bool
3492+
{
3493+
return $obj instanceof InternalProxy && ! $obj->__isInitialized();
3494+
}
3495+
34993496
/**
35003497
* Helper method to show an object as string.
35013498
*
@@ -3646,13 +3643,11 @@ private function assertThatThereAreNoUnintentionallyNonPersistedAssociations():
36463643
*/
36473644
private function mergeEntityStateIntoManagedCopy($entity, $managedCopy): void
36483645
{
3649-
if (! $this->isLoaded($entity)) {
3646+
if ($this->isUninitializedObject($entity)) {
36503647
return;
36513648
}
36523649

3653-
if (! $this->isLoaded($managedCopy)) {
3654-
$managedCopy->__load();
3655-
}
3650+
$this->initializeObject($managedCopy);
36563651

36573652
$class = $this->em->getClassMetadata(get_class($entity));
36583653

@@ -3673,7 +3668,7 @@ private function mergeEntityStateIntoManagedCopy($entity, $managedCopy): void
36733668
if ($other === null) {
36743669
$prop->setValue($managedCopy, null);
36753670
} else {
3676-
if ($other instanceof Proxy && ! $other->__isInitialized()) {
3671+
if ($this->isUninitializedObject($other)) {
36773672
// do not merge fields marked lazy that have not been fetched.
36783673
continue;
36793674
}

phpstan-persistence2.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,5 @@ parameters:
3434
count: 1
3535
path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
3636

37-
-
38-
message: '/^Call to an undefined method Doctrine\\Persistence\\Proxy::__setInitialized\(\)\.$/'
39-
count: 1
40-
path: lib/Doctrine/ORM/UnitOfWork.php
41-
4237
# Symfony cache supports passing a key prefix to the clear method.
4338
- '/^Method Psr\\Cache\\CacheItemPoolInterface\:\:clear\(\) invoked with 1 parameter, 0 required\.$/'

0 commit comments

Comments
 (0)