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

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;
}