Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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