8000 [DI] : Fix bad generation of proxy class when use overriden getter on… · symfony/symfony@baad4b6 · GitHub
[go: up one dir, main page]

Skip to content

Commit baad4b6

Browse files
[DI] : Fix bad generation of proxy class when use overriden getter on class with constructor
- [X] Add test fail - [X] Fix bug - [X] Run test pass
1 parent 46daa35 commit baad4b6

File tree

4 files changed

+246
-2
lines changed

4 files changed

+246
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,9 @@ private function addServiceOverriddenGetters($id, Definition $definition)
525525
}
526526
if (!$r->isFinal()) {
527527
if (0 < $r->getNumberOfParameters()) {
528-
$getters = implode('($container'.$this->salt.', ', explode('(', $this->generateSignature($r), 2));
528+
$getters = implode('__construct($container'.$this->salt.', ', explode('(', $this->generateSignature($r), 2));
529529
} else {
530-
$getters = '($container'.$this->salt.')';
530+
$getters = '__construct($container'.$this->salt.')';
531531
}
532532
$getters = sprintf("\n public function %s\n {\n \$this->container%3\$s = \$container%3\$s;\n parent::%s;\n }\n", $getters, $this->generateCall($r), $this->salt);
533533
} else {

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use DummyProxyDumper;
1515
use Symfony\Component\Config\FileLocator;
16+
use Symfony\Component\Config\Resource\ResourceInterface;
1617
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
1718
use Symfony\Component\DependencyInjection\ContainerBuilder;
1819
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
@@ -344,6 +345,32 @@ public function testDumpOverridenGetters()
344345
$this->assertSame('baz', $r->invoke($baz));
345346
}
346347

348+
public function testDumpOverridenGettersWithConstructor()
349+
{
350+
$container = include self::$fixturesPath.'/containers/container_dump_overriden_getters_with_constructor.php';
351+
$container->compile();
352+
$container->getDefinition('foo')
353+
->setOverriddenGetter('getInvalid', array(new Reference('bar', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE)));
354+
$dumper = new PhpDumper($container);
355+
356+
$dump = $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor'));
357+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dump_overriden_getters_with_constructor.php', $dump);
358+
$resources = array_map(
359+
function (ResourceInterface $resource) {
360+
return $resource->getResource();
361+
},
362+
$container->getResources()
363+
);
364+
$this->assertContains(realpath(self::$fixturesPath.'/containers/container_dump_overriden_getters_with_constructor.php'), $resources);
365+
366+
$baz = $container->get('baz');
367+
$r = new \ReflectionMethod($baz, 'getBaz');
368+
$r->setAccessible(true);
369+
370+
$this->assertTrue($r->isProtected());
371+
$this->assertSame('baz', $r->invoke($baz));
372+
}
373+
347374
/**
348375
* @dataProvider provideBadOverridenGetters
349376
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container34;
4+
5+
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
use Symfony\Component\DependencyInjection\Reference;
7+
8+
if (!class_exists(Foo::class, false)) {
9+
abstract class Foo
10+
{
11+
protected $bar;
12+
13+
public function __construct($bar = 'bar')
14+
{
15+
$this->bar = $bar;
16+
}
17+
18+
abstract public function getPublic();
19+
abstract protected function getProtected();
20+
21+
public function getSelf()
22+
{
23+
return 123;
24+
}
25+
26+
public function getInvalid()
27+
{
28+
return 456;
29+
}
30+
31+
public function getGetProtected()
32+
{
33+
return $this->getProtected();
34+
}
35+
}
36+
37+
class Baz
38+
{
39+
final public function __construct()
40+
{
41+
}
42+
43+
protected function getBaz()
44+
{
45+
return 234;
46+
}
47+
}
48+
}
49+
50+
$container = new ContainerBuilder();
51+
52+
$container
53+
->register('foo', Foo::class)
54+
->setOverriddenGetter('getPublic', 'public')
55+
->setOverriddenGetter('getProtected', 'protected')
56+
->setOverriddenGetter('getSelf', new Reference('foo'))
57+
;
58+
59+
$container
60+
->register('baz', Baz::class)
61+
->setOverriddenGetter('getBaz', 'baz')
62+
;
63+
64+
return $container;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
* Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor.
13+
*
14+
* This class has been auto-generated
15+
* by the Symfony Dependency Injection Component.
16+
*
17+
* @final since Symfony 3.3
18+
*/
19+
class Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor extends Container
20+
{
21+
private $parameters;
22+
private $targetDirs = array();
23+
24+
/**
25+
* Constructor.
26+
*/
27+
public function __construct()
28+
{
29+
$this->services = array();
30+
$this->methodMap = array(
31+
'baz' => 'getBazService',
32+
'foo' => 'getFooService',
33+
);
34+
35+
$this->aliases = array();
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function compile()
42+
{
43+
throw new LogicException('You cannot compile a dumped frozen container.');
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function isFrozen()
50+
{
51+
return true;
52+
}
53+
54+
/**
55+
* Gets the 'baz' service.
56+
*
57+
* This service is shared.
58+
* This method always returns the same instance of the service.
59+
*
60+
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz A Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz instance
61+
*/
62+
protected function getBazService()
63+
{
64+
return $this->services['baz'] = $this->instantiateProxy(SymfonyProxy_a9f1de23b86d1fe2b860654ab2128883::class, array(), true);
65+
}
66+
67+
/**
68+
* Gets the 'foo' service.
69+
*
70+
* This service is shared.
71+
* This method always returns the same instance of the service.
72+
*
73+
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo A Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo instance
74+
*/
75+
protected function getFooService()
76+
{
77+
return $this->services['foo'] = new SymfonyProxy_cbcc1d1a7dc6a97b54a307ad6a012531($this);
78+
}
79+
80+
private function instantiateProxy($class, $args, $useConstructor)
81+
{
82+
static $reflectionCache;
83+
84+
if (null === $r = &$reflectionCache[$class]) {
85+
$r[0] = new \ReflectionClass($class);
86+
$r[1] = $r[0]->getProperty('containerg3aCmsigw5jaB68sqMSEQQ');
87+
$r[1]->setAccessible(true);
88+
$r[2] = $r[0]->getConstructor();
89+
}
90+
$service = $useConstructor ? $r[0]->newInstanceWithoutConstructor() : $r[0]->newInstanceArgs($args);
91+
$r[1]->setValue($service, $this);
92+
if ($r[2] && $useConstructor) {
93+
$r[2]->invokeArgs($service, $args);
94+
}
95+
96+
return $service;
97+
}
98+
}
99+
100+
class SymfonyProxy_a9f1de23b86d1fe2b860654ab2128883 extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz implements \Symfony\Component\DependencyInjection\LazyProxy\GetterProxyInterface
101+
{
102+
private $containerg3aCmsigw5jaB68sqMSEQQ;
103+
private $gettersg3aCmsigw5jaB68sqMSEQQ;
104+
105+
protected function getBaz()
106+
{
107+
return 'baz';
108+
}
109+
}
110+
111+
class SymfonyProxy_cbcc1d1a7dc6a97b54a307ad6a012531 extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo implements \Symfony\Component\DependencyInjection\LazyProxy\GetterProxyInterface
112+
{
113+
private $containerg3aCmsigw5jaB68sqMSEQQ;
114+
private $gettersg3aCmsigw5jaB68sqMSEQQ;
115+
116+
public function __construct($containerg3aCmsigw5jaB68sqMSEQQ, $bar = 'bar')
117+
{
118+
$this->containerg3aCmsigw5jaB68sqMSEQQ = $containerg3aCmsigw5jaB68sqMSEQQ;
119+
parent::__construct($bar);
120+
}
121+
122+
public function getPublic()
123+
{
124+
return 'public';
125+
}
126+
127+
protected function getProtected()
128+
{
129+
return 'protected';
130+
}
131+
132+
public function getSelf()
133+
{
134+
if (null === $g = &$this->gettersg3aCmsigw5jaB68sqMSEQQ[__FUNCTION__]) {
135+
$g = \Closure::bind(function () { return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}; }, $this->containerg3aCmsigw5jaB68sqMSEQQ, $this->containerg3aCmsigw5jaB68sqMSEQQ);
136+
}
137+
138+
return $g();
139+
}
140+
141+
public function getInvalid()
142+
{
143+
if (null === $g = &$this->gettersg3aCmsigw5jaB68sqMSEQQ[__FUNCTION__]) {
144+
$g = \Closure::bind(function () { return array(0 => $this->get('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE)); }, $this->containerg3aCmsigw5jaB68sqMSEQQ, $this->containerg3aCmsigw5jaB68sqMSEQQ);
145+
}
146+
147+
if ($this->containerg3aCmsigw5jaB68sqMSEQQ->has('bar')) {
148+
return $g();
149+
}
150+
151+
return parent::getInvalid();
152+
}
153+
}

0 commit comments

Comments
 (0)
0