-
-
Notifications
You must be signed in to change notification settings - Fork 551
/
Copy pathApplicationCacher.php
130 lines (108 loc) · 3.6 KB
/
ApplicationCacher.php
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?php
namespace Statamic\StaticCaching\Cachers;
use Illuminate\Http\Request;
use Illuminate\Routing\Events\ResponsePrepared;
use Illuminate\Support\Facades\Event;
use Statamic\Events\UrlInvalidated;
use Statamic\StaticCaching\Page;
class ApplicationCacher extends AbstractCacher
{
/**
* @var \Illuminate\Contracts\Cache\Repository
*/
protected $cache;
/**
* @var string|null
*/
private $cached;
/**
* Cache a page.
*
* @param \Illuminate\Http\Request $request Request associated with the page to be cached
* @param string $content The response content to be cached
*/
public function cachePage(Request $request, $content)
{
$url = $this->getUrl($request);
if ($this->isExcluded($url)) {
return;
}
// Get a hashed version of the URL for the key since slashes
// and other URL characters wouldn't work as a cache key.
$key = $this->makeHash($url);
// Keep track of the URL and key the response content is about to be stored within.
$this->cacheUrl($key, ...$this->getPathAndDomain($url));
$key = $this->normalizeKey('responses:'.$key);
$value = $this->normalizeContent($content);
Event::listen(ResponsePrepared::class, function (ResponsePrepared $event) use ($key, $value) {
$headers = collect($event->response->headers->all())
->reject(fn ($value, $key) => in_array($key, ['date', 'x-powered-by', 'cache-control', 'expires', 'set-cookie']))
->all();
$cacheValue = [
'content' => $value,
'headers' => $headers,
'status' => $event->response->getStatusCode(),
];
$this->getDefaultExpiration()
? $this->cache->put($key, $cacheValue, now()->addMinutes($this->getDefaultExpiration()))
: $this->cache->forever($key, $cacheValue);
});
}
/**
* Check if a page has been cached.
*
* @return bool
*/
public function hasCachedPage(Request $request)
{
return (bool) $this->cached = $this->getFromCache($request);
}
/**
* Get a cached page.
*
* @return Page
*/
public function getCachedPage(Request $request)
{
$cachedPage = $this->cached ?? $this->getFromCache($request);
return new Page($cachedPage['content'], $cachedPage['headers'], $cachedPage['status'] ?? 200);
}
private function getFromCache(Request $request)
{
$url = $this->getUrl($request);
$key = $this->makeHash($url);
return $this->cache->get($this->normalizeKey('responses:'.$key));
}
/**
* Flush out the entire static cache.
*
* @return void
*/
public function flush()
{
$this->getDomains()->each(function ($domain) {
$this->getUrls($domain)->keys()->each(function ($key) {
$this->cache->forget($this->normalizeKey('responses:'.$key));
});
});
$this->flushUrls();
}
/**
* Invalidate a URL.
*
* @param string $url
* @param string|null $domain
* @return void
*/
public function invalidateUrl($url, $domain = null)
{
$this
->getUrls($domain)
->filter(fn ($value) => $value === $url || str_starts_with($value, $url.'?'))
->each(function ($value, $key) {
$this->cache->forget($this->normalizeKey('responses:'.$key));
$this->forgetUrl($key);
});
UrlInvalidated::dispatch($url, $domain);
}
}