[DI] enable improved syntax for defining method calls in Yaml

This commit is contained in:
Nicolas Grekas 2019-10-01 09:48:14 +02:00
parent bf406da78f
commit cdc7446051
4 changed files with 54 additions and 5 deletions

View File

@ -12,6 +12,7 @@ CHANGELOG
* added support for binding iterable and tagged services
* made singly-implemented interfaces detection be scoped by file
* added ability to define a static priority method for tagged service
* added support for improved syntax to define method calls in Yaml
4.3.0
-----

View File

@ -459,20 +459,48 @@ class YamlFileLoader extends FileLoader
throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
}
foreach ($service['calls'] as $call) {
foreach ($service['calls'] as $k => $call) {
if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) {
throw new InvalidArgumentException(sprintf('Invalid method call for service "%s": expected map or array, %s given in %s.', $id, $call instanceof TaggedValue ? '!'.$call->getTag() : \gettype($call), $file));
}
if (\is_string($k)) {
throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in %s?', $id, $k, $file));
}
if (isset($call['method'])) {
$method = $call['method'];
$args = isset($call['arguments']) ? $this->resolveServices($call['arguments'], $file) : [];
$args = $call['arguments'] ?? [];
$returnsClone = $call['returns_clone'] ?? false;
} else {
$method = $call[0];
$args = isset($call[1]) ? $this->resolveServices($call[1], $file) : [];
$returnsClone = $call[2] ?? false;
if (1 === \count($call) && \is_string(key($call))) {
$method = key($call);
$args = $call[$method];
if ($args instanceof TaggedValue) {
if ('returns_clone' !== $args->getTag()) {
throw new InvalidArgumentException(sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in %s?', $args->getTag(), $id, $file));
}
$returnsClone = true;
$args = $args->getValue();
} else {
$returnsClone = false;
}
} elseif (empty($call[0])) {
throw new InvalidArgumentException(sprintf('Invalid call for service "%s": the method must be defined as the first index of an array or as the only key of a map in %s.', $id, $file));
} else {
$method = $call[0];
$args = $call[1] ?? [];
$returnsClone = $call[2] ?? false;
}
}
if (!\is_array($args)) {
throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in %s. Check your YAML syntax.', $method, $id, $file));
}
$args = $this->resolveServices($args, $file);
$definition->addMethodCall($method, $args, $returnsClone);
}
}

View File

@ -0,0 +1,5 @@
services:
foo:
calls:
- foo: [1, 2, 3]
- bar: !returns_clone [1, 2, 3]

View File

@ -900,4 +900,19 @@ class YamlFileLoaderTest extends TestCase
$this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias);
}
public function testAlternativeMethodCalls()
{
$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
$loader->load('alt_call.yaml');
$expected = [
['foo', [1, 2, 3]],
['bar', [1, 2, 3], true],
];
$this->assertSame($expected, $container->getDefinition('foo')->getMethodCalls());
}
}