[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
This commit is contained in:
Jean Pasqualini 2017-02-02 09:32:30 +01:00
parent 46daa359ea
commit 2440b0f05d
4 changed files with 240 additions and 2 deletions

View File

@ -525,9 +525,9 @@ class PhpDumper extends Dumper
}
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 {

View File

@ -344,6 +344,27 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$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

View File

@ -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;

View File

@ -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();
}
}