Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 61acb29

Browse filesBrowse files
[HttpKernel][DI] allow bundles to declare classes that should be preloaded
1 parent b00b633 commit 61acb29
Copy full SHA for 61acb29

File tree

13 files changed

+408
-109
lines changed
Filter options

13 files changed

+408
-109
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+52Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,37 @@ public function load(array $configs, ContainerBuilder $container)
453453

454454
$container->registerForAutoconfiguration(RouteLoaderInterface::class)
455455
->addTag('routing.route_loader');
456+
457+
$this->addClassesToPreload([
458+
'Psr\Log\LogLevel',
459+
'Symfony\Component\Cache\Adapter\ApcuAdapter',
460+
'Symfony\Component\Cache\Adapter\ArrayAdapter',
461+
'Symfony\Component\Cache\Adapter\PhpArrayAdapter',
462+
'Symfony\Component\Cache\Adapter\PhpFilesAdapter',
463+
'Symfony\Component\Cache\CacheItem',
464+
'Symfony\Component\DependencyInjection\Argument\RewindableGenerator',
465+
'Symfony\Component\DependencyInjection\Argument\ServiceLocator',
466+
'Symfony\Component\DependencyInjection\ContainerAwareInterface',
467+
'Symfony\Component\DependencyInjection\ContainerAwareTrait',
468+
'Symfony\Component\Dotenv\Dotenv',
469+
'Symfony\Component\ErrorHandler\ErrorHandler',
470+
'Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy',
471+
'Symfony\Component\HttpFoundation\AcceptHeader',
472+
'Symfony\Component\HttpFoundation\AcceptHeaderItem',
473+
'Symfony\Component\HttpFoundation\FileBag',
474+
'Symfony\Component\HttpFoundation\HeaderBag',
475+
'Symfony\Component\HttpFoundation\HeaderUtils',
476+
'Symfony\Component\HttpFoundation\ParameterBag',
477+
'Symfony\Component\HttpFoundation\ResponseHeaderBag',
478+
'Symfony\Component\HttpFoundation\ServerBag',
479+
'Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent',
480+
'Symfony\Component\HttpKernel\Event\ControllerEvent',
481+
'Symfony\Component\HttpKernel\Event\TerminateEvent',
482+
'Symfony\Component\HttpKernel\KernelEvents',
483+
'Symfony\Component\VarExporter\Internal\Hydrator',
484+
'Symfony\Component\VarExporter\Internal\Registry',
485+
'Symfony\Component\WebLink\HttpHeaderSerializer',
486+
]);
456487
}
457488

458489
/**
@@ -850,6 +881,15 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
850881

851882
$loader->load('routing.xml');
852883

884+
$this->addClassesToPreload([
885+
'Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher',
886+
'Symfony\Component\Routing\Annotation\Route',
887+
'Symfony\Component\Routing\Matcher\CompiledUrlMatcher',
888+
'Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait',
889+
'Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface',
890+
'Symfony\Component\Routing\Matcher\UrlMatcher',
891+
]);
892+
853893
if ($config['utf8']) {
854894
$container->getDefinition('routing.loader')->replaceArgument(2, ['utf8' => true]);
855895
}
@@ -901,6 +941,14 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
901941
{
902942
$loader->load('session.xml');
903943

944+
$this->addClassesToPreload([
945+
'Symfony\Component\HttpFoundation\Session\SessionBagProxy',
946+
'Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler',
947+
'Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler',
948+
'Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy',
949+
'Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy',
950+
]);
951+
904952
// session storage
905953
$container->setAlias('session.storage', $config['storage_id'])->setPrivate(true);
906954
$options = ['cache_limiter' => '0'];
@@ -1118,6 +1166,10 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
11181166

11191167
$loader->load('translation.xml');
11201168

1169+
$this->addClassesToPreload([
1170+
'Symfony\Component\Translation\Formatter\IntlFormatter',
1171+
]);
1172+
11211173
// Use the "real" translator instead of the identity default
11221174
$container->setAlias('translator', 'translator.default')->setPublic(true);
11231175
$container->setAlias('translator.formatter', new Alias($config['formatter'], false));

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,18 @@ public function load(array $configs, ContainerBuilder $container)
161161

162162
$container->registerForAutoconfiguration(VoterInterface::class)
163163
->addTag('security.voter');
164+
165+
$this->addClassesToPreload([
166+
'Symfony\Component\HttpFoundation\RequestMatcher',
167+
'Symfony\Component\Security\Core\Authorization\ExpressionLanguageProvider',
168+
'Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider',
169+
'Symfony\Component\Security\Core\Authentication\Token\AbstractToken',
170+
'Symfony\Component\Security\Core\Authentication\Token\AnonymousToken',
171+
'Symfony\Component\Security\Core\AuthenticationEvents',
172+
'Symfony\Component\Security\Core\Event\AuthenticationEvent',
173+
'Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent',
174+
'Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface',
175+
]);
164176
}
165177

166178
private function createRoleHierarchy(array $config, ContainerBuilder $container)

‎src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@ public function load(array $configs, ContainerBuilder $container)
170170
$container->removeDefinition('twig.cache_warmer');
171171
$container->removeDefinition('twig.template_cache_warmer');
172172
}
173+
174+
$this->addClassesToPreload([
175+
'Symfony\Component\Stopwatch\Section',
176+
'Twig\Cache\FilesystemCache',
177+
'Twig\Extension\CoreExtension',
178+
'Twig\Extension\EscaperExtension',
179+
'Twig\Extension\OptimizerExtension',
180+
'Twig\Extension\StagingExtension',
181+
'Twig\ExtensionSet',
182+
'Twig\Template',
183+
'Twig\TemplateWrapper',
184+
]);
173185
}
174186

175187
private function getBundleTemplatePaths(ContainerBuilder $container, array $config)

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+68-14Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class PhpDumper extends Dumper
8080
private $inlinedRequires = [];
8181
private $circularReferences = [];
8282
private $singleUsePrivateIds = [];
83+
private $preload = [];
8384
private $addThrow = false;
8485
private $addGetService = false;
8586
private $locatedIds = [];
@@ -141,6 +142,7 @@ public function dump(array $options = [])
141142
'hot_path_tag' => 'container.hot_path',
142143
'inline_factories_parameter' => 'container.dumper.inline_factories',
143144
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
145+
'preload_classes' => [],
144146
'service_locator_tag' => 'container.service_locator',
145147
'build_time' => time(),
146148
], $options);
@@ -225,8 +227,13 @@ public function dump(array $options = [])
225227

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

230+
if ($options['preload_classes']) {
231+
$this->preload = $options['preload_classes'];
232+
$this->preload = array_combine($this->preload, $this->preload);
233+
}
234+
228235
$code =
229-
$this->startClass($options['class'], $baseClass, $preload).
236+
$this->startClass($options['class'], $baseClass).
230237
$this->addServices($services).
231238
$this->addDeprecatedAliases().
232239
$this->addDefaultParametersMethod()
@@ -301,7 +308,7 @@ public function dump(array $options = [])
301308
$id = hash('crc32', $hash.$time);
302309
$this->asFiles = false;
303310

304-
if ($preload && null !== $autoloadFile = $this->getAutoloadFile()) {
311+
if ($this->preload && null !== $autoloadFile = $this->getAutoloadFile()) {
305312
$autoloadFile = substr($this->export($autoloadFile), 2, -1);
306313

307314
$code[$options['class'].'.preload.php'] = <<<EOF
@@ -319,8 +326,10 @@ public function dump(array $options = [])
319326
320327
EOF;
321328

322-
foreach ($preload as $class) {
323-
$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+
}
324333
}
325334

326335
$code[$options['class'].'.preload.php'] .= <<<'EOF'
@@ -366,6 +375,7 @@ public function dump(array $options = [])
366375
$this->circularReferences = [];
367376
$this->locatedIds = [];
368377
$this->exportedVariables = [];
378+
$this->preload = [];
369379

370380
$unusedEnvs = [];
371381
foreach ($this->container->getEnvCounters() as $env => $use) {
@@ -541,8 +551,13 @@ private function addServiceInclude(string $cId, Definition $definition): string
541551
if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) {
542552
$lineage = [];
543553
foreach ($this->inlinedDefinitions as $def) {
544-
if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
545-
$this->collectLineage($class, $lineage);
554+
if (!$def->isDeprecated()) {
555+
if ($class = $this->getFactoryClass($def)) {
556+
$this->collectLineage($class, $lineage);
557+
}
558+
if ($class = $def->getClass()) {
559+
$this->collectLineage($class, $lineage);
560+
}
546561
}
547562
}
548563

@@ -551,9 +566,13 @@ private function addServiceInclude(string $cId, Definition $definition): string
551566
&& ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
552567
&& $this->container->has($id)
553568
&& $this->isTrivialInstance($def = $this->container->findDefinition($id))
554-
&& \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())
555569
) {
556-
$this->collectLineage($class, $lineage);
570+
if ($class = $this->getFactoryClass($def)) {
571+
$this->collectLineage($class, $lineage);
572+
}
573+
if ($class = $def->getClass()) {
574+
$this->collectLineage($class, $lineage);
575+
}
557576
}
558577
}
559578

@@ -798,6 +817,15 @@ protected function {$methodName}($lazyInitialization)
798817

799818
if ($definition->isDeprecated()) {
800819
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
820+
} else {
821+
foreach ($this->inlinedDefinitions as $def) {
822+
if ($class = $this->getFactoryClass($def)) {
823+
$this->preload[$class] = $class;
824+
}
825+
if ($class = ltrim($def->getClass(), '\\')) {
826+
$this->preload[$class] = $class;
827+
}
828+
}
801829
}
802830

803831
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
@@ -953,7 +981,18 @@ private function addServices(array &$services = null): string
953981
$definitions = $this->container->getDefinitions();
954982
ksort($definitions);
955983
foreach ($definitions as $id => $definition) {
956-
$services[$id] = $definition->isSynthetic() ? null : $this->addService($id, $definition);
984+
if (!$definition->isSynthetic()) {
985+
$services[$id] = $this->addService($id, $definition);
986+
} else {
987+
$services[$id] = null;
988+
989+
if ($class = $this->getFactoryClass($definition)) {
990+
$this->preload[$class] = $class;
991+
}
992+
if ($class = ltrim($definition->getClass(), '\\')) {
993+
$this->preload[$class] = $class;
994+
}
995+
}
957996
}
958997

959998
foreach ($definitions as $id => $definition) {
@@ -1054,7 +1093,7 @@ private function addNewInstance(Definition $definition, string $return = '', str
10541093
return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail;
10551094
}
10561095

1057-
private function startClass(string $class, string $baseClass, ?array &$preload): string
1096+
private function startClass(string $class, string $baseClass): string
10581097
{
10591098
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
10601099

@@ -1117,7 +1156,7 @@ public function __construct()
11171156
$code .= $this->addMethodMap();
11181157
$code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : '';
11191158
$code .= $this->addAliases();
1120-
$code .= $this->addInlineRequires($preload);
1159+
$code .= $this->addInlineRequires();
11211160
$code .= <<<EOF
11221161
}
11231162
@@ -1317,7 +1356,7 @@ protected function {$methodNameAlias}()
13171356
return $code;
13181357
}
13191358

1320-
private function addInlineRequires(?array &$preload): string
1359+
private function addInlineRequires(): string
13211360
{
13221361
if (!$this->hotPathTag || !$this->inlineRequires) {
13231362
return '';
@@ -1335,8 +1374,10 @@ private function addInlineRequires(?array &$preload): string
13351374
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
13361375

13371376
foreach ($inlinedDefinitions as $def) {
1338-
if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
1339-
$preload[$class] = $class;
1377+
if ($class = $this->getFactoryClass($def)) {
1378+
$this->collectLineage($class, $lineage);
1379+
}
1380+
if ($class = $def->getClass()) {
13401381
$this->collectLineage($class, $lineage);
13411382
}
13421383
}
@@ -2058,4 +2099,17 @@ private function getAutoloadFile(): ?string
20582099

20592100
return null;
20602101
}
2102+
2103+
private function getFactoryClass(Definition $definition): ?string
2104+
{
2105+
while ($definition instanceof Definition && \is_array($factory = $definition->getFactory())) {
2106+
if (\is_string($factory[0])) {
2107+
return ltrim($factory[0], '\\');
2108+
}
2109+
2110+
$definition = $factory[0];
2111+
}
2112+
2113+
return null;
2114+
}
20612115
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt
+18Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt
+10Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_lazy_inlined_factories.txt
+10Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy_as_files.txt
+9Lines 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.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.