MDL-42012 cache: Allow data sources to work when caching is disabled
[moodle.git] / cache / disabledlib.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  * This file contains classes that are used by the Cache API only when it is disabled.
19  *
20  * These classes are derivatives of other significant classes used by the Cache API customised specifically
21  * to only do what is absolutely necessary when initialising and using the Cache API when its been disabled.
22  *
23  * @package    core
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  * Required as it is needed for cache_config_disabled which extends cache_config_writer.
33  */
34 require_once($CFG->dirroot.'/cache/locallib.php');
36 /**
37  * The cache loader class used when the Cache has been disabled.
38  *
39  * @copyright  2012 Sam Hemelryk
40  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
42 class cache_disabled extends cache {
44     /**
45      * Constructs the cache.
46      *
47      * @param cache_definition $definition
48      * @param cache_store $store
49      * @param null $loader Unused.
50      */
51     public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
52         if ($loader instanceof cache_data_source) {
53             // Set the data source to allow data sources to work when caching is entirely disabled.
54             $this->set_data_source($loader);
55         }
57         // No other features are handled.
58     }
60     /**
61      * Gets a key from the cache.
62      *
63      * @param int|string $key
64      * @param int $strictness Unused.
65      * @return bool
66      */
67     public function get($key, $strictness = IGNORE_MISSING) {
68         if ($this->get_datasource() !== false) {
69             return $this->get_datasource()->load_for_cache($key);
70         }
72         return false;
73     }
75     /**
76      * Gets many keys at once from the cache.
77      *
78      * @param array $keys
79      * @param int $strictness Unused.
80      * @return array
81      */
82     public function get_many(array $keys, $strictness = IGNORE_MISSING) {
83         if ($this->get_datasource() !== false) {
84             return $this->get_datasource()->load_many_for_cache($keys);
85         }
87         return $return;
88     }
90     /**
91      * Sets a key value pair in the cache.
92      *
93      * @param int|string $key Unused.
94      * @param mixed $data Unused.
95      * @return bool
96      */
97     public function set($key, $data) {
98         return false;
99     }
101     /**
102      * Sets many key value pairs in the cache at once.
103      *
104      * @param array $keyvaluearray Unused.
105      * @return int
106      */
107     public function set_many(array $keyvaluearray) {
108         return 0;
109     }
111     /**
112      * Deletes an item from the cache.
113      *
114      * @param int|string $key Unused.
115      * @param bool $recurse Unused.
116      * @return bool
117      */
118     public function delete($key, $recurse = true) {
119         return false;
120     }
122     /**
123      * Deletes many items at once from the cache.
124      *
125      * @param array $keys Unused.
126      * @param bool $recurse Unused.
127      * @return int
128      */
129     public function delete_many(array $keys, $recurse = true) {
130         return 0;
131     }
133     /**
134      * Checks if the cache has the requested key.
135      *
136      * @param int|string $key Unused.
137      * @param bool $tryloadifpossible Unused.
138      * @return bool
139      */
140     public function has($key, $tryloadifpossible = false) {
141         $result = $this->get($key);
143         return $result !== false;
144     }
146     /**
147      * Checks if the cache has all of the requested keys.
148      * @param array $keys Unused.
149      * @return bool
150      */
151     public function has_all(array $keys) {
152         if (!$this->get_datasource()) {
153             return false;
154         }
156         foreach ($keys as $key) {
157             if (!$this->has($key)) {
158                 return false;
159             }
160         }
161         return true;
162     }
164     /**
165      * Checks if the cache has any of the requested keys.
166      *
167      * @param array $keys Unused.
168      * @return bool
169      */
170     public function has_any(array $keys) {
171         foreach ($keys as $key) {
172             if ($this->has($key)) {
173                 return true;
174             }
175         }
177         return false;
178     }
180     /**
181      * Purges all items from the cache.
182      *
183      * @return bool
184      */
185     public function purge() {
186         return true;
187     }
190 /**
191  * The cache factory class used when the Cache has been disabled.
192  *
193  * @copyright  2012 Sam Hemelryk
194  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
195  */
196 class cache_factory_disabled extends cache_factory {
198     /**
199      * Returns an instance of the cache_factor method.
200      *
201      * @param bool $forcereload Unused.
202      * @return cache_factory
203      * @throws coding_exception
204      */
205     public static function instance($forcereload = false) {
206         throw new coding_exception('You must not call to this cache factory within your code.');
207     }
209     /**
210      * Creates a definition instance or returns the existing one if it has already been created.
211      *
212      * @param string $component
213      * @param string $area
214      * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
215      * @return cache_definition
216      */
217     public function create_definition($component, $area, $unused = null) {
218         $definition = parent::create_definition($component, $area);
219         if ($definition->has_data_source()) {
220             return $definition;
221         }
223         return cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area);
224     }
226     /**
227      * Common public method to create a cache instance given a definition.
228      *
229      * @param cache_definition $definition
230      * @return cache_application|cache_session|cache_store
231      * @throws coding_exception
232      */
233     public function create_cache(cache_definition $definition) {
234         $loader = null;
235         if ($definition->has_data_source()) {
236             $loader = $definition->get_data_source();
237         }
238         return new cache_disabled($definition, $this->create_dummy_store($definition), $loader);
239     }
241     /**
242      * Creates a cache object given the parameters for a definition.
243      *
244      * @param string $component
245      * @param string $area
246      * @param array $identifiers
247      * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
248      * @return cache_application|cache_session|cache_request
249      */
250     public function create_cache_from_definition($component, $area, array $identifiers = array(), $unused = null) {
251         // Regular cache definitions are cached inside create_definition().  This is not the case for disabledlib.php
252         // definitions as they use load_adhoc().  They are built as a new object on each call.
253         // We do not need to clone the definition because we know it's new.
254         $definition = $this->create_definition($component, $area);
255         $definition->set_identifiers($identifiers);
256         $cache = $this->create_cache($definition);
257         return $cache;
258     }
260     /**
261      * Creates an ad-hoc cache from the given param.
262      *
263      * @param int $mode
264      * @param string $component
265      * @param string $area
266      * @param array $identifiers
267      * @param array $options An array of options, available options are:
268      *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
269      *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
270      *   - staticacceleration : If set to true the cache will hold onto all data passing through it.
271      *   - staticaccelerationsize : Sets the max size of the static acceleration array.
272      * @return cache_application|cache_session|cache_request
273      */
274     public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
275         // Regular cache definitions are cached inside create_definition().  This is not the case for disabledlib.php
276         // definitions as they use load_adhoc().  They are built as a new object on each call.
277         // We do not need to clone the definition because we know it's new.
278         $definition = cache_definition::load_adhoc($mode, $component, $area, $options);
279         $definition->set_identifiers($identifiers);
280         $cache = $this->create_cache($definition);
281         return $cache;
282     }
284     /**
285      * Creates a store instance given its name and configuration.
286      *
287      * @param string $name Unused.
288      * @param array $details Unused.
289      * @param cache_definition $definition
290      * @return boolean|cache_store
291      */
292     public function create_store_from_config($name, array $details, cache_definition $definition) {
293         return $this->create_dummy_store($definition);
294     }
296     /**
297      * Creates a cache config instance with the ability to write if required.
298      *
299      * @param bool $writer Unused.
300      * @return cache_config_disabled|cache_config_writer
301      */
302     public function create_config_instance($writer = false) {
303         // We are always going to use the cache_config_disabled class for all regular request.
304         // However if the code has requested the writer then likely something is changing and
305         // we're going to need to interact with the config.php file.
306         // In this case we will still use the cache_config_writer.
307         $class = 'cache_config_disabled';
308         if ($writer) {
309             // If the writer was requested then something is changing.
310             $class = 'cache_config_writer';
311         }
312         if (!array_key_exists($class, $this->configs)) {
313             self::set_state(self::STATE_INITIALISING);
314             if ($class === 'cache_config_disabled') {
315                 $configuration = $class::create_default_configuration();
316             } else {
317                 $configuration = false;
318                 if (!cache_config::config_file_exists()) {
319                     cache_config_writer::create_default_configuration(true);
320                 }
321             }
322             $this->configs[$class] = new $class;
323             $this->configs[$class]->load($configuration);
324         }
325         self::set_state(self::STATE_READY);
327         // Return the instance.
328         return $this->configs[$class];
329     }
332 /**
333  * The cache config class used when the Cache has been disabled.
334  *
335  * @copyright  2012 Sam Hemelryk
336  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
337  */
338 class cache_config_disabled extends cache_config_writer {
340     /**
341      * Returns an instance of the configuration writer.
342      *
343      * @return cache_config_disabled
344      */
345     public static function instance() {
346         $factory = cache_factory::instance();
347         return $factory->create_config_instance(true);
348     }
350     /**
351      * Saves the current configuration.
352      */
353     protected function config_save() {
354         // Nothing to do here.
355     }
357     /**
358      * Generates a configuration array suitable to be written to the config file.
359      *
360      * @return array
361      */
362     protected function generate_configuration_array() {
363         $configuration = array();
364         $configuration['stores'] = $this->configstores;
365         $configuration['modemappings'] = $this->configmodemappings;
366         $configuration['definitions'] = $this->configdefinitions;
367         $configuration['definitionmappings'] = $this->configdefinitionmappings;
368         $configuration['locks'] = $this->configlocks;
369         return $configuration;
370     }
372     /**
373      * Adds a plugin instance.
374      *
375      * @param string $name Unused.
376      * @param string $plugin Unused.
377      * @param array $configuration Unused.
378      * @return bool
379      * @throws cache_exception
380      */
381     public function add_store_instance($name, $plugin, array $configuration = array()) {
382         return false;
383     }
385     /**
386      * Sets the mode mappings.
387      *
388      * @param array $modemappings Unused.
389      * @return bool
390      * @throws cache_exception
391      */
392     public function set_mode_mappings(array $modemappings) {
393         return false;
394     }
396     /**
397      * Edits a give plugin instance.
398      *
399      * @param string $name Unused.
400      * @param string $plugin Unused.
401      * @param array $configuration Unused.
402      * @return bool
403      * @throws cache_exception
404      */
405     public function edit_store_instance($name, $plugin, $configuration) {
406         return false;
407     }
409     /**
410      * Deletes a store instance.
411      *
412      * @param string $name Unused.
413      * @return bool
414      * @throws cache_exception
415      */
416     public function delete_store_instance($name) {
417         return false;
418     }
420     /**
421      * Creates the default configuration and saves it.
422      *
423      * @param bool $forcesave Ignored because we are disabled!
424      * @return array
425      */
426     public static function create_default_configuration($forcesave = false) {
427         global $CFG;
429         // HACK ALERT.
430         // We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
431         // default store plugins are protected from deletion.
432         require_once($CFG->dirroot.'/cache/stores/file/lib.php');
433         require_once($CFG->dirroot.'/cache/stores/session/lib.php');
434         require_once($CFG->dirroot.'/cache/stores/static/lib.php');
436         $writer = new self;
437         $writer->configstores = array(
438             'default_application' => array(
439                 'name' => 'default_application',
440                 'plugin' => 'file',
441                 'configuration' => array(),
442                 'features' => cachestore_file::get_supported_features(),
443                 'modes' => cache_store::MODE_APPLICATION,
444                 'default' => true,
445             ),
446             'default_session' => array(
447                 'name' => 'default_session',
448                 'plugin' => 'session',
449                 'configuration' => array(),
450                 'features' => cachestore_session::get_supported_features(),
451                 'modes' => cache_store::MODE_SESSION,
452                 'default' => true,
453             ),
454             'default_request' => array(
455                 'name' => 'default_request',
456                 'plugin' => 'static',
457                 'configuration' => array(),
458                 'features' => cachestore_static::get_supported_features(),
459                 'modes' => cache_store::MODE_REQUEST,
460                 'default' => true,
461             )
462         );
463         $writer->configdefinitions = array();
464         $writer->configmodemappings = array(
465             array(
466                 'mode' => cache_store::MODE_APPLICATION,
467                 'store' => 'default_application',
468                 'sort' => -1
469             ),
470             array(
471                 'mode' => cache_store::MODE_SESSION,
472                 'store' => 'default_session',
473                 'sort' => -1
474             ),
475             array(
476                 'mode' => cache_store::MODE_REQUEST,
477                 'store' => 'default_request',
478                 'sort' => -1
479             )
480         );
481         $writer->configlocks = array(
482             'default_file_lock' => array(
483                 'name' => 'cachelock_file_default',
484                 'type' => 'cachelock_file',
485                 'dir' => 'filelocks',
486                 'default' => true
487             )
488         );
490         return $writer->generate_configuration_array();
491     }
493     /**
494      * Updates the definition in the configuration from those found in the cache files.
495      *
496      * @param bool $coreonly Unused.
497      */
498     public static function update_definitions($coreonly = false) {
499         // Nothing to do here.
500     }
502     /**
503      * Locates all of the definition files.
504      *
505      * @param bool $coreonly Unused.
506      * @return array
507      */
508     protected static function locate_definitions($coreonly = false) {
509         return array();
510     }
512     /**
513      * Sets the mappings for a given definition.
514      *
515      * @param string $definition Unused.
516      * @param array $mappings Unused.
517      * @throws coding_exception
518      */
519     public function set_definition_mappings($definition, $mappings) {
520         // Nothing to do here.
521     }