Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. XmlFileLoader.php

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\Loader

Code

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;
}
RSS feed
Powered by Drupal