Nette\DI\ContainerBuilder::completeStatement PHP Method

completeStatement() public method

public completeStatement ( Statement $statement ) : Statement
$statement Statement
return Statement
    public function completeStatement(Statement $statement)
    {
        $entity = $this->normalizeEntity($statement->getEntity());
        $arguments = $statement->arguments;
        if (is_string($entity) && Strings::contains($entity, '?')) {
            // PHP literal
        } elseif ($service = $this->getServiceName($entity)) {
            // factory calling
            $params = [];
            foreach ($this->definitions[$service]->parameters as $k => $v) {
                $params[] = preg_replace('#\\w+\\z#', '\\$$0', is_int($k) ? $v : $k) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v));
            }
            $rm = new \ReflectionFunction(create_function(implode(', ', $params), ''));
            $arguments = Helpers::autowireArguments($rm, $arguments, $this);
            $entity = '@' . $service;
        } elseif ($entity === 'not') {
            // operator
        } elseif (is_string($entity)) {
            // class name
            if (!class_exists($entity)) {
                throw new ServiceCreationException("Class {$entity} not found.");
            } elseif ((new ReflectionClass($entity))->isAbstract()) {
                throw new ServiceCreationException("Class {$entity} is abstract.");
            } elseif (($rm = (new ReflectionClass($entity))->getConstructor()) !== NULL && !$rm->isPublic()) {
                $visibility = $rm->isProtected() ? 'protected' : 'private';
                throw new ServiceCreationException("Class {$entity} has {$visibility} constructor.");
            } elseif ($constructor = (new ReflectionClass($entity))->getConstructor()) {
                $this->addDependency($constructor);
                $arguments = Helpers::autowireArguments($constructor, $arguments, $this);
            } elseif ($arguments) {
                throw new ServiceCreationException("Unable to pass arguments, class {$entity} has no constructor.");
            }
        } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) {
            throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity)));
        } elseif (!preg_match('#^\\$?' . PhpHelpers::PHP_IDENT . '(\\[\\])?\\z#', $entity[1])) {
            throw new ServiceCreationException("Expected function, method or property name, '{$entity['1']}' given.");
        } elseif ($entity[0] === '') {
            // globalFunc
            if (!Nette\Utils\Arrays::isList($arguments)) {
                throw new ServiceCreationException("Unable to pass specified arguments to {$entity['0']}.");
            } elseif (!function_exists($entity[1])) {
                throw new ServiceCreationException("Function {$entity['1']} doesn't exist.");
            }
            $rf = new \ReflectionFunction($entity[1]);
            $this->addDependency($rf);
            $arguments = Helpers::autowireArguments($rf, $arguments, $this);
        } else {
            if ($entity[0] instanceof Statement) {
                $entity[0] = $this->completeStatement($entity[0]);
            } elseif ($service = $this->getServiceName($entity[0])) {
                // service method
                $entity[0] = '@' . $service;
            }
            if ($entity[1][0] === '$') {
                // property getter, setter or appender
                Validators::assert($arguments, 'list:0..1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'");
                if (!$arguments && substr($entity[1], -2) === '[]') {
                    throw new ServiceCreationException("Missing argument for {$entity['1']}.");
                }
            } elseif ($class = empty($service) || $entity[1] === 'create' ? $this->resolveEntityClass($entity[0]) : $this->definitions[$service]->getClass()) {
                $arguments = $this->autowireArguments($class, $entity[1], $arguments);
            }
        }
        array_walk_recursive($arguments, function (&$val) {
            if ($val instanceof Statement) {
                $val = $this->completeStatement($val);
            } elseif ($val === $this) {
                trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
                $val = self::literal('$this');
            } elseif ($val instanceof ServiceDefinition) {
                $val = '@' . current(array_keys($this->getDefinitions(), $val, TRUE));
            } elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
                $pair = explode('::', $val, 2);
                $name = $this->getServiceName($pair[0]);
                if (!isset($pair[1])) {
                    // @service
                    $val = '@' . $name;
                } elseif (preg_match('#^[A-Z][A-Z0-9_]*\\z#', $pair[1], $m)) {
                    // @service::CONSTANT
                    $val = self::literal($this->getDefinition($name)->getClass() . '::' . $pair[1]);
                } else {
                    // @service::property
                    $val = new Statement(['@' . $name, '$' . $pair[1]]);
                }
            }
        });
        return new Statement($entity, $arguments);
    }