Skip to content

Commit ffd0538

Browse files
committed
Remove proxy class generators, only native lazy objects are supported
Remove dependencies to proxy-manager and var-exporter
1 parent 29dda5d commit ffd0538

38 files changed

+67
-1548
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ jobs:
111111
- name: "Remove optional dependencies"
112112
if: "${{ matrix.remove-optional-dependencies }}"
113113
run: |
114-
composer remove --no-update friendsofphp/proxy-manager-lts symfony/var-exporter
115114
composer remove --no-update --dev symfony/cache doctrine/orm doctrine/annotations
116115
composer remove --no-update --dev doctrine/coding-standard phpstan/phpstan phpstan/phpstan-deprecation-rule phpstan/phpstan-phpunit
117116
@@ -138,6 +137,4 @@ jobs:
138137
run: "vendor/bin/phpunit --exclude-group=atlas ${{ matrix.dependencies == 'lowest' && '--do-not-fail-on-deprecation --do-not-fail-on-warning --do-not-fail-on-notice' || '' }}"
139138
env:
140139
DOCTRINE_MONGODB_SERVER: ${{ steps.setup-mongodb.outputs.cluster-uri }}
141-
USE_LAZY_GHOST_OBJECT: 0
142-
USE_NATIVE_LAZY_OBJECT: 1
143140
CRYPT_SHARED_LIB_PATH: ${{ steps.setup-mongodb.outputs.crypt-shared-lib-path }}

UPGRADE-3.0.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,26 @@ no longer implements the `PropertyChangedListener` interface.
4747
`AnnotationDriver` class defined in `doctrine/persistence` (or in ODM's
4848
compatibility layer)
4949

50-
## Proxy Class Name Resolution
50+
## Proxy Classes replaced by Native Lazy Objects
51+
52+
The proxy system based on generated proxy classes has been replaced by
53+
native PHP lazy objects. The proxy classes don't exist anymore and don't
54+
need to be generated.
55+
56+
The following methods have been removed from `Doctrine\ODM\MongoDB\Configuration`:
57+
- `setProxyDir` and `getProxyDir`,
58+
- `setProxyNamespace` and `getProxyNamespace`,
59+
- `setUseLazyGhostObject` and `getUseLazyGhostObject`,
60+
- `setUseNativeLazyObject` and `getUseNativeLazyObject`,
61+
- `getProxyManagerConfiguration`
62+
- `getProxyFactory`
5163

5264
The `Doctrine\ODM\MongoDB\Proxy\Resolver\ClassNameResolver` interface has been
5365
dropped in favor of the `Doctrine\Persistence\Mapping\ProxyClassNameResolver`
5466
interface.
5567

5668
The `getClassNameResolver` method in `DocumentManager` has been removed. To
57-
retrieve the mapped class name for any object or class string, fetch metadata
69+
retrieve the mapped class name for any object or class string, fetch metadata
5870
for the class and read the class using `$metadata->getName()`. The metadata
5971
layer is aware of these proxy namespace changes and how to resolve them, so
6072
users should always go through the metadata layer to retrieve mapped class

benchmark/BaseBench.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ public function initDocumentManager(): void
3232
{
3333
$config = new Configuration();
3434

35-
$config->setProxyDir(__DIR__ . '/../../tests/Proxies');
36-
$config->setProxyNamespace('Proxies');
3735
$config->setHydratorDir(__DIR__ . '/../../tests/Hydrators');
3836
$config->setHydratorNamespace('Hydrators');
3937
$config->setPersistentCollectionDir(__DIR__ . '/../../tests/PersistentCollections');

composer.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,10 @@
3434
"doctrine/event-manager": "^1.0 || ^2.0",
3535
"doctrine/instantiator": "^1.1 || ^2",
3636
"doctrine/persistence": "^3.2 || ^4",
37-
"friendsofphp/proxy-manager-lts": "^1.0",
3837
"mongodb/mongodb": "^2.1.1",
3938
"psr/cache": "^1.0 || ^2.0 || ^3.0",
4039
"symfony/console": "^5.4 || ^6.4 || ^7.0 || ^8.0",
41-
"symfony/deprecation-contracts": "^2.2 || ^3.0",
42-
"symfony/var-exporter": "^6.4.1 || ^7.0 || ^8.0"
40+
"symfony/deprecation-contracts": "^2.2 || ^3.0"
4341
},
4442
"require-dev": {
4543
"ext-bcmath": "*",

phpunit.xml.dist

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,5 @@
3333
<ini name="error_reporting" value="-1"/>
3434
<const name="DOCTRINE_MONGODB_SERVER" value="mongodb://localhost:27017" />
3535
<const name="DOCTRINE_MONGODB_DATABASE" value="doctrine_odm_tests" />
36-
<env name="USE_LAZY_GHOST_OBJECT" value="1"/>
37-
<env name="USE_NATIVE_LAZY_OBJECT" value="0"/>
3836
</php>
3937
</phpunit>

src/Configuration.php

Lines changed: 10 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,26 @@
1414
use Doctrine\ODM\MongoDB\PersistentCollection\DefaultPersistentCollectionGenerator;
1515
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionFactory;
1616
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionGenerator;
17-
use Doctrine\ODM\MongoDB\Proxy\FileLocator;
1817
use Doctrine\ODM\MongoDB\Repository\DefaultGridFSRepository;
1918
use Doctrine\ODM\MongoDB\Repository\DefaultRepositoryFactory;
2019
use Doctrine\ODM\MongoDB\Repository\DocumentRepository;
2120
use Doctrine\ODM\MongoDB\Repository\GridFSRepository;
2221
use Doctrine\ODM\MongoDB\Repository\RepositoryFactory;
2322
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
2423
use Doctrine\Persistence\ObjectRepository;
25-
use InvalidArgumentException;
26-
use LogicException;
2724
use MongoDB\Client;
2825
use MongoDB\Driver\Manager;
2926
use MongoDB\Driver\WriteConcern;
30-
use ProxyManager\Configuration as ProxyManagerConfiguration;
31-
use ProxyManager\Factory\LazyLoadingGhostFactory;
32-
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
33-
use ProxyManager\GeneratorStrategy\FileWriterGeneratorStrategy;
3427
use Psr\Cache\CacheItemPoolInterface;
3528
use ReflectionClass;
3629
use stdClass;
37-
use Symfony\Component\VarExporter\LazyGhostTrait;
3830
use Throwable;
3931

4032
use function array_diff_key;
4133
use function array_intersect_key;
4234
use function array_key_exists;
43-
use function class_exists;
4435
use function interface_exists;
4536
use function is_string;
46-
use function trait_exists;
4737
use function trigger_deprecation;
4838
use function trim;
4939

@@ -63,42 +53,39 @@
6353
class Configuration
6454
{
6555
/**
66-
* Never autogenerate a proxy/hydrator/persistent collection and rely that
67-
* it was generated by some process before deployment. Copied from
68-
* \Doctrine\Common\Proxy\AbstractProxyFactory.
56+
* Never autogenerate a hydrator/persistent collection and rely that
57+
* it was generated by some process before deployment.
6958
*/
7059
public const int AUTOGENERATE_NEVER = 0;
7160

7261
/**
73-
* Always generates a new proxy/hydrator/persistent collection in every request.
62+
* Always generates a new hydrator/persistent collection in every request.
7463
*
7564
* This is only sane during development.
76-
* Copied from \Doctrine\Common\Proxy\AbstractProxyFactory.
7765
*/
7866
public const int AUTOGENERATE_ALWAYS = 1;
7967

8068
/**
81-
* Autogenerate the proxy/hydrator/persistent collection class when the file does not exist.
69+
* Autogenerate the hydrator/persistent collection class when the file does not exist.
8270
*
83-
* This strategy causes a file exists call whenever any proxy/hydrator is used the
84-
* first time in a request. Copied from \Doctrine\Common\Proxy\AbstractProxyFactory.
71+
* This strategy causes a file exists call whenever any hydrator is used the
72+
* first time in a request.
8573
*/
8674
public const int AUTOGENERATE_FILE_NOT_EXISTS = 2;
8775

8876
/**
89-
* Generate the proxy/hydrator/persistent collection classes using eval().
77+
* Generate the hydrator/persistent collection classes using eval().
9078
*
9179
* This strategy is only sane for development.
92-
* Copied from \Doctrine\Common\Proxy\AbstractProxyFactory.
9380
*/
9481
public const int AUTOGENERATE_EVAL = 3;
9582

9683
/**
97-
* Autogenerate the proxy class when the proxy file does not exist or
84+
* Autogenerate the class when the file does not exist or
9885
* when the proxied file changed.
9986
*
100-
* This strategy causes a file_exists() call whenever any proxy is used the
101-
* first time in a request. When the proxied file is changed, the proxy will
87+
* This strategy causes a file_exists() call whenever any class is used the
88+
* first time in a request. When the proxied file is changed, the class will
10289
* be updated.
10390
*/
10491
public const int AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED = 4;
@@ -109,7 +96,6 @@ class Configuration
10996
* @phpstan-var array{
11097
* autoGenerateHydratorClasses?: self::AUTOGENERATE_*,
11198
* autoGeneratePersistentCollectionClasses?: self::AUTOGENERATE_*,
112-
* autoGenerateProxyClasses?: self::AUTOGENERATE_*,
11399
* classMetadataFactoryName?: class-string<ClassMetadataFactoryInterface>,
114100
* defaultCommitOptions?: CommitOptions,
115101
* defaultDocumentRepositoryClassName?: class-string<ObjectRepository<object>>,
@@ -128,8 +114,6 @@ class Configuration
128114
* persistentCollectionGenerator?: PersistentCollectionGenerator,
129115
* persistentCollectionDir?: string,
130116
* persistentCollectionNamespace?: string,
131-
* proxyDir?: string,
132-
* proxyNamespace?: string,
133117
* repositoryFactory?: RepositoryFactory,
134118
* kmsProvider?: KmsProvider,
135119
* defaultMasterKey?: array<string, mixed>|null,
@@ -140,14 +124,8 @@ class Configuration
140124

141125
private ?CacheItemPoolInterface $metadataCache = null;
142126

143-
/** @deprecated */
144-
private ProxyManagerConfiguration $proxyManagerConfiguration;
145-
146127
private bool $useTransactionalFlush = false;
147128

148-
private bool $lazyGhostObject = false;
149-
private bool $nativeLazyObject = false;
150-
151129
private static string $version;
152130

153131
/**
@@ -298,65 +276,6 @@ public function setMetadataCache(CacheItemPoolInterface $cache): void
298276
$this->attributes['metadataCacheImpl'] = DoctrineProvider::wrap($cache);
299277
}
300278

301-
/**
302-
* Sets the directory where Doctrine generates any necessary proxy class files.
303-
*
304-
* @deprecated Since 2.16, proxy directory is no longer used when native lazy objects are enabled.
305-
*/
306-
public function setProxyDir(string $dir): void
307-
{
308-
$this->attributes['proxyDir'] = $dir;
309-
unset($this->proxyManagerConfiguration);
310-
}
311-
312-
/**
313-
* Gets the directory where Doctrine generates any necessary proxy class files.
314-
*
315-
* @deprecated Since 2.16, proxy directory is no longer used when native lazy objects are enabled.
316-
*/
317-
public function getProxyDir(): ?string
318-
{
319-
if ($this->isNativeLazyObjectEnabled()) {
320-
trigger_deprecation('doctrine/mongodb-odm', '2.16', 'Using "%s" is deprecated when native lazy objects are enabled.', __METHOD__);
321-
}
322-
323-
return $this->attributes['proxyDir'] ?? null;
324-
}
325-
326-
/**
327-
* Gets an int flag that indicates whether proxy classes should always be regenerated
328-
* during each script execution.
329-
*
330-
* @return self::AUTOGENERATE_*
331-
*/
332-
public function getAutoGenerateProxyClasses(): int
333-
{
334-
return $this->attributes['autoGenerateProxyClasses'] ?? self::AUTOGENERATE_FILE_NOT_EXISTS;
335-
}
336-
337-
/**
338-
* Sets an int flag that indicates whether proxy classes should always be regenerated
339-
* during each script execution.
340-
*
341-
* @param self::AUTOGENERATE_* $mode
342-
*/
343-
public function setAutoGenerateProxyClasses(int $mode): void
344-
{
345-
$this->attributes['autoGenerateProxyClasses'] = $mode;
346-
unset($this->proxyManagerConfiguration);
347-
}
348-
349-
public function getProxyNamespace(): ?string
350-
{
351-
return $this->attributes['proxyNamespace'] ?? null;
352-
}
353-
354-
public function setProxyNamespace(string $ns): void
355-
{
356-
$this->attributes['proxyNamespace'] = $ns;
357-
unset($this->proxyManagerConfiguration);
358-
}
359-
360279
public function setHydratorDir(string $dir): void
361280
{
362281
$this->attributes['hydratorDir'] = $dir;
@@ -634,41 +553,6 @@ public function getPersistentCollectionGenerator(): PersistentCollectionGenerato
634553
return $this->attributes['persistentCollectionGenerator'];
635554
}
636555

637-
/** @deprecated */
638-
public function buildGhostObjectFactory(): LazyLoadingGhostFactory
639-
{
640-
return new LazyLoadingGhostFactory($this->getProxyManagerConfiguration());
641-
}
642-
643-
/** @deprecated */
644-
public function getProxyManagerConfiguration(): ProxyManagerConfiguration
645-
{
646-
if (isset($this->proxyManagerConfiguration)) {
647-
return $this->proxyManagerConfiguration;
648-
}
649-
650-
$proxyManagerConfiguration = new ProxyManagerConfiguration();
651-
$proxyManagerConfiguration->setProxiesTargetDir($this->getProxyDir());
652-
$proxyManagerConfiguration->setProxiesNamespace($this->getProxyNamespace());
653-
654-
switch ($this->getAutoGenerateProxyClasses()) {
655-
case self::AUTOGENERATE_FILE_NOT_EXISTS:
656-
$proxyManagerConfiguration->setGeneratorStrategy(new FileWriterGeneratorStrategy(
657-
new FileLocator($proxyManagerConfiguration->getProxiesTargetDir()),
658-
));
659-
660-
break;
661-
case self::AUTOGENERATE_EVAL:
662-
$proxyManagerConfiguration->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
663-
664-
break;
665-
default:
666-
throw new InvalidArgumentException('Invalid proxy generation strategy given - only AUTOGENERATE_FILE_NOT_EXISTS and AUTOGENERATE_EVAL are supported.');
667-
}
668-
669-
return $this->proxyManagerConfiguration = $proxyManagerConfiguration;
670-
}
671-
672556
public function setUseTransactionalFlush(bool $useTransactionalFlush): void
673557
{
674558
$this->useTransactionalFlush = $useTransactionalFlush;
@@ -679,51 +563,6 @@ public function isTransactionalFlushEnabled(): bool
679563
return $this->useTransactionalFlush;
680564
}
681565

682-
/**
683-
* Generate proxy classes using Symfony VarExporter's LazyGhostTrait if true.
684-
* Otherwise, use ProxyManager's LazyLoadingGhostFactory (deprecated)
685-
*/
686-
public function setUseLazyGhostObject(bool $flag): void
687-
{
688-
if ($this->nativeLazyObject) {
689-
throw new LogicException('Cannot enable or disable LazyGhostObject when native lazy objects are enabled.');
690-
}
691-
692-
if ($flag && ! trait_exists(LazyGhostTrait::class)) {
693-
throw new LogicException('Package "symfony/var-exporter" >= 8.0 does not provide lazy ghost objects, use native lazy objects instead.');
694-
}
695-
696-
if (! $flag) {
697-
if (! class_exists(ProxyManagerConfiguration::class)) {
698-
throw new LogicException('Package "friendsofphp/proxy-manager-lts" is required to disable LazyGhostObject.');
699-
}
700-
701-
trigger_deprecation('doctrine/mongodb-odm', '2.10', 'Using "friendsofphp/proxy-manager-lts" is deprecated. Use "symfony/var-exporter" LazyGhostObjects instead.');
702-
}
703-
704-
$this->lazyGhostObject = $flag;
705-
}
706-
707-
public function isLazyGhostObjectEnabled(): bool
708-
{
709-
// Always false if native lazy objects are enabled
710-
return $this->lazyGhostObject && ! $this->nativeLazyObject;
711-
}
712-
713-
public function setUseNativeLazyObject(bool $nativeLazyObject): void
714-
{
715-
$this->nativeLazyObject = $nativeLazyObject;
716-
}
717-
718-
public function isNativeLazyObjectEnabled(): bool
719-
{
720-
if (! $this->nativeLazyObject) {
721-
trigger_deprecation('doctrine/mongodb-odm', '2.14', 'Not using native lazy objects is deprecated and will be impossible in Doctrine MongoDB ODM 3.0.');
722-
}
723-
724-
return $this->nativeLazyObject;
725-
}
726-
727566
/**
728567
* Set the KMS provider to use for auto-encryption. The name of the KMS provider
729568
* must be specified in the 'type' key of the array.

src/ConfigurationException.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ public static function noMetadataDriverConfigured(): self
2525
return new self('No metadata driver was configured. Please set a metadata driver implementation in your configuration.');
2626
}
2727

28-
public static function proxyDirMissing(): self
29-
{
30-
return new self('No proxy directory was configured. Please set a target directory first!');
31-
}
32-
3328
public static function clientEncryptionOptionsNotSet(): self
3429
{
3530
return new self('MongoDB client encryption options are not set in configuration');

0 commit comments

Comments
 (0)