Permalink
Browse files

bug #21508 [DI] : Fix bad generation of proxy class when use override…

…n getter on class with constructor (jean-pasqualini)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] : Fix bad generation of proxy class when use overriden getter on class with constructor

[DI] : Fix bad generation of proxy class when use overriden getter on class with constructor

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21507
| License       | MIT

- [X] Add test fail
- [X] Fix bug
- [X] Run test pass

Commits
-------

2440b0f [DI] : Fix bad generation of proxy class when use overriden getter on class with constructor
  • Loading branch information...
2 parents 35a49fb + 2440b0f commit 0b57d17081d5d9f7ad2dc090c465a75f6b0af8bd @nicolas-grekas nicolas-grekas committed Feb 2, 2017
@@ -525,9 +525,9 @@ private function addServiceOverriddenGetters($id, Definition $definition)
}
if (!$r->isFinal()) {
if (0 < $r->getNumberOfParameters()) {
- $getters = implode('($container'.$this->salt.', ', explode('(', $this->generateSignature($r), 2));
+ $getters = implode('__construct($container'.$this->salt.', ', explode('(', $this->generateSignature($r), 2));
} else {
- $getters = '($container'.$this->salt.')';
+ $getters = '__construct($container'.$this->salt.')';
}
$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);
} else {
@@ -344,6 +344,27 @@ public function testDumpOverridenGetters()
$this->assertSame('baz', $r->invoke($baz));
}
+ public function testDumpOverridenGettersWithConstructor()
+ {
+ $container = include self::$fixturesPath.'/containers/container_dump_overriden_getters_with_constructor.php';
+ $container->compile();
+ $container->getDefinition('foo')
+ ->setOverriddenGetter('getInvalid', array(new Reference('bar', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE)));
+ $dumper = new PhpDumper($container);
+
+ $dump = $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor'));
+ $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dump_overriden_getters_with_constructor.php', $dump);
+ $resources = array_map('strval', $container->getResources());
+ $this->assertContains(realpath(self::$fixturesPath.'/containers/container_dump_overriden_getters_with_constructor.php'), $resources);
+
+ $baz = $container->get('baz');
+ $r = new \ReflectionMethod($baz, 'getBaz');
+ $r->setAccessible(true);
+
+ $this->assertTrue($r->isProtected());
+ $this->assertSame('baz', $r->invoke($baz));
+ }
+
/**
* @dataProvider provideBadOverridenGetters
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
@@ -0,0 +1,64 @@
+<?php
+
+namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container34;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+if (!class_exists(Foo::class, false)) {
+ abstract class Foo
+ {
+ protected $bar;
+
+ public function __construct($bar = 'bar')
+ {
+ $this->bar = $bar;
+ }
+
+ abstract public function getPublic();
+ abstract protected function getProtected();
+
+ public function getSelf()
+ {
+ return 123;
+ }
+
+ public function getInvalid()
+ {
+ return 456;
+ }
+
+ public function getGetProtected()
+ {
+ return $this->getProtected();
+ }
+ }
+
+ class Baz
+ {
+ final public function __construct()
+ {
+ }
+
+ protected function getBaz()
+ {
+ return 234;
+ }
+ }
+}
+
+$container = new ContainerBuilder();
+
+$container
+ ->register('foo', Foo::class)
+ ->setOverriddenGetter('getPublic', 'public')
+ ->setOverriddenGetter('getProtected', 'protected')
+ ->setOverriddenGetter('getSelf', new Reference('foo'))
+;
+
+$container
+ ->register('baz', Baz::class)
+ ->setOverriddenGetter('getBaz', 'baz')
+;
+
+return $container;
@@ -0,0 +1,153 @@
+<?php
+
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\LogicException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
+
+/**
+ * Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor.
+ *
+ * This class has been auto-generated
+ * by the Symfony Dependency Injection Component.
+ *
+ * @final since Symfony 3.3
+ */
+class Symfony_DI_PhpDumper_Test_Overriden_Getters_With_Constructor extends Container
+{
+ private $parameters;
+ private $targetDirs = array();
+
+ /**
+ * Constructor.
+ */
+ public function __construct()
+ {
+ $this->services = array();
+ $this->methodMap = array(
+ 'baz' => 'getBazService',
+ 'foo' => 'getFooService',
+ );
+
+ $this->aliases = array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function compile()
+ {
+ throw new LogicException('You cannot compile a dumped frozen container.');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isFrozen()
+ {
+ return true;
+ }
+
+ /**
+ * Gets the 'baz' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz A Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz instance
+ */
+ protected function getBazService()
+ {
+ return $this->services['baz'] = $this->instantiateProxy(SymfonyProxy_a9f1de23b86d1fe2b860654ab2128883::class, array(), true);
+ }
+
+ /**
+ * Gets the 'foo' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo A Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo instance
+ */
+ protected function getFooService()
+ {
+ return $this->services['foo'] = new SymfonyProxy_cbcc1d1a7dc6a97b54a307ad6a012531($this);
+ }
+
+ private function instantiateProxy($class, $args, $useConstructor)
+ {
+ static $reflectionCache;
+
+ if (null === $r = &$reflectionCache[$class]) {
+ $r[0] = new \ReflectionClass($class);
+ $r[1] = $r[0]->getProperty('containerg3aCmsigw5jaB68sqMSEQQ');
+ $r[1]->setAccessible(true);
+ $r[2] = $r[0]->getConstructor();
+ }
+ $service = $useConstructor ? $r[0]->newInstanceWithoutConstructor() : $r[0]->newInstanceArgs($args);
+ $r[1]->setValue($service, $this);
+ if ($r[2] && $useConstructor) {
+ $r[2]->invokeArgs($service, $args);
+ }
+
+ return $service;
+ }
+}
+
+class SymfonyProxy_a9f1de23b86d1fe2b860654ab2128883 extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Baz implements \Symfony\Component\DependencyInjection\LazyProxy\GetterProxyInterface
+{
+ private $containerg3aCmsigw5jaB68sqMSEQQ;
+ private $gettersg3aCmsigw5jaB68sqMSEQQ;
+
+ protected function getBaz()
+ {
+ return 'baz';
+ }
+}
+
+class SymfonyProxy_cbcc1d1a7dc6a97b54a307ad6a012531 extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container34\Foo implements \Symfony\Component\DependencyInjection\LazyProxy\GetterProxyInterface
+{
+ private $containerg3aCmsigw5jaB68sqMSEQQ;
+ private $gettersg3aCmsigw5jaB68sqMSEQQ;
+
+ public function __construct($containerg3aCmsigw5jaB68sqMSEQQ, $bar = 'bar')
+ {
+ $this->containerg3aCmsigw5jaB68sqMSEQQ = $containerg3aCmsigw5jaB68sqMSEQQ;
+ parent::__construct($bar);
+ }
+
+ public function getPublic()
+ {
+ return 'public';
+ }
+
+ protected function getProtected()
+ {
+ return 'protected';
+ }
+
+ public function getSelf()
+ {
+ if (null === $g = &$this->gettersg3aCmsigw5jaB68sqMSEQQ[__FUNCTION__]) {
+ $g = \Closure::bind(function () { return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}; }, $this->containerg3aCmsigw5jaB68sqMSEQQ, $this->containerg3aCmsigw5jaB68sqMSEQQ);
+ }
+
+ return $g();
+ }
+
+ public function getInvalid()
+ {
+ if (null === $g = &$this->gettersg3aCmsigw5jaB68sqMSEQQ[__FUNCTION__]) {
+ $g = \Closure::bind(function () { return array(0 => $this->get('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE)); }, $this->containerg3aCmsigw5jaB68sqMSEQQ, $this->containerg3aCmsigw5jaB68sqMSEQQ);
+ }
+
+ if ($this->containerg3aCmsigw5jaB68sqMSEQQ->has('bar')) {
+ return $g();
+ }
+
+ return parent::getInvalid();
+ }
+}

0 comments on commit 0b57d17

Please sign in to comment.