eae6c0055deaf9174184e5d9dd1716025134070d
[moodle.git] / cache / stores / static / lib.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * The library file for the static cache store.
19  *
20  * This file is part of the static cache store, it contains the API for interacting with an instance of the store.
21  * This is used as a default cache store within the Cache API. It should never be deleted.
22  *
23  * @package    cachestore_static
24  * @category   cache
25  * @copyright  2012 Sam Hemelryk
26  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27  */
29 defined('MOODLE_INTERNAL') || die();
31 /**
32  * The static store class.
33  *
34  * @copyright  2012 Sam Hemelryk
35  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class cachestore_static extends static_data_store implements cache_store, cache_is_key_aware {
39     /**
40      * The name of the store
41      * @var store
42      */
43     protected $name;
45     /**
46      * The store id (should be unique)
47      * @var string
48      */
49     protected $storeid;
51     /**
52      * The store we use for data.
53      * @var array
54      */
55     protected $store;
57     /**
58      * The ttl if there is one. Hopefully not.
59      * @var int
60      */
61     protected $ttl = 0;
63     /**
64      * Constructs the store instance.
65      *
66      * Noting that this function is not an initialisation. It is used to prepare the store for use.
67      * The store will be initialised when required and will be provided with a cache_definition at that time.
68      *
69      * @param string $name
70      * @param array $configuration
71      */
72     public function __construct($name, array $configuration = array()) {
73         $this->name = $name;
74     }
76     /**
77      * Returns the supported features as a combined int.
78      *
79      * @param array $configuration
80      * @return int
81      */
82     public static function get_supported_features(array $configuration = array()) {
83         return self::SUPPORTS_DATA_GUARANTEE +
84                self::SUPPORTS_NATIVE_TTL;
85     }
87     /**
88      * Returns the supported modes as a combined int.
89      *
90      * @param array $configuration
91      * @return int
92      */
93     public static function get_supported_modes(array $configuration = array()) {
94         return self::MODE_REQUEST;
95     }
97     /**
98      * Returns true if the store requirements are met.
99      *
100      * @return bool
101      */
102     public static function are_requirements_met() {
103         return true;
104     }
106     /**
107      * Returns true if the given mode is supported by this store.
108      *
109      * @param int $mode One of cache_store::MODE_*
110      * @return bool
111      */
112     public static function is_supported_mode($mode) {
113         return ($mode === self::MODE_REQUEST);
114     }
116     /**
117      * Returns true if the store instance guarantees data.
118      *
119      * @return bool
120      */
121     public function supports_data_guarantee() {
122         return true;
123     }
125     /**
126      * Returns true if the store instance supports multiple identifiers.
127      *
128      * @return bool
129      */
130     public function supports_multiple_identifiers() {
131         return false;
132     }
134     /**
135      * Returns true if the store instance supports native ttl.
136      *
137      * @return bool
138      */
139     public function supports_native_ttl() {
140         return true;
141     }
143     /**
144      * Initialises the cache.
145      *
146      * Once this has been done the cache is all set to be used.
147      *
148      * @param cache_definition $definition
149      */
150     public function initialise(cache_definition $definition) {
151         $this->storeid = $definition->generate_definition_hash();
152         $this->store = &self::register_store_id($this->storeid);
153         $this->ttl = $definition->get_ttl();
154     }
156     /**
157      * Returns true once this instance has been initialised.
158      *
159      * @return bool
160      */
161     public function is_initialised() {
162         return (is_array($this->store));
163     }
165     /**
166      * Returns true if this store instance is ready to be used.
167      * @return bool
168      */
169     public function is_ready() {
170         return true;
171     }
173     /**
174      * Retrieves an item from the cache store given its key.
175      *
176      * @param string $key The key to retrieve
177      * @return mixed The data that was associated with the key, or false if the key did not exist.
178      */
179     public function get($key) {
180         $maxtime = cache::now() - $this->ttl;
181         if (array_key_exists($key, $this->store)) {
182             if ($this->ttl == 0) {
183                 return $this->store[$key];
184             } else if ($this->store[$key][1] >= $maxtime) {
185                 return $this->store[$key][0];
186             }
187         }
188         return false;
189     }
191     /**
192      * Retrieves several items from the cache store in a single transaction.
193      *
194      * If not all of the items are available in the cache then the data value for those that are missing will be set to false.
195      *
196      * @param array $keys The array of keys to retrieve
197      * @return array An array of items from the cache. There will be an item for each key, those that were not in the store will
198      *      be set to false.
199      */
200     public function get_many($keys) {
201         $return = array();
202         $maxtime = cache::now() - $this->ttl;
203         foreach ($keys as $key) {
204             $return[$key] = false;
205             if (array_key_exists($key, $this->store)) {
206                 if ($this->ttl == 0) {
207                     $return[$key] = $this->store[$key];
208                 } else if ($this->store[$key][1] >= $maxtime) {
209                     $return[$key] = $this->store[$key][0];
210                 }
211             }
212         }
213         return $return;
214     }
216     /**
217      * Sets an item in the cache given its key and data value.
218      *
219      * @param string $key The key to use.
220      * @param mixed $data The data to set.
221      * @return bool True if the operation was a success false otherwise.
222      */
223     public function set($key, $data) {
224         if ($this->ttl == 0) {
225             $this->store[$key] = $data;
226         } else {
227             $this->store[$key] = array($data, cache::now());
228         }
229         return true;
230     }
232     /**
233      * Sets many items in the cache in a single transaction.
234      *
235      * @param array $keyvaluearray An array of key value pairs. Each item in the array will be an associative array with two
236      *      keys, 'key' and 'value'.
237      * @return int The number of items successfully set. It is up to the developer to check this matches the number of items
238      *      sent ... if they care that is.
239      */
240     public function set_many(array $keyvaluearray) {
241         $count = 0;
242         foreach ($keyvaluearray as $pair) {
243             $this->set($pair['key'], $pair['value']);
244             $count++;
245         }
246         return $count;
247     }
249     /**
250      * Checks if the store has a record for the given key and returns true if so.
251      *
252      * @param string $key
253      * @return bool
254      */
255     public function has($key) {
256         $maxtime = cache::now() - $this->ttl;
257         if (array_key_exists($key, $this->store)) {
258             if ($this->ttl == 0) {
259                 return true;
260             } else if ($this->store[$key][1] >= $maxtime) {
261                 return true;
262             }
263         }
264         return false;
265     }
267     /**
268      * Returns true if the store contains records for all of the given keys.
269      *
270      * @param array $keys
271      * @return bool
272      */
273     public function has_all(array $keys) {
274         $maxtime = cache::now() - $this->ttl;
275         foreach ($keys as $key) {
276             if (!array_key_exists($key, $this->store)) {
277                 return false;
278             }
279             if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) {
280                 return false;
281             }
282         }
283         return true;
284     }
286     /**
287      * Returns true if the store contains records for any of the given keys.
288      *
289      * @param array $keys
290      * @return bool
291      */
292     public function has_any(array $keys) {
293         $maxtime = cache::now() - $this->ttl;
294         foreach ($keys as $key) {
295             if (array_key_exists($key, $this->store) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) {
296                 return true;
297             }
298         }
299         return false;
300     }
302     /**
303      * Deletes an item from the cache store.
304      *
305      * @param string $key The key to delete.
306      * @return bool Returns true if the operation was a success, false otherwise.
307      */
308     public function delete($key) {
309         unset($this->store[$key]);
310         return true;
311     }
313     /**
314      * Deletes several keys from the cache in a single action.
315      *
316      * @param array $keys The keys to delete
317      * @return int The number of items successfully deleted.
318      */
319     public function delete_many(array $keys) {
320         $count = 0;
321         foreach ($keys as $key) {
322             unset($this->store[$key]);
323             $count++;
324         }
325         return $count;
326     }
328     /**
329      * Purges the cache deleting all items within it.
330      *
331      * @return boolean True on success. False otherwise.
332      */
333     public function purge() {
334         $this->flush_store_by_id($this->storeid);
335     }
337     /**
338      * Returns true if the user can add an instance of the store plugin.
339      *
340      * @return bool
341      */
342     public static function can_add_instance() {
343         return false;
344     }
346     /**
347      * Performs any necessary clean up when the store instance is being deleted.
348      */
349     public function cleanup() {
350         $this->purge();
351     }
353     /**
354      * Generates an instance of the cache store that can be used for testing.
355      *
356      * @param cache_definition $definition
357      * @return false
358      */
359     public static function initialise_test_instance(cache_definition $definition) {
360         // Do something here perhaps.
361         $cache = new cachestore_static('Static store');
362         $cache->initialise($definition);
363         return $cache;;
364     }
366     /**
367      * Returns the name of this instance.
368      * @return string
369      */
370     public function my_name() {
371         return $this->name;
372     }
375 /**
376  * The static data store class
377  *
378  * @copyright  2012 Sam Hemelryk
379  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
380  */
381 abstract class static_data_store {
383     /**
384      * An array for storage.
385      * @var array
386      */
387     private static $staticstore = array();
389     /**
390      * Returns a static store by reference... REFERENCE SUPER IMPORTANT.
391      *
392      * @param string $id
393      * @return array
394      */
395     protected static function &register_store_id($id) {
396         if (!array_key_exists($id, self::$staticstore)) {
397             self::$staticstore[$id] = array();
398         }
399         return self::$staticstore[$id];
400     }
402     /**
403      * Flushes the store of all values for belonging to the store with the given id.
404      * @param string $id
405      */
406     protected static function flush_store_by_id($id) {
407         unset(self::$staticstore[$id]);
408         self::$staticstore[$id] = array();
409     }
411     /**
412      * Flushes all of the values from all stores.
413      *
414      * @copyright  2012 Sam Hemelryk
415      * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
416      */
417     protected static function flush_store() {
418         $ids = array_keys(self::$staticstore);
419         unset(self::$staticstore);
420         self::$staticstore = array();
421         foreach ($ids as $id) {
422             self::$staticstore[$id] = array();
423         }
424     }