Skip to content

Commit

Permalink
[DI] enable improved syntax for defining method calls in Yaml
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-grekas committed Oct 1, 2019
1 parent 2b71c6f commit f1dc5ec
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -459,20 +459,48 @@ private function parseDefinition(string $id, $service, string $file, array $defa
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];
} 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 ($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;
}
}

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);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
foo:
calls:
- foo: [1, 2, 3]
- bar: !returns_clone [1, 2, 3]
Original file line number Diff line number Diff line change
Expand Up @@ -887,4 +887,19 @@ public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviou

$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());
}
}

0 comments on commit f1dc5ec

Please sign in to comment.