function XmlFileLoader::parseDefinition
Parses an individual Definition.
3 calls to XmlFileLoader::parseDefinition()
- XmlFileLoader::getServiceDefaults in vendor/
symfony/ dependency-injection/ Loader/ XmlFileLoader.php - XmlFileLoader::parseDefinitions in vendor/
symfony/ dependency-injection/ Loader/ XmlFileLoader.php - XmlFileLoader::processAnonymousServices in vendor/
symfony/ dependency-injection/ Loader/ XmlFileLoader.php - Processes anonymous services.
File
-
vendor/
symfony/ dependency-injection/ Loader/ XmlFileLoader.php, line 207
Class
- XmlFileLoader
- XmlFileLoader loads XML files service definitions.
Namespace
Symfony\Component\DependencyInjection\LoaderCode
private function parseDefinition(\DOMElement $service, string $file, Definition $defaults) : ?Definition {
if ($alias = $service->getAttribute('alias')) {
$this->validateAlias($service, $file);
$this->container
->setAlias($service->getAttribute('id'), $alias = new Alias($alias));
if ($publicAttr = $service->getAttribute('public')) {
$alias->setPublic(XmlUtils::phpize($publicAttr));
}
elseif ($defaults->getChanges()['public'] ?? false) {
$alias->setPublic($defaults->isPublic());
}
if ($deprecated = $this->getChildren($service, 'deprecated')) {
$message = $deprecated[0]->nodeValue ?: '';
$package = $deprecated[0]->getAttribute('package') ?: '';
$version = $deprecated[0]->getAttribute('version') ?: '';
if (!$deprecated[0]->hasAttribute('package')) {
throw new InvalidArgumentException(\sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
}
if (!$deprecated[0]->hasAttribute('version')) {
throw new InvalidArgumentException(\sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
}
$alias->setDeprecated($package, $version, $message);
}
return null;
}
if ($this->isLoadingInstanceof) {
$definition = new ChildDefinition('');
}
elseif ($parent = $service->getAttribute('parent')) {
$definition = new ChildDefinition($parent);
}
else {
$definition = new Definition();
}
if ($defaults->getChanges()['public'] ?? false) {
$definition->setPublic($defaults->isPublic());
}
$definition->setAutowired($defaults->isAutowired());
$definition->setAutoconfigured($defaults->isAutoconfigured());
$definition->setChanges([]);
foreach ([
'class',
'public',
'shared',
'synthetic',
'abstract',
] as $key) {
if ($value = $service->getAttribute($key)) {
$method = 'set' . $key;
$definition->{$method}(XmlUtils::phpize($value));
}
}
if ($value = $service->getAttribute('lazy')) {
$definition->setLazy((bool) ($value = XmlUtils::phpize($value)));
if (\is_string($value)) {
$definition->addTag('proxy', [
'interface' => $value,
]);
}
}
if ($value = $service->getAttribute('autowire')) {
$definition->setAutowired(XmlUtils::phpize($value));
}
if ($value = $service->getAttribute('autoconfigure')) {
$definition->setAutoconfigured(XmlUtils::phpize($value));
}
if ($files = $this->getChildren($service, 'file')) {
$definition->setFile($files[0]->nodeValue);
}
if ($deprecated = $this->getChildren($service, 'deprecated')) {
$message = $deprecated[0]->nodeValue ?: '';
$package = $deprecated[0]->getAttribute('package') ?: '';
$version = $deprecated[0]->getAttribute('version') ?: '';
if (!$deprecated[0]->hasAttribute('package')) {
throw new InvalidArgumentException(\sprintf('Missing attribute "package" at node "deprecated" in "%s".', $file));
}
if (!$deprecated[0]->hasAttribute('version')) {
throw new InvalidArgumentException(\sprintf('Missing attribute "version" at node "deprecated" in "%s".', $file));
}
$definition->setDeprecated($package, $version, $message);
}
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition));
$definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file));
if ($factories = $this->getChildren($service, 'factory')) {
$factory = $factories[0];
if ($function = $factory->getAttribute('function')) {
$definition->setFactory($function);
}
elseif ($expression = $factory->getAttribute('expression')) {
if (!class_exists(Expression::class)) {
throw new \LogicException('The "expression" attribute cannot be used on factories without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
}
$definition->setFactory('@=' . $expression);
}
else {
if ($childService = $factory->getAttribute('service')) {
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
}
else {
$class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null;
}
$definition->setFactory([
$class,
$factory->getAttribute('method') ?: '__invoke',
]);
}
}
if ($constructor = $service->getAttribute('constructor')) {
if (null !== $definition->getFactory()) {
throw new LogicException(\sprintf('The "%s" service cannot declare a factory as well as a constructor.', $service->getAttribute('id')));
}
$definition->setFactory([
null,
$constructor,
]);
}
if ($configurators = $this->getChildren($service, 'configurator')) {
$configurator = $configurators[0];
if ($function = $configurator->getAttribute('function')) {
$definition->setConfigurator($function);
}
else {
if ($childService = $configurator->getAttribute('service')) {
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
}
else {
$class = $configurator->getAttribute('class');
}
$definition->setConfigurator([
$class,
$configurator->getAttribute('method') ?: '__invoke',
]);
}
}
foreach ($this->getChildren($service, 'call') as $call) {
$definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone')));
}
$tags = $this->getChildren($service, 'tag');
foreach ($tags as $tag) {
$tagNameComesFromAttribute = $tag->childElementCount || '' === $tag->nodeValue;
if ('' === ($tagName = $tagNameComesFromAttribute ? $tag->getAttribute('name') : $tag->nodeValue)) {
throw new InvalidArgumentException(\sprintf('The tag name for service "%s" in "%s" must be a non-empty string.', $service->getAttribute('id'), $file));
}
$parameters = $this->getTagAttributes($tag, \sprintf('The attribute name of tag "%s" for service "%s" in %s must be a non-empty string.', $tagName, $service->getAttribute('id'), $file));
foreach ($tag->attributes as $name => $node) {
if ($tagNameComesFromAttribute && 'name' === $name) {
continue;
}
if (str_contains($name, '-') && !str_contains($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) {
$parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue);
}
// keep not normalized key
$parameters[$name] = XmlUtils::phpize($node->nodeValue);
}
$definition->addTag($tagName, $parameters);
}
$definition->setTags(array_merge_recursive($definition->getTags(), $defaults->getTags()));
$bindings = $this->getArgumentsAsPhp($service, 'bind', $file);
$bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING;
foreach ($bindings as $argument => $value) {
$bindings[$argument] = new BoundArgument($value, true, $bindingType, $file);
}
// deep clone, to avoid multiple process of the same instance in the passes
$bindings = array_merge(unserialize(serialize($defaults->getBindings())), $bindings);
if ($bindings) {
$definition->setBindings($bindings);
}
if ($decorates = $service->getAttribute('decorates')) {
$decorationOnInvalid = $service->getAttribute('decoration-on-invalid') ?: 'exception';
if ('exception' === $decorationOnInvalid) {
$invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
}
elseif ('ignore' === $decorationOnInvalid) {
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
}
elseif ('null' === $decorationOnInvalid) {
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
}
else {
throw new InvalidArgumentException(\sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, $service->getAttribute('id'), $file));
}
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
$priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;
$definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior);
}
if ($callable = $this->getChildren($service, 'from-callable')) {
if ($definition instanceof ChildDefinition) {
throw new InvalidArgumentException(\sprintf('Attribute "parent" is unsupported when using "<from-callable>" on service "%s".', $service->getAttribute('id')));
}
foreach ([
'Attribute "synthetic"' => 'isSynthetic',
'Attribute "file"' => 'getFile',
'Tag "<factory>"' => 'getFactory',
'Tag "<argument>"' => 'getArguments',
'Tag "<property>"' => 'getProperties',
'Tag "<configurator>"' => 'getConfigurator',
'Tag "<call>"' => 'getMethodCalls',
] as $key => $method) {
if ($definition->{$method}()) {
throw new InvalidArgumentException($key . \sprintf(' is unsupported when using "<from-callable>" on service "%s".', $service->getAttribute('id')));
}
}
$definition->setFactory([
'Closure',
'fromCallable',
]);
if ('Closure' !== ($definition->getClass() ?? 'Closure')) {
$definition->setLazy(true);
}
else {
$definition->setClass('Closure');
}
$callable = $callable[0];
if ($function = $callable->getAttribute('function')) {
$definition->setArguments([
$function,
]);
}
elseif ($expression = $callable->getAttribute('expression')) {
if (!class_exists(Expression::class)) {
throw new \LogicException('The "expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".');
}
$definition->setArguments([
'@=' . $expression,
]);
}
else {
if ($childService = $callable->getAttribute('service')) {
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
}
else {
$class = $callable->hasAttribute('class') ? $callable->getAttribute('class') : null;
}
$definition->setArguments([
[
$class,
$callable->getAttribute('method') ?: '__invoke',
],
]);
}
}
return $definition;
}