[DI] fix definition and usage of AbstractArgument
This commit is contained in:
parent
69b6c90330
commit
abb463c749
@ -16,29 +16,26 @@ namespace Symfony\Component\DependencyInjection\Argument;
|
||||
*/
|
||||
final class AbstractArgument
|
||||
{
|
||||
private $serviceId;
|
||||
private $argKey;
|
||||
private $text;
|
||||
private $context;
|
||||
|
||||
public function __construct(string $serviceId, string $argKey, string $text = '')
|
||||
public function __construct(string $text = '')
|
||||
{
|
||||
$this->serviceId = $serviceId;
|
||||
$this->argKey = $argKey;
|
||||
$this->text = $text;
|
||||
$this->text = trim($text, '. ');
|
||||
}
|
||||
|
||||
public function getServiceId(): string
|
||||
public function setContext(string $context): void
|
||||
{
|
||||
return $this->serviceId;
|
||||
}
|
||||
|
||||
public function getArgumentKey(): string
|
||||
{
|
||||
return $this->argKey;
|
||||
$this->context = $context.' is abstract'.('' === $this->text ? '' : ': ');
|
||||
}
|
||||
|
||||
public function getText(): string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
public function getTextWithContext(): string
|
||||
{
|
||||
return $this->context.$this->text.'.';
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
@ -28,6 +29,10 @@ class ResolveNamedArgumentsPass extends AbstractRecursivePass
|
||||
*/
|
||||
protected function processValue($value, bool $isRoot = false)
|
||||
{
|
||||
if ($value instanceof AbstractArgument && $value->getText().'.' === $value->getTextWithContext()) {
|
||||
$value->setContext(sprintf('A value found in service "%s"', $this->currentId));
|
||||
}
|
||||
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
@ -41,6 +46,10 @@ class ResolveNamedArgumentsPass extends AbstractRecursivePass
|
||||
$resolvedArguments = [];
|
||||
|
||||
foreach ($arguments as $key => $argument) {
|
||||
if ($argument instanceof AbstractArgument && $argument->getText().'.' === $argument->getTextWithContext()) {
|
||||
$argument->setContext(sprintf('Argument '.(\is_int($key) ? 1 + $key : '"%3$s"').' of '.('__construct' === $method ? 'service "%s"' : 'method call "%s::%s()"'), $this->currentId, $method, $key));
|
||||
}
|
||||
|
||||
if (\is_int($key)) {
|
||||
$resolvedArguments[$key] = $argument;
|
||||
continue;
|
||||
@ -107,6 +116,12 @@ class ResolveNamedArgumentsPass extends AbstractRecursivePass
|
||||
$value->setMethodCalls($calls);
|
||||
}
|
||||
|
||||
foreach ($value->getProperties() as $key => $argument) {
|
||||
if ($argument instanceof AbstractArgument && $argument->getText().'.' === $argument->getTextWithContext()) {
|
||||
$argument->setContext(sprintf('Property "%s" of service "%s"', $key, $this->currentId));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
} elseif ($value instanceof Expression) {
|
||||
$value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]);
|
||||
} elseif ($value instanceof AbstractArgument) {
|
||||
throw new RuntimeException(sprintf('Argument "%s" of service "%s" is abstract%s, did you forget to define it?', $value->getArgumentKey(), $value->getServiceId(), $value->getText() ? ' ('.$value->getText().')' : ''));
|
||||
throw new RuntimeException($value->getTextWithContext());
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
@ -1787,7 +1787,7 @@ EOF;
|
||||
return $code;
|
||||
}
|
||||
} elseif ($value instanceof AbstractArgument) {
|
||||
throw new RuntimeException(sprintf('Argument "%s" of service "%s" is abstract%s, did you forget to define it?', $value->getArgumentKey(), $value->getServiceId(), $value->getText() ? ' ('.$value->getText().')' : ''));
|
||||
throw new RuntimeException($value->getTextWithContext());
|
||||
} elseif (\is_object($value) || \is_resource($value)) {
|
||||
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
|
||||
}
|
||||
|
@ -320,10 +320,6 @@ class XmlDumper extends Dumper
|
||||
$text = $this->document->createTextNode(self::phpToXml(base64_encode($value)));
|
||||
$element->appendChild($text);
|
||||
} elseif ($value instanceof AbstractArgument) {
|
||||
$argKey = $value->getArgumentKey();
|
||||
if (!is_numeric($argKey)) {
|
||||
$element->setAttribute('key', $argKey);
|
||||
}
|
||||
$element->setAttribute('type', 'abstract');
|
||||
$text = $this->document->createTextNode(self::phpToXml($value->getText()));
|
||||
$element->appendChild($text);
|
||||
|
@ -537,8 +537,7 @@ class XmlFileLoader extends FileLoader
|
||||
$arguments[$key] = $value;
|
||||
break;
|
||||
case 'abstract':
|
||||
$serviceId = $node->getAttribute('id');
|
||||
$arguments[$key] = new AbstractArgument($serviceId, (string) $key, $arg->nodeValue);
|
||||
$arguments[$key] = new AbstractArgument($arg->nodeValue);
|
||||
break;
|
||||
case 'string':
|
||||
$arguments[$key] = $arg->nodeValue;
|
||||
|
@ -449,7 +449,7 @@ class YamlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
if (isset($service['arguments'])) {
|
||||
$definition->setArguments($this->resolveServices($service['arguments'], $file, false, $id));
|
||||
$definition->setArguments($this->resolveServices($service['arguments'], $file));
|
||||
}
|
||||
|
||||
if (isset($service['properties'])) {
|
||||
@ -721,7 +721,7 @@ class YamlFileLoader extends FileLoader
|
||||
*
|
||||
* @return array|string|Reference|ArgumentInterface
|
||||
*/
|
||||
private function resolveServices($value, string $file, bool $isParameter = false, string $serviceId = '', string $argKey = '')
|
||||
private function resolveServices($value, string $file, bool $isParameter = false)
|
||||
{
|
||||
if ($value instanceof TaggedValue) {
|
||||
$argument = $value->getValue();
|
||||
@ -795,7 +795,7 @@ class YamlFileLoader extends FileLoader
|
||||
return new Reference($id);
|
||||
}
|
||||
if ('abstract' === $value->getTag()) {
|
||||
return new AbstractArgument($serviceId, $argKey, $value->getValue());
|
||||
return new AbstractArgument($value->getValue());
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag()));
|
||||
@ -803,7 +803,7 @@ class YamlFileLoader extends FileLoader
|
||||
|
||||
if (\is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
$value[$k] = $this->resolveServices($v, $file, $isParameter, $serviceId, $k);
|
||||
$value[$k] = $this->resolveServices($v, $file, $isParameter);
|
||||
}
|
||||
} elseif (\is_string($value) && 0 === strpos($value, '@=')) {
|
||||
if (!class_exists(Expression::class)) {
|
||||
|
@ -18,9 +18,7 @@ class AbstractArgumentTest extends TestCase
|
||||
{
|
||||
public function testAbstractArgumentGetters()
|
||||
{
|
||||
$argument = new AbstractArgument('foo', '$bar', 'should be defined by Pass');
|
||||
$this->assertSame('foo', $argument->getServiceId());
|
||||
$this->assertSame('$bar', $argument->getArgumentKey());
|
||||
$argument = new AbstractArgument('should be defined by Pass');
|
||||
$this->assertSame('should be defined by Pass', $argument->getText());
|
||||
}
|
||||
}
|
||||
|
@ -552,11 +552,14 @@ class ContainerBuilderTest extends TestCase
|
||||
public function testCreateServiceWithAbstractArgument()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Argument "$baz" of service "foo" is abstract (should be defined by Pass), did you forget to define it?');
|
||||
$this->expectExceptionMessage('Argument "$baz" of service "foo" is abstract: should be defined by Pass.');
|
||||
|
||||
$builder = new ContainerBuilder();
|
||||
$builder->register('foo', FooWithAbstractArgument::class)
|
||||
->addArgument(new AbstractArgument('foo', '$baz', 'should be defined by Pass'));
|
||||
->setArgument('$baz', new AbstractArgument('should be defined by Pass'))
|
||||
->setPublic(true);
|
||||
|
||||
$builder->compile();
|
||||
|
||||
$builder->get('foo');
|
||||
}
|
||||
|
@ -1372,12 +1372,12 @@ class PhpDumperTest extends TestCase
|
||||
public function testDumpServiceWithAbstractArgument()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Argument "$baz" of service "Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument" is abstract (should be defined by Pass), did you forget to define it?');
|
||||
$this->expectExceptionMessage('Argument "$baz" of service "Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument" is abstract: should be defined by Pass.');
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$container->register(FooWithAbstractArgument::class, FooWithAbstractArgument::class)
|
||||
->setArgument('$baz', new AbstractArgument(FooWithAbstractArgument::class, '$baz', 'should be defined by Pass'))
|
||||
->setArgument('$baz', new AbstractArgument('should be defined by Pass'))
|
||||
->setArgument('$bar', 'test')
|
||||
->setPublic(true);
|
||||
|
||||
|
@ -264,7 +264,7 @@ class XmlDumperTest extends TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(FooWithAbstractArgument::class, FooWithAbstractArgument::class)
|
||||
->setArgument('$baz', new AbstractArgument(FooWithAbstractArgument::class, '$baz', 'should be defined by Pass'))
|
||||
->setArgument('$baz', new AbstractArgument('should be defined by Pass'))
|
||||
->setArgument('$bar', 'test');
|
||||
|
||||
$dumper = new XmlDumper($container);
|
||||
|
@ -123,7 +123,7 @@ class YamlDumperTest extends TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(FooWithAbstractArgument::class, FooWithAbstractArgument::class)
|
||||
->setArgument('$baz', new AbstractArgument(FooWithAbstractArgument::class, '$baz', 'should be defined by Pass'))
|
||||
->setArgument('$baz', new AbstractArgument('should be defined by Pass'))
|
||||
->setArgument('$bar', 'test');
|
||||
|
||||
$dumper = new YamlDumper($container);
|
||||
|
Reference in New Issue
Block a user