Lines 96.07% 49 / 51
Methods 93.54% 29 / 31
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 keyedByEntityId 100.00% 1 / 1 100.00% 1 / 1 1
 find 100.00% 1 / 1 100.00% 1 / 1 1
 withState 100.00% 1 / 1 100.00% 1 / 1 1
 withoutState 100.00% 1 / 1 100.00% 1 / 1 1
 listEntityIds 100.00% 1 / 1 100.00% 1 / 1 1
 filterBySelector 100.00% 5 / 5 100.00% 1 / 1 3
 filterByEntityFilter 100.00% 1 / 1 100.00% 1 / 1 1
 sortedByEntityId 0.00% 0 / 1 0.00% 0 / 1 2
 groupByDomain 100.00% 4 / 4 100.00% 1 / 1 2
 listDomains 100.00% 3 / 3 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\KeyedCollection] keyedBy 100.00% 4 / 4 100.00% 1 / 1 2
 [Stewart\Contracts\Collection\KeyedCollection] fromElementsByKey 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\KeyedCollection] withElementAt 100.00% 3 / 3 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\KeyedCollection] withoutKey 100.00% 3 / 3 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\KeyedCollection] elementAt 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\KeyedCollection] hasKey 0.00% 0 / 1 0.00% 0 / 1 2
 [Stewart\Contracts\Collection\KeyedCollection] arrangeElements 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] __construct 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] empty 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] count 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] isEmpty 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] getFirst 100.00% 2 / 2 100.00% 1 / 1 2
 [Stewart\Contracts\Collection\TypedCollection] getLast 100.00% 2 / 2 100.00% 1 / 1 2
 [Stewart\Contracts\Collection\TypedCollection] listValues 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] filter 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] mapToList 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] containsWhere 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] findFirstWhere 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] sortedBy 100.00% 3 / 3 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] getIterator 100.00% 1 / 1 100.00% 1 / 1 1
 [Stewart\Contracts\Collection\TypedCollection] elements 100.00% 1 / 1 100.00% 1 / 1 1
16final readonly class EntityStateCollection extends KeyedCollection
17{
18    /** @param iterable<EntityState> $states */
19    public static function keyedByEntityId(iterable $states): self
20    {
21        return self::keyedBy($states, static fn(EntityState $state): string => $state->entityId->value);
22    }
23
24    public function find(EntityId $entityId): ?EntityState
25    {
26        return $this->elementAt($entityId->value);
27    }
28
29    public function withState(EntityState $state): self
30    {
31        return $this->withElementAt($state->entityId->value, $state);
32    }
33
34    public function withoutState(EntityId $entityId): self
35    {
36        return $this->withoutKey($entityId->value);
37    }
38
39    public function listEntityIds(): EntityIdCollection
40    {
41        return EntityIdCollection::fromList($this->mapToList(static fn(EntityState $state): EntityId => $state->entityId));
42    }
43
44    public function filterBySelector(Selector $selector): self
45    {
46        $exactPattern = $selector->findExactPattern();
47
48        if ($exactPattern !== null) {
49            $state = $this->elementAt($exactPattern);
50
51            return $state === null ? self::empty() : new self([$exactPattern => $state]);
52        }
53
54        return $this->filter(static fn(EntityState $state): bool => $selector->matches($state->entityId->value));
55    }
56
57    public function filterByEntityFilter(EntityFilter $filter, Registry $registry): self
58    {
59        return $this->filter(static fn(EntityState $state): bool => $filter->matchesEntity($state->entityId, $registry));
60    }
61
62    public function sortedByEntityId(): self
63    {
64        return $this->sortedBy(static fn(EntityState $a, EntityState $b): int => strcmp($a->entityId->value, $b->entityId->value));
65    }
66
67    /** @return array<string, self> */
68    public function groupByDomain(): array
69    {
70        $grouped = [];
71
72        foreach ($this as $key => $state) {
73            $grouped[$state->getDomain()][$key] = $state;
74        }
75
76        return array_map(static fn(array $states): self => new self($states), $grouped);
77    }
78
79    /** @return list<string> */
80    public function listDomains(): array
81    {
82        $domains = array_values(array_unique($this->mapToList(static fn(EntityState $state): string => $state->getDomain())));
83        sort($domains);
84
85        return $domains;
86    }
87}

Inherited from Stewart\Contracts\Collection\KeyedCollection

20    protected static function keyedBy(iterable $elements, Closure $keyOf): static
21    {
22        $keyed = [];
23
24        foreach ($elements as $element) {
25            $keyed[$keyOf($element)] = $element;
26        }
27
28        return new static($keyed);
29    }
32    protected static function fromElementsByKey(array $elementsByKey): static
33    {
34        return new static($elementsByKey);
35    }
41    protected function withElementAt(int|string $key, mixed $element): static
42    {
43        $elements = $this->elements();
44        $elements[$key] = $element;
45
46        return new static($elements);
47    }
50    protected function withoutKey(int|string $key): static
51    {
52        $elements = $this->elements();
53        unset($elements[$key]);
54
55        return new static($elements);
56    }
62    protected function elementAt(int|string $key): mixed
63    {
64        return $this->elements()[$key] ?? null;
65    }
68    protected function hasKey(int|string $key): bool
69    {
70        return \array_key_exists($key, $this->elements());
71    }
77    protected function arrangeElements(array $elements): array
78    {
79        return $elements;
80    }

Inherited from Stewart\Contracts\Collection\TypedCollection

21    final protected function __construct(private array $elements = []) {}
23    public static function empty(): static
24    {
25        return new static();
26    }
28    public function count(): int
29    {
30        return \count($this->elements);
31    }
33    public function isEmpty(): bool
34    {
35        return $this->elements === [];
36    }
39    public function getFirst(): mixed
40    {
41        $key = array_key_first($this->elements);
42
43        return $key === null ? null : $this->elements[$key];
44    }
47    public function getLast(): mixed
48    {
49        $key = array_key_last($this->elements);
50
51        return $key === null ? null : $this->elements[$key];
52    }
55    public function listValues(): array
56    {
57        return array_values($this->elements);
58    }
61    public function filter(Closure $predicate): static
62    {
63        return new static($this->arrangeElements(array_filter($this->elements, $predicate)));
64    }
71    public function mapToList(Closure $transform): array
72    {
73        return array_values(array_map($transform, $this->elements));
74    }
77    public function containsWhere(Closure $predicate): bool
78    {
79        return array_any($this->elements, $predicate);
80    }
86    public function findFirstWhere(Closure $predicate): mixed
87    {
88        return array_find($this->elements, $predicate);
89    }
92    public function sortedBy(Closure $comparator): static
93    {
94        $sorted = $this->elements;
95        uasort($sorted, $comparator);
96
97        return new static($this->arrangeElements($sorted));
98    }
101    public function getIterator(): Traversable
102    {
103        return new ArrayIterator($this->elements);
104    }
113    protected function elements(): array
114    {
115        return $this->elements;
116    }