Mercurial > hg > isophonics-drupal-site
comparison core/modules/user/src/SharedTempStore.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\user; | |
4 | |
5 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface; | |
6 use Drupal\Core\Lock\LockBackendInterface; | |
7 use Symfony\Component\HttpFoundation\RequestStack; | |
8 | |
9 /** | |
10 * Stores and retrieves temporary data for a given owner. | |
11 * | |
12 * A SharedTempStore can be used to make temporary, non-cache data available | |
13 * across requests. The data for the SharedTempStore is stored in one key/value | |
14 * collection. SharedTempStore data expires automatically after a given | |
15 * timeframe. | |
16 * | |
17 * The SharedTempStore is different from a cache, because the data in it is not | |
18 * yet saved permanently and so it cannot be rebuilt. Typically, the | |
19 * SharedTempStore might be used to store work in progress that is later saved | |
20 * permanently elsewhere, e.g. autosave data, multistep forms, or in-progress | |
21 * changes to complex configuration that are not ready to be saved. | |
22 * | |
23 * Each SharedTempStore belongs to a particular owner (e.g. a user, session, or | |
24 * process). Multiple owners may use the same key/value collection, and the | |
25 * owner is stored along with the key/value pair. | |
26 * | |
27 * Every key is unique within the collection, so the SharedTempStore can check | |
28 * whether a particular key is already set by a different owner. This is | |
29 * useful for informing one owner that the data is already in use by another; | |
30 * for example, to let one user know that another user is in the process of | |
31 * editing certain data, or even to restrict other users from editing it at | |
32 * the same time. It is the responsibility of the implementation to decide | |
33 * when and whether one owner can use or update another owner's data. | |
34 * | |
35 * If you want to be able to ensure that the data belongs to the current user, | |
36 * use \Drupal\user\PrivateTempStore. | |
37 */ | |
38 class SharedTempStore { | |
39 | |
40 /** | |
41 * The key/value storage object used for this data. | |
42 * | |
43 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface | |
44 */ | |
45 protected $storage; | |
46 | |
47 /** | |
48 * The lock object used for this data. | |
49 * | |
50 * @var \Drupal\Core\Lock\LockBackendInterface | |
51 */ | |
52 protected $lockBackend; | |
53 | |
54 /** | |
55 * The request stack. | |
56 * | |
57 * @var \Symfony\Component\HttpFoundation\RequestStack | |
58 */ | |
59 protected $requestStack; | |
60 | |
61 /** | |
62 * The owner key to store along with the data (e.g. a user or session ID). | |
63 * | |
64 * @var mixed | |
65 */ | |
66 protected $owner; | |
67 | |
68 /** | |
69 * The time to live for items in seconds. | |
70 * | |
71 * By default, data is stored for one week (604800 seconds) before expiring. | |
72 * | |
73 * @var int | |
74 */ | |
75 protected $expire; | |
76 | |
77 /** | |
78 * Constructs a new object for accessing data from a key/value store. | |
79 * | |
80 * @param KeyValueStoreExpirableInterface $storage | |
81 * The key/value storage object used for this data. Each storage object | |
82 * represents a particular collection of data and will contain any number | |
83 * of key/value pairs. | |
84 * @param \Drupal\Core\Lock\LockBackendInterface $lock_backend | |
85 * The lock object used for this data. | |
86 * @param mixed $owner | |
87 * The owner key to store along with the data (e.g. a user or session ID). | |
88 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack | |
89 * The request stack. | |
90 * @param int $expire | |
91 * The time to live for items, in seconds. | |
92 */ | |
93 public function __construct(KeyValueStoreExpirableInterface $storage, LockBackendInterface $lock_backend, $owner, RequestStack $request_stack, $expire = 604800) { | |
94 $this->storage = $storage; | |
95 $this->lockBackend = $lock_backend; | |
96 $this->owner = $owner; | |
97 $this->requestStack = $request_stack; | |
98 $this->expire = $expire; | |
99 } | |
100 | |
101 /** | |
102 * Retrieves a value from this SharedTempStore for a given key. | |
103 * | |
104 * @param string $key | |
105 * The key of the data to retrieve. | |
106 * | |
107 * @return mixed | |
108 * The data associated with the key, or NULL if the key does not exist. | |
109 */ | |
110 public function get($key) { | |
111 if ($object = $this->storage->get($key)) { | |
112 return $object->data; | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * Retrieves a value from this SharedTempStore for a given key. | |
118 * | |
119 * Only returns the value if the value is owned by $this->owner. | |
120 * | |
121 * @param string $key | |
122 * The key of the data to retrieve. | |
123 * | |
124 * @return mixed | |
125 * The data associated with the key, or NULL if the key does not exist. | |
126 */ | |
127 public function getIfOwner($key) { | |
128 if (($object = $this->storage->get($key)) && ($object->owner == $this->owner)) { | |
129 return $object->data; | |
130 } | |
131 } | |
132 | |
133 /** | |
134 * Stores a particular key/value pair only if the key doesn't already exist. | |
135 * | |
136 * @param string $key | |
137 * The key of the data to check and store. | |
138 * @param mixed $value | |
139 * The data to store. | |
140 * | |
141 * @return bool | |
142 * TRUE if the data was set, or FALSE if it already existed. | |
143 */ | |
144 public function setIfNotExists($key, $value) { | |
145 $value = (object) [ | |
146 'owner' => $this->owner, | |
147 'data' => $value, | |
148 'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'), | |
149 ]; | |
150 return $this->storage->setWithExpireIfNotExists($key, $value, $this->expire); | |
151 } | |
152 | |
153 /** | |
154 * Stores a particular key/value pair in this SharedTempStore. | |
155 * | |
156 * Only stores the given key/value pair if it does not exist yet or is owned | |
157 * by $this->owner. | |
158 * | |
159 * @param string $key | |
160 * The key of the data to store. | |
161 * @param mixed $value | |
162 * The data to store. | |
163 * | |
164 * @return bool | |
165 * TRUE if the data was set, or FALSE if it already exists and is not owned | |
166 * by $this->user. | |
167 * | |
168 * @throws \Drupal\user\TempStoreException | |
169 * Thrown when a lock for the backend storage could not be acquired. | |
170 */ | |
171 public function setIfOwner($key, $value) { | |
172 if ($this->setIfNotExists($key, $value)) { | |
173 return TRUE; | |
174 } | |
175 | |
176 if (($object = $this->storage->get($key)) && ($object->owner == $this->owner)) { | |
177 $this->set($key, $value); | |
178 return TRUE; | |
179 } | |
180 | |
181 return FALSE; | |
182 } | |
183 | |
184 /** | |
185 * Stores a particular key/value pair in this SharedTempStore. | |
186 * | |
187 * @param string $key | |
188 * The key of the data to store. | |
189 * @param mixed $value | |
190 * The data to store. | |
191 * | |
192 * @throws \Drupal\user\TempStoreException | |
193 * Thrown when a lock for the backend storage could not be acquired. | |
194 */ | |
195 public function set($key, $value) { | |
196 if (!$this->lockBackend->acquire($key)) { | |
197 $this->lockBackend->wait($key); | |
198 if (!$this->lockBackend->acquire($key)) { | |
199 throw new TempStoreException("Couldn't acquire lock to update item '$key' in '{$this->storage->getCollectionName()}' temporary storage."); | |
200 } | |
201 } | |
202 | |
203 $value = (object) [ | |
204 'owner' => $this->owner, | |
205 'data' => $value, | |
206 'updated' => (int) $this->requestStack->getMasterRequest()->server->get('REQUEST_TIME'), | |
207 ]; | |
208 $this->storage->setWithExpire($key, $value, $this->expire); | |
209 $this->lockBackend->release($key); | |
210 } | |
211 | |
212 /** | |
213 * Returns the metadata associated with a particular key/value pair. | |
214 * | |
215 * @param string $key | |
216 * The key of the data to store. | |
217 * | |
218 * @return mixed | |
219 * An object with the owner and updated time if the key has a value, or | |
220 * NULL otherwise. | |
221 */ | |
222 public function getMetadata($key) { | |
223 // Fetch the key/value pair and its metadata. | |
224 $object = $this->storage->get($key); | |
225 if ($object) { | |
226 // Don't keep the data itself in memory. | |
227 unset($object->data); | |
228 return $object; | |
229 } | |
230 } | |
231 | |
232 /** | |
233 * Deletes data from the store for a given key and releases the lock on it. | |
234 * | |
235 * @param string $key | |
236 * The key of the data to delete. | |
237 * | |
238 * @throws \Drupal\user\TempStoreException | |
239 * Thrown when a lock for the backend storage could not be acquired. | |
240 */ | |
241 public function delete($key) { | |
242 if (!$this->lockBackend->acquire($key)) { | |
243 $this->lockBackend->wait($key); | |
244 if (!$this->lockBackend->acquire($key)) { | |
245 throw new TempStoreException("Couldn't acquire lock to delete item '$key' from {$this->storage->getCollectionName()} temporary storage."); | |
246 } | |
247 } | |
248 $this->storage->delete($key); | |
249 $this->lockBackend->release($key); | |
250 } | |
251 | |
252 /** | |
253 * Deletes data from the store for a given key and releases the lock on it. | |
254 * | |
255 * Only delete the given key if it is owned by $this->owner. | |
256 * | |
257 * @param string $key | |
258 * The key of the data to delete. | |
259 * | |
260 * @return bool | |
261 * TRUE if the object was deleted or does not exist, FALSE if it exists but | |
262 * is not owned by $this->owner. | |
263 * | |
264 * @throws \Drupal\user\TempStoreException | |
265 * Thrown when a lock for the backend storage could not be acquired. | |
266 */ | |
267 public function deleteIfOwner($key) { | |
268 if (!$object = $this->storage->get($key)) { | |
269 return TRUE; | |
270 } | |
271 elseif ($object->owner == $this->owner) { | |
272 $this->delete($key); | |
273 return TRUE; | |
274 } | |
275 | |
276 return FALSE; | |
277 } | |
278 | |
279 } |