Passed
Push — donut_body_cache ( 410a05...9f5c24 )
by Akihito
11:44 queued 09:35
created

DonutRepository::refreshDonut()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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