DonutRepository::putStatic()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 3
dl 0
loc 16
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\QueryRepository;
6
7
use BEAR\Resource\AbstractUri;
8
use BEAR\Resource\ResourceInterface;
9
use BEAR\Resource\ResourceObject;
10
11
use function assert;
12
use function explode;
13
14
final class DonutRepository implements DonutRepositoryInterface
15
{
16
    public function __construct(
17
        private readonly QueryRepositoryInterface $queryRepository,
18
        private readonly HeaderSetter $headerSetter,
19
        private readonly ResourceStorageInterface $resourceStorage,
20
        private readonly ResourceInterface $resource,
21
        private readonly CdnCacheControlHeaderSetterInterface $cdnCacheControlHeaderSetter,
22
        private readonly RepositoryLoggerInterface $logger,
23
        private readonly DonutRendererInterface $renderer,
24
    ) {
25
    }
26
27
    public function get(ResourceObject $ro): ResourceObject|null
28
    {
29
        $maybeState = $this->queryRepository->get($ro->uri);
30
        $this->logger->log('try-donut-view: uri:%s', $ro->uri);
31
        if ($maybeState instanceof ResourceState) {
32
            $this->logger->log('found-donut-view: uri:%s', $ro->uri);
33
            $ro->headers = $maybeState->headers;
34
            $ro->view = $maybeState->view;
35
36
            return $ro;
37
        }
38
39
        return $this->refreshDonut($ro);
40
    }
41
42
    /**
43
     * {@inheritDoc}
44
     */
45
    public function putStatic(ResourceObject $ro, int|null $ttl = null, int|null $sMaxAge = null): ResourceObject
46
    {
47
        $this->logger->log('put-donut: uri:%s ttl:%s s-maxage:%d', (string) $ro->uri, $sMaxAge, $ttl);
48
        $keys = new SurrogateKeys($ro->uri);
49
        $keys->addTag($ro);
50
        $headerKeys = $this->getHeaderKeys($ro);
51
        $donut = ResourceDonut::create($ro, $this->renderer, $keys, $sMaxAge, true);
52
        $donut->render($ro, $this->renderer);
53
        $this->setHeaders($keys, $ro, $sMaxAge);
54
        // delete
55
        $this->resourceStorage->invalidateTags([(new UriTag())($ro->uri)]);
56
        // save content cache and donut
57
        $this->saveView($ro, $sMaxAge);
58
        $this->resourceStorage->saveDonut($ro->uri, $donut, $ttl, $headerKeys);
59
60
        return $ro;
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    public function putDonut(ResourceObject $ro, int|null $donutTtl): ResourceObject
67
    {
68
        $this->logger->log('put-donut: uri:%s ttl:%s', (string) $ro->uri, $donutTtl);
69
        $keys = new SurrogateKeys($ro->uri);
70
        $keyArrays = $this->getHeaderKeys($ro);
71
        $donut = ResourceDonut::create($ro, $this->renderer, $keys, $donutTtl, false);
72
        $donut->render($ro, $this->renderer);
73
        $keys->setSurrogateHeader($ro);
74
        // delete
75
        $this->resourceStorage->invalidateTags([(new UriTag())($ro->uri)]);
76
        // save donut
77
        $this->resourceStorage->saveDonut($ro->uri, $donut, $donutTtl, $keyArrays);
78
79
        return $ro;
80
    }
81
82
    /**
83
     * {@inheritDoc}
84
     */
85
    public function purge(AbstractUri $uri): void
86
    {
87
        $this->queryRepository->purge($uri);
88
    }
89
90
    /**
91
     * {@inheritDoc}
92
     */
93
    public function invalidateTags(array $tags): void
94
    {
95
        $this->resourceStorage->invalidateTags($tags);
96
    }
97
98
    private function refreshDonut(ResourceObject $ro): ResourceObject|null
99
    {
100
        $donut = $this->resourceStorage->getDonut($ro->uri);
101
        $this->logger->log('try-donut uri:%s', (string) $ro->uri);
102
        if (! $donut instanceof ResourceDonut) {
103
            $this->logger->log('no-donut-found uri:%s', (string) $ro->uri);
104
105
            return null;
106
        }
107
108
        $this->logger->log('refresh-donut: uri:%s', $ro->uri);
109
        $donut->refresh($this->resource, $ro);
110
        if (! $donut->isCacheble) {
111
            return $ro;
112
        }
113
114
        ($this->headerSetter)($ro, $donut->ttl, null);
115
        $ro->headers[Header::ETAG] .= 'r'; // mark refreshed by resource static
116
        ($this->cdnCacheControlHeaderSetter)($ro, $donut->ttl);
117
        $this->saveView($ro, $donut->ttl);
118
119
        return $ro;
120
    }
121
122
    private function saveView(ResourceObject $ro, int|null $ttl): bool
123
    {
124
        assert(isset($ro->headers[Header::ETAG]));
125
        $surrogateKeys = $ro->headers[Header::SURROGATE_KEY] ?? '';
126
        $this->resourceStorage->saveEtag($ro->uri, $ro->headers[Header::ETAG], $surrogateKeys, $ttl);
127
128
        return $this->resourceStorage->saveDonutView($ro, $ttl);
129
    }
130
131
    private function setHeaders(SurrogateKeys $keys, ResourceObject $ro, int|null $sMaxAge): void
132
    {
133
        $keys->setSurrogateHeader($ro);
134
        ($this->cdnCacheControlHeaderSetter)($ro, $sMaxAge);
135
        ($this->headerSetter)($ro, 0, null);
136
    }
137
138
    /** @return list<string> */
0 ignored issues
show
Bug introduced by
The type BEAR\QueryRepository\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
139
    public function getHeaderKeys(ResourceObject $ro): array
140
    {
141
        return isset($ro->headers[Header::SURROGATE_KEY]) ? explode(' ', $ro->headers[Header::SURROGATE_KEY]) : [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return IssetNode ? explo...RROGATE_KEY]) : array() returns the type array|string[] which is incompatible with the documented return type BEAR\QueryRepository\list.
Loading history...
142
    }
143
}
144