Skip to content

Commit 3c8c8f7

Browse files
Merge branch '4.1'
* 4.1: (27 commits) Added the Code of Conduct file do not override custom access decision configs [Security] Do not deauthenticate user when the first refreshed user has changed fix a return type hint invalidate stale commits for PRs too add missing cache prefix seed attribute to XSD fix command description Fix class documentation [Validator] Add a missing translation [FrameworkBundle] Fix 3.4 tests [DI] fix dumping inline services again Rename consumer to receiver Register messenger before the profiler Fix phpdocs [EventDispatcher] Remove template method in test case Added LB translation for #27993 (UUID validator message translation) Replace deprecated validateValue with validate [FWBundle] Automatically enable PropertyInfo when using Flex [Process] fix locking of pipe files on Windows Correct PHPDoc type for float ttl ...
2 parents 2d93e47 + faaa406 commit 3c8c8f7

File tree

7 files changed

+346
-34
lines changed

7 files changed

+346
-34
lines changed

Dumper/PhpDumper.php

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,6 @@ private function isTrivialInstance(Definition $definition): bool
519519
}
520520
}
521521

522-
if (false !== strpos($this->dumpLiteralClass($this->dumpValue($definition->getClass())), '$')) {
523-
return false;
524-
}
525-
526522
return true;
527523
}
528524

@@ -589,18 +585,16 @@ private function addService(string $id, Definition $definition): array
589585
$return = array();
590586

591587
if ($class = $definition->getClass()) {
592-
$class = $this->container->resolveEnvPlaceholders($class);
588+
$class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
593589
$return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\'));
594590
} elseif ($definition->getFactory()) {
595591
$factory = $definition->getFactory();
596592
if (\is_string($factory)) {
597593
$return[] = sprintf('@return object An instance returned by %s()', $factory);
598594
} elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
599-
if (\is_string($factory[0]) || $factory[0] instanceof Reference) {
600-
$return[] = sprintf('@return object An instance returned by %s::%s()', (string) $factory[0], $factory[1]);
601-
} elseif ($factory[0] instanceof Definition) {
602-
$return[] = sprintf('@return object An instance returned by %s::%s()', $factory[0]->getClass(), $factory[1]);
603-
}
595+
$class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0];
596+
$class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class);
597+
$return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]);
604598
}
605599
}
606600

@@ -696,7 +690,7 @@ private function addInlineVariables(string &$head, string &$tail, string $id, ar
696690
if (\is_array($argument)) {
697691
$hasSelfRef = $this->addInlineVariables($head, $tail, $id, $argument, $forConstructor) || $hasSelfRef;
698692
} elseif ($argument instanceof Reference) {
699-
$hasSelfRef = $this->addInlineReference($head, $tail, $id, $argument, $forConstructor) || $hasSelfRef;
693+
$hasSelfRef = $this->addInlineReference($head, $id, $argument, $forConstructor) || $hasSelfRef;
700694
} elseif ($argument instanceof Definition) {
701695
$hasSelfRef = $this->addInlineService($head, $tail, $id, $argument, $forConstructor) || $hasSelfRef;
702696
}
@@ -705,37 +699,31 @@ private function addInlineVariables(string &$head, string &$tail, string $id, ar
705699
return $hasSelfRef;
706700
}
707701

708-
private function addInlineReference(string &$head, string &$tail, string $id, string $targetId, bool $forConstructor): bool
702+
private function addInlineReference(string &$code, string $id, string $targetId, bool $forConstructor): bool
709703
{
704+
$hasSelfRef = isset($this->circularReferences[$id][$targetId]);
705+
710706
if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
711-
return isset($this->circularReferences[$id][$targetId]);
707+
return $hasSelfRef;
712708
}
713709

714710
list($callCount, $behavior) = $this->serviceCalls[$targetId];
715711

716-
if (2 > $callCount && (!$forConstructor || !isset($this->circularReferences[$id][$targetId]))) {
717-
return isset($this->circularReferences[$id][$targetId]);
712+
if (2 > $callCount && (!$hasSelfRef || !$forConstructor)) {
713+
return $hasSelfRef;
718714
}
719715

720716
$name = $this->getNextVariableName();
721717
$this->referenceVariables[$targetId] = new Variable($name);
722718

723719
$reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null;
724-
$code = sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
725-
726-
if (!isset($this->circularReferences[$id][$targetId])) {
727-
$head .= $code;
720+
$code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
728721

729-
return false;
722+
if (!$hasSelfRef || !$forConstructor) {
723+
return $hasSelfRef;
730724
}
731725

732-
if (!$forConstructor) {
733-
$tail .= $code;
734-
735-
return true;
736-
}
737-
738-
$head .= $code.sprintf(<<<'EOTXT'
726+
$code .= sprintf(<<<'EOTXT'
739727
740728
if (isset($this->%s['%s'])) {
741729
return $this->%1$s['%2$s'];
@@ -758,17 +746,21 @@ private function addInlineService(string &$head, string &$tail, string $id, Defi
758746

759747
$arguments = array($definition->getArguments(), $definition->getFactory());
760748

761-
if (2 > $this->inlinedDefinitions[$definition] && !$definition->getMethodCalls() && !$definition->getProperties() && !$definition->getConfigurator() && false === strpos($this->dumpValue($definition->getClass()), '$')) {
749+
if (2 > $this->inlinedDefinitions[$definition] && !$definition->getMethodCalls() && !$definition->getProperties() && !$definition->getConfigurator()) {
762750
return $this->addInlineVariables($head, $tail, $id, $arguments, $forConstructor);
763751
}
764752

765753
$name = $this->getNextVariableName();
766754
$this->definitionVariables[$definition] = new Variable($name);
767755

768756
$code = '';
769-
$hasSelfRef = $this->addInlineVariables($code, $tail, $id, $arguments, $forConstructor);
757+
if ($forConstructor) {
758+
$hasSelfRef = $this->addInlineVariables($code, $tail, $id, $arguments, $forConstructor);
759+
} else {
760+
$hasSelfRef = $this->addInlineVariables($code, $code, $id, $arguments, $forConstructor);
761+
}
770762
$code .= $this->addNewInstance($definition, ' $'.$name.' = ', $id);
771-
$hasSelfRef ? $tail .= ('' !== $tail ? "\n" : '').$code : $head .= ('' !== $head ? "\n" : '').$code;
763+
$hasSelfRef && !$forConstructor ? $tail .= ('' !== $tail ? "\n" : '').$code : $head .= ('' !== $head ? "\n" : '').$code;
772764

773765
$code = '';
774766
$arguments = array($definition->getProperties(), $definition->getMethodCalls(), $definition->getConfigurator());

Tests/Dumper/PhpDumperTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,28 @@ public function testDeepServiceGraph()
910910
$this->assertEquals((object) array('p2' => (object) array('p3' => (object) array())), $container->get('foo')->bClone);
911911
}
912912

913+
public function testInlineSelfRef()
914+
{
915+
$container = new ContainerBuilder();
916+
917+
$bar = (new Definition('App\Bar'))
918+
->setProperty('foo', new Reference('App\Foo'));
919+
920+
$baz = (new Definition('App\Baz'))
921+
->setProperty('bar', $bar)
922+
->addArgument($bar);
923+
924+
$container->register('App\Foo')
925+
->setPublic(true)
926+
->addArgument($baz);
927+
928+
$passConfig = $container->getCompiler()->getPassConfig();
929+
$container->compile();
930+
931+
$dumper = new PhpDumper($container);
932+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_inline_self_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Inline_Self_Ref')));
933+
}
934+
913935
public function testHotPathOptimizations()
914936
{
915937
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
@@ -987,6 +1009,18 @@ public function testUninitializedSyntheticReference()
9871009
$this->assertEquals((object) array('foo' => (object) array(123)), $container->get('bar'));
9881010
}
9891011

1012+
public function testAdawsonContainer()
1013+
{
1014+
$container = new ContainerBuilder();
1015+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
1016+
$loader->load('services_adawson.yml');
1017+
$container->compile();
1018+
1019+
$dumper = new PhpDumper($container);
1020+
$dump = $dumper->dump();
1021+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_adawson.php', $dumper->dump());
1022+
}
1023+
9901024
/**
9911025
* This test checks the trigger of a deprecation note and should not be removed in major releases.
9921026
*

Tests/Fixtures/containers/container19.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77

88
$container = new ContainerBuilder();
99

10+
$container->setParameter('env(FOO)', 'Bar\FaooClass');
11+
$container->setParameter('foo', '%env(FOO)%');
12+
1013
$container
11-
->register('service_from_anonymous_factory', 'Bar\FooClass')
12-
->setFactory(array(new Definition('Bar\FooClass'), 'getInstance'))
14+
->register('service_from_anonymous_factory', '%foo%')
15+
->setFactory(array(new Definition('%foo%'), 'getInstance'))
1316
->setPublic(true)
1417
;
1518

Tests/Fixtures/php/services19.php

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class ProjectServiceContainer extends Container
2121

2222
public function __construct()
2323
{
24+
$this->parameters = $this->getDefaultParameters();
25+
2426
$this->services = $this->privates = array();
2527
$this->methodMap = array(
2628
'service_from_anonymous_factory' => 'getServiceFromAnonymousFactoryService',
@@ -51,11 +53,11 @@ public function getRemovedIds()
5153
/**
5254
* Gets the public 'service_from_anonymous_factory' shared service.
5355
*
54-
* @return \Bar\FooClass
56+
* @return object A %env(FOO)% instance
5557
*/
5658
protected function getServiceFromAnonymousFactoryService()
5759
{
58-
return $this->services['service_from_anonymous_factory'] = (new \Bar\FooClass())->getInstance();
60+
return $this->services['service_from_anonymous_factory'] = (new ${($_ = $this->getEnv('FOO')) && false ?: "_"}())->getInstance();
5961
}
6062

6163
/**
@@ -71,4 +73,80 @@ protected function getServiceWithMethodCallAndFactoryService()
7173

7274
return $instance;
7375
}
76+
77+
public function getParameter($name)
78+
{
79+
$name = (string) $name;
80+
81+
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
82+
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
83+
}
84+
if (isset($this->loadedDynamicParameters[$name])) {
85+
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
86+
}
87+
88+
return $this->parameters[$name];
89+
}
90+
91+
public function hasParameter($name)
92+
{
93+
$name = (string) $name;
94+
95+
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
96+
}
97+
98+
public function setParameter($name, $value)
99+
{
100+
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
101+
}
102+
103+
public function getParameterBag()
104+
{
105+
if (null === $this->parameterBag) {
106+
$parameters = $this->parameters;
107+
foreach ($this->loadedDynamicParameters as $name => $loaded) {
108+
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
109+
}
110+
$this->parameterBag = new FrozenParameterBag($parameters);
111+
}
112+
113+
return $this->parameterBag;
114+
}
115+
116+
private $loadedDynamicParameters = array(
117+
'foo' => false,
118+
);
119+
private $dynamicParameters = array();
120+
121+
/**
122+
* Computes a dynamic parameter.
123+
*
124+
* @param string The name of the dynamic parameter to load
125+
*
126+
* @return mixed The value of the dynamic parameter
127+
*
128+
* @throws InvalidArgumentException When the dynamic parameter does not exist
129+
*/
130+
private function getDynamicParameter($name)
131+
{
132+
switch ($name) {
133+
case 'foo': $value = $this->getEnv('FOO'); break;
134+
default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
135+
}
136+
$this->loadedDynamicParameters[$name] = true;
137+
138+
return $this->dynamicParameters[$name] = $value;
139+
}
140+
141+
/**
142+
* Gets the default parameters.
143+
*
144+
* @return array An array of the default parameters
145+
*/
146+
protected function getDefaultParameters()
147+
{
148+
return array(
149+
'env(FOO)' => 'Bar\\FaooClass',
150+
);
151+
}
74152
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
11+
/**
12+
* This class has been auto-generated
13+
* by the Symfony Dependency Injection Component.
14+
*
15+
* @final since Symfony 3.3
16+
*/
17+
class ProjectServiceContainer extends Container
18+
{
19+
private $parameters;
20+
private $targetDirs = array();
21+
22+
public function __construct()
23+
{
24+
$this->services = $this->privates = array();
25+
$this->methodMap = array(
26+
'App\\Bus' => 'getBusService',
27+
'App\\Db' => 'getDbService',
28+
);
29+
30+
$this->aliases = array();
31+
}
32+
33+
public function compile()
34+
{
35+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
36+
}
37+
38+
public function isCompiled()
39+
{
40+
return true;
41+
}
42+
43+
public function getRemovedIds()
44+
{
45+
return array(
46+
'App\\Handler1' => true,
47+
'App\\Handler2' => true,
48+
'App\\Processor' => true,
49+
'App\\Registry' => true,
50+
'App\\Schema' => true,
51+
'Psr\\Container\\ContainerInterface' => true,
52+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
53+
);
54+
}
55+
56+
/**
57+
* Gets the public 'App\Bus' shared service.
58+
*
59+
* @return \App\Bus
60+
*/
61+
protected function getBusService()
62+
{
63+
$a = ($this->services['App\Db'] ?? $this->getDbService());
64+
65+
$this->services['App\Bus'] = $instance = new \App\Bus($a);
66+
67+
$b = ($this->privates['App\Schema'] ?? $this->getSchemaService());
68+
69+
$d = new \App\Registry();
70+
71+
$d->processor = array(0 => $a, 1 => $instance);
72+
$c = new \App\Processor($d, $a);
73+
74+
$instance->handler1 = new \App\Handler1($a, $b, $c);
75+
$instance->handler2 = new \App\Handler2($a, $b, $c);
76+
77+
return $instance;
78+
}
79+
80+
/**
81+
* Gets the public 'App\Db' shared service.
82+
*
83+
* @return \App\Db
84+
*/
85+
protected function getDbService()
86+
{
87+
$this->services['App\Db'] = $instance = new \App\Db();
88+
89+
$instance->schema = ($this->privates['App\Schema'] ?? $this->getSchemaService());
90+
91+
return $instance;
92+
}
93+
94+
/**
95+
* Gets the private 'App\Schema' shared service.
96+
*
97+
* @return \App\Schema
98+
*/
99+
protected function getSchemaService()
100+
{
101+
$a = ($this->services['App\Db'] ?? $this->getDbService());
102+
103+
if (isset($this->privates['App\Schema'])) {
104+
return $this->privates['App\Schema'];
105+
}
106+
107+
return $this->privates['App\Schema'] = new \App\Schema($a);
108+
}
109+
}

0 commit comments

Comments
 (0)