* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXF\Resource\Identifier; /** * Typed collection of resource identifiers * * Accepts an array of identifier strings (e.g. ["imap:account1:inbox:1001", "imap:account1:sent"]) * and provides filtering/search helpers. */ class ResourceIdentifiers implements ResourceIdentifiersInterface { /** @var ResourceIdentifierInterface[] */ private array $identifiers = []; /** Create a collection from an array of identifier strings */ public static function fromArray(array $strings): static { $collection = new static(); foreach ($strings as $string) { if (!is_string($string)) { throw new \InvalidArgumentException('Each identifier must be a string'); } $collection->add(ResourceIdentifier::fromString($string)); } return $collection; } public function add(ResourceIdentifierInterface $identifier): void { $this->identifiers[] = $identifier; } /** @return ResourceIdentifierInterface[] */ public function all(): array { return $this->identifiers; } public function count(): int { return count($this->identifiers); } public function getIterator(): \ArrayIterator { return new \ArrayIterator($this->identifiers); } /** Filter identifiers by depth level (1–4) */ public function byDepth(int $depth): static { $filtered = new static(); foreach ($this->identifiers as $id) { if ($id->depth() === $depth) { $filtered->add($id); } } return $filtered; } /** Filter identifiers by provider */ public function byProvider(string $provider): static { $filtered = new static(); foreach ($this->identifiers as $id) { if ($id->provider() === $provider) { $filtered->add($id); } } return $filtered; } /** Filter identifiers by service (only identifiers with depth >= 2) */ public function byService(string $service): static { $filtered = new static(); foreach ($this->identifiers as $id) { if ($id instanceof ServiceIdentifierInterface && $id->service() === $service) { $filtered->add($id); } } return $filtered; } /** Filter identifiers by collection (only identifiers with depth >= 3) */ public function byCollection(string $collection): static { $filtered = new static(); foreach ($this->identifiers as $id) { if ($id instanceof CollectionIdentifierInterface && $id->collection() === $collection) { $filtered->add($id); } } return $filtered; } /** Filter identifiers by entity (only identifiers with depth == 4) */ public function byEntity(string $entity): static { $filtered = new static(); foreach ($this->identifiers as $id) { if ($id instanceof EntityIdentifierInterface && $id->entity() === $entity) { $filtered->add($id); } } return $filtered; } /** Get unique provider names */ public function providers(): array { $values = []; foreach ($this->identifiers as $id) { $values[$id->provider()] = true; } return array_keys($values); } /** Get unique service names */ public function services(): array { $values = []; foreach ($this->identifiers as $id) { if ($id instanceof ServiceIdentifierInterface) { $values[$id->service()] = true; } } return array_keys($values); } /** Get unique collection names */ public function collections(): array { $values = []; foreach ($this->identifiers as $id) { if ($id instanceof CollectionIdentifierInterface) { $values[$id->collection()] = true; } } return array_keys($values); } /** Get unique entity names */ public function entities(): array { $values = []; foreach ($this->identifiers as $id) { if ($id instanceof EntityIdentifierInterface) { $values[$id->entity()] = true; } } return array_keys($values); } /** Check if the collection is empty */ public function isEmpty(): bool { return count($this->identifiers) === 0; } }