Skip to content

Commit c6f572c

Browse files
nicolas-grekasfabpot
authored andcommitted
[DI] add tags container.preload/.no_preload to declare extra classes to preload/services to not preload
1 parent fbb92e9 commit c6f572c

File tree

11 files changed

+102
-8
lines changed

11 files changed

+102
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CHANGELOG
1313
* deprecated the `Psr\Container\ContainerInterface` and `Symfony\Component\DependencyInjection\ContainerInterface` aliases of the `service_container` service,
1414
configure them explicitly instead
1515
* added class `Symfony\Component\DependencyInjection\Dumper\Preloader` to help with preloading on PHP 7.4+
16+
* added tags `container.preload`/`.no_preload` to declare extra classes to preload/services to not preload
1617

1718
5.0.0
1819
-----

Dumper/PhpDumper.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class PhpDumper extends Dumper
7878
private $namespace;
7979
private $asFiles;
8080
private $hotPathTag;
81+
private $preloadTags;
8182
private $inlineFactories;
8283
private $inlineRequires;
8384
private $inlinedRequires = [];
@@ -143,6 +144,7 @@ public function dump(array $options = [])
143144
'as_files' => false,
144145
'debug' => true,
145146
'hot_path_tag' => 'container.hot_path',
147+
'preload_tags' => ['container.preload', 'container.no_preload'],
146148
'inline_factories_parameter' => 'container.dumper.inline_factories',
147149
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
148150
'preload_classes' => [],
@@ -154,6 +156,7 @@ public function dump(array $options = [])
154156
$this->namespace = $options['namespace'];
155157
$this->asFiles = $options['as_files'];
156158
$this->hotPathTag = $options['hot_path_tag'];
159+
$this->preloadTags = $options['preload_tags'];
157160
$this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && (!$this->container->hasParameter($options['inline_factories_parameter']) || $this->container->getParameter($options['inline_factories_parameter']));
158161
$this->inlineRequires = $options['inline_class_loader_parameter'] && ($this->container->hasParameter($options['inline_class_loader_parameter']) ? $this->container->getParameter($options['inline_class_loader_parameter']) : (\PHP_VERSION_ID < 70400 || $options['debug']));
159162
$this->serviceLocatorTag = $options['service_locator_tag'];
@@ -571,7 +574,7 @@ private function addServiceInclude(string $cId, Definition $definition): string
571574
$lineage = [];
572575
foreach ($this->inlinedDefinitions as $def) {
573576
if (!$def->isDeprecated()) {
574-
foreach ($this->getClasses($def) as $class) {
577+
foreach ($this->getClasses($def, $cId) as $class) {
575578
$this->collectLineage($class, $lineage);
576579
}
577580
}
@@ -583,7 +586,7 @@ private function addServiceInclude(string $cId, Definition $definition): string
583586
&& $this->container->has($id)
584587
&& $this->isTrivialInstance($def = $this->container->findDefinition($id))
585588
) {
586-
foreach ($this->getClasses($def) as $class) {
589+
foreach ($this->getClasses($def, $cId) as $class) {
587590
$this->collectLineage($class, $lineage);
588591
}
589592
}
@@ -838,9 +841,9 @@ protected function {$methodName}($lazyInitialization)
838841
if ($definition->isDeprecated()) {
839842
$deprecation = $definition->getDeprecation($id);
840843
$code .= sprintf(" trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['version']), $this->export($deprecation['message']));
841-
} else {
844+
} elseif (!$definition->hasTag($this->preloadTags[1])) {
842845
foreach ($this->inlinedDefinitions as $def) {
843-
foreach ($this->getClasses($def) as $class) {
846+
foreach ($this->getClasses($def, $id) as $class) {
844847
$this->preload[$class] = $class;
845848
}
846849
}
@@ -1003,10 +1006,10 @@ private function addServices(array &$services = null): string
10031006
foreach ($definitions as $id => $definition) {
10041007
if (!$definition->isSynthetic()) {
10051008
$services[$id] = $this->addService($id, $definition);
1006-
} else {
1009+
} elseif (!$definition->hasTag($this->preloadTags[1])) {
10071010
$services[$id] = null;
10081011

1009-
foreach ($this->getClasses($definition) as $class) {
1012+
foreach ($this->getClasses($definition, $id) as $class) {
10101013
$this->preload[$class] = $class;
10111014
}
10121015
}
@@ -1385,7 +1388,7 @@ private function addInlineRequires(): string
13851388
$inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]);
13861389

13871390
foreach ($inlinedDefinitions as $def) {
1388-
foreach ($this->getClasses($def) as $class) {
1391+
foreach ($this->getClasses($def, $id) as $class) {
13891392
$this->collectLineage($class, $lineage);
13901393
}
13911394
}
@@ -2112,11 +2115,19 @@ private function getAutoloadFile(): ?string
21122115
return null;
21132116
}
21142117

2115-
private function getClasses(Definition $definition): array
2118+
private function getClasses(Definition $definition, string $id): array
21162119
{
21172120
$classes = [];
21182121

21192122
while ($definition instanceof Definition) {
2123+
foreach ($definition->getTag($this->preloadTags[0]) as $tag) {
2124+
if (!isset($tag['class'])) {
2125+
throw new InvalidArgumentException(sprintf('Missing attribute "class" on tag "%s" for service "%s".', $this->preloadTags[0], $id));
2126+
}
2127+
2128+
$classes[] = trim($tag['class'], '\\');
2129+
}
2130+
21202131
$classes[] = trim($definition->getClass(), '\\');
21212132
$factory = $definition->getFactory();
21222133

Tests/Fixtures/config/services9.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@
134134
->args([new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)])
135135
->public();
136136
$s->set('errored_definition', 'stdClass')->private();
137+
$s->set('preload_sidekick', 'stdClass')
138+
->tag('container.preload', ['class' => 'Some\Sidekick1'])
139+
->tag('container.preload', ['class' => 'Some\Sidekick2'])
140+
->public();
137141

138142
$s->alias('alias_for_foo', 'foo')->private()->public();
139143
$s->alias('alias_for_alias', ref('alias_for_foo'));

Tests/Fixtures/containers/container9.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,9 @@
187187
$container->register('errored_definition', 'stdClass')
188188
->addError('Service "errored_definition" is broken.');
189189

190+
$container->register('preload_sidekick', 'stdClass')
191+
->setPublic(true)
192+
->addTag('container.preload', ['class' => 'Some\Sidekick1'])
193+
->addTag('container.preload', ['class' => 'Some\Sidekick2']);
194+
190195
return $container;

Tests/Fixtures/graphviz/services9.dot

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ digraph sc {
3636
node_tagged_iterator [label="tagged_iterator\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
3737
node_runtime_error [label="runtime_error\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
3838
node_errored_definition [label="errored_definition\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
39+
node_preload_sidekick [label="preload_sidekick\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
3940
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
4041
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
4142
node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];

Tests/Fixtures/php/services9_as_files.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,29 @@ class getNonSharedFooService extends ProjectServiceContainer
578578
}
579579
}
580580

581+
[Container%s/getPreloadSidekickService.php] => <?php
582+
583+
namespace Container%s;
584+
585+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
586+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
587+
588+
/**
589+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
590+
*/
591+
class getPreloadSidekickService extends ProjectServiceContainer
592+
{
593+
/**
594+
* Gets the public 'preload_sidekick' shared service.
595+
*
596+
* @return \stdClass
597+
*/
598+
public static function do($container, $lazyLoad = true)
599+
{
600+
return $container->services['preload_sidekick'] = new \stdClass();
601+
}
602+
}
603+
581604
[Container%s/getRuntimeErrorService.php] => <?php
582605

583606
namespace Container%s;
@@ -731,6 +754,7 @@ class ProjectServiceContainer extends Container
731754
'method_call1' => 'getMethodCall1Service',
732755
'new_factory_service' => 'getNewFactoryServiceService',
733756
'non_shared_foo' => 'getNonSharedFooService',
757+
'preload_sidekick' => 'getPreloadSidekickService',
734758
'runtime_error' => 'getRuntimeErrorService',
735759
'service_from_static_method' => 'getServiceFromStaticMethodService',
736760
'tagged_iterator' => 'getTaggedIteratorService',
@@ -873,6 +897,7 @@ require __DIR__.'/Container%s/getThrowingOneService.php';
873897
require __DIR__.'/Container%s/getTaggedIteratorService.php';
874898
require __DIR__.'/Container%s/getServiceFromStaticMethodService.php';
875899
require __DIR__.'/Container%s/getRuntimeErrorService.php';
900+
require __DIR__.'/Container%s/getPreloadSidekickService.php';
876901
require __DIR__.'/Container%s/getNonSharedFooService.php';
877902
require __DIR__.'/Container%s/getNewFactoryServiceService.php';
878903
require __DIR__.'/Container%s/getMethodCall1Service.php';
@@ -906,6 +931,8 @@ $classes[] = 'Foo';
906931
$classes[] = 'LazyContext';
907932
$classes[] = 'FooBarBaz';
908933
$classes[] = 'FactoryClass';
934+
$classes[] = 'Some\Sidekick1';
935+
$classes[] = 'Some\Sidekick2';
909936
$classes[] = 'Request';
910937
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
911938

Tests/Fixtures/php/services9_compiled.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function __construct()
4545
'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService',
4646
'method_call1' => 'getMethodCall1Service',
4747
'new_factory_service' => 'getNewFactoryServiceService',
48+
'preload_sidekick' => 'getPreloadSidekickService',
4849
'runtime_error' => 'getRuntimeErrorService',
4950
'service_from_static_method' => 'getServiceFromStaticMethodService',
5051
'tagged_iterator' => 'getTaggedIteratorService',
@@ -359,6 +360,16 @@ protected function getNewFactoryServiceService()
359360
return $instance;
360361
}
361362

363+
/**
364+
* Gets the public 'preload_sidekick' shared service.
365+
*
366+
* @return \stdClass
367+
*/
368+
protected function getPreloadSidekickService()
369+
{
370+
return $this->services['preload_sidekick'] = new \stdClass();
371+
}
372+
362373
/**
363374
* Gets the public 'runtime_error' shared service.
364375
*

Tests/Fixtures/php/services9_inlined_factories.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class ProjectServiceContainer extends Container
7575
'method_call1' => 'getMethodCall1Service',
7676
'new_factory_service' => 'getNewFactoryServiceService',
7777
'non_shared_foo' => 'getNonSharedFooService',
78+
'preload_sidekick' => 'getPreloadSidekickService',
7879
'runtime_error' => 'getRuntimeErrorService',
7980
'service_from_static_method' => 'getServiceFromStaticMethodService',
8081
'tagged_iterator' => 'getTaggedIteratorService',
@@ -400,6 +401,16 @@ class ProjectServiceContainer extends Container
400401
return new \Bar\FooClass();
401402
}
402403

404+
/**
405+
* Gets the public 'preload_sidekick' shared service.
406+
*
407+
* @return \stdClass
408+
*/
409+
protected function getPreloadSidekickService()
410+
{
411+
return $this->services['preload_sidekick'] = new \stdClass();
412+
}
413+
403414
/**
404415
* Gets the public 'runtime_error' shared service.
405416
*
@@ -549,6 +560,8 @@ $classes[] = 'Foo';
549560
$classes[] = 'LazyContext';
550561
$classes[] = 'FooBarBaz';
551562
$classes[] = 'FactoryClass';
563+
$classes[] = 'Some\Sidekick1';
564+
$classes[] = 'Some\Sidekick2';
552565
$classes[] = 'Request';
553566
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
554567

Tests/Fixtures/php/services_errored_definition.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public function __construct()
4545
'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService',
4646
'method_call1' => 'getMethodCall1Service',
4747
'new_factory_service' => 'getNewFactoryServiceService',
48+
'preload_sidekick' => 'getPreloadSidekickService',
4849
'runtime_error' => 'getRuntimeErrorService',
4950
'service_from_static_method' => 'getServiceFromStaticMethodService',
5051
'tagged_iterator' => 'getTaggedIteratorService',
@@ -359,6 +360,16 @@ protected function getNewFactoryServiceService()
359360
return $instance;
360361
}
361362

363+
/**
364+
* Gets the public 'preload_sidekick' shared service.
365+
*
366+
* @return \stdClass
367+
*/
368+
protected function getPreloadSidekickService()
369+
{
370+
return $this->services['preload_sidekick'] = new \stdClass();
371+
}
372+
362373
/**
363374
* Gets the public 'runtime_error' shared service.
364375
*

Tests/Fixtures/xml/services9.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@
148148
<argument type="service" id="errored_definition"/>
149149
</service>
150150
<service id="errored_definition" class="stdClass"/>
151+
<service id="preload_sidekick" class="stdClass" public="true">
152+
<tag name="container.preload" class="Some\Sidekick1"/>
153+
<tag name="container.preload" class="Some\Sidekick2"/>
154+
</service>
151155
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false">
152156
<deprecated package="symfony/dependency-injection" version="5.1">The "%alias_id%" autowiring alias is deprecated. Define it explicitly in your app if you want to keep using it.</deprecated>
153157
</service>

0 commit comments

Comments
 (0)