Skip to content

Commit

Permalink
[DependencyInjection] Interface Injection implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
avalanche123 authored and fabpot committed Nov 30, 2010
1 parent dca8a79 commit 73331cf
Show file tree
Hide file tree
Showing 24 changed files with 1,108 additions and 6 deletions.
61 changes: 60 additions & 1 deletion src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Expand Up @@ -5,6 +5,7 @@
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\Resource\FileResource;
use Symfony\Component\DependencyInjection\InterfaceInjector;

/*
* This file is part of the Symfony framework.
Expand All @@ -29,6 +30,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
protected $loading = array();
protected $resources = array();
protected $extensionConfigs = array();
protected $injectors = array();

/**
* Registers an extension.
Expand Down Expand Up @@ -130,9 +132,15 @@ public function loadFromExtension($extension, $tag, array $values = array())
*
* @param string $id The service identifier
* @param object $service The service instance
*
* @throws BadMethodCallException
*/
public function set($id, $service)
{
if ($this->isFrozen()) {
throw new \BadMethodCallException('Setting service on a frozen container is not allowed');
}

unset($this->definitions[$id]);
unset($this->aliases[$id]);

Expand Down Expand Up @@ -287,12 +295,25 @@ public function freeze()

$this->merge($container);
}
$this->extensionConfigs = array();

$this->extensionConfigs = array();
$this->addDefinitions($definitions);
$this->addAliases($aliases);
$this->parameterBag->add($parameters);

foreach ($this->definitions as $definition) {
foreach ($this->injectors as $injector) {
if (null !== $definition->getFactoryService()) {
continue;
}
$defClass = $this->parameterBag->resolveValue($definition->getClass());
$definition->setClass($defClass);
if ($injector->supports($defClass)) {
$injector->processDefinition($definition);
}
}
}

parent::freeze();
}

Expand Down Expand Up @@ -392,6 +413,34 @@ public function getAlias($id)
return $this->aliases[$id];
}

public function addInterfaceInjectors(array $injectors)
{
foreach ($injectors as $injector) {
$this->addInterfaceInjector($injector);
}
}

public function addInterfaceInjector(InterfaceInjector $injector)
{
$class = $injector->getClass();
if (isset($this->injectors[$class])) {
return $this->injectors[$class]->merge($injector);
}

$this->injectors[$class] = $injector;
}

public function getInterfaceInjectors($service = null)
{
if (null === $service) {
return $this->injectors;
}

return array_filter($this->injectors, function(InterfaceInjector $injector) use ($service) {
return $injector->supports($service);
});
}

/**
* Registers a service definition.
*
Expand Down Expand Up @@ -446,9 +495,15 @@ public function getDefinitions()
*
* @param string $id The service identifier
* @param Definition $definition A Definition instance
*
* @throws BadMethodCallException
*/
public function setDefinition($id, Definition $definition)
{
if ($this->isFrozen()) {
throw new \BadMethodCallException('Adding definition to a frozen container is not allowed');
}

unset($this->aliases[$id]);

return $this->definitions[$id] = $definition;
Expand Down Expand Up @@ -536,6 +591,10 @@ protected function createService(Definition $definition, $id)
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
}

foreach ($this->getInterfaceInjectors($service) as $injector) {
$injector->processDefinition($definition, $service);
}

if ($definition->isShared()) {
$this->services[$id] = $service;
}
Expand Down
39 changes: 39 additions & 0 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Expand Up @@ -49,10 +49,45 @@ public function dump(array $options = array())
$this->addServices().
$this->addTags().
$this->addDefaultParametersMethod().
$this->addInterfaceInjectors().
$this->endClass()
;
}

protected function addInterfaceInjectors()
{
if ($this->container->isFrozen() || 0 === count($this->container->getInterfaceInjectors())) {
return;
}

$code = <<<EOF
/**
* Applies all known interface injection calls
*
* @param Object \$instance
*/
protected function applyIntrefaceInjectors(\$instance)
{
EOF;
foreach ($this->container->getInterfaceInjectors() as $injector) {
$code .= sprintf(" if (\$instance instanceof \\%s) {\n", $injector->getClass());
foreach ($injector->getMethodCalls() as $call) {
foreach ($call[1] as $value) {
$arguments[] = $this->dumpValue($value);
}
$code .= $this->wrapServiceConditionals($call[1], sprintf(" \$instance->%s(%s);\n", $call[0], implode(', ', $arguments)));
}
$code .= sprintf(" }\n");
}
$code .= <<<EOF
}
EOF;
return $code;
}

protected function addServiceInclude($id, $definition)
{
if (null !== $definition->getFile()) {
Expand Down Expand Up @@ -125,6 +160,10 @@ protected function addServiceMethodCalls($id, $definition)
$calls .= $this->wrapServiceConditionals($call[1], sprintf(" \$instance->%s(%s);\n", $call[0], implode(', ', $arguments)));
}

if (!$this->container->isFrozen() && count($this->container->getInterfaceInjectors()) > 0) {
$calls = sprintf("\n \$this->applyInterfaceInjection(\$instance);\n");
}

return $calls;
}

Expand Down
34 changes: 33 additions & 1 deletion src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
Expand Up @@ -5,6 +5,7 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\InterfaceInjector;

/*
* This file is part of the Symfony framework.
Expand All @@ -31,7 +32,7 @@ class XmlDumper extends Dumper
*/
public function dump(array $options = array())
{
return $this->startXml().$this->addParameters().$this->addServices().$this->endXml();
return $this->startXml().$this->addParameters().$this->addInterfaceInjectors().$this->addServices().$this->endXml();
}

protected function addParameters()
Expand All @@ -49,6 +50,37 @@ protected function addParameters()
return sprintf(" <parameters>\n%s </parameters>\n", $this->convertParameters($parameters, 'parameter', 4));
}

protected function addInterfaceInjector(InterfaceInjector $injector)
{
$code = \sprintf(" <interface class=\"%s\">\n", $injector->getClass());

foreach ($injector->getMethodCalls() as $call) {
if (count($call[1])) {
$code .= sprintf(" <call method=\"%s\">\n%s </call>\n", $call[0], $this->convertParameters($call[1], 'argument', 8));
} else {
$code .= sprintf(" <call method=\"%s\" />\n", $call[0]);
}
}

$code .= " </interface>\n";

return $code;
}

protected function addInterfaceInjectors()
{
if (!$this->container->getInterfaceInjectors()) {
return '';
}

$code = '';
foreach ($this->container->getInterfaceInjectors() as $injector) {
$code .= $this->addInterfaceInjector($injector);
}

return sprintf(" <interfaces>\n%s </interfaces>\n", $code);
}

protected function addService($id, $definition)
{
$code = sprintf(" <service id=\"%s\"%s%s%s%s>\n",
Expand Down
19 changes: 18 additions & 1 deletion src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
Expand Up @@ -32,7 +32,24 @@ class YamlDumper extends Dumper
*/
public function dump(array $options = array())
{
return $this->addParameters()."\n".$this->addServices();
return $this->addParameters().$this->addInterfaceInjectors()."\n".$this->addServices();
}

protected function addInterfaceInjectors()
{
if (!$this->container->getInterfaceInjectors()) {
return '';
}

$code = "\ninterfaces:\n";
foreach ($this->container->getInterfaceInjectors() as $injector) {
$code .= sprintf(" %s:\n", $injector->getClass());
if ($injector->getMethodCalls()) {
$code .= sprintf(" calls:\n %s\n", str_replace("\n", "\n ", Yaml::dump($this->dumpValue($injector->getMethodCalls()), 1)));
}
}

return $code;
}

protected function addService($id, $definition)
Expand Down
22 changes: 22 additions & 0 deletions src/Symfony/Component/DependencyInjection/Exception/Exception.php
@@ -0,0 +1,22 @@
<?php

namespace Symfony\Component\DependencyInjection\Exception;

/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

/**
* Exception
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
*/
interface Exception
{
}
@@ -0,0 +1,18 @@
<?php

namespace Symfony\Component\DependencyInjection\Exception;

use \InvalidArgumentException as BaseInvalidArgumentException;

/**
* InvalidArgumentException
*
* @package OpenSky Messaging
* @version $Id$
* @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
* @copyright (c) 2010 OpenSky Project Inc
* @license http://www.gnu.org/licenses/agpl.txt GNU Affero General Public License
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements Exception
{
}

0 comments on commit 73331cf

Please sign in to comment.