# packeta/trunk/deps/nette/di/src/DI/ContainerBuilder.php

Packeta, version trunk. 324 lines.

- Page: https://pluginprobe.com/plugins/packeta/trunk/code/deps/nette/di/src/DI/ContainerBuilder.php
- Raw: https://pluginprobe.com/plugins/packeta/trunk/raw/deps/nette/di/src/DI/ContainerBuilder.php
- Modified: 2025-03-10T10:47:38+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/packeta/trunk/code/deps/nette/di/src/DI/ContainerBuilder.php#L10-L20`.

```php
<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
 */
declare (strict_types=1);
namespace Packetery\Nette\DI;

use Packetery\Nette;
use Packetery\Nette\DI\Definitions\Definition;
/**
 * Container builder.
 */
class ContainerBuilder
{
    use \Packetery\Nette\SmartObject;
    public const ThisService = 'self', ThisContainer = 'container';
    /** @deprecated use ContainerBuilder::ThisService */
    public const THIS_SERVICE = self::ThisService;
    /** @deprecated use ContainerBuilder::ThisContainer */
    public const THIS_CONTAINER = self::ThisContainer;
    /** @var array */
    public $parameters = [];
    /** @var Definition[] */
    private $definitions = [];
    /** @var array of alias => service */
    private $aliases = [];
    /** @var Autowiring */
    private $autowiring;
    /** @var bool */
    private $needsResolve = \true;
    /** @var bool */
    private $resolving = \false;
    /** @var array */
    private $dependencies = [];
    public function __construct()
    {
        $this->autowiring = new Autowiring($this);
        $this->addImportedDefinition(self::ThisContainer)->setType(Container::class);
    }
    /**
     * Adds new service definition.
     * @return Definitions\ServiceDefinition
     */
    public function addDefinition(?string $name, ?Definition $definition = null) : Definition
    {
        $this->needsResolve = \true;
        if ($name === null) {
            for ($i = 1; isset($this->definitions['0' . $i]) || isset($this->aliases['0' . $i]); $i++) {
            }
            $name = '0' . $i;
            // prevents converting to integer in array key
        } elseif (\is_int(\key([$name => 1])) || !\preg_match('#^\\w+(\\.\\w+)*$#D', $name)) {
            throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Service name must be a alpha-numeric string and not a number, '%s' given.", $name));
        } else {
            $name = $this->aliases[$name] ?? $name;
            if (isset($this->definitions[$name])) {
                throw new \Packetery\Nette\InvalidStateException(\sprintf("Service '%s' has already been added.", $name));
            }
            $lname = \strtolower($name);
            foreach ($this->definitions as $nm => $foo) {
                if ($lname === \strtolower($nm)) {
                    throw new \Packetery\Nette\InvalidStateException(\sprintf("Service '%s' has the same name as '%s' in a case-insensitive manner.", $name, $nm));
                }
            }
        }
        $definition = $definition ?: new Definitions\ServiceDefinition();
        $definition->setName($name);
        $definition->setNotifier(function () : void {
            $this->needsResolve = \true;
        });
        return $this->definitions[$name] = $definition;
    }
    public function addAccessorDefinition(?string $name) : Definitions\AccessorDefinition
    {
        return $this->addDefinition($name, new Definitions\AccessorDefinition());
    }
    public function addFactoryDefinition(?string $name) : Definitions\FactoryDefinition
    {
        return $this->addDefinition($name, new Definitions\FactoryDefinition());
    }
    public function addLocatorDefinition(?string $name) : Definitions\LocatorDefinition
    {
        return $this->addDefinition($name, new Definitions\LocatorDefinition());
    }
    public function addImportedDefinition(?string $name) : Definitions\ImportedDefinition
    {
        return $this->addDefinition($name, new Definitions\ImportedDefinition());
    }
    /**
     * Removes the specified service definition.
     */
    public function removeDefinition(string $name) : void
    {
        $this->needsResolve = \true;
        $name = $this->aliases[$name] ?? $name;
        unset($this->definitions[$name]);
    }
    /**
     * Gets the service definition.
     */
    public function getDefinition(string $name) : Definition
    {
        $service = $this->aliases[$name] ?? $name;
        if (!isset($this->definitions[$service])) {
            throw new MissingServiceException(\sprintf("Service '%s' not found.", $name));
        }
        return $this->definitions[$service];
    }
    /**
     * Gets all service definitions.
     * @return Definition[]
     */
    public function getDefinitions() : array
    {
        return $this->definitions;
    }
    /**
     * Does the service definition or alias exist?
     */
    public function hasDefinition(string $name) : bool
    {
        $name = $this->aliases[$name] ?? $name;
        return isset($this->definitions[$name]);
    }
    public function addAlias(string $alias, string $service) : void
    {
        if (!$alias) {
            // builder is not ready for falsy names such as '0'
            throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Alias name must be a non-empty string, '%s' given.", $alias));
        } elseif (!$service) {
            // builder is not ready for falsy names such as '0'
            throw new \Packetery\Nette\InvalidArgumentException(\sprintf("Service name must be a non-empty string, '%s' given.", $service));
        } elseif (isset($this->aliases[$alias])) {
            throw new \Packetery\Nette\InvalidStateException(\sprintf("Alias '%s' has already been added.", $alias));
        } elseif (isset($this->definitions[$alias])) {
            throw new \Packetery\Nette\InvalidStateException(\sprintf("Service '%s' has already been added.", $alias));
        }
        $this->aliases[$alias] = $service;
    }
    /**
     * Removes the specified alias.
     */
    public function removeAlias(string $alias) : void
    {
        unset($this->aliases[$alias]);
    }
    /**
     * Gets all service aliases.
     */
    public function getAliases() : array
    {
        return $this->aliases;
    }
    /**
     * @param  string[]  $types
     * @return static
     */
    public function addExcludedClasses(array $types)
    {
        $this->needsResolve = \true;
        $this->autowiring->addExcludedClasses($types);
        return $this;
    }
    /**
     * Resolves autowired service name by type.
     * @param  bool  $throw exception if service doesn't exist?
     * @return ($throw is true ? string : ?string)
     * @throws MissingServiceException
     */
    public function getByType(string $type, bool $throw = \false) : ?string
    {
        $this->needResolved();
        return $this->autowiring->getByType($type, $throw);
    }
    /**
     * Gets autowired service definition of the specified type.
     * @throws MissingServiceException
     */
    public function getDefinitionByType(string $type) : Definition
    {
        return $this->getDefinition($this->getByType($type, \true));
    }
    /**
     * Gets the autowired service names and definitions of the specified type.
     * @return Definition[]  service name is key
     * @internal
     */
    public function findAutowired(string $type) : array
    {
        $this->needResolved();
        return $this->autowiring->findByType($type);
    }
    /**
     * Gets the service names and definitions of the specified type.
     * @return Definition[]  service name is key
     */
    public function findByType(string $type) : array
    {
        $this->needResolved();
        $found = [];
        foreach ($this->definitions as $name => $def) {
            if (\is_a($def->getType(), $type, \true)) {
                $found[$name] = $def;
            }
        }
        return $found;
    }
    /**
     * Gets the service names and tag values.
     * @return array of [service name => tag attributes]
     */
    public function findByTag(string $tag) : array
    {
        $found = [];
        foreach ($this->definitions as $name => $def) {
            if (($tmp = $def->getTag($tag)) !== null) {
                $found[$name] = $tmp;
            }
        }
        return $found;
    }
    /********************* building ****************d*g**/
    /**
     * Checks services, resolves types and rebuilts autowiring classlist.
     */
    public function resolve() : void
    {
        if ($this->resolving) {
            return;
        }
        $this->resolving = \true;
        $resolver = new Resolver($this);
        foreach ($this->definitions as $def) {
            $resolver->resolveDefinition($def);
        }
        $this->autowiring->rebuild();
        $this->resolving = $this->needsResolve = \false;
    }
    private function needResolved() : void
    {
        if ($this->resolving) {
            throw new NotAllowedDuringResolvingException();
        } elseif ($this->needsResolve) {
            $this->resolve();
        }
    }
    public function complete() : void
    {
        $this->resolve();
        foreach ($this->definitions as $def) {
            $def->setNotifier(null);
        }
        $resolver = new Resolver($this);
        foreach ($this->definitions as $def) {
            $resolver->completeDefinition($def);
        }
    }
    /**
     * Adds item to the list of dependencies.
     * @param  \ReflectionClass|\ReflectionFunctionAbstract|string  $dep
     * @return static
     * @internal
     */
    public function addDependency($dep)
    {
        $this->dependencies[] = $dep;
        return $this;
    }
    /**
     * Returns the list of dependencies.
     */
    public function getDependencies() : array
    {
        return $this->dependencies;
    }
    /** @internal */
    public function exportMeta() : array
    {
        $defs = $this->definitions;
        \ksort($defs);
        foreach ($defs as $name => $def) {
            if ($def instanceof Definitions\ImportedDefinition) {
                $meta['types'][$name] = $def->getType();
            }
            foreach ($def->getTags() as $tag => $value) {
                $meta['tags'][$tag][$name] = $value;
            }
        }
        $meta['aliases'] = $this->aliases;
        \ksort($meta['aliases']);
        $all = [];
        foreach ($this->definitions as $name => $def) {
            if ($type = $def->getType()) {
                foreach (\class_parents($type) + \class_implements($type) + [$type] as $class) {
                    $all[$class][] = $name;
                }
            }
        }
        [$low, $high] = $this->autowiring->getClassList();
        foreach ($all as $class => $names) {
            $meta['wiring'][$class] = \array_filter([$high[$class] ?? [], $low[$class] ?? [], \array_diff($names, $low[$class] ?? [], $high[$class] ?? [])]);
        }
        return $meta;
    }
    public static function literal(string $code, ?array $args = null) : \Packetery\Nette\PhpGenerator\PhpLiteral
    {
        return new \Packetery\Nette\PhpGenerator\PhpLiteral($args === null ? $code : (new \Packetery\Nette\PhpGenerator\Dumper())->format($code, ...$args));
    }
    /** @deprecated */
    public function formatPhp(string $statement, array $args) : string
    {
        \array_walk_recursive($args, function (&$val) : void {
            if ($val instanceof \Packetery\Nette\DI\Definitions\Statement) {
                $val = (new Resolver($this))->completeStatement($val);
            } elseif ($val instanceof Definition) {
                $val = new Definitions\Reference($val->getName());
            }
        });
        return (new PhpGenerator($this))->formatPhp($statement, $args);
    }
}

```
