-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathDonutCommandInterceptor.php
More file actions
77 lines (66 loc) · 2.21 KB
/
DonutCommandInterceptor.php
File metadata and controls
77 lines (66 loc) · 2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
// phpcs:ignoreFile SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing -- for call_user_func_array
namespace BEAR\QueryRepository;
use BEAR\QueryRepository\Exception\UnmatchedQuery;
use BEAR\Resource\AbstractUri;
use BEAR\Resource\Code;
use BEAR\Resource\ResourceObject;
use Ray\Aop\MethodInterceptor;
use Ray\Aop\MethodInvocation;
use ReflectionMethod;
use function array_values;
use function assert;
use function call_user_func_array;
use function get_class;
use function is_callable;
use function sprintf;
/**
* Interceptor for donut cache invalidation on CQRS commands
*
* Bound to command methods (onPut/onPatch/onDelete) of classes marked with #[CacheableResponse].
* Refreshes donut cache and resource state after successful write operations.
*
* @see \BEAR\RepositoryModule\Annotation\CacheableResponse
* @see \BEAR\RepositoryModule\Annotation\DonutCache
* @see https://bearsunday.github.io/manuals/1.0/en/cache.html#event-driven-content
*/
final readonly class DonutCommandInterceptor implements MethodInterceptor
{
public function __construct(
private DonutRepositoryInterface $repository,
private MatchQueryInterface $matchQuery
){
}
#[\Override]
public function invoke(MethodInvocation $invocation): ResourceObject
{
$ro = $invocation->proceed();
assert($ro instanceof ResourceObject);
if ($ro->code >= Code::BAD_REQUEST) {
return $ro;
}
$this->refreshDonutAndState($ro);
return $ro;
}
public function refreshDonutAndState(ResourceObject $ro): void
{
$getQuery =($this->matchQuery)($ro);
$delUri = clone $ro->uri;
$delUri->query = $getQuery;
// purge donut, resource state cache and etag
$this->repository->purge($delUri);
// update donut and create resource state
$this->refresh($getQuery, $ro);
}
/**
* @param array<string, mixed> $getQuery
*/
private function refresh(array $getQuery, ResourceObject $ro): void
{
$ro->uri->query = $getQuery;
$get = [$ro, 'onGet'];
if (is_callable($get)) {
call_user_func_array($get, array_values($getQuery));
}
}
}