Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 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 implements cache_loader_with_locking {
  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       * Pretend that we got a lock to avoid errors.
 206       *
 207       * @param int|string $key
 208       * @return bool
 209       */
 210      public function acquire_lock($key) : bool {
 211          return true;
 212      }
 213  
 214      /**
 215       * Pretend that we released a lock to avoid errors.
 216       *
 217       * @param int|string $key
 218       * @return bool
 219       */
 220      public function release_lock($key) : bool {
 221          return true;
 222      }
 223  
 224      /**
 225       * Pretend that we have a lock to avoid errors.
 226       *
 227       * @param int|string $key
 228       * @return bool
 229       */
 230      public function check_lock_state($key) : bool {
 231          return true;
 232      }
 233  }
 234  
 235  /**
 236   * The cache factory class used when the Cache has been disabled.
 237   *
 238   * @copyright  2012 Sam Hemelryk
 239   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 240   */
 241  class cache_factory_disabled extends cache_factory {
 242  
 243      /**
 244       * Returns an instance of the cache_factor method.
 245       *
 246       * @param bool $forcereload Unused.
 247       * @return cache_factory
 248       * @throws coding_exception
 249       */
 250      public static function instance($forcereload = false) {
 251          throw new coding_exception('You must not call to this cache factory within your code.');
 252      }
 253  
 254      /**
 255       * Creates a definition instance or returns the existing one if it has already been created.
 256       *
 257       * @param string $component
 258       * @param string $area
 259       * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
 260       * @return cache_definition
 261       */
 262      public function create_definition($component, $area, $unused = null) {
 263          $definition = parent::create_definition($component, $area);
 264          if ($definition->has_data_source()) {
 265              return $definition;
 266          }
 267  
 268          return cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area);
 269      }
 270  
 271      /**
 272       * Common public method to create a cache instance given a definition.
 273       *
 274       * @param cache_definition $definition
 275       * @return cache_application|cache_session|cache_store
 276       * @throws coding_exception
 277       */
 278      public function create_cache(cache_definition $definition) {
 279          $loader = null;
 280          if ($definition->has_data_source()) {
 281              $loader = $definition->get_data_source();
 282          }
 283          return new cache_disabled($definition, $this->create_dummy_store($definition), $loader);
 284      }
 285  
 286      /**
 287       * Creates a cache object given the parameters for a definition.
 288       *
 289       * @param string $component
 290       * @param string $area
 291       * @param array $identifiers
 292       * @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
 293       * @return cache_application|cache_session|cache_request
 294       */
 295      public function create_cache_from_definition($component, $area, array $identifiers = array(), $unused = null) {
 296          // Regular cache definitions are cached inside create_definition().  This is not the case for disabledlib.php
 297          // definitions as they use load_adhoc().  They are built as a new object on each call.
 298          // We do not need to clone the definition because we know it's new.
 299          $definition = $this->create_definition($component, $area);
 300          $definition->set_identifiers($identifiers);
 301          $cache = $this->create_cache($definition);
 302          return $cache;
 303      }
 304  
 305      /**
 306       * Creates an ad-hoc cache from the given param.
 307       *
 308       * @param int $mode
 309       * @param string $component
 310       * @param string $area
 311       * @param array $identifiers
 312       * @param array $options An array of options, available options are:
 313       *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
 314       *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
 315       *   - staticacceleration : If set to true the cache will hold onto all data passing through it.
 316       *   - staticaccelerationsize : Sets the max size of the static acceleration array.
 317       * @return cache_application|cache_session|cache_request
 318       */
 319      public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
 320          // Regular cache definitions are cached inside create_definition().  This is not the case for disabledlib.php
 321          // definitions as they use load_adhoc().  They are built as a new object on each call.
 322          // We do not need to clone the definition because we know it's new.
 323          $definition = cache_definition::load_adhoc($mode, $component, $area, $options);
 324          $definition->set_identifiers($identifiers);
 325          $cache = $this->create_cache($definition);
 326          return $cache;
 327      }
 328  
 329      /**
 330       * Creates a store instance given its name and configuration.
 331       *
 332       * @param string $name Unused.
 333       * @param array $details Unused.
 334       * @param cache_definition $definition
 335       * @return boolean|cache_store
 336       */
 337      public function create_store_from_config($name, array $details, cache_definition $definition) {
 338          return $this->create_dummy_store($definition);
 339      }
 340  
 341      /**
 342       * Creates a cache config instance with the ability to write if required.
 343       *
 344       * @param bool $writer Unused.
 345       * @return cache_config_disabled|cache_config_writer
 346       */
 347      public function create_config_instance($writer = false) {
 348          // We are always going to use the cache_config_disabled class for all regular request.
 349          // However if the code has requested the writer then likely something is changing and
 350          // we're going to need to interact with the config.php file.
 351          // In this case we will still use the cache_config_writer.
 352          $class = 'cache_config_disabled';
 353          if ($writer) {
 354              // If the writer was requested then something is changing.
 355              $class = 'cache_config_writer';
 356          }
 357          if (!array_key_exists($class, $this->configs)) {
 358              self::set_state(self::STATE_INITIALISING);
 359              if ($class === 'cache_config_disabled') {
 360                  $configuration = $class::create_default_configuration();
 361                  $this->configs[$class] = new $class;
 362              } else {
 363                  $configuration = false;
 364                  // If we need a writer, we should get the classname from the generic factory.
 365                  // This is so alternative classes can be used if a different writer is required.
 366                  $this->configs[$class] = parent::get_disabled_writer();
 367              }
 368              $this->configs[$class]->load($configuration);
 369          }
 370          self::set_state(self::STATE_READY);
 371  
 372          // Return the instance.
 373          return $this->configs[$class];
 374      }
 375  
 376      /**
 377       * Returns true if the cache API has been disabled.
 378       *
 379       * @return bool
 380       */
 381      public function is_disabled() {
 382          return true;
 383      }
 384  }
 385  
 386  /**
 387   * The cache config class used when the Cache has been disabled.
 388   *
 389   * @copyright  2012 Sam Hemelryk
 390   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 391   */
 392  class cache_config_disabled extends cache_config_writer {
 393  
 394      /**
 395       * Returns an instance of the configuration writer.
 396       *
 397       * @return cache_config_disabled
 398       */
 399      public static function instance() {
 400          $factory = cache_factory::instance();
 401          return $factory->create_config_instance(true);
 402      }
 403  
 404      /**
 405       * Saves the current configuration.
 406       */
 407      protected function config_save() {
 408          // Nothing to do here.
 409      }
 410  
 411      /**
 412       * Generates a configuration array suitable to be written to the config file.
 413       *
 414       * @return array
 415       */
 416      protected function generate_configuration_array() {
 417          $configuration = array();
 418          $configuration['stores'] = $this->configstores;
 419          $configuration['modemappings'] = $this->configmodemappings;
 420          $configuration['definitions'] = $this->configdefinitions;
 421          $configuration['definitionmappings'] = $this->configdefinitionmappings;
 422          $configuration['locks'] = $this->configlocks;
 423          return $configuration;
 424      }
 425  
 426      /**
 427       * Adds a plugin instance.
 428       *
 429       * @param string $name Unused.
 430       * @param string $plugin Unused.
 431       * @param array $configuration Unused.
 432       * @return bool
 433       * @throws cache_exception
 434       */
 435      public function add_store_instance($name, $plugin, array $configuration = array()) {
 436          return false;
 437      }
 438  
 439      /**
 440       * Sets the mode mappings.
 441       *
 442       * @param array $modemappings Unused.
 443       * @return bool
 444       * @throws cache_exception
 445       */
 446      public function set_mode_mappings(array $modemappings) {
 447          return false;
 448      }
 449  
 450      /**
 451       * Edits a give plugin instance.
 452       *
 453       * @param string $name Unused.
 454       * @param string $plugin Unused.
 455       * @param array $configuration Unused.
 456       * @return bool
 457       * @throws cache_exception
 458       */
 459      public function edit_store_instance($name, $plugin, $configuration) {
 460          return false;
 461      }
 462  
 463      /**
 464       * Deletes a store instance.
 465       *
 466       * @param string $name Unused.
 467       * @return bool
 468       * @throws cache_exception
 469       */
 470      public function delete_store_instance($name) {
 471          return false;
 472      }
 473  
 474      /**
 475       * Creates the default configuration and saves it.
 476       *
 477       * @param bool $forcesave Ignored because we are disabled!
 478       * @return array
 479       */
 480      public static function create_default_configuration($forcesave = false) {
 481          global $CFG;
 482  
 483          // HACK ALERT.
 484          // We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
 485          // default store plugins are protected from deletion.
 486          require_once($CFG->dirroot.'/cache/stores/file/lib.php');
 487          require_once($CFG->dirroot.'/cache/stores/session/lib.php');
 488          require_once($CFG->dirroot.'/cache/stores/static/lib.php');
 489  
 490          $writer = new self;
 491          $writer->configstores = array(
 492              'default_application' => array(
 493                  'name' => 'default_application',
 494                  'plugin' => 'file',
 495                  'configuration' => array(),
 496                  'features' => cachestore_file::get_supported_features(),
 497                  'modes' => cache_store::MODE_APPLICATION,
 498                  'default' => true,
 499              ),
 500              'default_session' => array(
 501                  'name' => 'default_session',
 502                  'plugin' => 'session',
 503                  'configuration' => array(),
 504                  'features' => cachestore_session::get_supported_features(),
 505                  'modes' => cache_store::MODE_SESSION,
 506                  'default' => true,
 507              ),
 508              'default_request' => array(
 509                  'name' => 'default_request',
 510                  'plugin' => 'static',
 511                  'configuration' => array(),
 512                  'features' => cachestore_static::get_supported_features(),
 513                  'modes' => cache_store::MODE_REQUEST,
 514                  'default' => true,
 515              )
 516          );
 517          $writer->configdefinitions = array();
 518          $writer->configmodemappings = array(
 519              array(
 520                  'mode' => cache_store::MODE_APPLICATION,
 521                  'store' => 'default_application',
 522                  'sort' => -1
 523              ),
 524              array(
 525                  'mode' => cache_store::MODE_SESSION,
 526                  'store' => 'default_session',
 527                  'sort' => -1
 528              ),
 529              array(
 530                  'mode' => cache_store::MODE_REQUEST,
 531                  'store' => 'default_request',
 532                  'sort' => -1
 533              )
 534          );
 535          $writer->configlocks = array(
 536              'default_file_lock' => array(
 537                  'name' => 'cachelock_file_default',
 538                  'type' => 'cachelock_file',
 539                  'dir' => 'filelocks',
 540                  'default' => true
 541              )
 542          );
 543  
 544          return $writer->generate_configuration_array();
 545      }
 546  
 547      /**
 548       * Updates the definition in the configuration from those found in the cache files.
 549       *
 550       * @param bool $coreonly Unused.
 551       */
 552      public static function update_definitions($coreonly = false) {
 553          // Nothing to do here.
 554      }
 555  
 556      /**
 557       * Locates all of the definition files.
 558       *
 559       * @param bool $coreonly Unused.
 560       * @return array
 561       */
 562      protected static function locate_definitions($coreonly = false) {
 563          return array();
 564      }
 565  
 566      /**
 567       * Sets the mappings for a given definition.
 568       *
 569       * @param string $definition Unused.
 570       * @param array $mappings Unused.
 571       * @throws coding_exception
 572       */
 573      public function set_definition_mappings($definition, $mappings) {
 574          // Nothing to do here.
 575      }
 576  }