Skip to content

Commit 774fbfa

Browse files
committed
Merge branch '7.4' into 8.0
* 7.4: [OptionsResolver] Optimize splitOutsideParenthesis() - 5.9x faster Use unique identifier for RequestContextProvider [DependencyInjection] Update `ResolveClassPass` to check class existence [Validator] Add Japanese translation for Twig template validator fix doc url [FrameworkBundle] Fix `lint:container --resolve-env-vars`
2 parents 38133f1 + 9986cfe commit 774fbfa

File tree

21 files changed

+387
-126
lines changed

21 files changed

+387
-126
lines changed

src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
2525
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
2626
use Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass;
27+
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
28+
use Symfony\Component\DependencyInjection\Container;
2729
use Symfony\Component\DependencyInjection\ContainerBuilder;
2830
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
2931
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@@ -48,8 +50,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4850
$io = new SymfonyStyle($input, $output);
4951
$errorIo = $io->getErrorStyle();
5052

53+
$resolveEnvVars = $input->getOption('resolve-env-vars');
54+
5155
try {
52-
$container = $this->getContainerBuilder();
56+
$container = $this->getContainerBuilder($resolveEnvVars);
5357
} catch (RuntimeException $e) {
5458
$errorIo->error($e->getMessage());
5559

@@ -59,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5963
$container->setParameter('container.build_time', time());
6064

6165
try {
62-
$container->compile((bool) $input->getOption('resolve-env-vars'));
66+
$container->compile($resolveEnvVars);
6367
} catch (InvalidArgumentException $e) {
6468
$errorIo->error($e->getMessage());
6569

@@ -71,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7175
return 0;
7276
}
7377

74-
private function getContainerBuilder(): ContainerBuilder
78+
private function getContainerBuilder(bool $resolveEnvVars): ContainerBuilder
7579
{
7680
if (isset($this->container)) {
7781
return $this->container;
@@ -103,17 +107,23 @@ private function getContainerBuilder(): ContainerBuilder
103107
throw new RuntimeException(\sprintf('This command does not support the application container: "%s" is not a "%s".', get_debug_type($container), ContainerBuilder::class));
104108
}
105109

106-
$parameterBag = $container->getParameterBag();
107-
$refl = new \ReflectionProperty($parameterBag, 'resolved');
108-
$refl->setValue($parameterBag, true);
110+
if ($resolveEnvVars) {
111+
$container->getCompilerPassConfig()->setOptimizationPasses([new ResolveParameterPlaceHoldersPass(), new ResolveFactoryClassPass()]);
112+
} else {
113+
$parameterBag = $container->getParameterBag();
114+
$refl = new \ReflectionProperty($parameterBag, 'resolved');
115+
$refl->setValue($parameterBag, true);
116+
117+
$container->getCompilerPassConfig()->setOptimizationPasses([new ResolveFactoryClassPass()]);
118+
}
109119

110120
$container->getCompilerPassConfig()->setBeforeOptimizationPasses([]);
111-
$container->getCompilerPassConfig()->setOptimizationPasses([new ResolveFactoryClassPass()]);
112121
$container->getCompilerPassConfig()->setBeforeRemovingPasses([]);
113122
}
114123

115124
$container->setParameter('container.build_hash', 'lint_container');
116125
$container->setParameter('container.build_id', 'lint_container');
126+
$container->setParameter('container.runtime_mode', 'web=0');
117127

118128
$container->addCompilerPass(new CheckAliasValidityPass(), PassConfig::TYPE_BEFORE_REMOVING, -100);
119129
$container->addCompilerPass(new CheckTypeDeclarationsPass(true), PassConfig::TYPE_AFTER_REMOVING, -100);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TestServiceContainerRefPassesTest.php

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,44 +33,44 @@ public function testProcess()
3333
$container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
3434
$container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING);
3535

36-
$container->register('Test\public_service')
36+
$container->register('test.public_service', 'stdClass')
3737
->setPublic(true)
38-
->addArgument(new Reference('Test\private_used_shared_service'))
39-
->addArgument(new Reference('Test\private_used_non_shared_service'))
40-
->addArgument(new Reference('Test\soon_private_service'))
38+
->addArgument(new Reference('test.private_used_shared_service'))
39+
->addArgument(new Reference('test.private_used_non_shared_service'))
40+
->addArgument(new Reference('test.soon_private_service'))
4141
;
4242

43-
$container->register('Test\soon_private_service')
43+
$container->register('test.soon_private_service', 'stdClass')
4444
->setPublic(true)
4545
->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42'])
4646
;
47-
$container->register('Test\soon_private_service_decorated')
47+
$container->register('test.soon_private_service_decorated', 'stdClass')
4848
->setPublic(true)
4949
->addTag('container.private', ['package' => 'foo/bar', 'version' => '1.42'])
5050
;
51-
$container->register('Test\soon_private_service_decorator')
52-
->setDecoratedService('Test\soon_private_service_decorated')
53-
->setArguments(['Test\soon_private_service_decorator.inner']);
51+
$container->register('test.soon_private_service_decorator', 'stdClass')
52+
->setDecoratedService('test.soon_private_service_decorated')
53+
->setArguments(['test.soon_private_service_decorator.inner']);
5454

55-
$container->register('Test\private_used_shared_service');
56-
$container->register('Test\private_unused_shared_service');
57-
$container->register('Test\private_used_non_shared_service')->setShared(false);
58-
$container->register('Test\private_unused_non_shared_service')->setShared(false);
55+
$container->register('test.private_used_shared_service', 'stdClass');
56+
$container->register('test.private_unused_shared_service', 'stdClass');
57+
$container->register('test.private_used_non_shared_service', 'stdClass')->setShared(false);
58+
$container->register('test.private_unused_non_shared_service', 'stdClass')->setShared(false);
5959

6060
$container->compile();
6161

6262
$expected = [
63-
'Test\private_used_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_shared_service')),
64-
'Test\private_used_non_shared_service' => new ServiceClosureArgument(new Reference('Test\private_used_non_shared_service')),
65-
'Test\soon_private_service' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service')),
66-
'Test\soon_private_service_decorator' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')),
67-
'Test\soon_private_service_decorated' => new ServiceClosureArgument(new Reference('.container.private.Test\soon_private_service_decorated')),
63+
'test.private_used_shared_service' => new ServiceClosureArgument(new Reference('test.private_used_shared_service')),
64+
'test.private_used_non_shared_service' => new ServiceClosureArgument(new Reference('test.private_used_non_shared_service')),
65+
'test.soon_private_service' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service')),
66+
'test.soon_private_service_decorator' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service_decorated')),
67+
'test.soon_private_service_decorated' => new ServiceClosureArgument(new Reference('.container.private.test.soon_private_service_decorated')),
6868
];
6969

7070
$privateServices = $container->getDefinition('test.private_services_locator')->getArgument(0);
7171
unset($privateServices[\Symfony\Component\DependencyInjection\ContainerInterface::class], $privateServices[ContainerInterface::class]);
7272

7373
$this->assertEquals($expected, $privateServices);
74-
$this->assertFalse($container->getDefinition('Test\private_used_non_shared_service')->isShared());
74+
$this->assertFalse($container->getDefinition('test.private_used_non_shared_service')->isShared());
7575
}
7676
}

src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,28 @@ class ContainerLintCommandTest extends AbstractWebTestCase
2424
/**
2525
* @dataProvider containerLintProvider
2626
*/
27-
public function testLintContainer(string $configFile, string $expectedOutput)
27+
public function testLintContainer(string $configFile, bool $resolveEnvVars, int $expectedExitCode, string $expectedOutput)
2828
{
2929
$kernel = static::createKernel([
30-
'test_case' => 'ContainerDebug',
30+
'test_case' => 'ContainerLint',
3131
'root_config' => $configFile,
3232
'debug' => true,
3333
]);
3434
$this->application = new Application($kernel);
3535

3636
$tester = $this->createCommandTester();
37-
$exitCode = $tester->execute([]);
37+
$exitCode = $tester->execute(['--resolve-env-vars' => $resolveEnvVars]);
3838

39-
$this->assertSame(0, $exitCode);
39+
$this->assertSame($expectedExitCode, $exitCode);
4040
$this->assertStringContainsString($expectedOutput, $tester->getDisplay());
4141
}
4242

4343
public static function containerLintProvider(): array
4444
{
4545
return [
46-
'default container' => ['config.yml', 'The container was linted successfully'],
47-
'missing dump file' => ['no_dump.yml', 'The container was linted successfully'],
46+
['escaped_percent.yml', false, 0, 'The container was linted successfully'],
47+
['missing_env_var.yml', false, 0, 'The container was linted successfully'],
48+
['missing_env_var.yml', true, 1, 'Environment variable not found: "BAR"'],
4849
];
4950
}
5051

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
];
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
parameters:
5+
percent: '%%foo%%'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
parameters:
5+
foo: '%env(BAR)%'

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ public function process(ContainerBuilder $container): void
2727
continue;
2828
}
2929
if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) {
30-
if ($definition instanceof ChildDefinition && !class_exists($id)) {
31-
throw new InvalidArgumentException(\sprintf('Service definition "%s" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
30+
if (!class_exists($id) && !interface_exists($id)) {
31+
$error = $definition instanceof ChildDefinition ?
32+
'has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service' :
33+
'name looks like a FQCN but the class does not exist';
34+
35+
throw new InvalidArgumentException("Service definition \"{$id}\" {$error}. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.");
3236
}
37+
3338
$definition->setClass($id);
3439
}
3540
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveClassPassTest.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public function testResolveClassFromId($serviceId)
3535

3636
public static function provideValidClassId()
3737
{
38-
yield ['Acme\UnknownClass'];
3938
yield [CaseSensitiveClass::class];
4039
}
4140

@@ -62,7 +61,7 @@ public static function provideInvalidClassId()
6261
public function testNonFqcnChildDefinition()
6362
{
6463
$container = new ContainerBuilder();
65-
$parent = $container->register('App\Foo', null);
64+
$parent = $container->register('App\Foo.parent', 'App\Foo');
6665
$child = $container->setDefinition('App\Foo.child', new ChildDefinition('App\Foo'));
6766

6867
(new ResolveClassPass())->process($container);
@@ -74,7 +73,7 @@ public function testNonFqcnChildDefinition()
7473
public function testClassFoundChildDefinition()
7574
{
7675
$container = new ContainerBuilder();
77-
$parent = $container->register('App\Foo', null);
76+
$parent = $container->register('foo.parent', 'App\Foo');
7877
$child = $container->setDefinition(self::class, new ChildDefinition('App\Foo'));
7978

8079
(new ResolveClassPass())->process($container);
@@ -86,11 +85,21 @@ public function testClassFoundChildDefinition()
8685
public function testAmbiguousChildDefinition()
8786
{
8887
$this->expectException(InvalidArgumentException::class);
89-
$this->expectExceptionMessage('Service definition "App\Foo\Child" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.');
88+
$this->expectExceptionMessage('Service definition "App\Foo\Child" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.');
9089
$container = new ContainerBuilder();
91-
$container->register('App\Foo', null);
90+
$container->register('app.foo', 'App\Foo');
9291
$container->setDefinition('App\Foo\Child', new ChildDefinition('App\Foo'));
9392

9493
(new ResolveClassPass())->process($container);
9594
}
95+
96+
public function testInvalidClassNameDefinition()
97+
{
98+
$this->expectException(InvalidArgumentException::class);
99+
$this->expectExceptionMessage('Service definition "Acme\UnknownClass" name looks like a FQCN but the class does not exist. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.');
100+
$container = new ContainerBuilder();
101+
$container->register('Acme\UnknownClass');
102+
103+
(new ResolveClassPass())->process($container);
104+
}
96105
}

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,11 +1527,9 @@ public function testClassFromId()
15271527
{
15281528
$container = new ContainerBuilder();
15291529

1530-
$unknown = $container->register('Acme\UnknownClass');
15311530
$autoloadClass = $container->register(CaseSensitiveClass::class);
15321531
$container->compile();
15331532

1534-
$this->assertSame('Acme\UnknownClass', $unknown->getClass());
15351533
$this->assertEquals(CaseSensitiveClass::class, $autoloadClass->getClass());
15361534
}
15371535

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
require_once __DIR__.'/../Fixtures/includes/classes.php';
7676
require_once __DIR__.'/../Fixtures/includes/foo.php';
7777
require_once __DIR__.'/../Fixtures/includes/foo_lazy.php';
78+
require_once __DIR__.'/../Fixtures/includes/fixture_app_services.php';
7879

7980
class PhpDumperTest extends TestCase
8081
{
@@ -1301,7 +1302,7 @@ public function testInlineSelfRef()
13011302
->setProperty('bar', $bar)
13021303
->addArgument($bar);
13031304

1304-
$container->register('App\Foo')
1305+
$container->register('App\Foo', 'App\Foo')
13051306
->setPublic(true)
13061307
->addArgument($baz);
13071308

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy