Skip to content

[DependencyInjection] Add support for short services configurators syntax #19190

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
wants to merge 4 commits into from
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
10 changes: 7 additions & 3 deletions src/Symfony/Component/DependencyInjection/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -612,13 +612,17 @@ public function getDeprecationMessage($id)
/**
* Sets a configurator to call after the service is fully initialized.
*
* @param callable $callable A PHP callable
* @param string|array $configurator A PHP callable
*
* @return Definition The current instance
*/
public function setConfigurator($callable)
public function setConfigurator($configurator)
{
$this->configurator = $callable;
if (is_string($configurator) && strpos($configurator, '::') !== false) {
$configurator = explode('::', $configurator, 2);
}

$this->configurator = $configurator;

return $this;
}
Expand Down
56 changes: 41 additions & 15 deletions src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,7 @@ private function parseDefinition($id, $service, $file)
}

if (isset($service['factory'])) {
if (is_string($service['factory'])) {
if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) {
$parts = explode(':', $service['factory']);
$definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1]));
} else {
$definition->setFactory($service['factory']);
}
} else {
$definition->setFactory(array($this->resolveServices($service['factory'][0]), $service['factory'][1]));
}
$definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file));
}

if (isset($service['file'])) {
Expand All @@ -248,11 +239,7 @@ private function parseDefinition($id, $service, $file)
}

if (isset($service['configurator'])) {
if (is_string($service['configurator'])) {
$definition->setConfigurator($service['configurator']);
} else {
$definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
}
$definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file));
}

if (isset($service['calls'])) {
Expand Down Expand Up @@ -339,6 +326,45 @@ private function parseDefinition($id, $service, $file)
$this->container->setDefinition($id, $definition);
}

/**
* Parses a callable.
*
* @param string|array $callable A callable
* @param string $parameter A parameter (e.g. 'factory' or 'configurator')
* @param string $id A service identifier
* @param string $file A parsed file
*
* @throws InvalidArgumentException When errors are occuried
*
* @return string|array A parsed callable
*/
private function parseCallable($callable, $parameter, $id, $file)
{
if (is_string($callable)) {
if ('' !== $callable && '@' === $callable[0]) {
throw new InvalidArgumentException(sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $parameter, $id, $callable, substr($callable, 1)));
}

if (false !== strpos($callable, ':') && false === strpos($callable, '::')) {
$parts = explode(':', $callable);

return array($this->resolveServices('@'.$parts[0]), $parts[1]);
}

return $callable;
}

if (is_array($callable)) {
if (isset($callable[0]) && isset($callable[1])) {
return array($this->resolveServices($callable[0]), $callable[1]);
}

throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file));
}

throw new InvalidArgumentException(sprintf('Parameter "%s" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file));
}

/**
* Loads a YAML file.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:

foo_bar:
class: FooBarClass
configurator: foo_bar_configurator:configure

foo_bar_with_static_call:
class: FooBarClass
configurator: FooBarConfigurator::configureFooBar
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ public function testLoadFactoryShortSyntax()
$this->assertEquals(array('FooBacFactory', 'createFooBar'), $services['factory_with_static_call']->getFactory(), '->load() parses the factory tag with Class::method');
}

public function testLoadConfiguratorShortSyntax()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('services_configurator_short_syntax.yml');
$services = $container->getDefinitions();

$this->assertEquals(array(new Reference('foo_bar_configurator'), 'configure'), $services['foo_bar']->getConfigurator(), '->load() parses the configurator tag with service:method');
$this->assertEquals(array('FooBarConfigurator', 'configureFooBar'), $services['foo_bar_with_static_call']->getConfigurator(), '->load() parses the configurator tag with Class::method');
}

public function testExtensions()
{
$container = new ContainerBuilder();
Expand Down