1
+ <?php
2
+
3
+ namespace Symfony \Component \HttpKernel \HttpCache ;
4
+
5
+ use Psr \Cache \CacheItemPoolInterface ;
6
+ use Symfony \Component \Cache \CacheItem ;
7
+ use Symfony \Component \HttpFoundation \Request ;
8
+ use Symfony \Component \HttpFoundation \Response ;
9
+
10
+ final class Psr6Store implements StoreInterface
11
+ {
12
+ /**
13
+ * @var CacheItemPoolInterface
14
+ */
15
+ private $ cacheBackend ;
16
+
17
+ /**
18
+ * List of locks acquired by the current process.
19
+ *
20
+ * @var array
21
+ */
22
+ private $ locks = array ();
23
+
24
+ /**
25
+ * @param CacheItemPoolInterface $cacheBackend
26
+ */
27
+ public function __construct (CacheItemPoolInterface $ cacheBackend )
28
+ {
29
+ $ this ->cacheBackend = $ cacheBackend ;
30
+ }
31
+
32
+ /**
33
+ * Locates a cached Response for the Request provided.
34
+ *
35
+ * @param Request $request A Request instance
36
+ *
37
+ * @return Response|null A Response instance, or null if no cache entry was found
38
+ */
39
+ public function lookup (Request $ request )
40
+ {
41
+ // TODO: Implement lookup() method.
42
+ }
43
+
44
+ /**
45
+ * Writes a cache entry to the store for the given Request and Response.
46
+ *
47
+ * Existing entries are read and any that match the response are removed. This
48
+ * method calls write with the new list of cache entries.
49
+ *
50
+ * @param Request $request A Request instance
51
+ * @param Response $response A Response instance
52
+ *
53
+ * @return string The key under which the response is stored
54
+ */
55
+ public function write (Request $ request , Response $ response )
56
+ {
57
+ if (!$ response ->headers ->has ('X-Content-Digest ' )) {
58
+ $ contentDigest = $ this ->generateContentDigest ($ response );
59
+ $ item = $ this ->createCacheItem ($ contentDigest , $ response ->getContent ());
60
+ $ this ->cacheBackend ->save ($ item );
61
+ $ response ->headers ->set ('X-Content-Digest ' , $ contentDigest );
62
+
63
+ if (!$ response ->headers ->has ('Transfer-Encoding ' )) {
64
+ $ response ->headers ->set ('Content-Length ' , strlen ($ response ->getContent ()));
65
+ }
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Invalidates all cache entries that match the request.
71
+ *
72
+ * @param Request $request A Request instance
73
+ */
74
+ public function invalidate (Request $ request )
75
+ {
76
+ // TODO: Implement invalidate() method.
77
+ }
78
+
79
+ /**
80
+ * Locks the cache for a given Request.
81
+ *
82
+ * @param Request $request A Request instance
83
+ *
84
+ * @return bool|string true if the lock is acquired, the path to the current lock otherwise
85
+ */
86
+ public function lock (Request $ request )
87
+ {
88
+ $ lockKey = $ this ->getLockKey ($ request );
89
+
90
+ if (isset ($ this ->locks [$ lockKey ])) {
91
+ return true ;
92
+ }
93
+
94
+ $ item = $ this ->cacheBackend ->getItem ($ lockKey );
95
+
96
+ if ($ item ->isHit ()) {
97
+ return false ;
98
+ }
99
+
100
+ $ this ->cacheBackend ->save ($ item );
101
+
102
+ $ this ->locks [$ lockKey ] = true ;
103
+
104
+ return true ;
105
+ }
106
+
107
+ /**
108
+ * Releases the lock for the given Request.
109
+ *
110
+ * @param Request $request A Request instance
111
+ *
112
+ * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
113
+ */
114
+ public function unlock (Request $ request )
115
+ {
116
+ $ lockKey = $ this ->getLockKey ($ request );
117
+
118
+ if (!isset ($ this ->locks [$ lockKey ])) {
119
+ return false ;
120
+ }
121
+
122
+ $ this ->cacheBackend ->deleteItem ($ lockKey );
123
+
124
+ unset($ this ->locks [$ lockKey ]);
125
+
126
+ return true ;
127
+ }
128
+
129
+ /**
130
+ * Returns whether or not a lock exists.
131
+ *
132
+ * @param Request $request A Request instance
133
+ *
134
+ * @return bool true if lock exists, false otherwise
135
+ */
136
+ public function isLocked (Request $ request )
137
+ {
138
+ $ lockKey = $ this ->getLockKey ($ request );
139
+
140
+ if (isset ($ this ->locks [$ lockKey ])) {
141
+ return true ;
142
+ }
143
+
144
+ return $ this ->cacheBackend ->hasItem ($ this ->getLockKey ($ request ));
145
+ }
146
+
147
+ /**
148
+ * Purges data for the given URL.
149
+ *
150
+ * @param string $url A URL
151
+ *
152
+ * @return bool true if the URL exists and has been purged, false otherwise
153
+ */
154
+ public function purge ($ url )
155
+ {
156
+ // TODO: Implement purge() method.
157
+ }
158
+
159
+ /**
160
+ * Cleanups storage.
161
+ */
162
+ public function cleanup ()
163
+ {
164
+ $ this ->cacheBackend ->deleteItems (array_keys ($ this ->locks ));
165
+ $ this ->locks = array ();
166
+ }
167
+
168
+ /**
169
+ * @param Request $request
170
+ *
171
+ * @return string
172
+ */
173
+ private function getCacheKey (Request $ request )
174
+ {
175
+ return 'md ' .hash ('sha256 ' , $ request ->getUri ());
176
+ }
177
+
178
+ /**
179
+ * @param Request $request
180
+ *
181
+ * @return string
182
+ */
183
+ private function getLockKey (Request $ request )
184
+ {
185
+ return $ this ->getCacheKey ($ request ).'.lock ' ;
186
+ }
187
+
188
+ /**
189
+ * @param Response $response
190
+ *
191
+ * @return string
192
+ */
193
+ private function generateContentDigest (Response $ response )
194
+ {
195
+ return 'en ' .hash ('sha256 ' , $ response ->getContent ());
196
+ }
197
+
198
+ /**
199
+ * @param string $key
200
+ * @param mixed $value
201
+ * @param bool $isHit
202
+ *
203
+ * @return CacheItem
204
+ */
205
+ private function createCacheItem ($ key , $ value , $ isHit = false )
206
+ {
207
+ $ f = \Closure::bind (
208
+ function ($ key , $ value , $ isHit ) {
209
+ $ item = new CacheItem ();
210
+ $ item ->key = $ key ;
211
+ $ item ->value = $ value ;
212
+ $ item ->isHit = $ isHit ;
213
+
214
+ return $ item ;
215
+ },
216
+ null ,
217
+ CacheItem::class
218
+ );
219
+
220
+ return $ f ($ key , $ value , $ isHit );
221
+ }
222
+ }
0 commit comments