5f08b1b8fecd12e97e663fe513a53403eb0bd126
[moodle.git] / cache / classes / definition.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  * Cache definition class
19  *
20  * This file is part of Moodle's cache API, affectionately called MUC.
21  * It contains the components that are requried in order to use caching.
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  * The cache definition class.
33  *
34  * Cache definitions need to be defined in db/caches.php files.
35  * They can be constructed with the following options.
36  *
37  * Required settings:
38  *     + mode
39  *          [int] Sets the mode for the definition. Must be one of cache_store::MODE_*
40  *
41  * Optional settings:
42  *     + simplekeys
43  *          [bool] Set to true if your cache will only use simple keys for its items.
44  *          Simple keys consist of digits, underscores and the 26 chars of the english language. a-zA-Z0-9_
45  *          If true the keys won't be hashed before being passed to the cache store for gets/sets/deletes. It will be
46  *          better for performance and possible only becase we know the keys are safe.
47  *     + simpledata
48  *          [bool] If set to true we know that the data is scalar or array of scalar.
49  *     + requireidentifiers
50  *          [array] An array of identifiers that must be provided to the cache when it is created.
51  *     + requiredataguarantee
52  *          [bool] If set to true then only stores that can guarantee data will remain available once set will be used.
53  *     + requiremultipleidentifiers
54  *          [bool] If set to true then only stores that support multiple identifiers will be used.
55  *     + requirelockingread
56  *          [bool] If set to true then a lock will be gained before reading from the cache store. It is recommended not to use
57  *          this setting unless 100% absolutely positively required. Remember 99.9% of caches will NOT need this setting.
58  *          This setting will only be used for application caches presently.
59  *     + requirelockingwrite
60  *          [bool] If set to true then a lock will be gained before writing to the cache store. As above this is not recommended
61  *          unless truly needed. Please think about the order of your code and deal with race conditions there first.
62  *          This setting will only be used for application caches presently.
63  *     + maxsize
64  *          [int] If set this will be used as the maximum number of entries within the cache store for this definition.
65  *          Its important to note that cache stores don't actually have to acknowledge this setting or maintain it as a hard limit.
66  *     + overrideclass
67  *          [string] A class to use as the loader for this cache. This is an advanced setting and will allow the developer of the
68  *          definition to take 100% control of the caching solution.
69  *          Any class used here must inherit the cache_loader interface and must extend default cache loader for the mode they are
70  *          using.
71  *     + overrideclassfile
72  *          [string] Suplements the above setting indicated the file containing the class to be used. This file is included when
73  *          required.
74  *     + datasource
75  *          [string] A class to use as the data loader for this definition.
76  *          Any class used here must inherit the cache_data_loader interface.
77  *     + datasourcefile
78  *          [string] Supplements the above setting indicating the file containing the class to be used. This file is included when
79  *          required.
80  *     + staticacceleration
81  *          The cache loader will keep an array of the items set and retrieved to the cache during the request.
82  *          Consider using this setting when you know that there are going to be many calls to the cache for the same information.
83  *          Requests for data in this array will be ultra fast, but it will cost memory.
84  *     + staticaccelerationsize
85  *          [int] This supplements the above setting by limiting the number of items in the static acceleration array.
86  *          Tweaking this setting lower will allow you to minimise the memory implications above while hopefully still managing to
87  *          offset calls to the cache store.
88  *     + ttl
89  *          [int] A time to live for the data (in seconds). It is strongly recommended that you don't make use of this and
90  *          instead try to create an event driven invalidation system.
91  *          Not all cache stores will support this natively and there are undesired performance impacts if the cache store does not.
92  *     + mappingsonly
93  *          [bool] If set to true only the mapped cache store(s) will be used and the default mode store will not. This is a super
94  *          advanced setting and should not be used unless absolutely required. It allows you to avoid the default stores for one
95  *          reason or another.
96  *     + invalidationevents
97  *          [array] An array of events that should cause this cache to invalidate some or all of the items within it.
98  *     + sharingoptions
99  *          [int] The sharing options that are appropriate for this definition. Should be the sum of the possible options.
100  *     + defaultsharing
101  *          [int] The default sharing option to use. It's highly recommended that you don't set this unless there is a very
102  *          specific reason not to use the system default.
103  *     + canuselocalstore
104  *          [bool] The cache is able to safely run with multiple copies on different webservers without any need for administrator
105  *                 intervention to ensure that data stays in sync across nodes.  This is usually managed by a revision
106  *                 system as seen in modinfo cache or language cache.  Requiring purge on upgrade is not sufficient as
107  *                 it requires administrator intervention on each node to make it work.
108  *
109  * For examples take a look at lib/db/caches.php
110  *
111  * @package    core
112  * @category   cache
113  * @copyright  2012 Sam Hemelryk
114  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
115  */
116 class cache_definition {
118     /** The cache can be shared with everyone */
119     const SHARING_ALL = 1;
120     /** The cache can be shared with other sites using the same siteid. */
121     const SHARING_SITEID = 2;
122     /** The cache can be shared with other sites of the same version. */
123     const SHARING_VERSION = 4;
124     /** The cache can be shared with other sites using the same key */
125     const SHARING_INPUT = 8;
127     /**
128      * The default sharing options available.
129      * All + SiteID + Version + Input.
130      */
131     const SHARING_DEFAULTOPTIONS = 15;
132     /**
133      * The default sharing option that gets used if none have been selected.
134      * SiteID. It is the most restrictive.
135      */
136     const SHARING_DEFAULT = 2;
138     /**
139      * The identifier for the definition
140      * @var string
141      */
142     protected $id;
144     /**
145      * The mode for the defintion. One of cache_store::MODE_*
146      * @var int
147      */
148     protected $mode;
150     /**
151      * The component this definition is associated with.
152      * @var string
153      */
154     protected $component;
156     /**
157      * The area this definition is associated with.
158      * @var string
159      */
160     protected $area;
162     /**
163      * If set to true we know the keys are simple. a-zA-Z0-9_
164      * @var bool
165      */
166     protected $simplekeys = false;
168     /**
169      * Set to true if we know the data is scalar or array of scalar.
170      * @var bool
171      */
172     protected $simpledata = false;
174     /**
175      * An array of identifiers that must be provided when the definition is used to create a cache.
176      * @var array
177      */
178     protected $requireidentifiers = array();
180     /**
181      * If set to true then only stores that guarantee data may be used with this definition.
182      * @var bool
183      */
184     protected $requiredataguarantee = false;
186     /**
187      * If set to true then only stores that support multple identifiers may be used with this definition.
188      * @var bool
189      */
190     protected $requiremultipleidentifiers = false;
192     /**
193      * If set to true then we know that this definition requires the locking functionality.
194      * This gets set during construction based upon the settings requirelockingread and requirelockingwrite.
195      * @var bool
196      */
197     protected $requirelocking = false;
199     /**
200      * Set to true if this definition requires read locking.
201      * @var bool
202      */
203     protected $requirelockingread = false;
205     /**
206      * Gets set to true if this definition requires write locking.
207      * @var bool
208      */
209     protected $requirelockingwrite = false;
211     /**
212      * Gets set to true if this definition requires searchable stores.
213      * @since Moodle 2.4.4
214      * @var bool
215      */
216     protected $requiresearchable = false;
218     /**
219      * Sets the maximum number of items that can exist in the cache.
220      * Please note this isn't a hard limit, and doesn't need to be enforced by the caches. They can choose to do so optionally.
221      * @var int
222      */
223     protected $maxsize = null;
225     /**
226      * The class to use as the cache loader for this definition.
227      * @var string
228      */
229     protected $overrideclass = null;
231     /**
232      * The file in which the override class exists. This will be included if required.
233      * @var string Absolute path
234      */
235     protected $overrideclassfile = null;
237     /**
238      * The data source class to use with this definition.
239      * @var string
240      */
241     protected $datasource = null;
243     /**
244      * The file in which the data source class exists. This will be included if required.
245      * @var string
246      */
247     protected $datasourcefile = null;
249     /**
250      * Deprecated - this is completely unused.
251      * @deprecated since 2.9
252      * @var string
253      */
254     protected $datasourceaggregate = null;
256     /**
257      * Set to true if the cache should hold onto items passing through it to speed up subsequent requests.
258      * @var bool
259      */
260     protected $staticacceleration = false;
262     /**
263      * The maximum number of items that static acceleration cache should hold onto.
264      * @var int
265      */
266     protected $staticaccelerationsize = false;
268     /**
269      * The TTL for data in this cache. Please don't use this, instead use event driven invalidation.
270      * @var int
271      */
272     protected $ttl = 0;
274     /**
275      * Set to true if this cache should only use mapped cache stores and not the default mode cache store.
276      * @var bool
277      */
278     protected $mappingsonly = false;
280     /**
281      * An array of events that should cause this cache to invalidate.
282      * @var array
283      */
284     protected $invalidationevents = array();
286     /**
287      * An array of identifiers provided to this cache when it was initialised.
288      * @var array
289      */
290     protected $identifiers = null;
292     /**
293      * Key prefix for use with single key cache stores
294      * @var string
295      */
296     protected $keyprefixsingle = null;
298     /**
299      * Key prefix to use with cache stores that support multi keys.
300      * @var array
301      */
302     protected $keyprefixmulti = null;
304     /**
305      * A hash identifier of this definition.
306      * @var string
307      */
308     protected $definitionhash = null;
310     /**
311      * The selected sharing mode for this definition.
312      * @var int
313      */
314     protected $sharingoptions;
316     /**
317      * Whether this cache supports local storages.
318      * @var bool
319      */
320     protected $canuselocalstore = false;
321     /**
322      * The selected sharing option.
323      * @var int One of self::SHARING_*
324      */
325     protected $selectedsharingoption = self::SHARING_DEFAULT;
327     /**
328      * The user input key to use if the SHARING_INPUT option has been selected.
329      * @var string Must be ALPHANUMEXT
330      */
331     protected $userinputsharingkey = '';
333     /**
334      * Creates a cache definition given a definition from the cache configuration or from a caches.php file.
335      *
336      * @param string $id
337      * @param array $definition
338      * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
339      * @return cache_definition
340      * @throws coding_exception
341      */
342     public static function load($id, array $definition, $unused = null) {
343         global $CFG;
345         if (!array_key_exists('mode', $definition)) {
346             throw new coding_exception('You must provide a mode when creating a cache definition');
347         }
348         if (!array_key_exists('component', $definition)) {
349             throw new coding_exception('You must provide a component when creating a cache definition');
350         }
351         if (!array_key_exists('area', $definition)) {
352             throw new coding_exception('You must provide an area when creating a cache definition');
353         }
354         $mode = (int)$definition['mode'];
355         $component = (string)$definition['component'];
356         $area = (string)$definition['area'];
358         // Set the defaults.
359         $simplekeys = false;
360         $simpledata = false;
361         $requireidentifiers = array();
362         $requiredataguarantee = false;
363         $requiremultipleidentifiers = false;
364         $requirelockingread = false;
365         $requirelockingwrite = false;
366         $requiresearchable = ($mode === cache_store::MODE_SESSION) ? true : false;
367         $maxsize = null;
368         $overrideclass = null;
369         $overrideclassfile = null;
370         $datasource = null;
371         $datasourcefile = null;
372         $staticacceleration = false;
373         $staticaccelerationsize = false;
374         $ttl = 0;
375         $mappingsonly = false;
376         $invalidationevents = array();
377         $sharingoptions = self::SHARING_DEFAULT;
378         $selectedsharingoption = self::SHARING_DEFAULT;
379         $userinputsharingkey = '';
380         $canuselocalstore = false;
382         if (array_key_exists('simplekeys', $definition)) {
383             $simplekeys = (bool)$definition['simplekeys'];
384         }
385         if (array_key_exists('simpledata', $definition)) {
386             $simpledata = (bool)$definition['simpledata'];
387         }
388         if (array_key_exists('requireidentifiers', $definition)) {
389             $requireidentifiers = (array)$definition['requireidentifiers'];
390         }
391         if (array_key_exists('requiredataguarantee', $definition)) {
392             $requiredataguarantee = (bool)$definition['requiredataguarantee'];
393         }
394         if (array_key_exists('requiremultipleidentifiers', $definition)) {
395             $requiremultipleidentifiers = (bool)$definition['requiremultipleidentifiers'];
396         }
398         if (array_key_exists('requirelockingread', $definition)) {
399             $requirelockingread = (bool)$definition['requirelockingread'];
400         }
401         if (array_key_exists('requirelockingwrite', $definition)) {
402             $requirelockingwrite = (bool)$definition['requirelockingwrite'];
403         }
404         $requirelocking = $requirelockingwrite || $requirelockingread;
406         if (array_key_exists('requiresearchable', $definition)) {
407             $requiresearchable = (bool)$definition['requiresearchable'];
408         }
410         if (array_key_exists('maxsize', $definition)) {
411             $maxsize = (int)$definition['maxsize'];
412         }
414         if (array_key_exists('overrideclass', $definition)) {
415             $overrideclass = $definition['overrideclass'];
416         }
417         if (array_key_exists('overrideclassfile', $definition)) {
418             $overrideclassfile = $definition['overrideclassfile'];
419         }
421         if (array_key_exists('datasource', $definition)) {
422             $datasource = $definition['datasource'];
423         }
424         if (array_key_exists('datasourcefile', $definition)) {
425             $datasourcefile = $definition['datasourcefile'];
426         }
428         if (array_key_exists('persistent', $definition)) {
429             // Ahhh this is the legacy persistent option.
430             $staticacceleration = (bool)$definition['persistent'];
431         }
432         if (array_key_exists('staticacceleration', $definition)) {
433             $staticacceleration = (bool)$definition['staticacceleration'];
434         }
435         if (array_key_exists('persistentmaxsize', $definition)) {
436             // Ahhh this is the legacy persistentmaxsize option.
437             $staticaccelerationsize = (int)$definition['persistentmaxsize'];
438         }
439         if (array_key_exists('staticaccelerationsize', $definition)) {
440             $staticaccelerationsize = (int)$definition['staticaccelerationsize'];
441         }
442         if (array_key_exists('ttl', $definition)) {
443             $ttl = (int)$definition['ttl'];
444         }
445         if (array_key_exists('mappingsonly', $definition)) {
446             $mappingsonly = (bool)$definition['mappingsonly'];
447         }
448         if (array_key_exists('invalidationevents', $definition)) {
449             $invalidationevents = (array)$definition['invalidationevents'];
450         }
451         if (array_key_exists('sharingoptions', $definition)) {
452             $sharingoptions = (int)$definition['sharingoptions'];
453         }
454         if (array_key_exists('selectedsharingoption', $definition)) {
455             $selectedsharingoption = (int)$definition['selectedsharingoption'];
456         } else if (array_key_exists('defaultsharing', $definition)) {
457             $selectedsharingoption = (int)$definition['defaultsharing'];
458         } else if ($sharingoptions ^ $selectedsharingoption) {
459             if ($sharingoptions & self::SHARING_SITEID) {
460                 $selectedsharingoption = self::SHARING_SITEID;
461             } else if ($sharingoptions & self::SHARING_VERSION) {
462                 $selectedsharingoption = self::SHARING_VERSION;
463             } else {
464                 $selectedsharingoption = self::SHARING_ALL;
465             }
466         }
467         if (array_key_exists('canuselocalstore', $definition)) {
468             $canuselocalstore = (bool)$definition['canuselocalstore'];
469         }
471         if (array_key_exists('userinputsharingkey', $definition) && !empty($definition['userinputsharingkey'])) {
472             $userinputsharingkey = (string)$definition['userinputsharingkey'];
473         }
475         if (!is_null($overrideclass)) {
476             if (!is_null($overrideclassfile)) {
477                 if (strpos($overrideclassfile, $CFG->dirroot) !== 0) {
478                     $overrideclassfile = $CFG->dirroot.'/'.$overrideclassfile;
479                 }
480                 if (strpos($overrideclassfile, '../') !== false) {
481                     throw new coding_exception('No path craziness allowed within override class file path.');
482                 }
483                 if (!file_exists($overrideclassfile)) {
484                     throw new coding_exception('The override class file does not exist.');
485                 }
486                 require_once($overrideclassfile);
487             }
488             if (!class_exists($overrideclass)) {
489                 throw new coding_exception('The override class does not exist.');
490             }
492             // Make sure that the provided class extends the default class for the mode.
493             if (get_parent_class($overrideclass) !== cache_helper::get_class_for_mode($mode)) {
494                 throw new coding_exception('The override class does not immediately extend the relevant cache class.');
495             }
496         }
498         if (!is_null($datasource)) {
499             if (!is_null($datasourcefile)) {
500                 if (strpos($datasourcefile, $CFG->dirroot) !== 0) {
501                     $datasourcefile = $CFG->dirroot.'/'.$datasourcefile;
502                 }
503                 if (strpos($datasourcefile, '../') !== false) {
504                     throw new coding_exception('No path craziness allowed within data source file path.');
505                 }
506                 if (!file_exists($datasourcefile)) {
507                     throw new coding_exception('The data source class file does not exist.');
508                 }
509                 require_once($datasourcefile);
510             }
511             if (!class_exists($datasource)) {
512                 throw new coding_exception('The data source class does not exist.');
513             }
514             if (!array_key_exists('cache_data_source', class_implements($datasource))) {
515                 throw new coding_exception('Cache data source classes must implement the cache_data_source interface');
516             }
517         }
519         $cachedefinition = new cache_definition();
520         $cachedefinition->id = $id;
521         $cachedefinition->mode = $mode;
522         $cachedefinition->component = $component;
523         $cachedefinition->area = $area;
524         $cachedefinition->simplekeys = $simplekeys;
525         $cachedefinition->simpledata = $simpledata;
526         $cachedefinition->requireidentifiers = $requireidentifiers;
527         $cachedefinition->requiredataguarantee = $requiredataguarantee;
528         $cachedefinition->requiremultipleidentifiers = $requiremultipleidentifiers;
529         $cachedefinition->requirelocking = $requirelocking;
530         $cachedefinition->requirelockingread = $requirelockingread;
531         $cachedefinition->requirelockingwrite = $requirelockingwrite;
532         $cachedefinition->requiresearchable = $requiresearchable;
533         $cachedefinition->maxsize = $maxsize;
534         $cachedefinition->overrideclass = $overrideclass;
535         $cachedefinition->overrideclassfile = $overrideclassfile;
536         $cachedefinition->datasource = $datasource;
537         $cachedefinition->datasourcefile = $datasourcefile;
538         $cachedefinition->staticacceleration = $staticacceleration;
539         $cachedefinition->staticaccelerationsize = $staticaccelerationsize;
540         $cachedefinition->ttl = $ttl;
541         $cachedefinition->mappingsonly = $mappingsonly;
542         $cachedefinition->invalidationevents = $invalidationevents;
543         $cachedefinition->sharingoptions = $sharingoptions;
544         $cachedefinition->selectedsharingoption = $selectedsharingoption;
545         $cachedefinition->userinputsharingkey = $userinputsharingkey;
546         $cachedefinition->canuselocalstore = $canuselocalstore;
548         return $cachedefinition;
549     }
551     /**
552      * Creates an ah-hoc cache definition given the required params.
553      *
554      * Please note that when using an adhoc definition you cannot set any of the optional params.
555      * This is because we cannot guarantee consistent access and we don't want to mislead people into thinking that.
556      *
557      * @param int $mode One of cache_store::MODE_*
558      * @param string $component The component this definition relates to.
559      * @param string $area The area this definition relates to.
560      * @param array $options An array of options, available options are:
561      *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
562      *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
563      *   - overrideclass : The class to use as the loader.
564      *   - staticacceleration : If set to true the cache will hold onto data passing through it.
565      *   - staticaccelerationsize : Set it to an int to limit the size of the staticacceleration cache.
566      * @return cache_application|cache_session|cache_request
567      */
568     public static function load_adhoc($mode, $component, $area, array $options = array()) {
569         $id = 'adhoc/'.$component.'_'.$area;
570         $definition = array(
571             'mode' => $mode,
572             'component' => $component,
573             'area' => $area,
574         );
575         if (!empty($options['simplekeys'])) {
576             $definition['simplekeys'] = $options['simplekeys'];
577         }
578         if (!empty($options['simpledata'])) {
579             $definition['simpledata'] = $options['simpledata'];
580         }
581         if (!empty($options['persistent'])) {
582             // Ahhh this is the legacy persistent option.
583             $definition['staticacceleration'] = (bool)$options['persistent'];
584         }
585         if (!empty($options['staticacceleration'])) {
586             $definition['staticacceleration'] = (bool)$options['staticacceleration'];
587         }
588         if (!empty($options['staticaccelerationsize'])) {
589             $definition['staticaccelerationsize'] = (int)$options['staticaccelerationsize'];
590         }
591         if (!empty($options['overrideclass'])) {
592             $definition['overrideclass'] = $options['overrideclass'];
593         }
594         if (!empty($options['sharingoptions'])) {
595             $definition['sharingoptions'] = $options['sharingoptions'];
596         }
597         return self::load($id, $definition, null);
598     }
600     /**
601      * Returns the cache loader class that should be used for this definition.
602      * @return string
603      */
604     public function get_cache_class() {
605         if (!is_null($this->overrideclass)) {
606             return $this->overrideclass;
607         }
608         return cache_helper::get_class_for_mode($this->mode);
609     }
611     /**
612      * Returns the id of this definition.
613      * @return string
614      */
615     public function get_id() {
616         return $this->id;
617     }
619     /**
620      * Returns the name for this definition
621      * @return string
622      */
623     public function get_name() {
624         $identifier = 'cachedef_'.clean_param($this->area, PARAM_STRINGID);
625         $component = $this->component;
626         if ($component === 'core') {
627             $component = 'cache';
628         }
629         return new lang_string($identifier, $component);
630     }
632     /**
633      * Returns the mode of this definition
634      * @return int One more cache_store::MODE_
635      */
636     public function get_mode() {
637         return $this->mode;
638     }
640     /**
641      * Returns the area this definition is associated with.
642      * @return string
643      */
644     public function get_area() {
645         return $this->area;
646     }
648     /**
649      * Returns the component this definition is associated with.
650      * @return string
651      */
652     public function get_component() {
653         return $this->component;
654     }
656     /**
657      * Returns true if this definition is using simple keys.
658      *
659      * Simple keys contain only a-zA-Z0-9_
660      *
661      * @return bool
662      */
663     public function uses_simple_keys() {
664         return $this->simplekeys;
665     }
667     /**
668      * Returns the identifiers that are being used for this definition.
669      * @return array
670      */
671     public function get_identifiers() {
672         if (!isset($this->identifiers)) {
673             return array();
674         }
675         return $this->identifiers;
676     }
678     /**
679      * Returns the ttl in seconds for this definition if there is one, or null if not.
680      * @return int|null
681      */
682     public function get_ttl() {
683         return $this->ttl;
684     }
686     /**
687      * Returns the maximum number of items allowed in this cache.
688      * @return int
689      */
690     public function get_maxsize() {
691         return $this->maxsize;
692     }
694     /**
695      * Returns true if this definition should only be used with mappings.
696      * @return bool
697      */
698     public function is_for_mappings_only() {
699         return $this->mappingsonly;
700     }
702     /**
703      * Returns true if the data is known to be scalar or array of scalar.
704      * @return bool
705      */
706     public function uses_simple_data() {
707         return $this->simpledata;
708     }
710     /**
711      * Returns true if this definition requires a data guarantee from the cache stores being used.
712      * @return bool
713      */
714     public function require_data_guarantee() {
715         return $this->requiredataguarantee;
716     }
718     /**
719      * Returns true if this definition requires that the cache stores support multiple identifiers
720      * @return bool
721      */
722     public function require_multiple_identifiers() {
723         return $this->requiremultipleidentifiers;
724     }
726     /**
727      * Returns true if this definition requires locking functionality. Either read or write locking.
728      * @return bool
729      */
730     public function require_locking() {
731         return $this->requirelocking;
732     }
734     /**
735      * Returns true if this definition requires read locking.
736      * @return bool
737      */
738     public function require_locking_read() {
739         return $this->requirelockingread;
740     }
742     /**
743      * Returns true if this definition requires write locking.
744      * @return bool
745      */
746     public function require_locking_write() {
747         return $this->requirelockingwrite;
748     }
750     /**
751      * Returns true if this definition allows local storage to be used for caching.
752      * @since Moodle 3.1.0
753      * @return bool
754      */
755     public function can_use_localstore() {
756         return $this->canuselocalstore;
757     }
759     /**
760      * Returns true if this definition requires a searchable cache.
761      * @since Moodle 2.4.4
762      * @return bool
763      */
764     public function require_searchable() {
765         return $this->requiresearchable;
766     }
768     /**
769      * Returns true if this definition has an associated data source.
770      * @return bool
771      */
772     public function has_data_source() {
773         return !is_null($this->datasource);
774     }
776     /**
777      * Returns an instance of the data source class used for this definition.
778      *
779      * @return cache_data_source
780      * @throws coding_exception
781      */
782     public function get_data_source() {
783         if (!$this->has_data_source()) {
784             throw new coding_exception('This cache does not use a data source.');
785         }
786         return forward_static_call(array($this->datasource, 'get_instance_for_cache'), $this);
787     }
789     /**
790      * Sets the identifiers for this definition, or updates them if they have already been set.
791      *
792      * @param array $identifiers
793      * @return bool false if no identifiers where changed, true otherwise.
794      * @throws coding_exception
795      */
796     public function set_identifiers(array $identifiers = array()) {
797         // If we are setting the exact same identifiers then just return as nothing really changed.
798         // We don't care about order as cache::make will use the same definition order all the time.
799         if ($identifiers === $this->identifiers) {
800             return false;
801         }
803         foreach ($this->requireidentifiers as $identifier) {
804             if (!isset($identifiers[$identifier])) {
805                 throw new coding_exception('Identifier required for cache has not been provided: '.$identifier);
806             }
807         }
809         if ($this->identifiers === null) {
810             // Initialize identifiers if they have not been.
811             $this->identifiers = array();
812         }
813         foreach ($identifiers as $name => $value) {
814             $this->identifiers[$name] = (string)$value;
815         }
816         // Reset the key prefix's they need updating now.
817         $this->keyprefixsingle = null;
818         $this->keyprefixmulti = null;
820         return true;
821     }
823     /**
824      * Returns the requirements of this definition as a binary flag.
825      * @return int
826      */
827     public function get_requirements_bin() {
828         $requires = 0;
829         if ($this->require_data_guarantee()) {
830             $requires += cache_store::SUPPORTS_DATA_GUARANTEE;
831         }
832         if ($this->require_multiple_identifiers()) {
833             $requires += cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS;
834         }
835         if ($this->require_searchable()) {
836             $requires += cache_store::IS_SEARCHABLE;
837         }
838         return $requires;
839     }
841     /**
842      * Returns true if this definitions cache should be made persistent.
843      *
844      * Please call {@link cache_definition::use_static_acceleration()} instead.
845      *
846      * @see cache_definition::use_static_acceleration()
847      * @deprecated since 2.6
848      * @return bool
849      */
850     public function should_be_persistent() {
851         debugging('Please upgrade your code to use cache_definition::use_static_acceleration', DEBUG_DEVELOPER);
852         return $this->use_static_acceleration();
853     }
855     /**
856      * Returns true if we should hold onto the data flowing through the cache.
857      *
858      * If set to true data flowing through the cache will be stored in a static variable
859      * to make subsequent requests for the data much faster.
860      *
861      * @return bool
862      */
863     public function use_static_acceleration() {
864         if ($this->mode === cache_store::MODE_REQUEST) {
865             // Request caches should never use static acceleration - it just doesn't make sense.
866             return false;
867         }
868         return $this->staticacceleration;
869     }
871     /**
872      * Returns the max size for the static acceleration array.
873      *
874      * Please call {@link cache_definition::get_static_acceleration_size()} instead.
875      *
876      * @see cache_definition::get_static_acceleration_size()
877      * @deprecated since 2.6
878      * @return int
879      */
880     public function get_persistent_max_size() {
881         debugging('Please upgrade your code to call cache_definition::get_static_acceleration_size', DEBUG_DEVELOPER);
882         return $this->get_static_acceleration_size();
883     }
885     /**
886      * Returns the max size for the static acceleration array.
887      * @return int
888      */
889     public function get_static_acceleration_size() {
890         return $this->staticaccelerationsize;
891     }
893     /**
894      * Generates a hash of this definition and returns it.
895      * @return string
896      */
897     public function generate_definition_hash() {
898         if ($this->definitionhash === null) {
899             $this->definitionhash = md5("{$this->mode} {$this->component} {$this->area}");
900         }
901         return $this->definitionhash;
902     }
904     /**
905      * Generates a single key prefix for this definition
906      *
907      * @return string
908      */
909     public function generate_single_key_prefix() {
910         if ($this->keyprefixsingle === null) {
911             $this->keyprefixsingle = $this->mode.'/'.$this->component.'/'.$this->area;
912             $this->keyprefixsingle .= '/'.$this->get_cache_identifier();
913             $identifiers = $this->get_identifiers();
914             if ($identifiers) {
915                 foreach ($identifiers as $key => $value) {
916                     $this->keyprefixsingle .= '/'.$key.'='.$value;
917                 }
918             }
919             $this->keyprefixsingle = md5($this->keyprefixsingle);
920         }
921         return $this->keyprefixsingle;
922     }
924     /**
925      * Generates a multi key prefix for this definition
926      *
927      * @return array
928      */
929     public function generate_multi_key_parts() {
930         if ($this->keyprefixmulti === null) {
931             $this->keyprefixmulti = array(
932                 'mode' => $this->mode,
933                 'component' => $this->component,
934                 'area' => $this->area,
935                 'siteidentifier' => $this->get_cache_identifier()
936             );
937             if (isset($this->identifiers) && !empty($this->identifiers)) {
938                 $identifiers = array();
939                 foreach ($this->identifiers as $key => $value) {
940                     $identifiers[] = htmlentities($key, ENT_QUOTES, 'UTF-8').'='.htmlentities($value, ENT_QUOTES, 'UTF-8');
941                 }
942                 $this->keyprefixmulti['identifiers'] = join('&', $identifiers);
943             }
944         }
945         return $this->keyprefixmulti;
946     }
948     /**
949      * Check if this definition should invalidate on the given event.
950      *
951      * @param string $event
952      * @return bool True if the definition should invalidate on the event. False otherwise.
953      */
954     public function invalidates_on_event($event) {
955         return (in_array($event, $this->invalidationevents));
956     }
958     /**
959      * Check if the definition has any invalidation events.
960      *
961      * @return bool True if it does, false otherwise
962      */
963     public function has_invalidation_events() {
964         return !empty($this->invalidationevents);
965     }
967     /**
968      * Returns all of the invalidation events for this definition.
969      *
970      * @return array
971      */
972     public function get_invalidation_events() {
973         return $this->invalidationevents;
974     }
976     /**
977      * Returns a cache identification string.
978      *
979      * @return string A string to be used as part of keys.
980      */
981     protected function get_cache_identifier() {
982         $identifiers = array();
983         if ($this->selectedsharingoption & self::SHARING_ALL) {
984             // Nothing to do here.
985         } else {
986             if ($this->selectedsharingoption & self::SHARING_SITEID) {
987                 $identifiers[] = cache_helper::get_site_identifier();
988             }
989             if ($this->selectedsharingoption & self::SHARING_VERSION) {
990                 $identifiers[] = cache_helper::get_site_version();
991             }
992             if ($this->selectedsharingoption & self::SHARING_INPUT && !empty($this->userinputsharingkey)) {
993                 $identifiers[] = $this->userinputsharingkey;
994             }
995         }
996         return join('/', $identifiers);
997     }
999     /**
1000      * Returns true if this definition requires identifiers.
1001      *
1002      * @param bool
1003      */
1004     public function has_required_identifiers() {
1005         return (count($this->requireidentifiers) > 0);
1006     }
1008     /**
1009      * Returns the possible sharing options that can be used with this defintion.
1010      *
1011      * @return int
1012      */
1013     public function get_sharing_options() {
1014         return $this->sharingoptions;
1015     }
1017     /**
1018      * Returns the user entered sharing key for this definition.
1019      *
1020      * @return string
1021      */
1022     public function get_user_input_sharing_key() {
1023         return $this->userinputsharingkey;
1024     }
1026     /**
1027      * Returns the user selected sharing option for this definition.
1028      *
1029      * @return int
1030      */
1031     public function get_selected_sharing_option() {
1032         return $this->selectedsharingoption;
1033     }