Skip to content

Commit f1dc5ec

Browse files
[DI] enable improved syntax for defining method calls in Yaml
1 parent 2b71c6f commit f1dc5ec

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,20 +459,48 @@ private function parseDefinition(string $id, $service, string $file, array $defa
459459
throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file));
460460
}
461461

462-
foreach ($service['calls'] as $call) {
462+
foreach ($service['calls'] as $k => $call) {
463+
if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) {
464+
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));
465+
}
466+
467+
if (\is_string($k)) {
468+
throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in %s?', $id, $k, $file));
469+
}
470+
463471
if (isset($call['method'])) {
464472
$method = $call['method'];
465-
$args = isset($call['arguments']) ? $this->resolveServices($call['arguments'], $file) : [];
473+
$args = $call['arguments'] ?? [];
466474
$returnsClone = $call['returns_clone'] ?? false;
467475
} else {
468-
$method = $call[0];
469-
$args = isset($call[1]) ? $this->resolveServices($call[1], $file) : [];
470-
$returnsClone = $call[2] ?? false;
476+
if (1 === \count($call) && \is_string(key($call))) {
477+
$method = key($call);
478+
$args = $call[$method];
479+
} elseif (empty($call[0])) {
480+
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));
481+
} else {
482+
$method = $call[0];
483+
$args = $call[1] ?? [];
484+
$returnsClone = $call[2] ?? false;
485+
}
486+
487+
if ($args instanceof TaggedValue) {
488+
if ('returns_clone' !== $args->getTag()) {
489+
throw new InvalidArgumentException(sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in %s?', $args->getTag(), $id, $file));
490+
}
491+
492+
$returnsClone = true;
493+
$args = $args->getValue();
494+
} else {
495+
$returnsClone = false;
496+
}
471497
}
472498

473499
if (!\is_array($args)) {
474500
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));
475501
}
502+
503+
$args = $this->resolveServices($args, $file);
476504
$definition->addMethodCall($method, $args, $returnsClone);
477505
}
478506
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
foo:
3+
calls:
4+
- foo: [1, 2, 3]
5+
- bar: !returns_clone [1, 2, 3]

src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,4 +887,19 @@ public function testNotSinglyImplementedInterfacesInMultipleResourcesWithPreviou
887887

888888
$this->assertSame(Prototype\SinglyImplementedInterface\Adapter\Adapter::class, (string) $alias);
889889
}
890+
891+
public function testAlternativeMethodCalls()
892+
{
893+
$container = new ContainerBuilder();
894+
895+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
896+
$loader->load('alt_call.yaml');
897+
898+
$expected = [
899+
['foo', [1, 2, 3]],
900+
['bar', [1, 2, 3], true],
901+
];
902+
903+
$this->assertSame($expected, $container->getDefinition('foo')->getMethodCalls());
904+
}
890905
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy