Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
InMemoryActionRequestStore
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
7 / 7
19
100.00% covered (success)
100.00%
1 / 1
 save
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 transition
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 auditTrail
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
11
 pendingChanges
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 accepted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 all
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace LambdaTwelve\OneRecord\Server\InMemory;
6
7use LambdaTwelve\OneRecord\Api\ActionRequest;
8use LambdaTwelve\OneRecord\Api\ActionRequestType;
9use LambdaTwelve\OneRecord\Api\RequestStatus;
10use LambdaTwelve\OneRecord\Rdf\Iri;
11use LambdaTwelve\OneRecord\Server\Spi\ActionRequestStore;
12use LambdaTwelve\OneRecord\Server\Spi\AuditTrailQuery;
13use LambdaTwelve\OneRecord\Server\Spi\StoreException;
14use LambdaTwelve\OneRecord\Server\Spi\Volatile;
15
16final class InMemoryActionRequestStore implements ActionRequestStore, Volatile
17{
18    /** @var array<string, ActionRequest> */
19    private array $requests = [];
20
21    public function save(ActionRequest $request): void
22    {
23        $this->requests[$request->iri->value] = $request;
24    }
25
26    public function transition(ActionRequest $request, RequestStatus $expectedCurrent): void
27    {
28        $current = $this->requests[$request->iri->value] ?? throw StoreException::notFound($request->iri);
29        if ($current->status !== $expectedCurrent) {
30            throw StoreException::statusConflict($request->iri, $expectedCurrent->shortName(), $current->status->shortName());
31        }
32        $this->requests[$request->iri->value] = $request;
33    }
34
35    public function get(Iri $iri): ?ActionRequest
36    {
37        return $this->requests[$iri->value] ?? null;
38    }
39
40    public function auditTrail(Iri $logisticsObject, AuditTrailQuery $query): array
41    {
42        $out = [];
43        foreach ($this->requests as $request) {
44            if (!\in_array($request->type, [ActionRequestType::Change, ActionRequestType::Verification], true)) {
45                continue;
46            }
47            if (array_filter($request->logisticsObjects(), static fn(Iri $i): bool => $i->equals($logisticsObject)) === []) {
48                continue;
49            }
50            $modified = $request->lastModified();
51            if ($query->updatedFrom !== null && $modified < $query->updatedFrom) {
52                continue;
53            }
54            if ($query->updatedTo !== null && $modified > $query->updatedTo) {
55                continue;
56            }
57            if ($query->status !== null && $request->status !== $query->status) {
58                continue;
59            }
60            $out[] = $request;
61        }
62        usort($out, static function (ActionRequest $a, ActionRequest $b): int {
63            $byTime = $a->requestedAt <=> $b->requestedAt;
64
65            return $byTime !== 0 ? $byTime : strcmp($a->iri->value, $b->iri->value);
66        });
67
68        return $out;
69    }
70
71    public function pendingChanges(Iri $logisticsObject): array
72    {
73        return array_values(array_filter(
74            $this->auditTrail($logisticsObject, new AuditTrailQuery(status: RequestStatus::Pending)),
75            static fn(ActionRequest $r): bool => $r->type === ActionRequestType::Change,
76        ));
77    }
78
79    public function accepted(ActionRequestType $type): array
80    {
81        return array_values(array_filter($this->requests, static fn(ActionRequest $r): bool => $r->type === $type && $r->status === RequestStatus::Accepted));
82    }
83
84    /**
85     * @return list<ActionRequest>
86     */
87    public function all(): array
88    {
89        return array_values($this->requests);
90    }
91}