Proyectos de Subversion Moodle

Rev

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