Lines 85.00% 17 / 20
Functions and Methods 72.72% 8 / 11
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
RecordingExposedEntity 85.00% 17 / 20 72.72% 8 / 11 11.41 0.00% 0 / 1
 __construct 100.00% 2 / 2 100.00% 1 / 1 1
 applySnapshot 100.00% 4 / 4 100.00% 1 / 1 1
 getEntityId 100.00% 1 / 1 100.00% 1 / 1 1
 getAttributes 0.00% 0 / 1 0.00% 0 / 1 2
 isAvailable 100.00% 1 / 1 100.00% 1 / 1 1
 setAttributes 0.00% 0 / 1 0.00% 0 / 1 2
 markAvailable 0.00% 0 / 1 0.00% 0 / 1 2
 markUnavailable 100.00% 1 / 1 100.00% 1 / 1 1
 recordChange 100.00% 5 / 5 100.00% 1 / 1 1
 deliverCommand 100.00% 2 / 2 100.00% 1 / 1 1
 findStateValue 100.00% 1 / 1 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Testing\Exposure;
6
7use Stewart\Contracts\Entity\EntityId;
8use Stewart\Contracts\Exception\ExposureException;
9use Stewart\Contracts\Exposure\Collection\ExposedStateChangeCollection;
10use Stewart\Contracts\Exposure\Command\ExposedCommand;
11use Stewart\Contracts\Exposure\ExposedEntity;
12use Stewart\Contracts\Exposure\ExposedEntityConfig;
13use Stewart\Contracts\Exposure\ExposedEntityKey;
14use Stewart\Contracts\Exposure\ExposedEntitySnapshot;
15use Stewart\Contracts\Exposure\ExposedState;
16use Stewart\Contracts\Exposure\ExposedStateChange;
17use Stewart\Testing\Time\ManualTimers;
18
19/**
20 * @phpstan-import-type ExposedAttributes from ExposedEntity
21 *
22 * @template TConfig of ExposedEntityConfig
23 * @extends RecordingExposure<TConfig>
24 */
25abstract class RecordingExposedEntity extends RecordingExposure implements ExposedEntity
26{
27    public private(set) ExposedStateChangeCollection $changes;
28
29    private ?EntityId $entityId = null;
30
31    private ?ExposedState $state = null;
32
33    /** @var ExposedAttributes */
34    private array $attributes = [];
35
36    private bool $available = true;
37
38    /** @param TConfig $config */
39    public function __construct(ExposedEntityKey $key, ExposedEntityConfig $config, ManualTimers $timers)
40    {
41        parent::__construct($key, $config, $timers);
42        $this->changes = ExposedStateChangeCollection::empty();
43    }
44
45    public function applySnapshot(ExposedEntitySnapshot $snapshot): void
46    {
47        $this->entityId = $snapshot->entityId;
48        $this->state = $snapshot->state;
49        $this->attributes = $snapshot->attributes;
50        $this->available = $snapshot->available;
51    }
52
53    public function getEntityId(): ?EntityId
54    {
55        return $this->entityId;
56    }
57
58    public function getAttributes(): array
59    {
60        return $this->attributes;
61    }
62
63    public function isAvailable(): bool
64    {
65        return $this->available;
66    }
67
68    public function setAttributes(array $attributes): void
69    {
70        $this->recordChange(new ExposedStateChange(attributes: $attributes));
71    }
72
73    public function markAvailable(): void
74    {
75        $this->recordChange(new ExposedStateChange(available: true));
76    }
77
78    public function markUnavailable(): void
79    {
80        $this->recordChange(new ExposedStateChange(available: false));
81    }
82
83    /** @throws ExposureException */
84    protected function recordChange(ExposedStateChange $change): void
85    {
86        $this->assertNotRemoved();
87        $this->changes = $this->changes->withChange($change);
88        $this->state = $change->state ?? $this->state;
89        $this->attributes = $change->attributes ?? $this->attributes;
90        $this->available = $change->available ?? $this->available;
91    }
92
93    protected function deliverCommand(ExposedCommand $command): void
94    {
95        parent::deliverCommand($command);
96        $this->state = $command->getRequestedState() ?? $this->state;
97    }
98
99    protected function findStateValue(): int|float|string|bool|null
100    {
101        return $this->state?->value;
102    }
103}