Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

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