function PhpArrayContainer::resolveServicesAndParameters

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php \Drupal\Component\DependencyInjection\PhpArrayContainer::resolveServicesAndParameters()
  2. 8.9.x core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php \Drupal\Component\DependencyInjection\PhpArrayContainer::resolveServicesAndParameters()
  3. 10 core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php \Drupal\Component\DependencyInjection\PhpArrayContainer::resolveServicesAndParameters()

Overrides Container::resolveServicesAndParameters

1 call to PhpArrayContainer::resolveServicesAndParameters()
PhpArrayContainer::createService in core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php
Creates a service from a service definition.

File

core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php, line 126

Class

PhpArrayContainer
Provides a container optimized for Drupal's needs.

Namespace

Drupal\Component\DependencyInjection

Code

protected function resolveServicesAndParameters($arguments) {
    // This method is different from the parent method only for the following
    // cases:
    // - A service is denoted by '@service' and not by a \stdClass object.
    // - A parameter is denoted by '%parameter%' and not by a \stdClass object.
    // - The depth of the tree representing the arguments is not known in
    //   advance, so it needs to be fully traversed recursively.
    foreach ($arguments as $key => $argument) {
        if ($argument instanceof \stdClass) {
            $type = $argument->type;
            // Private services are a special flavor: In case a private service is
            // only used by one other service, the ContainerBuilder uses a
            // Definition object as an argument, which does not have an ID set.
            // Therefore the format uses a \stdClass object to store the definition
            // and to be able to create the service on the fly.
            //
            // Note: When constructing a private service by hand, 'id' must be set.
            //
            // The PhpArrayDumper just uses the hash of the private service
            // definition to generate a unique ID.
            //
            // @see \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper::getPrivateServiceCall
            if ($type == 'private_service') {
                $id = $argument->id;
                // Check if the private service already exists - in case it is shared.
                if (!empty($argument->shared) && isset($this->privateServices[$id])) {
                    $arguments[$key] = $this->privateServices[$id];
                    continue;
                }
                // Create a private service from a service definition.
                $arguments[$key] = $this->createService($argument->value, $id);
                if (!empty($argument->shared)) {
                    $this->privateServices[$id] = $arguments[$key];
                }
                continue;
            }
            elseif ($type == 'service_closure') {
                $arguments[$key] = function () use ($argument) {
                    return $this->get($argument->id, $argument->invalidBehavior);
                };
                continue;
            }
            elseif ($type == 'raw') {
                $arguments[$key] = $argument->value;
                continue;
            }
            elseif ($type == 'iterator') {
                $services = $argument->value;
                $arguments[$key] = new RewindableGenerator(function () use ($services) {
                    foreach ($services as $key => $service) {
                        (yield $key => $this->resolveServicesAndParameters([
                            $service,
                        ])[0]);
                    }
                }, count($services));
                continue;
            }
            if ($type !== NULL) {
                throw new InvalidArgumentException("Undefined type '{$type}' while resolving parameters and services.");
            }
        }
        if (is_array($argument)) {
            $arguments[$key] = $this->resolveServicesAndParameters($argument);
            continue;
        }
        if (!is_string($argument)) {
            continue;
        }
        // Resolve parameters.
        if ($argument[0] === '%') {
            $name = substr($argument, 1, -1);
            if (!isset($this->parameters[$name])) {
                $arguments[$key] = $this->getParameter($name);
                // This can never be reached as getParameter() throws an Exception,
                // because we already checked that the parameter is not set above.
            }
            $argument = $this->parameters[$name];
            $arguments[$key] = $argument;
        }
        // Resolve services.
        if ($argument[0] === '@') {
            $id = substr($argument, 1);
            $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            if ($id[0] === '?') {
                $id = substr($id, 1);
                $invalid_behavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
            }
            if (isset($this->services[$id])) {
                $arguments[$key] = $this->services[$id];
            }
            else {
                $arguments[$key] = $this->get($id, $invalid_behavior);
            }
        }
    }
    return $arguments;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.