Skip to content

[DependencyInjection] [RFC] Plain array configs #11953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"symfony/icu": "~1.0",
"doctrine/common": "~2.2",
"twig/twig": "~1.12",
"psr/log": "~1.0"
"psr/log": "~1.0",
"jeremeamia/SuperClosure": "~1.0"
},
"replace": {
"symfony/browser-kit": "self.version",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,14 @@ public function createService(Definition $definition, $id, $tryProxy = true)

$arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));

if (null !== $definition->getFactoryMethod()) {
if ($definition->getFactoryMethod() instanceof \Closure) {
if (null !== $definition->getFactoryMethod() || null !== $definition->getFactoryClass()) {
throw new RuntimeException(sprintf('Definition of service "%s" is inconsistent (mixing of closure and factory service/class)', $id));
}

$closure = $definition->getFactoryMethod();
$service = $closure($this);
} elseif (null !== $definition->getFactoryMethod()) {
if (null !== $definition->getFactoryClass()) {
$factory = $parameterBag->resolveValue($definition->getFactoryClass());
} elseif (null !== $definition->getFactoryService()) {
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Component/DependencyInjection/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function getFactoryClass()
/**
* Sets the factory method able to create an instance of this class.
*
* @param string $factoryMethod The factory method name
* @param string|\Closure $factoryMethod The factory method name or closure
*
* @return Definition The current instance
*
Expand All @@ -109,7 +109,7 @@ public function setFactoryMethod($factoryMethod)
*
* @return Definition The current instance
*
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
* @throws \InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
*/
public function setDecoratedService($id, $renamedId = null)
{
Expand Down Expand Up @@ -139,7 +139,7 @@ public function getDecoratedService()
/**
* Gets the factory method.
*
* @return string|null The factory method name
* @return string|\Closure|null The factory method name
*
* @api
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection\Dumper\ClosureDumper;

/**
* Dumper is the abstract class for all built-in dumpers.
*
* @api
*/
interface ClosureDumperInterface
{
/**
* @param \Closure $closure
* @return string
*
* @throws \Symfony\Component\DependencyInjection\Exception\DumpingClosureException If closure couldn't be dumped
*/
public function dump(\Closure $closure);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection\Dumper\ClosureDumper;

use Jeremeamia\SuperClosure\ClosureParser;
use Symfony\Component\DependencyInjection\Exception\DumpingClosureException;

final class SuperClosureDumper implements ClosureDumperInterface
{
/**
* {@inheritdoc}
*/
public function dump(\Closure $closure)
{
$reflection = new \ReflectionFunction($closure);
$closureParser = new ClosureParser($reflection);

try {
$closureCode = $closureParser->getCode();
} catch (\InvalidArgumentException $e) {
throw new DumpingClosureException($closure);
}

// Remove ";" from the end of code
return substr($closureCode, 0, -1);
}
}
26 changes: 26 additions & 0 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\Dumper\ClosureDumper\ClosureDumperInterface;
use Symfony\Component\DependencyInjection\Variable;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -60,6 +61,11 @@ class PhpDumper extends Dumper
*/
private $proxyDumper;

/**
* @var \Symfony\Component\DependencyInjection\Dumper\ClosureDumper\ClosureDumperInterface
*/
private $closureDumper;

/**
* {@inheritdoc}
*
Expand All @@ -82,6 +88,16 @@ public function setProxyDumper(ProxyDumper $proxyDumper)
$this->proxyDumper = $proxyDumper;
}

/**
* Sets the dumper of closures
*
* @param ClosureDumperInterface $closureDumper
*/
public function setClosureDumper(ClosureDumperInterface $closureDumper)
{
$this->closureDumper = $closureDumper;
}

/**
* Dumps the service container as a PHP class.
*
Expand Down Expand Up @@ -701,6 +717,16 @@ private function addNewInstance($id, Definition $definition, $return, $instantia
}

if (null !== $definition->getFactoryMethod()) {
if ($definition->getFactoryMethod() instanceof \Closure) {
if ($this->closureDumper === null) {
throw new RuntimeException('DIC PhpDumper requires ClosureParser in order to dump closures');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requires a ClosureDumperInterface implementation set in order to dump closures

}

$closureCode = $this->closureDumper->dump($definition->getFactoryMethod());

return sprintf(" $return{$instantiation}call_user_func(%s, %s);\n", $closureCode, $arguments ? implode(', ', $arguments) : '$this');
}

if (null !== $definition->getFactoryClass()) {
$class = $this->dumpValue($definition->getFactoryClass());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Symfony\Component\DependencyInjection\Exception;

final class DumpingClosureException extends \RuntimeException implements ExceptionInterface
{
public function __construct(\Closure $closure)
{
$reflection = new \ReflectionFunction($closure);

parent::__construct(sprintf(
'Closure defined in %s at line %d could not be dumped',
$reflection->getFileName(),
$reflection->getStartLine()
));
}
}
Loading