Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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   *     + 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 {
 117  
 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;
 126  
 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;
 137  
 138      /**
 139       * The identifier for the definition
 140       * @var string
 141       */
 142      protected $id;
 143  
 144      /**
 145       * The mode for the defintion. One of cache_store::MODE_*
 146       * @var int
 147       */
 148      protected $mode;
 149  
 150      /**
 151       * The component this definition is associated with.
 152       * @var string
 153       */
 154      protected $component;
 155  
 156      /**
 157       * The area this definition is associated with.
 158       * @var string
 159       */
 160      protected $area;
 161  
 162      /**
 163       * If set to true we know the keys are simple. a-zA-Z0-9_
 164       * @var bool
 165       */
 166      protected $simplekeys = false;
 167  
 168      /**
 169       * Set to true if we know the data is scalar or array of scalar.
 170       * @var bool
 171       */
 172      protected $simpledata = false;
 173  
 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();
 179  
 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;
 185  
 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;
 191  
 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;
 198  
 199      /**
 200       * Set to true if this definition requires read locking.
 201       * @var bool
 202       */
 203      protected $requirelockingread = false;
 204  
 205      /**
 206       * Gets set to true if this definition requires write locking.
 207       * @var bool
 208       */
 209      protected $requirelockingwrite = false;
 210  
 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;
 217  
 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;
 224  
 225      /**
 226       * The class to use as the cache loader for this definition.
 227       * @var string
 228       */
 229      protected $overrideclass = null;
 230  
 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;
 236  
 237      /**
 238       * The data source class to use with this definition.
 239       * @var string
 240       */
 241      protected $datasource = null;
 242  
 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;
 248  
 249      /**
 250       * Set to true if the cache should hold onto items passing through it to speed up subsequent requests.
 251       * @var bool
 252       */
 253      protected $staticacceleration = false;
 254  
 255      /**
 256       * The maximum number of items that static acceleration cache should hold onto.
 257       * @var int
 258       */
 259      protected $staticaccelerationsize = false;
 260  
 261      /**
 262       * The TTL for data in this cache. Please don't use this, instead use event driven invalidation.
 263       * @var int
 264       */
 265      protected $ttl = 0;
 266  
 267      /**
 268       * Set to true if this cache should only use mapped cache stores and not the default mode cache store.
 269       * @var bool
 270       */
 271      protected $mappingsonly = false;
 272  
 273      /**
 274       * An array of events that should cause this cache to invalidate.
 275       * @var array
 276       */
 277      protected $invalidationevents = array();
 278  
 279      /**
 280       * An array of identifiers provided to this cache when it was initialised.
 281       * @var array
 282       */
 283      protected $identifiers = null;
 284  
 285      /**
 286       * Key prefix for use with single key cache stores
 287       * @var string
 288       */
 289      protected $keyprefixsingle = null;
 290  
 291      /**
 292       * Key prefix to use with cache stores that support multi keys.
 293       * @var array
 294       */
 295      protected $keyprefixmulti = null;
 296  
 297      /**
 298       * A hash identifier of this definition.
 299       * @var string
 300       */
 301      protected $definitionhash = null;
 302  
 303      /**
 304       * The selected sharing mode for this definition.
 305       * @var int
 306       */
 307      protected $sharingoptions;
 308  
 309      /**
 310       * Whether this cache supports local storages.
 311       * @var bool
 312       */
 313      protected $canuselocalstore = false;
 314  
 315      /**
 316       * The selected sharing option.
 317       * @var int One of self::SHARING_*
 318       */
 319      protected $selectedsharingoption = self::SHARING_DEFAULT;
 320  
 321      /**
 322       * The user input key to use if the SHARING_INPUT option has been selected.
 323       * @var string Must be ALPHANUMEXT
 324       */
 325      protected $userinputsharingkey = '';
 326  
 327      /**
 328       * Creates a cache definition given a definition from the cache configuration or from a caches.php file.
 329       *
 330       * @param string $id
 331       * @param array $definition
 332       * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
 333       * @return cache_definition
 334       * @throws coding_exception
 335       */
 336      public static function load($id, array $definition, $unused = null) {
 337          global $CFG;
 338  
 339          if (!array_key_exists('mode', $definition)) {
 340              throw new coding_exception('You must provide a mode when creating a cache definition');
 341          }
 342          if (!array_key_exists('component', $definition)) {
 343              throw new coding_exception('You must provide a component when creating a cache definition');
 344          }
 345          if (!array_key_exists('area', $definition)) {
 346              throw new coding_exception('You must provide an area when creating a cache definition');
 347          }
 348          $mode = (int)$definition['mode'];
 349          $component = (string)$definition['component'];
 350          $area = (string)$definition['area'];
 351  
 352          // Set the defaults.
 353          $simplekeys = false;
 354          $simpledata = false;
 355          $requireidentifiers = array();
 356          $requiredataguarantee = false;
 357          $requiremultipleidentifiers = false;
 358          $requirelockingread = false;
 359          $requirelockingwrite = false;
 360          $requiresearchable = ($mode === cache_store::MODE_SESSION) ? true : false;
 361          $maxsize = null;
 362          $overrideclass = null;
 363          $overrideclassfile = null;
 364          $datasource = null;
 365          $datasourcefile = null;
 366          $staticacceleration = false;
 367          $staticaccelerationsize = false;
 368          $ttl = 0;
 369          $mappingsonly = false;
 370          $invalidationevents = array();
 371          $sharingoptions = self::SHARING_DEFAULT;
 372          $selectedsharingoption = self::SHARING_DEFAULT;
 373          $userinputsharingkey = '';
 374          $canuselocalstore = false;
 375  
 376          if (array_key_exists('simplekeys', $definition)) {
 377              $simplekeys = (bool)$definition['simplekeys'];
 378          }
 379          if (array_key_exists('simpledata', $definition)) {
 380              $simpledata = (bool)$definition['simpledata'];
 381          }
 382          if (array_key_exists('requireidentifiers', $definition)) {
 383              $requireidentifiers = (array)$definition['requireidentifiers'];
 384          }
 385          if (array_key_exists('requiredataguarantee', $definition)) {
 386              $requiredataguarantee = (bool)$definition['requiredataguarantee'];
 387          }
 388          if (array_key_exists('requiremultipleidentifiers', $definition)) {
 389              $requiremultipleidentifiers = (bool)$definition['requiremultipleidentifiers'];
 390          }
 391  
 392          if (array_key_exists('requirelockingread', $definition)) {
 393              $requirelockingread = (bool)$definition['requirelockingread'];
 394          }
 395          if (array_key_exists('requirelockingwrite', $definition)) {
 396              $requirelockingwrite = (bool)$definition['requirelockingwrite'];
 397          }
 398          $requirelocking = $requirelockingwrite || $requirelockingread;
 399  
 400          if (array_key_exists('requiresearchable', $definition)) {
 401              $requiresearchable = (bool)$definition['requiresearchable'];
 402          }
 403  
 404          if (array_key_exists('maxsize', $definition)) {
 405              $maxsize = (int)$definition['maxsize'];
 406          }
 407  
 408          if (array_key_exists('overrideclass', $definition)) {
 409              $overrideclass = $definition['overrideclass'];
 410          }
 411          if (array_key_exists('overrideclassfile', $definition)) {
 412              $overrideclassfile = $definition['overrideclassfile'];
 413          }
 414  
 415          if (array_key_exists('datasource', $definition)) {
 416              $datasource = $definition['datasource'];
 417          }
 418          if (array_key_exists('datasourcefile', $definition)) {
 419              $datasourcefile = $definition['datasourcefile'];
 420          }
 421  
 422          if (array_key_exists('persistent', $definition)) {
 423              // Ahhh this is the legacy persistent option.
 424              $staticacceleration = (bool)$definition['persistent'];
 425          }
 426          if (array_key_exists('staticacceleration', $definition)) {
 427              $staticacceleration = (bool)$definition['staticacceleration'];
 428          }
 429          if (array_key_exists('persistentmaxsize', $definition)) {
 430              // Ahhh this is the legacy persistentmaxsize option.
 431              $staticaccelerationsize = (int)$definition['persistentmaxsize'];
 432          }
 433          if (array_key_exists('staticaccelerationsize', $definition)) {
 434              $staticaccelerationsize = (int)$definition['staticaccelerationsize'];
 435          }
 436          if (array_key_exists('ttl', $definition)) {
 437              $ttl = (int)$definition['ttl'];
 438          }
 439          if (array_key_exists('mappingsonly', $definition)) {
 440              $mappingsonly = (bool)$definition['mappingsonly'];
 441          }
 442          if (array_key_exists('invalidationevents', $definition)) {
 443              $invalidationevents = (array)$definition['invalidationevents'];
 444          }
 445          if (array_key_exists('sharingoptions', $definition)) {
 446              $sharingoptions = (int)$definition['sharingoptions'];
 447          }
 448          if (array_key_exists('selectedsharingoption', $definition)) {
 449              $selectedsharingoption = (int)$definition['selectedsharingoption'];
 450          } else if (array_key_exists('defaultsharing', $definition)) {
 451              $selectedsharingoption = (int)$definition['defaultsharing'];
 452          } else if ($sharingoptions ^ $selectedsharingoption) {
 453              if ($sharingoptions & self::SHARING_SITEID) {
 454                  $selectedsharingoption = self::SHARING_SITEID;
 455              } else if ($sharingoptions & self::SHARING_VERSION) {
 456                  $selectedsharingoption = self::SHARING_VERSION;
 457              } else {
 458                  $selectedsharingoption = self::SHARING_ALL;
 459              }
 460          }
 461          if (array_key_exists('canuselocalstore', $definition)) {
 462              $canuselocalstore = (bool)$definition['canuselocalstore'];
 463          }
 464  
 465          if (array_key_exists('userinputsharingkey', $definition) && !empty($definition['userinputsharingkey'])) {
 466              $userinputsharingkey = (string)$definition['userinputsharingkey'];
 467          }
 468  
 469          if (!is_null($overrideclass)) {
 470              if (!is_null($overrideclassfile)) {
 471                  if (strpos($overrideclassfile, $CFG->dirroot) !== 0) {
 472                      $overrideclassfile = $CFG->dirroot.'/'.$overrideclassfile;
 473                  }
 474                  if (strpos($overrideclassfile, '../') !== false) {
 475                      throw new coding_exception('No path craziness allowed within override class file path.');
 476                  }
 477                  if (!file_exists($overrideclassfile)) {
 478                      throw new coding_exception('The override class file does not exist.');
 479                  }
 480                  require_once($overrideclassfile);
 481              }
 482              if (!class_exists($overrideclass)) {
 483                  throw new coding_exception('The override class does not exist.');
 484              }
 485  
 486              // Make sure that the provided class extends the default class for the mode.
 487              if (get_parent_class($overrideclass) !== cache_helper::get_class_for_mode($mode)) {
 488                  throw new coding_exception('The override class does not immediately extend the relevant cache class.');
 489              }
 490          }
 491  
 492          if (!is_null($datasource)) {
 493              if (!is_null($datasourcefile)) {
 494                  if (strpos($datasourcefile, $CFG->dirroot) !== 0) {
 495                      $datasourcefile = $CFG->dirroot.'/'.$datasourcefile;
 496                  }
 497                  if (strpos($datasourcefile, '../') !== false) {
 498                      throw new coding_exception('No path craziness allowed within data source file path.');
 499                  }
 500                  if (!file_exists($datasourcefile)) {
 501                      throw new coding_exception('The data source class file does not exist.');
 502                  }
 503                  require_once($datasourcefile);
 504              }
 505              if (!class_exists($datasource)) {
 506                  throw new coding_exception('The data source class does not exist.');
 507              }
 508              if (!array_key_exists('cache_data_source', class_implements($datasource))) {
 509                  throw new coding_exception('Cache data source classes must implement the cache_data_source interface');
 510              }
 511          }
 512  
 513          $cachedefinition = new cache_definition();
 514          $cachedefinition->id = $id;
 515          $cachedefinition->mode = $mode;
 516          $cachedefinition->component = $component;
 517          $cachedefinition->area = $area;
 518          $cachedefinition->simplekeys = $simplekeys;
 519          $cachedefinition->simpledata = $simpledata;
 520          $cachedefinition->requireidentifiers = $requireidentifiers;
 521          $cachedefinition->requiredataguarantee = $requiredataguarantee;
 522          $cachedefinition->requiremultipleidentifiers = $requiremultipleidentifiers;
 523          $cachedefinition->requirelocking = $requirelocking;
 524          $cachedefinition->requirelockingread = $requirelockingread;
 525          $cachedefinition->requirelockingwrite = $requirelockingwrite;
 526          $cachedefinition->requiresearchable = $requiresearchable;
 527          $cachedefinition->maxsize = $maxsize;
 528          $cachedefinition->overrideclass = $overrideclass;
 529          $cachedefinition->overrideclassfile = $overrideclassfile;
 530          $cachedefinition->datasource = $datasource;
 531          $cachedefinition->datasourcefile = $datasourcefile;
 532          $cachedefinition->staticacceleration = $staticacceleration;
 533          $cachedefinition->staticaccelerationsize = $staticaccelerationsize;
 534          $cachedefinition->ttl = $ttl;
 535          $cachedefinition->mappingsonly = $mappingsonly;
 536          $cachedefinition->invalidationevents = $invalidationevents;
 537          $cachedefinition->sharingoptions = $sharingoptions;
 538          $cachedefinition->selectedsharingoption = $selectedsharingoption;
 539          $cachedefinition->userinputsharingkey = $userinputsharingkey;
 540          $cachedefinition->canuselocalstore = $canuselocalstore;
 541  
 542          return $cachedefinition;
 543      }
 544  
 545      /**
 546       * Creates an ah-hoc cache definition given the required params.
 547       *
 548       * Please note that when using an adhoc definition you cannot set any of the optional params.
 549       * This is because we cannot guarantee consistent access and we don't want to mislead people into thinking that.
 550       *
 551       * @param int $mode One of cache_store::MODE_*
 552       * @param string $component The component this definition relates to.
 553       * @param string $area The area this definition relates to.
 554       * @param array $options An array of options, available options are:
 555       *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
 556       *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
 557       *   - overrideclass : The class to use as the loader.
 558       *   - staticacceleration : If set to true the cache will hold onto data passing through it.
 559       *   - staticaccelerationsize : Set it to an int to limit the size of the staticacceleration cache.
 560       * @return cache_application|cache_session|cache_request
 561       */
 562      public static function load_adhoc($mode, $component, $area, array $options = array()) {
 563          $id = 'adhoc/'.$component.'_'.$area;
 564          $definition = array(
 565              'mode' => $mode,
 566              'component' => $component,
 567              'area' => $area,
 568          );
 569          if (!empty($options['simplekeys'])) {
 570              $definition['simplekeys'] = $options['simplekeys'];
 571          }
 572          if (!empty($options['simpledata'])) {
 573              $definition['simpledata'] = $options['simpledata'];
 574          }
 575          if (!empty($options['persistent'])) {
 576              // Ahhh this is the legacy persistent option.
 577              $definition['staticacceleration'] = (bool)$options['persistent'];
 578          }
 579          if (!empty($options['staticacceleration'])) {
 580              $definition['staticacceleration'] = (bool)$options['staticacceleration'];
 581          }
 582          if (!empty($options['staticaccelerationsize'])) {
 583              $definition['staticaccelerationsize'] = (int)$options['staticaccelerationsize'];
 584          }
 585          if (!empty($options['overrideclass'])) {
 586              $definition['overrideclass'] = $options['overrideclass'];
 587          }
 588          if (!empty($options['sharingoptions'])) {
 589              $definition['sharingoptions'] = $options['sharingoptions'];
 590          }
 591          return self::load($id, $definition, null);
 592      }
 593  
 594      /**
 595       * Returns the cache loader class that should be used for this definition.
 596       * @return string
 597       */
 598      public function get_cache_class() {
 599          if (!is_null($this->overrideclass)) {
 600              return $this->overrideclass;
 601          }
 602          return cache_helper::get_class_for_mode($this->mode);
 603      }
 604  
 605      /**
 606       * Returns the id of this definition.
 607       * @return string
 608       */
 609      public function get_id() {
 610          return $this->id;
 611      }
 612  
 613      /**
 614       * Returns the name for this definition
 615       * @return string
 616       */
 617      public function get_name() {
 618          $identifier = 'cachedef_'.clean_param($this->area, PARAM_STRINGID);
 619          $component = $this->component;
 620          if ($component === 'core') {
 621              $component = 'cache';
 622          }
 623          return new lang_string($identifier, $component);
 624      }
 625  
 626      /**
 627       * Returns the mode of this definition
 628       * @return int One more cache_store::MODE_
 629       */
 630      public function get_mode() {
 631          return $this->mode;
 632      }
 633  
 634      /**
 635       * Returns the area this definition is associated with.
 636       * @return string
 637       */
 638      public function get_area() {
 639          return $this->area;
 640      }
 641  
 642      /**
 643       * Returns the component this definition is associated with.
 644       * @return string
 645       */
 646      public function get_component() {
 647          return $this->component;
 648      }
 649  
 650      /**
 651       * Returns true if this definition is using simple keys.
 652       *
 653       * Simple keys contain only a-zA-Z0-9_
 654       *
 655       * @return bool
 656       */
 657      public function uses_simple_keys() {
 658          return $this->simplekeys;
 659      }
 660  
 661      /**
 662       * Returns the identifiers that are being used for this definition.
 663       * @return array
 664       */
 665      public function get_identifiers() {
 666          if (!isset($this->identifiers)) {
 667              return array();
 668          }
 669          return $this->identifiers;
 670      }
 671  
 672      /**
 673       * Returns the ttl in seconds for this definition if there is one, or null if not.
 674       * @return int|null
 675       */
 676      public function get_ttl() {
 677          return $this->ttl;
 678      }
 679  
 680      /**
 681       * Returns the maximum number of items allowed in this cache.
 682       * @return int
 683       */
 684      public function get_maxsize() {
 685          return $this->maxsize;
 686      }
 687  
 688      /**
 689       * Returns true if this definition should only be used with mappings.
 690       * @return bool
 691       */
 692      public function is_for_mappings_only() {
 693          return $this->mappingsonly;
 694      }
 695  
 696      /**
 697       * Returns true if the data is known to be scalar or array of scalar.
 698       * @return bool
 699       */
 700      public function uses_simple_data() {
 701          return $this->simpledata;
 702      }
 703  
 704      /**
 705       * Returns true if this definition requires a data guarantee from the cache stores being used.
 706       * @return bool
 707       */
 708      public function require_data_guarantee() {
 709          return $this->requiredataguarantee;
 710      }
 711  
 712      /**
 713       * Returns true if this definition requires that the cache stores support multiple identifiers
 714       * @return bool
 715       */
 716      public function require_multiple_identifiers() {
 717          return $this->requiremultipleidentifiers;
 718      }
 719  
 720      /**
 721       * Returns true if this definition requires locking functionality. Either read or write locking.
 722       * @return bool
 723       */
 724      public function require_locking() {
 725          return $this->requirelocking;
 726      }
 727  
 728      /**
 729       * Returns true if this definition requires read locking.
 730       * @return bool
 731       */
 732      public function require_locking_read() {
 733          return $this->requirelockingread;
 734      }
 735  
 736      /**
 737       * Returns true if this definition requires write locking.
 738       * @return bool
 739       */
 740      public function require_locking_write() {
 741          return $this->requirelockingwrite;
 742      }
 743  
 744      /**
 745       * Returns true if this definition allows local storage to be used for caching.
 746       * @since Moodle 3.1.0
 747       * @return bool
 748       */
 749      public function can_use_localstore() {
 750          return $this->canuselocalstore;
 751      }
 752  
 753      /**
 754       * Returns true if this definition requires a searchable cache.
 755       * @since Moodle 2.4.4
 756       * @return bool
 757       */
 758      public function require_searchable() {
 759          return $this->requiresearchable;
 760      }
 761  
 762      /**
 763       * Returns true if this definition has an associated data source.
 764       * @return bool
 765       */
 766      public function has_data_source() {
 767          return !is_null($this->datasource);
 768      }
 769  
 770      /**
 771       * Returns an instance of the data source class used for this definition.
 772       *
 773       * @return cache_data_source
 774       * @throws coding_exception
 775       */
 776      public function get_data_source() {
 777          if (!$this->has_data_source()) {
 778              throw new coding_exception('This cache does not use a data source.');
 779          }
 780          return forward_static_call(array($this->datasource, 'get_instance_for_cache'), $this);
 781      }
 782  
 783      /**
 784       * Sets the identifiers for this definition, or updates them if they have already been set.
 785       *
 786       * @param array $identifiers
 787       * @return bool false if no identifiers where changed, true otherwise.
 788       * @throws coding_exception
 789       */
 790      public function set_identifiers(array $identifiers = array()) {
 791          if ($this->identifiers !== null) {
 792              throw new coding_exception("You can only set identifiers on initial definition creation." .
 793                  " Define a new cache to set different identifiers.");
 794          }
 795          if (!empty($identifiers) && !empty($this->invalidationevents)) {
 796              throw new coding_exception("You cannot use event invalidation and identifiers at the same time.");
 797          }
 798  
 799          foreach ($this->requireidentifiers as $identifier) {
 800              if (!isset($identifiers[$identifier])) {
 801                  throw new coding_exception('Identifier required for cache has not been provided: '.$identifier);
 802              }
 803          }
 804  
 805          $this->identifiers = array();
 806  
 807          foreach ($identifiers as $name => $value) {
 808              $this->identifiers[$name] = (string)$value;
 809          }
 810          // Reset the key prefix's they need updating now.
 811          $this->keyprefixsingle = null;
 812          $this->keyprefixmulti = null;
 813  
 814          return true;
 815      }
 816  
 817      /**
 818       * Returns the requirements of this definition as a binary flag.
 819       * @return int
 820       */
 821      public function get_requirements_bin() {
 822          $requires = 0;
 823          if ($this->require_data_guarantee()) {
 824              $requires += cache_store::SUPPORTS_DATA_GUARANTEE;
 825          }
 826          if ($this->require_multiple_identifiers()) {
 827              $requires += cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS;
 828          }
 829          if ($this->require_searchable()) {
 830              $requires += cache_store::IS_SEARCHABLE;
 831          }
 832          return $requires;
 833      }
 834  
 835      /**
 836       * Please call {@link cache_definition::use_static_acceleration()} instead.
 837       *
 838       * @see cache_definition::use_static_acceleration()
 839       * @deprecated since 2.6
 840       */
 841      public function should_be_persistent() {
 842          throw new coding_exception('cache_definition::should_be_persistent() can not be used anymore.' .
 843              ' Please use cache_definition::use_static_acceleration() instead.');
 844      }
 845  
 846      /**
 847       * Returns true if we should hold onto the data flowing through the cache.
 848       *
 849       * If set to true data flowing through the cache will be stored in a static variable
 850       * to make subsequent requests for the data much faster.
 851       *
 852       * @return bool
 853       */
 854      public function use_static_acceleration() {
 855          if ($this->mode === cache_store::MODE_REQUEST) {
 856              // Request caches should never use static acceleration - it just doesn't make sense.
 857              return false;
 858          }
 859          return $this->staticacceleration;
 860      }
 861  
 862      /**
 863       * Please call {@link cache_definition::get_static_acceleration_size()} instead.
 864       *
 865       * @see cache_definition::get_static_acceleration_size()
 866       * @deprecated since 2.6
 867       */
 868      public function get_persistent_max_size() {
 869          throw new coding_exception('cache_definition::get_persistent_max_size() can not be used anymore.' .
 870              ' Please use cache_definition::get_static_acceleration_size() instead.');
 871      }
 872  
 873      /**
 874       * Returns the max size for the static acceleration array.
 875       * @return int
 876       */
 877      public function get_static_acceleration_size() {
 878          return $this->staticaccelerationsize;
 879      }
 880  
 881      /**
 882       * Generates a hash of this definition and returns it.
 883       * @return string
 884       */
 885      public function generate_definition_hash() {
 886          if ($this->definitionhash === null) {
 887              $this->definitionhash = md5("{$this->mode} {$this->component} {$this->area}");
 888          }
 889          return $this->definitionhash;
 890      }
 891  
 892      /**
 893       * Generates a single key prefix for this definition
 894       *
 895       * @return string
 896       */
 897      public function generate_single_key_prefix() {
 898          if ($this->keyprefixsingle === null) {
 899              $this->keyprefixsingle = $this->mode.'/'.$this->component.'/'.$this->area;
 900              $this->keyprefixsingle .= '/'.$this->get_cache_identifier();
 901              $identifiers = $this->get_identifiers();
 902              if ($identifiers) {
 903                  foreach ($identifiers as $key => $value) {
 904                      $this->keyprefixsingle .= '/'.$key.'='.$value;
 905                  }
 906              }
 907              $this->keyprefixsingle = md5($this->keyprefixsingle);
 908          }
 909          return $this->keyprefixsingle;
 910      }
 911  
 912      /**
 913       * Generates a multi key prefix for this definition
 914       *
 915       * @return array
 916       */
 917      public function generate_multi_key_parts() {
 918          if ($this->keyprefixmulti === null) {
 919              $this->keyprefixmulti = array(
 920                  'mode' => $this->mode,
 921                  'component' => $this->component,
 922                  'area' => $this->area,
 923                  'siteidentifier' => $this->get_cache_identifier()
 924              );
 925              if (isset($this->identifiers) && !empty($this->identifiers)) {
 926                  $identifiers = array();
 927                  foreach ($this->identifiers as $key => $value) {
 928                      $identifiers[] = htmlentities($key, ENT_QUOTES, 'UTF-8').'='.htmlentities($value, ENT_QUOTES, 'UTF-8');
 929                  }
 930                  $this->keyprefixmulti['identifiers'] = join('&', $identifiers);
 931              }
 932          }
 933          return $this->keyprefixmulti;
 934      }
 935  
 936      /**
 937       * Check if this definition should invalidate on the given event.
 938       *
 939       * @param string $event
 940       * @return bool True if the definition should invalidate on the event. False otherwise.
 941       */
 942      public function invalidates_on_event($event) {
 943          return (in_array($event, $this->invalidationevents));
 944      }
 945  
 946      /**
 947       * Check if the definition has any invalidation events.
 948       *
 949       * @return bool True if it does, false otherwise
 950       */
 951      public function has_invalidation_events() {
 952          return !empty($this->invalidationevents);
 953      }
 954  
 955      /**
 956       * Returns all of the invalidation events for this definition.
 957       *
 958       * @return array
 959       */
 960      public function get_invalidation_events() {
 961          return $this->invalidationevents;
 962      }
 963  
 964      /**
 965       * Returns a cache identification string.
 966       *
 967       * @return string A string to be used as part of keys.
 968       */
 969      protected function get_cache_identifier() {
 970          $identifiers = array();
 971          if ($this->selectedsharingoption & self::SHARING_ALL) {
 972              // Nothing to do here.
 973          } else {
 974              if ($this->selectedsharingoption & self::SHARING_SITEID) {
 975                  $identifiers[] = cache_helper::get_site_identifier();
 976              }
 977              if ($this->selectedsharingoption & self::SHARING_VERSION) {
 978                  $identifiers[] = cache_helper::get_site_version();
 979              }
 980              if ($this->selectedsharingoption & self::SHARING_INPUT && !empty($this->userinputsharingkey)) {
 981                  $identifiers[] = $this->userinputsharingkey;
 982              }
 983          }
 984          return join('/', $identifiers);
 985      }
 986  
 987      /**
 988       * Returns true if this definition requires identifiers.
 989       *
 990       * @param bool
 991       */
 992      public function has_required_identifiers() {
 993          return (count($this->requireidentifiers) > 0);
 994      }
 995  
 996      /**
 997       * Returns the possible sharing options that can be used with this defintion.
 998       *
 999       * @return int
1000       */
1001      public function get_sharing_options() {
1002          return $this->sharingoptions;
1003      }
1004  
1005      /**
1006       * Returns the user entered sharing key for this definition.
1007       *
1008       * @return string
1009       */
1010      public function get_user_input_sharing_key() {
1011          return $this->userinputsharingkey;
1012      }
1013  
1014      /**
1015       * Returns the user selected sharing option for this definition.
1016       *
1017       * @return int
1018       */
1019      public function get_selected_sharing_option() {
1020          return $this->selectedsharingoption;
1021      }
1022  }