8000 [DI] fix preloading script generation · symfony/symfony@d443a87 · GitHub
[go: up one dir, main page]

Skip to content

Commit d443a87

Browse files
[DI] fix preloading script generation
1 parent 46e441f commit d443a87

30 files changed

+217
-14
lines changed

src/Symfony/Bridge/Twig/Extension/TranslationExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use Twig\TokenParser\AbstractTokenParser;
2525
use Twig\TwigFilter;
2626

27+
class_exists(TranslatorInterface::class);
28+
2729
/**
2830
* Provides integration of the Translation component with Twig.
2931
*

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass;
2424
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
2525
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass;
26+
use Symfony\Component\Cache\Adapter\ApcuAdapter;
27+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
28+
use Symfony\Component\Cache\Adapter\ChainAdapter;
29+
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
30+
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
2631
use Symfony\Component\Cache\DependencyInjection\CacheCollectorPass;
2732
use Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass;
2833
use Symfony\Component\Cache\DependencyInjection\CachePoolPass;
@@ -32,6 +37,7 @@
3237
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
3338
use Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass;
3439
use Symfony\Component\DependencyInjection\ContainerBuilder;
40+
use Symfony\Component\Dotenv\Dotenv;
3541
use Symfony\Component\ErrorHandler\ErrorHandler;
3642
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
3743
use Symfony\Component\Form\DependencyInjection\FormPass;
@@ -58,6 +64,18 @@
5864
use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass;
5965
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
6066
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
67+
use Symfony\Component\VarExporter\Internal\Hydrator;
68+
use Symfony\Component\VarExporter\Internal\Registry;
69+
70+
class_exists(ApcuAdapter::class);
71+
class_exists(ArrayAdapter::class);
72+
class_exists(ChainAdapter::class);
73+
class_exists(PhpArrayAdapter::class);
74+
class_exists(PhpFilesAdapter::class);
75+
class_exists(Dotenv::class);
76+
class_exists(ErrorHandler::class);
77+
class_exists(Hydrator::class);
78+
class_exists(Registry::class);
6179

6280
/**
6381
* Bundle.

src/Symfony/Bundle/FrameworkBundle/Routing/Router.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
2121
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
2222
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
23+
use Symfony\Component\Routing\Annotation\Route;
2324
use Symfony\Component\Routing\RequestContext;
2425
use Symfony\Component\Routing\RouteCollection;
2526
use Symfony\Component\Routing\Router as BaseRouter;
2627

28+
class_exists(RedirectableCompiledUrlMatcher::class);
29+
class_exists(Route::class);
30+
2731
/**
2832
* This Router creates the Loader only when the cache is empty.
2933
*

src/Symfony/Bundle/TwigBundle/TwigBundle.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@
2020
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
2121
use Symfony\Component\DependencyInjection\ContainerBuilder;
2222
use Symfony\Component\HttpKernel\Bundle\Bundle;
23+
use Twig\Cache\FilesystemCache;
24+
use Twig\Extension\CoreExtension;
25+
use Twig\Extension\EscaperExtension;
26+
use Twig\Extension\OptimizerExtension;
27+
use Twig\Extension\StagingExtension;
28+
use Twig\ExtensionSet;
29+
30+
class_exists(FilesystemCache::class);
31+
class_exists(CoreExtension::class);
32+
class_exists(EscaperExtension::class);
33+
class_exists(OptimizerExtension::class);
34+
class_exists(StagingExtension::class);
35+
class_exists(ExtensionSet::class);
2336

2437
/**
2538
* Bundle.

src/Symfony/Component/Cache/Adapter/AdapterInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Psr\Cache\CacheItemPoolInterface;
1515
use Symfony\Component\Cache\CacheItem;
1616

17+
class_exists(CacheItem::class);
18+
1719
/**
1820
* Interface for adapters managing instances of Symfony's CacheItem.
1921
*

src/Symfony/Component/DependencyInjection/Container.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\DependencyInjection;
1313

14+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator;
1416
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
1517
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1618
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
@@ -22,6 +24,9 @@
2224
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
2325
use Symfony\Contracts\Service\ResetInterface;
2426

27+
class_exists(RewindableGenerator::class);
28+
class_exists(ArgumentServiceLocator::class);
29+
2530
/**
2631
* Container is a dependency injection container.
2732
*

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

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class PhpDumper extends Dumper
8181
private $inlinedRequires = [];
8282
private $circularReferences = [];
8383
private $singleUsePrivateIds = [];
84+
private $preload = [];
8485
private $addThrow = false;
8586
private $addGetService = false;
8687
private $locatedIds = [];
@@ -142,6 +143,7 @@ public function dump(array $options = [])
142143
'hot_path_tag' => 'container.hot_path',
143144
'inline_factories_parameter' => 'container.dumper.inline_factories',
144145
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
146+
'preload_classes' => [],
145147
'service_locator_tag' => 'container.service_locator',
146148
'build_time' => time(),
147149
], $options);
@@ -226,8 +228,12 @@ public function dump(array $options = [])
226228

227229
$proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null;
228230

231+
if ($options['preload_classes']) {
232+
$this->preload = array_combine($options['preload_classes'], $options['preload_classes']);
233+
}
234+
229235
$code =
230-
$this->startClass($options['class'], $baseClass, $preload).
236+
$this->startClass($options['class'], $baseClass).
231237
$this->addServices($services).
232238
$this->addDeprecatedAliases().
233239
$this->addDefaultParametersMethod()
@@ -302,7 +308,7 @@ public function dump(array $options = [])
302308
$id = hash('crc32', $hash.$time);
303309
$this->asFiles = false;
304310

305-
if ($preload && null !== $autoloadFile = $this->getAutoloadFile()) {
311+
if ($this->preload && null !== $autoloadFile = $this->getAutoloadFile()) {
306312
$autoloadFile = substr($this->export($autoloadFile), 2, -1);
307313

308314
$code[$options['class'].'.preload.php'] = <<<EOF
@@ -320,8 +326,10 @@ public function dump(array $options = [])
320326
321327
EOF;
322328

323-
foreach ($preload as $class) {
324-
$code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class);
329+
foreach ($this->preload as $class) {
330+
if ($class && (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined())) {
331+
$code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class);
332+
}
325333
}
326334

327335
$code[$options['class'].'.preload.php'] .= <<<'EOF'
@@ -367,6 +375,7 @@ public function dump(array $options = [])
367375
$this->circularReferences = [];
368376
$this->locatedIds = [];
369377
$this->exportedVariables = [];
378+
$this->preload = [];
370379

371380
$unusedEnvs = [];
372381
foreach ($this->container->getEnvCounters() as $env => $use) {
@@ -542,8 +551,10 @@ private function addServiceInclude(string $cId, Definition $definition): string
542551
if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) {
543552
$lineage = [];
544553
foreach ($this->inlinedDefinitions as $def) {
545-
if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
546-
$this->collectLineage($class, $lineage);
554+
if (!$def->isDeprecated()) {
555+
foreach ($this->getClasses($def) as $class) {
556+
$this->collectLineage($class, $lineage);
557+
}
547558
}
548559
}
549560

@@ -552,9 +563,10 @@ private function addServiceInclude(string $cId, Definition $definition): string
552563
&& ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
553564
&& $this->container->has($id)
554565
&& $this->isTrivialInstance($def = $this->container->findDefinition($id))
555-
&& \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())
556566
) {
557-
$this->collectLineage($class, $lineage);
567+
foreach ($this->getClasses($def) as $class) {
568+
$this->collectLineage($class, $lineage);
569+
}
558570
}
559571
}
560572

@@ -804,6 +816,12 @@ protected function {$methodName}($lazyInitialization)
804816

805817
if ($definition->isDeprecated()) {
806818
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
819+
} else {
820+
foreach ($this->inlinedDefinitions as $def) {
821+
foreach ($this->getClasses($def) as $class) {
822+
$this->preload[$class] = $class;
823+
}
824+
}
807825
}
808826

809827
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
@@ -960,7 +978,15 @@ private function addServices(array &$services = null): string
960978
$definitions = $this->container->getDefinitions();
961979
ksort($definitions);
962980
foreach ($definitions as $id => $definition) {
963-
$services[$id] = $definition->isSynthetic() ? null : $this->addService($id, $definition);
981+
if (!$definition->isSynthetic()) {
982+
$services[$id] = $this->addService($id, $definition);
983+
} else {
984+
$services[$id] = null;
985+
986+
foreach ($this->getClasses($definition) as $class) {
987+
$this->preload[$class] = $class;
988+
}
989+
}
964990
}
965991

966992
foreach ($definitions as $id => $definition) {
@@ -1061,7 +1087,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
10611087
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
10621088
}
10631089

1064-
private function startClass(string $class, string $baseClass, ?array &$preload): string
1090+
private function startClass(string $class, string $baseClass): string
10651091
{
10661092
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
10671093

@@ -1124,7 +1150,7 @@ public function __construct()
11241150
$code .= $this->addMethodMap();
11251151
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
11261152
$code .= $this->addAliases();
1127-
$code .= $this->addInlineRequires($preload);
1153+
$code .= $this->addInlineRequires();
11281154
$code .= <<<EOF
11291155
}
11301156
@@ -1324,7 +1350,7 @@ protected function {$methodNameAlias}()
13241350
return $code;
13251351
}
13261352

1327-
private function addInlineRequires(?array &$preload): string
1353+
private function addInlineRequires(): string
13281354
{
13291355
if (!$this->hotPathTag || !$this->inlineRequires) {
13301356
return '';
@@ -1342,8 +1368,7 @@ private function addInlineRequires(?array &$preload): string
13421368
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
13431369

13441370
foreach ($inlinedDefinitions as $def) {
1345-
if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
1346-
$preload[$class] = $class;
1371+
foreach ($this->getClasses($def) as $class) {
13471372
$this->collectLineage($class, $lineage);
13481373
}
13491374
}
@@ -2065,4 +2090,29 @@ private function getAutoloadFile(): ?string
20652090

20662091
return null;
20672092
}
2093+
2094+
private function getClasses(Definition $definition): array
2095+
{
2096+
$classes = [];
2097+
2098+
while ($definition instanceof Definition) {
2099+
$classes[] = trim($definition->getClass(), '\\');
2100+
$factory = $definition->getFactory();
2101+
2102+
if (!\is_array($factory)) {
2103+
$factory = [$factory];
2104+
}
2105+
2106+
if (\is_string($factory[0])) {
2107+
if (false !== $i = strrpos($factory[0], '::')) {
2108+
$factory[0] = substr($factory[0], 0, $i);
2109+
}
2110+
$classes[] = trim($factory[0], '\\');
2111+
}
2112+
2113+
$definition = $factory[0];
2114+
}
2115+
2116+
return array_filter($classes);
2117+
}
20682118
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,24 @@ class ProjectServiceContainer extends Container
531531
}
532532
}
533533

534+
[ProjectServiceContainer.preload.php] => <?php
535+
%A
536+
537+
$classes = [];
538+
$classes[] = 'Bar\FooClass';
539+
$classes[] = 'Baz';
540+
$classes[] = 'ConfClass';
541+
$classes[] = 'Bar';
542+
$classes[] = 'BazClass';
543+
$classes[] = 'Foo';
544+
$classes[] = 'LazyContext';
545+
$classes[] = 'FooBarBaz';
546+
$classes[] = 'FactoryClass';
547+
$classes[] = 'Request';
548+
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
549+
550+
%A
551+
534552
[ProjectServiceContainer.php] => <?php
535553

536554
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,16 @@ class ProjectServiceContainer extends Container
536536

537537
$classes = [];
538538
$classes[] = 'Bar\FooClass';
539+
$classes[] = 'Baz';
540+
$classes[] = 'ConfClass';
541+
$classes[] = 'Bar';
542+
$classes[] = 'BazClass';
543+
$classes[] = 'Foo';
544+
$classes[] = 'LazyContext';
545+
$classes[] = 'FooBarBaz';
546+
$classes[] = 'FactoryClass';
547+
$classes[] = 'Request';
548+
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
539549

540550
%A
541551

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ class FooClass_%s extends \Bar\FooClass implements \ProxyManager\Proxy\VirtualPr
165165
%A
166166
}
167167

168+
[ProjectServiceContainer.preload.php] => <?php
169+
%A
170+
171+
$classes = [];
172+
$classes[] = 'Bar\FooClass';
173+
$classes[] = 'Bar\FooLazyClass';
174+
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
175+
176+
%A
177+
168178
[ProjectServiceContainer.php] => <?php
169179

170180
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_as_files.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ class ProjectServiceContainer extends Container
8383
}
8484
}
8585

86+
[ProjectServiceContainer.preload.php] => <?php
87+
%A
88+
89+
$classes = [];
90+
$classes[] = 'Bar\FooLazyClass';
91+
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
92+
93+
%A
94+
8695
[ProjectServiceContainer.php] => <?php
8796

8897
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.

src/Symfony/Component/ErrorHandler/ErrorRenderer/CliErrorRenderer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Symfony\Component\VarDumper\Cloner\VarCloner;
1616
use Symfony\Component\VarDumper\Dumper\CliDumper;
1717

18+
class_exists(CliDumper::class);
19+
1820
/**
1921
* @author Nicolas Grekas <p@tchwork.com>
2022
*/

src/Symfony/Component/HttpFoundation/AcceptHeader.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\HttpFoundation;
1313

14+
class_exists(AcceptHeaderItem::class);
15+
1416
/**
1517
* Represents an Accept-* header.
1618
*

0 commit comments

Comments
 (0)
0