8000 feature #47680 [DependencyInjection][HttpKernel] Introduce build para… · symfony/symfony@6c8f6b3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6c8f6b3

Browse files
committed
feature #47680 [DependencyInjection][HttpKernel] Introduce build parameters (HeahDude)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [DependencyInjection][HttpKernel] Introduce build parameters | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | yes | Tickets | ~ | License | MIT | Doc PR | TODO Alternative implementation of #47608. Add a convention for parameters named with a starting dot to be available at compile-time only: ```php $containerBuilder->setParameter('foo'); // nothing changes $containerBuilder->setParameter('.bar'); // will not be dumped ``` Calling `$container->getParameter('.bar')` on a compiled container will throw. Commits ------- c75dbca [DependencyInjection][HttpKernel] Introduce build parameters
2 parents 4785cc7 + c75dbca commit 6c8f6b3

14 files changed

+173
-81
lines changed

UPGRADE-6.3.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
UPGRADE FROM 6.2 to 6.3
22
=======================
33

4+
DependencyInjection
5+
-------------------
6+
7+
* Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`, use `inline_factories` and `inline_class_loader` instead
8+
9+
HttpKernel
10+
----------
11+
12+
* Deprecate parameters `container.dumper.inline_factories` and `container.dumper.inline_class_loader`, use `.container.dumper.inline_factories` and `.container.dumper.inline_class_loader` instead
13+
414
SecurityBundle
515
--------------
616

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
6.3
5+
---
6+
7+
* Add options `inline_factories` and `inline_class_loader` to `PhpDumper::dump()`
8+
* Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`
9+
* Add `RemoveBuildParametersPass`, which removes parameters starting with a dot during compilation
10+
411
6.2
512
---
613

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,15 @@ public function __construct()
9090
new DefinitionErrorExceptionPass(),
9191
]];
9292

93-
$this->afterRemovingPasses = [[
94-
new ResolveHotPathPass(),
95-
new ResolveNoPreloadPass(),
96-
new AliasDeprecatedPublicServicesPass(),
97-
]];
93+
$this->afterRemovingPasses = [
94+
0 => [
95+
new ResolveHotPathPass(),
96+
new ResolveNoPreloadPass(),
97+
new AliasDeprecatedPublicServicesPass(),
98+
],
99+
// Let build parameters be available as late as possible
100+
-2048 => [new RemoveBuildParametersPass()],
101+
];
98102
}
99103

100104
/**
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
16+
class RemoveBuildParametersPass implements CompilerPassInterface
17+
{
18+
/**
19+
* @var array<string, mixed>
20+
*/
21+
private array $removedParameters = [];
22+
23+
public function process(ContainerBuilder $container)
24+
{
25+
$parameterBag = $container->getParameterBag();
26+
$this->removedParameters = [];
27+
28+
foreach ($parameterBag->all() as $name => $value) {
29+
if ('.' === ($name[0] ?? '')) {
30+
$this->removedParameters[$name] = $value;
31+
32+
$parameterBag->remove($name);
33+
$container->log($this, sprintf('Removing build parameter "%s".', $name));
34+
}
35+
}
36+
}
37+
38+
/**
39+
* @return array<string, mixed>
40+
*/
41+
public function getRemovedParameters(): array
42+
{
43+
return $this->removedParameters;
44+
}
45+
}

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,10 @@ public function dump(array $options = []): string|array
137137
'debug' => true,
138138
'hot_path_tag' => 'container.hot_path',
139139
'preload_tags' => ['container.preload', 'container.no_preload'],
140-
'inline_factories_parameter' => 'container.dumper.inline_factories',
141-
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
140+
'inline_factories_parameter' => 'container.dumper.inline_factories', // @deprecated since Symfony 6.3
141+
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', // @deprecated since Symfony 6.3
142+
'inline_factories' => null,
143+
'inline_class_loader' => null,
142144
'preload_classes' => [],
143145
'service_locator_tag' => 'container.service_locator',
144146
'build_time' => time(),
@@ -149,8 +151,28 @@ public function dump(array $options = []): string|array
149151
$this->asFiles = $options['as_files'];
150152
$this->hotPathTag = $options['hot_path_tag'];
151153
$this->preloadTags = $options['preload_tags'];
152-
$this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']);
153-
$this->inlineRequires = $options['inline_class_loader_parameter'] && ($this->container->hasParameter($options['inline_class_loader_parameter']) ? $this->container->getParameter($options['inline_class_loader_parameter']) : $options['debug']);
154+
155+
$this->inlineFactories = false;
156+
if (isset($options['inline_factories'])) {
157+
$this->inlineFactories = $this->asFiles && $options['inline_factories'];
158+
} elseif (!$options['inline_factories_parameter']) {
159+
trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_factories_parameter" passed to "%s()" is deprecated, use option "inline_factories" instead.', __METHOD__);
160+
} elseif ($this->container->hasParameter($options['inline_factories_parameter'])) {
161+
trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_factories_parameter" passed to "%s()" is deprecated, use option "inline_factories" instead.', __METHOD__);
162+
$this->inlineFactories = $this->asFiles && $this->container->getParameter($options['inline_factories_parameter']);
163+
}
164+
165+
$this->inlineRequires = $options['debug'];
166+
if (isset($options['inline_class_loader'])) {
167+
$this->inlineRequires = $options['inline_class_loader'];
168+
} elseif (!$options['inline_class_loader_parameter']) {
169+
trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_class_loader_parameter" passed to "%s()" is deprecated, use option "inline_class_loader" instead.', __METHOD__);
170+
$this->inlineRequires = false;
171+
} elseif ($this->container->hasParameter($options['inline_class_loader_parameter'])) {
172+
trigger_deprecation('symfony/dependency-injection', '6.3', 'Option "inline_class_loader_parameter" passed to "%s()" is deprecated, use option "inline_class_loader" instead.', __METHOD__);
173+
$this->inlineRequires = $this->container->getParameter($options['inline_class_loader_parameter']);
174+
}
175+
154176
$this->serviceLocatorTag = $options['service_locator_tag'];
155177
$this->class = $options['class'];
156178

src/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public function updateRepr()
5353
$this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key);
5454
} elseif (null !== $this->sourceKey) {
5555
$this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key);
56+
} elseif ('.' === ($this->key[0] ?? '')) {
57+
$this->message = sprintf('Parameter "%s" not found. It was probably deleted during the compilation of the container.', $this->key);
5658
} else {
5759
$this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key);
5860
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Compiler\RemoveBuildParametersPass;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
18+
class RemoveBuildParametersPassTest extends TestCase
19+
{
20+
public function testBuildParametersShouldBeRemoved()
21+
{
22+
$builder = new ContainerBuilder();
23+
$builder->setParameter('foo', 'Foo');
24+
$builder->setParameter('.bar', 'Bar');
25+
26+
$pass = new RemoveBuildParametersPass();
27+
$pass->process($builder);
28+
29+
$this->assertSame('Foo', $builder->getParameter('foo'), '"foo" parameter must be defined.');
30+
$this->assertFalse($builder->hasParameter('.bar'), '".bar" parameter must be removed.');
31+
$this->assertSame(['.bar' => 'Bar'], $pass->getRemovedParameters(), '".baz" parameter must be returned with its value.');
32+
}
33+
}

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public function testDumpAsFiles()
222222
->addError('No-no-no-no');
223223
$container->compile();
224224
$dumper = new PhpDumper($container);
225-
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]), true);
225+
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'inline_factories' => false, 'inline_class_loader' => false]), true);
226226
if ('\\' === \DIRECTORY_SEPARATOR) {
227227
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
228228
}
@@ -241,7 +241,7 @@ public function testDumpAsFilesWithTypedReference()
241241
->setPublic(true);
242242
$container->compile();
243243
$dumper = new PhpDumper($container);
244-
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]), true);
244+
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'inline_factories' => false, 'inline_class_loader' => false]), true);
245245
if ('\\' === \DIRECTORY_SEPARATOR) {
246246
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
247247
}
@@ -252,8 +252,6 @@ public function testDumpAsFilesWithTypedReference()
252252
public function testDumpAsFilesWithFactoriesInlined()
253253
{
254254
$container = include self::$fixturesPath.'/containers/container9.php';
255-
$container->setParameter('container.dumper.inline_factories', true);
256-
$container->setParameter('container.dumper.inline_class_loader', true);
257255

258256
$container->getDefinition('bar')->addTag('hot');
259257
$container->register('non_shared_foo', \Bar\FooClass::class)
@@ -268,7 +266,7 @@ public function testDumpAsFilesWithFactoriesInlined()
268266
$container->compile();
269267

270268
$dumper = new PhpDumper($container);
271-
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
269+
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341, 'inline_factories' => true, 'inline_class_loader' => true]), true);
272270

273271
if ('\\' === \DIRECTORY_SEPARATOR) {
274272
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
@@ -279,8 +277,6 @@ public function testDumpAsFilesWithFactoriesInlined()
279277
public function testDumpAsFilesWithLazyFactoriesInlined()
280278
{
281279
$container = new ContainerBuilder();
282-
$container->setParameter('container.dumper.inline_factories', true);
283-
$container->setParameter('container.dumper.inline_class_loader', true);
284280
$container->setParameter('lazy_foo_class', \Bar\FooClass::class);
285281

286282
$container->register('lazy_foo', '%lazy_foo_class%')
@@ -292,7 +288,7 @@ public function testDumpAsFilesWithLazyFactoriesInlined()
292288
$container->compile();
293289

294290
$dumper = new PhpDumper($container);
295-
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341]), true);
291+
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot', 'build_time' => 1563381341, 'inline_factories' => true, 'inline_class_loader' => true]), true);
296292

297293
if ('\\' === \DIRECTORY_SEPARATOR) {
298294
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
@@ -310,7 10000 +306,7 @@ public function testNonSharedLazyDumpAsFiles()
310306
->setLazy(true);
311307
$container->compile();
312308
$dumper = new PhpDumper($container);
313-
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]), true);
309+
$dump = print_r($dumper->dump(['as_files' => true, 'file' => __DIR__, 'inline_factories' => false, 'inline_class_loader' => false]), true);
314310

315311
if ('\\' === \DIRECTORY_SEPARATOR) {
316312
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
@@ -473,7 +469,7 @@ public function testEnvParameter()
473469
$container->compile();
474470
$dumper = new PhpDumper($container);
475471

476-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_EnvParameters', 'file' => self::$fixturesPath.'/php/services26.php', 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false]));
472+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_EnvParameters', 'file' => self::$fixturesPath.'/php/services26.php', 'inline_factories' => false, 'inline_class_loader' => false]));
477473

478474
require self::$fixturesPath.'/php/services26.php';
479475
$container = new \Symfony_DI_PhpDumper_Test_EnvParameters();
@@ -994,7 +990,7 @@ public function testArrayParameters()
994990

995991
$dumper = new PhpDumper($container);
996992

997-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dumper->dump(['file' => self::$fixturesPath.'/php/services_array_params.php', 'inline_factories_parameter' => false, 'inline_class_loader_parameter' => false])));
993+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dumper->dump(['file' => self::$fixturesPath.'/php/services_array_params.php', 'inline_factories' => false, 'inline_class_loader' => false])));
998994
}
999995

1000996
public function testExpressionReferencingPrivateService()
@@ -1162,11 +1158,10 @@ public function testInlineSelfRef()
11621158
public function testHotPathOptimizations()
11631159
{
11641160
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
1165-
$container->setParameter('inline_requires', true);
11661161
$container->compile();
11671162
$dumper = new PhpDumper($container);
11681163

1169-
$dump = $dumper->dump(['hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'inline_requires', 'file' => self::$fixturesPath.'/php/services_inline_requires.php']);
1164+
$dump = $dumper->dump(['hot_path_tag' => 'container.hot_path', 'inline_class_loader' => true, 'file' => self::$fixturesPath.'/php/services_inline_requires.php']);
11701165
if ('\\' === \DIRECTORY_SEPARATOR) {
11711166
$dump = str_replace("'.\\DIRECTORY_SEPARATOR.'", '/', $dump);
11721167
}
@@ -1199,13 +1194,12 @@ public function testDumpHandlesObjectClassNames()
11991194
new Reference('foo'),
12001195
]))->setPublic(true);
12011196

1202-
$container->setParameter('inline_requires', true);
12031197
$container->compile();
12041198

12051199
$dumper = new PhpDumper($container);
12061200
eval('?>'.$dumper->dump([
12071201
'class' => 'Symfony_DI_PhpDumper_Test_Object_Class_Name',
1208-
'inline_class_loader_parameter' => 'inline_requires',
1202+
'inline_class_loader' => true,
12091203
]));
12101204

12111205
$container = new \Symfony_DI_PhpDumper_Test_Object_Class_Name();
@@ -1281,7 +1275,6 @@ public function testUninitializedSyntheticReference()
12811275
$dumper = new PhpDumper($container);
12821276
eval('?>'.$dumper->dump([
12831277
'class' => 'Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference',
1284-
'inline_class_loader_parameter' => 'inline_requires',
12851278
]));
12861279

12871280
$container = new \Symfony_DI_PhpDumper_Test_UninitializedSyntheticReference();

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,6 @@ class ProjectServiceContainer extends Container
557557
'baz_class' => 'BazClass',
558558
'foo_class' => 'Bar\\FooClass',
559559
'foo' => 'bar',
560-
'container.dumper.inline_factories' => true,
561-
'container.dumper.inline_class_loader' => true,
562560
];
563561
}
564562
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ class ProjectServiceContainer extends Container
143143
protected function getDefaultParameters(): array
144144
{
145145
return [
146-
'container.dumper.inline_factories' => true,
147-
'container.dumper.inline_class_loader' => true,
148146
'lazy_foo_class' => 'Bar\\FooClass',
149147
];
150148
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_inline_requires.php

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ class ProjectServiceContainer extends Container
1818

1919
public function __construct()
2020
{
21-
$this->parameters = $this->getDefaultParameters();
22-
2321
$this->services = $this->privates = [];
2422
$this->methodMap = [
2523
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\ParentNotExists' => 'getParentNotExistsService',
@@ -86,54 +84,4 @@ protected function getC2Service()
8684

8785
return $this->services['Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C2'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2(new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3());
8886
}
89-
90-
public function getParameter(string $name): array|bool|string|int|float|\UnitEnum|null
91-
{
92-
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters))) {
93-
throw new ParameterNotFoundException($name);
94-
}
95-
if (isset($this->loadedDynamicParameters[$name])) {
96-
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
97-
}
98-
99-
return $this->parameters[$name];
100-
}
101-
102-
public function hasParameter(string $name): bool
103-
{
104-
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || \array_key_exists($name, $this->parameters);
105-
}
106-
107-
public function setParameter(string $name, $value): void
108-
{
109-
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
110-
}
111-
112-
public function getParameterBag(): ParameterBagInterface
113-
{
114-
if (null === $this->parameterBag) {
115-
$parameters = $this->parameters;
116-
foreach ($this->loadedDynamicParameters as $name => $loaded) {
117-
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
118-
}
119-
$this->parameterBag = new FrozenParameterBag($parameters);
120-
}
121-
122-
return $this->parameterBag;
123-
}
124-
125-
private $loadedDynamicParameters = [];
126-
private $dynamicParameters = [];
127-
128-
private function getDynamicParameter(string $name)
129-
{
130-
throw new ParameterNotFoundException($name);
131-
}
132-
133-
protected function getDefaultParameters(): array
134-
{
135-
return [
136-
'inline_requires' => true,
137-
];
138-
}
13987
}

src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ public function provideGetThrowParameterNotFoundExceptionData()
121121
['', 'You have requested a non-existent parameter "".'],
122122

123123
['fiz.bar.boo', 'You have requested a non-existent parameter "fiz.bar.boo". You cannot access nested array items, do you want to inject "fiz" instead?'],
124+
['.foo', 'Parameter ".foo" not found. It was probably deleted during the compilation of the container. Did you mean this: "foo"?'],
124125
];
125126
}
126127

0 commit comments

Comments
 (0)
0