Skip to content

Commit

Permalink
[DependencyInjection] Add anonymous services and decorates() for flue…
Browse files Browse the repository at this point in the history
…nt PHP configuration
  • Loading branch information
unkind committed Oct 19, 2017
1 parent fa1887d commit 02bf763
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 6 deletions.
@@ -0,0 +1,11 @@
<?php

namespace Symfony\Component\DependencyInjection\Argument;


/**
*
*/
final class DecoratedServiceArgument
{
}
14 changes: 14 additions & 0 deletions src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Expand Up @@ -1440,6 +1440,20 @@ public function log(CompilerPassInterface $pass, $message)
$this->getCompiler()->log($pass, $message);
}

/**
* @param string $prefix
* @return string
*/
public function generateServiceName($prefix) {
$i = 0;

while ($this->hasDefinition($prefix . $i)) {
$i++;
}

return $prefix . $i;
}

/**
* Returns the Service Conditionals.
*
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/DependencyInjection/Definition.php
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\Argument\DecoratedServiceArgument;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;

Expand Down
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\Component\DependencyInjection\Argument\DecoratedServiceArgument;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -139,3 +140,13 @@ function expr($expression)
{
return new Expression($expression);
}

/**
* Placeholder for decorated service.
*
* @return DecoratedServiceArgument
*/
function decorated()
{
return new DecoratedServiceArgument();
}
Expand Up @@ -90,6 +90,17 @@ final public function set($id, $class = null)
return null !== $class ? $configurator->class($class) : $configurator;
}

/**
* Creates anonymous service (service without explicit name).
*
* @param string $class
* @return ServiceConfigurator
*/
final public function anonymous($class)
{
return $this->set($this->container->generateServiceName('anon'), $class)->private();
}

/**
* Creates an alias.
*
Expand Down
Expand Up @@ -11,6 +11,14 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits;

use Symfony\Component\DependencyInjection\Argument\DecoratedServiceArgument;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader\Configurator\ReferenceConfigurator;

/**
* @property string $id
* @property Definition $definition
*/
trait ArgumentTrait
{
/**
Expand All @@ -22,6 +30,25 @@ trait ArgumentTrait
*/
final public function args(array $arguments)
{
$arguments = array_map(
function ($argument) {
if ($argument instanceof DecoratedServiceArgument) {
$decorated = $this->definition->getDecoratedService();

if (!$decorated) {
throw new \LogicException(
sprintf('Specify decorates() for the "%s" service', $this->id)
);
}

return new ReferenceConfigurator($decorated[1] ? $decorated[1] : $this->id . '.inner');
}

return $argument;
},
$arguments
);

$this->definition->setArguments(static::processValue($arguments, true));

return $this;
Expand Down
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Component\DependencyInjection\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
Expand Down
Expand Up @@ -144,6 +144,7 @@ public function testAddServiceWithoutCompilation()
{
$container = include self::$fixturesPath.'/containers/container9.php';
$dumper = new PhpDumper($container);

$this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
}

Expand Down
@@ -0,0 +1,29 @@
<?php

namespace Symfony\Component\DependencyInjection\Tests\Fixtures;


/**
*
*/
final class StdClassDecorator
{
private $foo;
private $bar;

public function __construct(\stdClass $foo, $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}

public function getFoo()
{
return $this->foo;
}

public function getBar()
{
return $this->bar;
}
}
Expand Up @@ -125,4 +125,11 @@

$s->alias('alias_for_foo', 'foo')->private()->public();
$s->alias('alias_for_alias', ref('alias_for_foo'));

$s->anonymous('\Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator')
->decorate('configured_service')
->args([
decorated(),
42
]);
};
Expand Up @@ -173,4 +173,13 @@
$container->setAlias('alias_for_foo', 'foo')->setPublic(true);
$container->setAlias('alias_for_alias', 'alias_for_foo')->setPublic(true);

$container
->register('anon0', '\Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator')
->setPublic(false)
->setDecoratedService('configured_service')
->setArguments([
new Reference('anon0.inner'),
42
]);

return $container;
Expand Up @@ -66,6 +66,8 @@ public function getRemovedIds()
return array(
'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
'anon0' => true,
'anon0.inner' => true,
'configurator_service' => true,
'configurator_service_simple' => true,
'decorated.pif-pouf' => true,
Expand Down Expand Up @@ -125,18 +127,17 @@ protected function getBazService()
/**
* Gets the public 'configured_service' shared service.
*
* @return \stdClass
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator
*/
protected function getConfiguredServiceService()
{
$a = new \ConfClass();
$a->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->getBazService()) && false ?: '_'});

$this->services['configured_service'] = $instance = new \stdClass();

$a->configureStdClass($instance);
$b = new \stdClass();
$a->configureStdClass($b);

return $instance;
return $this->services['configured_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator($b, 42);
}

/**
Expand Down
Expand Up @@ -139,6 +139,10 @@
<service id="tagged_iterator" class="Bar" public="true">
<argument type="tagged" tag="foo"/>
</service>
<service id="anon0" class="Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator" public="false" decorates="configured_service">
<argument type="service" id="anon0.inner"/>
<argument>42</argument>
</service>
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
<service id="alias_for_foo" alias="foo" public="true"/>
Expand Down

0 comments on commit 02bf763

Please sign in to comment.