[DependencyInjection] fixed PhpDumper optimizations when an inlined service depends on the current one indirectly

This commit is contained in:
Fabien Potencier 2013-01-05 10:16:41 +01:00
parent cd153901ea
commit e0923ae1d0
8 changed files with 80 additions and 8 deletions

View File

@ -246,7 +246,7 @@ class PhpDumper extends Dumper
$code .= sprintf(" \$%s = new \\%s(%s);\n", $name, substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
}
if (!$this->hasReference($id, $sDefinition->getMethodCalls()) && !$this->hasReference($id, $sDefinition->getProperties())) {
if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
$code .= $this->addServiceProperties(null, $sDefinition, $name);
$code .= $this->addServiceConfigurator(null, $sDefinition, $name);
@ -415,7 +415,7 @@ class PhpDumper extends Dumper
}
$processed->offsetSet($iDefinition);
if (!$this->hasReference($id, $iDefinition->getMethodCalls()) && !$this->hasReference($id, $iDefinition->getProperties())) {
if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
continue;
}
@ -958,17 +958,26 @@ EOF;
*
* @return Boolean
*/
private function hasReference($id, array $arguments)
private function hasReference($id, array $arguments, $deep = false)
{
foreach ($arguments as $argument) {
if (is_array($argument)) {
if ($this->hasReference($id, $argument)) {
if ($this->hasReference($id, $argument, $deep)) {
return true;
}
} elseif ($argument instanceof Reference) {
if ($id === (string) $argument) {
return true;
}
if ($deep) {
$service = $this->container->getDefinition((string) $argument);
$arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
if ($this->hasReference($id, $arguments, $deep)) {
return true;
}
}
}
}

View File

@ -64,8 +64,12 @@ $container
$container
->register('inlined', 'Bar')
->setProperty('pub', 'pub')
->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
->addMethodCall('setBaz', array(new Reference('baz')))
->setPublic(false)
;
$container
->register('baz', 'Baz')
->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
;
return $container;

View File

@ -11,6 +11,7 @@ digraph sc {
node_factory_service [label="factory_service\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_foo_with_inline [label="foo_with_inline\nFoo\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_inlined [label="inlined\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
@ -25,5 +26,6 @@ digraph sc {
node_method_call1 -> node_foo3 [label="setBar()" style="dashed"];
node_method_call1 -> node_foobaz [label="setBar()" style="dashed"];
node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"];
node_inlined -> node_foo_with_inline [label="setFoo()" style="dashed"];
node_inlined -> node_baz [label="setBaz()" style="dashed"];
node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
}

View File

@ -7,10 +7,23 @@ function sc_configure($instance)
class BarClass
{
protected $baz;
public function setBaz(BazClass $baz)
{
$this->baz = $baz;
}
}
class BazClass
{
protected $foo;
public function setFoo(Foo $foo)
{
$this->foo = $foo;
}
public function configure($instance)
{
$instance->configure();

View File

@ -40,6 +40,23 @@ class ProjectServiceContainer extends Container
return $instance;
}
/**
* Gets the 'baz' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* @return Baz A Baz instance.
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \Baz();
$instance->setFoo($this->get('foo_with_inline'));
return $instance;
}
/**
* Gets the 'factory_service' service.
*
@ -173,7 +190,7 @@ class ProjectServiceContainer extends Container
{
$this->services['inlined'] = $instance = new \Bar();
$instance->setFoo($this->get('foo_with_inline'));
$instance->setBaz($this->get('baz'));
$instance->pub = 'pub';
return $instance;

View File

@ -49,6 +49,23 @@ class ProjectServiceContainer extends Container
return $instance;
}
/**
* Gets the 'baz' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* @return Baz A Baz instance.
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \Baz();
$instance->setFoo($this->get('foo_with_inline'));
return $instance;
}
/**
* Gets the 'factory_service' service.
*
@ -126,7 +143,7 @@ class ProjectServiceContainer extends Container
$this->services['foo_with_inline'] = $instance = new \Foo();
$a->setFoo($instance);
$a->setBaz($this->get('baz'));
$a->pub = 'pub';
$instance->setBar($a);

View File

@ -58,6 +58,11 @@
</service>
<service id="inlined" class="Bar" public="false">
<property name="pub">pub</property>
<call method="setBaz">
<argument type="service" id="baz"/>
</call>
</service>
<service id="baz" class="Baz">
<call method="setFoo">
<argument type="service" id="foo_with_inline"/>
</call>

View File

@ -49,6 +49,11 @@ services:
inlined:
class: Bar
properties: { pub: pub }
calls:
- [setBaz, ['@baz']]
baz:
class: Baz
calls:
- [setFoo, ['@foo_with_inline']]