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

Skip to content

Commit f790bb9

Browse files
[DependencyInjection][VarExporter] Generate lazy proxies for non-ghostable lazy services out of the box
1 parent 667e635 commit f790bb9

Some content is hidden

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

46 files changed

+1369
-402
lines changed

.github/expected-missing-return-types.diff

+23-23
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ head=$(sed '/^diff /Q' .github/expected-missing-return-types.diff)
77
git checkout composer.json src/
88

99
diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
10-
index 165797504b..0c0922088a 100644
10+
index 18b5c21b9f..8fca8244e3 100644
1111
--- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
1212
+++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php
13-
@@ -87,5 +87,5 @@ abstract class KernelTestCase extends TestCase
13+
@@ -88,5 +88,5 @@ abstract class KernelTestCase extends TestCase
1414
* @return Container
1515
*/
1616
- protected static function getContainer(): ContainerInterface
@@ -156,52 +156,52 @@ index 6b1c6c5fbe..bb80ed461e 100644
156156
+ public function isFresh(ResourceInterface $resource, int $timestamp): bool;
157157
}
158158
diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php
159-
index 64068fcc23..f29aaf1b94 100644
159+
index 53f2021fa9..cf95c1fe99 100644
160160
--- a/src/Symfony/Component/Console/Application.php
161161
+++ b/src/Symfony/Component/Console/Application.php
162-
@@ -218,5 +218,5 @@ class Application implements ResetInterface
162+
@@ -219,5 +219,5 @@ class Application implements ResetInterface
163163
* @return int 0 if everything went fine, or an error code
164164
*/
165165
- public function doRun(InputInterface $input, OutputInterface $output)
166166
+ public function doRun(InputInterface $input, OutputInterface $output): int
167167
{
168168
if (true === $input->hasParameterOption(['--version', '-V'], true)) {
169-
@@ -454,5 +454,5 @@ class Application implements ResetInterface
169+
@@ -453,5 +453,5 @@ class Application implements ResetInterface
170170
* @return string
171171
*/
172172
- public function getLongVersion()
173173
+ public function getLongVersion(): string
174174
{
175175
if ('UNKNOWN' !== $this->getName()) {
176-
@@ -497,5 +497,5 @@ class Application implements ResetInterface
176+
@@ -496,5 +496,5 @@ class Application implements ResetInterface
177177
* @return Command|null
178178
*/
179179
- public function add(Command $command)
180180
+ public function add(Command $command): ?Command
181181
{
182182
$this->init();
183-
@@ -534,5 +534,5 @@ class Application implements ResetInterface
183+
@@ -533,5 +533,5 @@ class Application implements ResetInterface
184184
* @throws CommandNotFoundException When given command name does not exist
185185
*/
186186
- public function get(string $name)
187187
+ public function get(string $name): Command
188188
{
189189
$this->init();
190-
@@ -641,5 +641,5 @@ class Application implements ResetInterface
190+
@@ -640,5 +640,5 @@ class Application implements ResetInterface
191191
* @throws CommandNotFoundException When command name is incorrect or ambiguous
192192
*/
193193
- public function find(string $name)
194194
+ public function find(string $name): Command
195195
{
196196
$this->init();
197-
@@ -751,5 +751,5 @@ class Application implements ResetInterface
197+
@@ -750,5 +750,5 @@ class Application implements ResetInterface
198198
* @return Command[]
199199
*/
200200
- public function all(string $namespace = null)
201201
+ public function all(string $namespace = null): array
202202
{
203203
$this->init();
204-
@@ -950,5 +950,5 @@ class Application implements ResetInterface
204+
@@ -949,5 +949,5 @@ class Application implements ResetInterface
205205
* @return int 0 if everything went fine, or an error code
206206
*/
207207
- protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
@@ -234,7 +234,7 @@ index b41e691537..34de10fa70 100644
234234
{
235235
if (null === $this->helperSet) {
236236
diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php
237-
index 3c6b0efccd..121664f15a 100644
237+
index 0112350a50..dc972564fb 100644
238238
--- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php
239239
+++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php
240240
@@ -137,5 +137,5 @@ class OutputFormatter implements WrappableOutputFormatterInterface
@@ -301,22 +301,22 @@ index 2f1631ed30..a4b572771e 100644
301301
{
302302
if (\is_array($value)) {
303303
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
304-
index 04b7022484..5d736ec754 100644
304+
index 20ca68e514..e0850df0f8 100644
305305
--- a/src/Symfony/Component/DependencyInjection/Container.php
306306
+++ b/src/Symfony/Component/DependencyInjection/Container.php
307-
@@ -108,5 +108,5 @@ class Container implements ContainerInterface, ResetInterface
308-
* @throws InvalidArgumentException if the parameter is not defined
307+
@@ -109,5 +109,5 @@ class Container implements ContainerInterface, ResetInterface
308+
* @throws ParameterNotFoundException if the parameter is not defined
309309
*/
310310
- public function getParameter(string $name)
311311
+ public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
312312
{
313313
return $this->parameterBag->get($name);
314314
diff --git a/src/Symfony/Component/DependencyInjection/ContainerInterface.php b/src/Symfony/Component/DependencyInjection/ContainerInterface.php
315-
index cad44026c0..14cd192e07 100644
315+
index 9e97fb71fc..1cda97c611 100644
316316
--- a/src/Symfony/Component/DependencyInjection/ContainerInterface.php
317317
+++ b/src/Symfony/Component/DependencyInjection/ContainerInterface.php
318318
@@ -53,5 +53,5 @@ interface ContainerInterface extends PsrContainerInterface
319-
* @throws InvalidArgumentException if the parameter is not defined
319+
* @throws ParameterNotFoundException if the parameter is not defined
320320
*/
321321
- public function getParameter(string $name);
322322
+ public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null;
@@ -358,7 +358,7 @@ index d553203c43..1163f4b107 100644
358358
{
359359
$class = static::class;
360360
diff --git a/src/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php b/src/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php
361-
index 4f66f18073..e96d867296 100644
361+
index 11cda00cc5..07b4990160 100644
362362
--- a/src/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php
363363
+++ b/src/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php
364364
@@ -35,5 +35,5 @@ interface ExtensionInterface
@@ -913,7 +913,7 @@ index 5014b9bd51..757c76f546 100644
913913
+ public function supportsDecoding(string $format /* , array $context = [] */): bool;
914914
}
915915
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
916-
index 391cdcb39c..f637687e74 100644
916+
index e426d87076..350cbc6335 100644
917917
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
918918
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
919919
@@ -213,5 +213,5 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
@@ -1094,11 +1094,11 @@ index b22d6ae609..31d1a25f9d 100644
10941094
+ public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array
10951095
{
10961096
$refs = $values;
1097-
diff --git a/src/Symfony/Component/VarExporter/Internal/GhostObjectState.php b/src/Symfony/Component/VarExporter/Internal/GhostObjectState.php
1098-
index 471c1a6b91..2e19d2ab2d 100644
1099-
--- a/src/Symfony/Component/VarExporter/Internal/GhostObjectState.php
1100-
+++ b/src/Symfony/Component/VarExporter/Internal/GhostObjectState.php
1101-
@@ -54,5 +54,5 @@ class GhostObjectState
1097+
diff --git a/src/Symfony/Component/VarExporter/Internal/LazyObjectState.php b/src/Symfony/Component/VarExporter/Internal/LazyObjectState.php
1098+
index 6ea89bc831..01748bcfc0 100644
1099+
--- a/src/Symfony/Component/VarExporter/Internal/LazyObjectState.php
1100+
+++ b/src/Symfony/Component/VarExporter/Internal/LazyObjectState.php
1101+
@@ -56,5 +56,5 @@ class LazyObjectState
11021102
* @return bool Returns true when fully-initializing, false when partial-initializing
11031103
*/
11041104
- public function initialize($instance, $propertyName, $propertyScope)

src/Symfony/Bridge/Doctrine/ManagerRegistry.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use ProxyManager\Proxy\GhostObjectInterface;
1616
use ProxyManager\Proxy\LazyLoadingInterface;
1717
use Symfony\Component\DependencyInjection\Container;
18-
use Symfony\Component\VarExporter\LazyGhostObjectInterface;
18+
use Symfony\Component\VarExporter\LazyObjectInterface;
1919

2020
/**
2121
* References Doctrine connections and entity/document managers.
@@ -47,8 +47,8 @@ protected function resetService($name): void
4747
}
4848
$manager = $this->container->get($name);
4949

50-
if ($manager instanceof LazyGhostObjectInterface) {
51-
if (!$manager->resetLazyGhostObject()) {
50+
if ($manager instanceof LazyObjectInterface) {
51+
if (!$manager->resetLazyObject()) {
5252
throw new \LogicException(sprintf('Resetting a non-lazy manager service is not supported. Declare the "%s" service as lazy.', $name));
5353
}
5454

src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPUnit\Framework\TestCase;
1717
use ProxyManager\Proxy\LazyLoadingInterface;
1818
use ProxyManagerBridgeFooClass;
19+
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
1920
use Symfony\Component\DependencyInjection\ContainerBuilder;
2021

2122
/**
@@ -29,6 +30,7 @@ class ContainerBuilderTest extends TestCase
2930
public function testCreateProxyServiceWithRuntimeInstantiator()
3031
{
3132
$builder = new ContainerBuilder();
33+
$builder->setProxyInstantiator(new RuntimeInstantiator());
3234

3335
$builder->register('foo1', ProxyManagerBridgeFooClass::class)->setFile(__DIR__.'/Fixtures/includes/foo.php')->setPublic(true);
3436
$builder->getDefinition('foo1')->setLazy(true)->addTag('proxy', ['interface' => ProxyManagerBridgeFooClass::class]);

src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use ProxyManager\Proxy\LazyLoadingInterface;
16+
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1819

@@ -66,6 +67,7 @@ private function dumpLazyServiceProjectServiceContainer()
6667
$container->compile();
6768

6869
$dumper = new PhpDumper($container);
70+
$dumper->setProxyDumper(new ProxyDumper());
6971

7072
return $dumper->dump(['class' => 'LazyServiceProjectServiceContainer']);
7173
}

src/Symfony/Component/DependencyInjection/CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CHANGELOG
44
6.2
55
---
66

7-
* Use lazy-loading ghost object proxies out of the box
7+
* Use lazy-loading ghost objects and virtual proxies out of the box
88
* Add argument `&$asGhostObject` to LazyProxy's `DumperInterface` to allow using ghost objects for lazy loading services
99
* Add `enum` env var processor
1010
* Add `shuffle` env var processor

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
use Symfony\Component\DependencyInjection\Definition;
2525
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
2626
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
27-
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
2827
use Symfony\Component\DependencyInjection\Reference;
2928
use Symfony\Component\DependencyInjection\TypedReference;
29+
use Symfony\Component\VarExporter\ProxyHelper;
3030

3131
/**
3232
* Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
@@ -245,7 +245,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
245245
continue;
246246
}
247247

248-
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
248+
$type = $parameter->hasType() ? ProxyHelper::exportType($reflectionMethod, $parameter->getType(), true) : null;
249249

250250
if ($checkAttributes) {
251251
foreach ($parameter->getAttributes() as $attribute) {
@@ -301,8 +301,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
301301
--$index;
302302
break;
303303
}
304-
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
305-
$type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint';
304+
$type = $parameter->hasType() ? ProxyHelper::exportType($reflectionMethod, $parameter->getType()) : null;
305+
$type = $type ? sprintf('is type-hinted "%s"', preg_replace('/(^|[(|&])\\\\|^\?\\\\?/', '\1', $type)) : 'has no type-hint';
306306

307307
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type));
308308
}

src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
use Symfony\Component\DependencyInjection\Definition;
2020
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
2121
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
22-
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
2322
use Symfony\Component\DependencyInjection\Reference;
2423
use Symfony\Component\DependencyInjection\TypedReference;
24+
use Symfony\Component\VarExporter\ProxyHelper;
2525

2626
/**
2727
* @author Guilhem Niot <[email protected]>
@@ -182,10 +182,11 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
182182
continue;
183183
}
184184

185-
$typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter);
185+
$typeHint = $parameter->hasType() ? ltrim(ProxyHelper::exportType($reflectionMethod, $parameter->getType()), '?') : null;
186+
186187
$name = Target::parseName($parameter);
187188

188-
if ($typeHint && \array_key_exists($k = ltrim($typeHint, '\\').' $'.$name, $bindings)) {
189+
if ($typeHint && \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)) {
189190
$arguments[$key] = $this->getBindingValue($bindings[$k]);
190191

191192
continue;

src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
1515
use Symfony\Component\DependencyInjection\Definition;
1616
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
17-
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
1817
use Symfony\Component\DependencyInjection\Reference;
18+
use Symfony\Component\VarExporter\ProxyHelper;
1919

2020
/**
2121
* Resolves named arguments to their corresponding numeric index.
@@ -90,7 +90,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
9090

9191
$typeFound = false;
9292
foreach ($parameters as $j => $p) {
93-
if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) {
93+
if (!\array_key_exists($j, $resolvedArguments) && $p->hasType() && ProxyHelper::exportType($r, $p->getType(), true) === $key) {
9494
$resolvedArguments[$j] = $argument;
9595
$typeFound = true;
9696
}

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
4747
use Symfony\Component\ExpressionLanguage\Expression;
4848
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
49-
use Symfony\Component\VarExporter\Hydrator;
5049

5150
/**
5251
* ContainerBuilder is a DI container that provides an API to easily describe services.
@@ -1040,10 +1039,6 @@ private function createService(Definition $definition, array &$inlineServices, b
10401039
if (null !== $factory) {
10411040
$service = $factory(...$arguments);
10421041

1043-
if (\is_object($tryProxy) && \get_class($service) !== $parameterBag->resolveValue($definition->getClass())) {
1044-
throw new LogicException(sprintf('Lazy service of type "%s" cannot be hydrated because its factory returned an unexpected instance of "%s". Try adding the "proxy" tag to the corresponding service definition with attribute "interface" set to "%1$s".', $definition->getClass(), get_debug_type($service)));
1045-
}
1046-
10471042
if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
10481043
$r = new \ReflectionClass($factory[0]);
10491044

@@ -1113,10 +1108,6 @@ private function createService(Definition $definition, array &$inlineServices, b
11131108
$callable($service);
11141109
}
11151110

1116-
if (\is_object($tryProxy) && $tryProxy !== $service) {
1117-
return Hydrator::hydrate($tryProxy, (array) $service);
1118-
}
1119-
11201111
return $service;
11211112
}
11221113

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

+2-24
Original file line numberDiff line numberDiff line change
@@ -676,9 +676,6 @@ private function addServiceInstance(string $id, Definition $definition, bool $is
676676

677677
$return = '';
678678
if ($isSimpleInstance) {
679-
if ($asGhostObject && null !== $definition->getFactory()) {
680-
$instantiation .= '$this->hydrateProxy($lazyLoad, ';
681-
}
682679
$return = 'return ';
683680
} else {
684681
$instantiation .= ' = ';
@@ -896,9 +893,7 @@ protected function {$methodName}($lazyInitialization)
896893
$code .= sprintf(' %s ??= ', $factory);
897894

898895
if ($asFile) {
899-
$code .= "function () {\n";
900-
$code .= " return self::do(\$container);\n";
901-
$code .= " };\n\n";
896+
$code .= "fn () => self::do(\$container);\n\n";
902897
} else {
903898
$code .= sprintf("\$this->%s(...);\n\n", $methodName);
904899
}
@@ -1079,11 +1074,7 @@ private function addInlineService(string $id, Definition $definition, Definition
10791074
return $code;
10801075
}
10811076

1082-
if (!$asGhostObject) {
1083-
return $code."\n return \$instance;\n";
1084-
}
1085-
1086-
return $code."\n return \$this->hydrateProxy(\$lazyLoad, \$instance);\n";
1077+
return $code."\n return \$instance;\n";
10871078
}
10881079

10891080
private function addServices(array &$services = null): string
@@ -1329,19 +1320,6 @@ protected function createProxy(\$class, \Closure \$factory)
13291320
{$proxyLoader}return \$factory();
13301321
}
13311322
1332-
protected function hydrateProxy(\$proxy, \$instance)
1333-
{
1334-
if (\$proxy === \$instance) {
1335-
return \$proxy;
1336-
}
1337-
1338-
if (!\in_array(\get_class(\$instance), [\get_class(\$proxy), get_parent_class(\$proxy)], true)) {
1339-
throw new LogicException(sprintf('Lazy service of type "%s" cannot be hydrated because its factory returned an unexpected instance of "%s". Try adding the "proxy" tag to the corresponding service definition with attribute "interface" set to "%1\$s".', get_parent_class(\$proxy), get_debug_type(\$instance)));
1340-
}
1341-
1342-
return \Symfony\Component\VarExporter\Hydrator::hydrate(\$proxy, (array) \$instance);
1343-
}
1344-
13451323
EOF;
13461324
break;
13471325
}

src/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/LazyServiceInstantiator.php

+4-10
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111

1212
namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator;
1313

14-
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
1514
use Symfony\Component\DependencyInjection\ContainerInterface;
1615
use Symfony\Component\DependencyInjection\Definition;
1716
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper;
18-
use Symfony\Component\VarExporter\LazyGhostObjectInterface;
19-
use Symfony\Component\VarExporter\LazyGhostObjectTrait;
17+
use Symfony\Component\VarExporter\LazyGhostTrait;
2018

2119
/**
2220
* @author Nicolas Grekas <[email protected]>
@@ -30,14 +28,10 @@ public function instantiateProxy(ContainerInterface $container, Definition $defi
3028
{
3129
$dumper = new LazyServiceDumper();
3230

33-
if ($dumper->useProxyManager($definition)) {
34-
return (new RuntimeInstantiator())->instantiateProxy($container, $definition, $id, $realInstantiator);
31+
if (!class_exists($proxyClass = $dumper->getProxyClass($definition, $class), false)) {
32+
eval($dumper->getProxyCode($definition));
3533
}
3634

37-
if (!class_exists($proxyClass = $dumper->getProxyClass($definition), false)) {
38-
eval(sprintf('class %s extends %s implements %s { use %s; }', $proxyClass, $definition->getClass(), LazyGhostObjectInterface::class, LazyGhostObjectTrait::class));
39-
}
40-
41-
return $proxyClass::createLazyGhostObject($realInstantiator);
35+
return isset(class_uses($proxyClass)[LazyGhostTrait::class]) ? $proxyClass::createLazyGhost($realInstantiator) : $proxyClass::createLazyProxy($realInstantiator);
4236
}
4337
}

0 commit comments

Comments
 (0)