*/ private Collection $chain; /** * Types this injector is allowed to register. * * Implementations MAY overwrite this value. * * @var list */ private array $allowedTypes = []; /** * Optionally accept the project root directory; if non-empty, it is used * to prefix the $configFile. * * @param array> $injectors * @param Collection $availableTypes */ public function __construct( array $injectors, DiscoveryChainInterface $discoveryChain, Collection $availableTypes, string $projectRoot = '' ) { $this->chain = (new Collection($injectors)) // Keep only those injectors that discovery exists in discoveryChain ->filter( /** @psalm-suppress UnusedClosureParam https://github.com/vimeo/psalm/issues/8095 */ fn(string $injector, string $file) => $discoveryChain->discoveryExists($file) ) // Create an injector for the config file ->map( fn(string $injector): InjectorInterface => new $injector($projectRoot) ) // Keep only those injectors that match types available for the package ->filter(fn(InjectorInterface $injector) => $availableTypes->anySatisfies( fn(int $type) => $injector->registersType($type) )); } /** * {@inheritDoc} */ public function registersType(int $type): bool { return in_array($type, $this->getTypesAllowed(), true); } /** * {@inheritDoc} */ public function getTypesAllowed(): array { if ($this->allowedTypes) { return $this->allowedTypes; } $allowedTypes = []; foreach ($this->chain->getIterator() as $injector) { $allowedTypes[] = $injector->getTypesAllowed(); } $this->allowedTypes = array_values(array_unique(array_merge([], ...$allowedTypes))); return $this->allowedTypes; } /** * {@inheritDoc} */ public function isRegistered(string $package): bool { $isRegisteredCount = $this->chain ->filter(fn(InjectorInterface $injector): bool => $injector->isRegistered($package)) ->count(); return $this->chain->count() === $isRegisteredCount; } /** * {@inheritDoc} */ public function inject(string $package, int $type): bool { $injected = false; $this->chain ->each(function ($injector) use ($package, $type, &$injected) { $injected = $injector->inject($package, $type) || $injected; }); assert(is_bool($injected)); return $injected; } /** * {@inheritDoc} */ public function remove(string $package): bool { $removed = false; $this->chain ->each(function ($injector) use ($package, &$removed) { $removed = $injector->remove($package) || $removed; }); assert(is_bool($removed)); return $removed; } /** * @return Collection */ public function getCollection(): Collection { return $this->chain; } /** * {@inheritDoc} */ public function setApplicationModules(array $modules): self { return $this; } /** * {@inheritDoc} */ public function setModuleDependencies(array $modules): self { return $this; } }