3947259b51d5a09ef57a7157599bc3c6d50f3e9c
[m6w6/seekat] / lib / API / Call / Cache.php
1 <?php
2
3 namespace seekat\API\Call;
4
5 use http\Client\Request;
6 use http\Client\Response;
7 use seekat\API\Call\Cache\Control;
8 use seekat\API\Call\Cache\Service;
9 use seekat\API\Call\Cache\Service\Hollow;
10
11
12 final class Cache {
13 /**
14 * @var Service
15 */
16 private $cache;
17
18 /**
19 * @param Service $cache
20 */
21 public function __construct(Service $cache = null) {
22 $this->cache = $cache ?? new Hollow;
23 }
24
25 /**
26 * Save call data
27 * @param Request $request
28 * @param Response $response
29 * @return bool
30 */
31 public function save(Request $request, Response $response) : bool {
32 $ctl = new Control($request);
33 if (!$ctl->isValid()) {
34 return false;
35 }
36
37 $time = time();
38 if ($time - 1 <= $response->getHeader("X-Cache-Time")) {
39 return true;
40 }
41 $response->setHeader("X-Cache-Time", $time);
42
43 return $this->cache->store($ctl->getKey(), $response);
44 }
45
46 /**
47 * Attempt to load call data
48 * @param Request $request
49 * @param Response $response out param
50 * @return bool
51 */
52 public function load(Request $request, Response &$response = null) : bool {
53 $ctl = new Control($request);
54 if (!$ctl->isValid()) {
55 return false;
56 }
57
58 if (!$this->cache->fetch($ctl->getKey(), $response)) {
59 return false;
60 }
61 if ($ctl->isStale($response)) {
62 if (($lmod = $response->getHeader("Last-Modified"))) {
63 $request->setOptions(["lastmodified" => strtotime($lmod)]);
64 }
65 if (($etag = $response->getHeader("ETag"))) {
66 $request->setOptions(["etag" => $etag]);
67 }
68 return false;
69 }
70 $response->setHeader("X-Cache-Hit", $response->getHeader("X-Cache-Hit") + 1);
71 return true;
72 }
73
74 /**
75 * Update call data
76 * @param Request $request
77 * @param Response $response
78 * @return bool
79 */
80 public function update(Request $request, Response &$response) : bool {
81 $ctl = new Control($request);
82 if (!$ctl->isValid()) {
83 return false;
84 }
85
86 if ($response->getResponseCode() !== 304) {
87 return $this->save($request, $response);
88 }
89
90 /** @var Response $cached */
91 if (!$this->cache->fetch($ctl->getKey(), $cached)) {
92 return $this->save($request, $response);
93 }
94
95 if ($response->getHeader("ETag") !== $cached->getHeader("ETag")) {
96 return $this->save($request, $response);
97 }
98
99 $cached->setHeader("X-Cache-Update", $cached->getHeader("X-Cache-Update") + 1);
100 $response = $cached;
101 return true;
102 }
103 }