MDL-82158 core_cache: Coding style fixes

This commit is contained in:
Andrew Nicols 2024-08-05 09:49:33 +08:00
parent bac9672b7f
commit b92008c92c
No known key found for this signature in database
GPG key ID: 6D1E3157C8CFBF14
53 changed files with 2506 additions and 2081 deletions

8
cache/admin.php vendored
View file

@ -19,14 +19,14 @@
*
* This file is part of Moodle's cache API, affectionately called MUC.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->dirroot.'/lib/adminlib.php');
require_once($CFG->dirroot . '/lib/adminlib.php');
// The first time the user visits this page we are going to reparse the definitions.
// Just ensures that everything is up to date.
@ -42,7 +42,7 @@ $action = optional_param('action', null, PARAM_ALPHA);
admin_externalpage_setup('cacheconfig');
$adminhelper = cache_factory::instance()->get_administration_display_helper();
$notifications = array();
$notifications = [];
// Empty array to hold any form information returned from actions.
$forminfo = [];
@ -57,7 +57,7 @@ if (!empty($action)) {
// Add cache store warnings to the list of notifications.
// Obviously as these are warnings they are show as failures.
foreach (cache_helper::warnings(core_cache\administration_helper::get_store_instance_summaries()) as $warning) {
$notifications[] = array($warning, false);
$notifications[] = [$warning, false];
}
// Decide on display mode based on returned forminfo.

View file

@ -14,47 +14,33 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Cache administration helper.
*
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are requried in order to use caching.
*
* @package core
* @category cache
* @author Peter Burnett <peterburnett@catalyst-au.net>
* @copyright 2020 Catalyst IT
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_cache;
defined('MOODLE_INTERNAL') || die();
use cache_helper, cache_store, cache_config, cache_factory, cache_definition;
use core_component;
use core\output\pix_icon;
use lang_string;
/**
* Administration helper base class.
*
* Defines abstract methods for a subclass to define the admin page.
*
* @package core
* @package core_cache
* @category cache
* @author Peter Burnett <peterburnett@catalyst-au.net>
* @copyright 2020 Catalyst IT
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class administration_helper extends cache_helper {
abstract class administration_helper extends helper {
/**
* Returns an array containing all of the information about stores a renderer needs.
* @return array
*/
public static function get_store_instance_summaries(): array {
$return = array();
$default = array();
$instance = \cache_config::instance();
$return = [];
$default = [];
$instance = config::instance();
$stores = $instance->get_all_stores();
$locks = $instance->get_locks();
foreach ($stores as $name => $details) {
@ -64,7 +50,7 @@ abstract class administration_helper extends cache_helper {
$store = new $class($details['name'], $details['configuration']);
}
$lock = (isset($details['lock'])) ? $locks[$details['lock']] : $instance->get_default_lock();
$record = array(
$record = [
'name' => $name,
'plugin' => $details['plugin'],
'default' => $details['default'],
@ -72,24 +58,24 @@ abstract class administration_helper extends cache_helper {
'requirementsmet' => $class::are_requirements_met(),
'mappings' => 0,
'lock' => $lock,
'modes' => array(
cache_store::MODE_APPLICATION =>
($class::get_supported_modes($return) & cache_store::MODE_APPLICATION) == cache_store::MODE_APPLICATION,
cache_store::MODE_SESSION =>
($class::get_supported_modes($return) & cache_store::MODE_SESSION) == cache_store::MODE_SESSION,
cache_store::MODE_REQUEST =>
($class::get_supported_modes($return) & cache_store::MODE_REQUEST) == cache_store::MODE_REQUEST,
),
'supports' => array(
'modes' => [
store::MODE_APPLICATION =>
($class::get_supported_modes($return) & store::MODE_APPLICATION) == store::MODE_APPLICATION,
store::MODE_SESSION =>
($class::get_supported_modes($return) & store::MODE_SESSION) == store::MODE_SESSION,
store::MODE_REQUEST =>
($class::get_supported_modes($return) & store::MODE_REQUEST) == store::MODE_REQUEST,
],
'supports' => [
'multipleidentifiers' => $store ? $store->supports_multiple_identifiers() : false,
'dataguarantee' => $store ? $store->supports_data_guarantee() : false,
'nativettl' => $store ? $store->supports_native_ttl() : false,
'nativelocking' => ($store instanceof \cache_is_lockable),
'keyawareness' => ($store instanceof \cache_is_key_aware),
'searchable' => ($store instanceof \cache_is_searchable)
),
'warnings' => $store ? $store->get_warnings() : array()
);
'searchable' => ($store instanceof \cache_is_searchable),
],
'warnings' => $store ? $store->get_warnings() : [],
];
if (empty($details['default'])) {
$return[$name] = $record;
} else {
@ -136,31 +122,31 @@ abstract class administration_helper extends cache_helper {
* See the code below for details
*/
public static function get_store_plugin_summaries(): array {
$return = array();
$return = [];
$plugins = \core_component::get_plugin_list_with_file('cachestore', 'lib.php', true);
foreach ($plugins as $plugin => $path) {
$class = 'cachestore_'.$plugin;
$return[$plugin] = array(
'name' => get_string('pluginname', 'cachestore_'.$plugin),
$class = 'cachestore_' . $plugin;
$return[$plugin] = [
'name' => get_string('pluginname', 'cachestore_' . $plugin),
'requirementsmet' => $class::are_requirements_met(),
'instances' => 0,
'modes' => array(
cache_store::MODE_APPLICATION => ($class::get_supported_modes() & cache_store::MODE_APPLICATION),
cache_store::MODE_SESSION => ($class::get_supported_modes() & cache_store::MODE_SESSION),
cache_store::MODE_REQUEST => ($class::get_supported_modes() & cache_store::MODE_REQUEST),
),
'supports' => array(
'multipleidentifiers' => ($class::get_supported_features() & cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS),
'dataguarantee' => ($class::get_supported_features() & cache_store::SUPPORTS_DATA_GUARANTEE),
'nativettl' => ($class::get_supported_features() & cache_store::SUPPORTS_NATIVE_TTL),
'nativelocking' => (in_array('cache_is_lockable', class_implements($class))),
'keyawareness' => (array_key_exists('cache_is_key_aware', class_implements($class))),
),
'canaddinstance' => ($class::can_add_instance() && $class::are_requirements_met())
);
'modes' => [
store::MODE_APPLICATION => ($class::get_supported_modes() & store::MODE_APPLICATION),
store::MODE_SESSION => ($class::get_supported_modes() & store::MODE_SESSION),
store::MODE_REQUEST => ($class::get_supported_modes() & store::MODE_REQUEST),
],
'supports' => [
'multipleidentifiers' => ($class::get_supported_features() & store::SUPPORTS_MULTIPLE_IDENTIFIERS),
'dataguarantee' => ($class::get_supported_features() & store::SUPPORTS_DATA_GUARANTEE),
'nativettl' => ($class::get_supported_features() & store::SUPPORTS_NATIVE_TTL),
'nativelocking' => (in_array(lockable_cache_interface::class, class_implements($class))),
'keyawareness' => (array_key_exists(key_aware_cache_interface::class, class_implements($class))),
],
'canaddinstance' => ($class::can_add_instance() && $class::are_requirements_met()),
];
}
$instance = cache_config::instance();
$instance = config::instance();
$stores = $instance->get_all_stores();
foreach ($stores as $store) {
$plugin = $store['plugin'];
@ -179,28 +165,28 @@ abstract class administration_helper extends cache_helper {
* See the code below for details
*/
public static function get_definition_summaries(): array {
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance();
$storenames = array();
$storenames = [];
foreach ($config->get_all_stores() as $key => $store) {
if (!empty($store['default'])) {
$storenames[$key] = new \lang_string('store_'.$key, 'cache');
$storenames[$key] = new lang_string('store_' . $key, 'cache');
} else {
$storenames[$store['name']] = $store['name'];
}
}
/* @var cache_definition[] $definitions */
/* @var definition[] $definitions */
$definitions = [];
$return = [];
foreach ($config->get_definitions() as $key => $definition) {
$definitions[$key] = cache_definition::load($definition['component'].'/'.$definition['area'], $definition);
$definitions[$key] = definition::load($definition['component'] . '/' . $definition['area'], $definition);
}
foreach ($definitions as $id => $definition) {
$mappings = array();
foreach (cache_helper::get_stores_suitable_for_definition($definition) as $store) {
$mappings = [];
foreach (helper::get_stores_suitable_for_definition($definition) as $store) {
$mappings[] = $storenames[$store->my_name()];
}
$return[$id] = array(
$return[$id] = [
'id' => $id,
'name' => $definition->get_name(),
'mode' => $definition->get_mode(),
@ -210,8 +196,8 @@ abstract class administration_helper extends cache_helper {
'canuselocalstore' => $definition->can_use_localstore(),
'sharingoptions' => self::get_definition_sharing_options($definition->get_sharing_options(), false),
'selectedsharingoption' => self::get_definition_sharing_options($definition->get_selected_sharing_option(), true),
'userinputsharingkey' => $definition->get_user_input_sharing_key()
);
'userinputsharingkey' => $definition->get_user_input_sharing_key(),
];
}
return $return;
}
@ -223,20 +209,20 @@ abstract class administration_helper extends cache_helper {
*/
public static function get_default_mode_stores(): array {
global $OUTPUT;
$instance = cache_config::instance();
$adequatestores = cache_helper::get_stores_suitable_for_mode_default();
$icon = new \pix_icon('i/warning', new \lang_string('inadequatestoreformapping', 'cache'));
$storenames = array();
$instance = config::instance();
$adequatestores = helper::get_stores_suitable_for_mode_default();
$icon = new pix_icon('i/warning', new lang_string('inadequatestoreformapping', 'cache'));
$storenames = [];
foreach ($instance->get_all_stores() as $key => $store) {
if (!empty($store['default'])) {
$storenames[$key] = new \lang_string('store_'.$key, 'cache');
$storenames[$key] = new lang_string('store_' . $key, 'cache');
}
}
$modemappings = array(
cache_store::MODE_APPLICATION => array(),
cache_store::MODE_SESSION => array(),
cache_store::MODE_REQUEST => array(),
);
$modemappings = [
store::MODE_APPLICATION => [],
store::MODE_SESSION => [],
store::MODE_REQUEST => [],
];
foreach ($instance->get_mode_mappings() as $mapping) {
$mode = $mapping['mode'];
if (!array_key_exists($mode, $modemappings)) {
@ -249,7 +235,7 @@ abstract class administration_helper extends cache_helper {
$modemappings[$mode][$mapping['store']] = $mapping['store'];
}
if (!array_key_exists($mapping['store'], $adequatestores)) {
$modemappings[$mode][$mapping['store']] = $modemappings[$mode][$mapping['store']].' '.$OUTPUT->render($icon);
$modemappings[$mode][$mapping['store']] = $modemappings[$mode][$mapping['store']] . ' ' . $OUTPUT->render($icon);
}
}
return $modemappings;
@ -261,13 +247,13 @@ abstract class administration_helper extends cache_helper {
* @return array array of lock summaries.
*/
public static function get_lock_summaries(): array {
$locks = array();
$instance = cache_config::instance();
$locks = [];
$instance = config::instance();
$stores = $instance->get_all_stores();
foreach ($instance->get_locks() as $lock) {
$default = !empty($lock['default']);
if ($default) {
$name = new \lang_string($lock['name'], 'cache');
$name = new lang_string($lock['name'], 'cache');
} else {
$name = $lock['name'];
}
@ -277,12 +263,12 @@ abstract class administration_helper extends cache_helper {
$uses++;
}
}
$lockdata = array(
$lockdata = [
'name' => $name,
'default' => $default,
'uses' => $uses,
'type' => get_string('pluginname', $lock['type'])
);
'type' => get_string('pluginname', $lock['type']),
];
$locks[$lock['name']] = $lockdata;
}
return $locks;
@ -296,19 +282,19 @@ abstract class administration_helper extends cache_helper {
* @return array An array of lang_string's.
*/
public static function get_definition_sharing_options(int $sharingoption, bool $isselectedoptions = true): array {
$options = array();
$options = [];
$prefix = ($isselectedoptions) ? 'sharingselected' : 'sharing';
if ($sharingoption & cache_definition::SHARING_ALL) {
$options[cache_definition::SHARING_ALL] = new \lang_string($prefix.'_all', 'cache');
if ($sharingoption & definition::SHARING_ALL) {
$options[definition::SHARING_ALL] = new lang_string($prefix . '_all', 'cache');
}
if ($sharingoption & cache_definition::SHARING_SITEID) {
$options[cache_definition::SHARING_SITEID] = new \lang_string($prefix.'_siteid', 'cache');
if ($sharingoption & definition::SHARING_SITEID) {
$options[definition::SHARING_SITEID] = new lang_string($prefix . '_siteid', 'cache');
}
if ($sharingoption & cache_definition::SHARING_VERSION) {
$options[cache_definition::SHARING_VERSION] = new \lang_string($prefix.'_version', 'cache');
if ($sharingoption & definition::SHARING_VERSION) {
$options[definition::SHARING_VERSION] = new lang_string($prefix . '_version', 'cache');
}
if ($sharingoption & cache_definition::SHARING_INPUT) {
$options[cache_definition::SHARING_INPUT] = new \lang_string($prefix.'_input', 'cache');
if ($sharingoption & definition::SHARING_INPUT) {
$options[definition::SHARING_INPUT] = new lang_string($prefix . '_input', 'cache');
}
return $options;
}
@ -324,13 +310,13 @@ abstract class administration_helper extends cache_helper {
* 3. An array of default stores
*/
public static function get_definition_store_options(string $component, string $area): array {
$factory = cache_factory::instance();
$factory = factory::instance();
$definition = $factory->create_definition($component, $area);
$config = cache_config::instance();
$config = config::instance();
$currentstores = $config->get_stores_for_definition($definition);
$possiblestores = $config->get_stores($definition->get_mode(), $definition->get_requirements_bin());
$defaults = array();
$defaults = [];
foreach ($currentstores as $key => $store) {
if (!empty($store['default'])) {
$defaults[] = $key;
@ -343,7 +329,7 @@ abstract class administration_helper extends cache_helper {
$possiblestores[$key] = $store;
}
}
return array($currentstores, $possiblestores, $defaults);
return [$currentstores, $possiblestores, $defaults];
}
/**
@ -354,7 +340,7 @@ abstract class administration_helper extends cache_helper {
* @return array array of actions.
*/
public function get_store_plugin_actions(string $name, array $plugindetails): array {
return array();
return [];
}
/**
@ -365,7 +351,7 @@ abstract class administration_helper extends cache_helper {
* @return array array of actions.
*/
public function get_store_instance_actions(string $name, array $storedetails): array {
return array();
return [];
}
/**
@ -376,7 +362,7 @@ abstract class administration_helper extends cache_helper {
* @return array array of actions.
*/
public function get_definition_actions(\context $context, array $definitionsummary): array {
return array();
return [];
}
/**
@ -385,7 +371,7 @@ abstract class administration_helper extends cache_helper {
* @return array array of locks that are addable.
*/
public function get_addable_lock_options(): array {
return array();
return [];
}
/**

View file

@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use core\exception\moodle_exception;
/**
* An application cache.
*
@ -26,13 +31,12 @@
*
* @internal don't use me directly.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_application extends cache implements cache_loader_with_locking {
class application_cache extends cache implements loader_with_locking_interface {
/**
* Lock identifier.
* This is used to ensure the lock belongs to the cache instance + definition + user.
@ -43,7 +47,7 @@ class cache_application extends cache implements cache_loader_with_locking {
/**
* Gets set to true if the cache's primary store natively supports locking.
* If it does then we use that, otherwise we need to instantiate a second store to use for locking.
* @var cache_store
* @var store
*/
protected $nativelocking = null;
@ -62,7 +66,7 @@ class cache_application extends cache implements cache_loader_with_locking {
protected $requirelockingbeforewrite = false;
/**
* Gets set to a cache_store to use for locking if the caches primary store doesn't support locking natively.
* Gets set to a store to use for locking if the caches primary store doesn't support locking natively.
* @var cache_lock_interface
*/
protected $cachelockinstance;
@ -78,11 +82,11 @@ class cache_application extends cache implements cache_loader_with_locking {
*
* You should not call this method from your code, instead you should use the cache::make methods.
*
* @param cache_definition $definition
* @param cache_store $store
* @param cache_loader|cache_data_source $loader
* @param definition $definition
* @param store $store
* @param loader_interface|data_source_interface $loader
*/
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
public function __construct(definition $definition, store $store, $loader = null) {
parent::__construct($definition, $store, $loader);
$this->nativelocking = $this->store_supports_native_locking();
if ($definition->require_locking()) {
@ -141,7 +145,7 @@ class cache_application extends cache implements cache_loader_with_locking {
// We need to release this lock later if the lock is not successful.
$releaseparent = true;
}
$hashedkey = cache_helper::hash_key($key, $this->get_definition());
$hashedkey = helper::hash_key($key, $this->get_definition());
$before = microtime(true);
if ($this->nativelocking) {
$lock = $this->get_store()->acquire_lock($hashedkey, $this->get_identifier());
@ -153,14 +157,25 @@ class cache_application extends cache implements cache_loader_with_locking {
if ($lock) {
$this->locks[$hashedkey] = $lock;
if (MDL_PERF || $this->perfdebug) {
\core\lock\timing_wrapper_lock_factory::record_lock_data($after, $before,
$this->get_definition()->get_id(), $hashedkey, $lock, $this->get_identifier() . $hashedkey);
\core\lock\timing_wrapper_lock_factory::record_lock_data(
$after,
$before,
$this->get_definition()->get_id(),
$hashedkey,
$lock,
$this->get_identifier() . $hashedkey
);
}
$releaseparent = false;
return true;
} else {
throw new moodle_exception('ex_unabletolock', 'cache', '', null,
'store: ' . get_class($this->get_store()) . ', lock: ' . $hashedkey);
throw new moodle_exception(
'ex_unabletolock',
'cache',
'',
null,
'store: ' . get_class($this->get_store()) . ', lock: ' . $hashedkey
);
}
} finally {
// Release the parent lock if we acquired it, then threw an exception.
@ -178,7 +193,7 @@ class cache_application extends cache implements cache_loader_with_locking {
* someone else has the lock.
*/
public function check_lock_state($key) {
$key = cache_helper::hash_key($key, $this->get_definition());
$key = helper::hash_key($key, $this->get_definition());
if (!empty($this->locks[$key])) {
return true; // Shortcut to save having to make a call to the cache store if the lock is held by this process.
}
@ -198,7 +213,7 @@ class cache_application extends cache implements cache_loader_with_locking {
*/
public function release_lock($key) {
$loaderkey = $key;
$key = cache_helper::hash_key($key, $this->get_definition());
$key = helper::hash_key($key, $this->get_definition());
if ($this->nativelocking) {
$released = $this->get_store()->release_lock($key, $this->get_identifier());
} else {
@ -224,7 +239,7 @@ class cache_application extends cache implements cache_loader_with_locking {
*/
protected function ensure_cachelock_available() {
if ($this->cachelockinstance === null) {
$this->cachelockinstance = cache_helper::get_cachelock_for_store($this->get_store());
$this->cachelockinstance = helper::get_cachelock_for_store($this->get_store());
}
}
@ -328,3 +343,8 @@ class cache_application extends cache implements cache_loader_with_locking {
return parent::delete_many($keys, $recurse);
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(application_cache::class, \cache_application::class);

View file

@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use stdClass;
/**
* The main cache class.
*
@ -21,13 +26,12 @@
* In order to create an instance of a cache that they can work with they must call one of the static make methods belonging
* to this class.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache implements cache_loader {
class cache implements loader_interface {
/**
* @var int Constant for cache entries that do not have a version number
*/
@ -51,13 +55,13 @@ class cache implements cache_loader {
/**
* The definition used when loading this cache if there was one.
* @var cache_definition
* @var definition
*/
private $definition = false;
/**
* The cache store that this loader will make use of.
* @var cache_store
* @var store
*/
private $store;
@ -66,14 +70,14 @@ class cache implements cache_loader {
* If a cache request misses for the store belonging to this loader then the loader
* stored here will be checked next.
* If there is a loader here then $datasource must be false.
* @var cache_loader|false
* @var loader_interface|false
*/
private $loader = false;
/**
* The data source to use if we need to load data (because if doesn't exist in the cache store).
* If there is a data source here then $loader above must be false.
* @var cache_data_source|false
* @var data_source_interface|false
*/
private $datasource = false;
@ -105,7 +109,7 @@ class cache implements cache_loader {
* Items will be stored in this cache as they were provided. This ensure there is no unnecessary processing taking place.
* @var array
*/
private $staticaccelerationarray = array();
private $staticaccelerationarray = [];
/**
* The number of items in the static acceleration array. Avoids count calls like you wouldn't believe.
@ -120,7 +124,7 @@ class cache implements cache_loader {
* key that is first on this array.
* @var array
*/
private $staticaccelerationkeys = array();
private $staticaccelerationkeys = [];
/**
* The maximum size of the static acceleration array.
@ -168,7 +172,7 @@ class cache implements cache_loader {
/**
* Gets set to true if the cache's primary store natively supports locking.
* If it does then we use that, otherwise we need to instantiate a second store to use for locking.
* @var cache_store|null
* @var store|null
*/
protected $nativelocking = null;
@ -179,17 +183,17 @@ class cache implements cache_loader {
* @param string $area The area for the definition
* @param array $identifiers Any additional identifiers that should be provided to the definition.
* @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
* @return cache_application|cache_session|cache_store
* @return application_cache|session_cache|store
*/
public static function make($component, $area, array $identifiers = array(), $unused = null) {
$factory = cache_factory::instance();
public static function make($component, $area, array $identifiers = [], $unused = null) {
$factory = factory::instance();
return $factory->create_cache_from_definition($component, $area, $identifiers);
}
/**
* Creates a new cache instance based upon the given params.
*
* @param int $mode One of cache_store::MODE_*
* @param int $mode One of store::MODE_*
* @param string $component The component this cache relates to.
* @param string $area The area this cache relates to.
* @param array $identifiers Any additional identifiers that should be provided to the definition.
@ -198,10 +202,10 @@ class cache implements cache_loader {
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
* - staticacceleration : If set to true the cache will hold onto data passing through it.
* - staticaccelerationsize : The max size for the static acceleration array.
* @return cache_application|cache_session|cache_request
* @return application_cache|session_cache|request_cache
*/
public static function make_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
$factory = cache_factory::instance();
public static function make_from_params($mode, $component, $area, array $identifiers = [], array $options = []) {
$factory = factory::instance();
return $factory->create_cache_from_params($mode, $component, $area, $identifiers, $options);
}
@ -210,25 +214,25 @@ class cache implements cache_loader {
*
* You should not call this method from your code, instead you should use the cache::make methods.
*
* This method is public so that the cache_factory is able to instantiate cache instances.
* This method is public so that the factory is able to instantiate cache instances.
* Ideally we would make this method protected and expose its construction to the factory method internally somehow.
* The factory class is responsible for this in order to centralise the storage of instances once created. This way if needed
* we can force a reset of the cache API (used during unit testing).
*
* @param cache_definition $definition The definition for the cache instance.
* @param cache_store $store The store that cache should use.
* @param cache_loader|cache_data_source $loader The next loader in the chain or the data source if there is one and there
* are no other cache_loaders in the chain.
* @param definition $definition The definition for the cache instance.
* @param store $store The store that cache should use.
* @param loader_interface|data_source_interface $loader The next loader in the chain or the data source if there is one
* and there are no other loader_interfaces in the chain.
*/
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
public function __construct(definition $definition, store $store, $loader = null) {
global $CFG;
$this->definition = $definition;
$this->store = $store;
$this->storetype = get_class($store);
$this->perfdebug = (!empty($CFG->perfdebug) and $CFG->perfdebug > 7);
if ($loader instanceof cache_loader) {
if ($loader instanceof loader_interface) {
$this->set_loader($loader);
} else if ($loader instanceof cache_data_source) {
} else if ($loader instanceof data_source_interface) {
$this->set_data_source($loader);
}
$this->definition->generate_definition_hash();
@ -242,9 +246,9 @@ class cache implements cache_loader {
/**
* Set the loader for this cache.
*
* @param cache_loader $loader
* @param loader_interface $loader
*/
protected function set_loader(cache_loader $loader): void {
protected function set_loader(loader_interface $loader): void {
$this->loader = $loader;
// Mark the loader as a sub (chained) loader.
@ -254,9 +258,9 @@ class cache implements cache_loader {
/**
* Set the data source for this cache.
*
* @param cache_data_source $datasource
* @param data_source_interface $datasource
*/
protected function set_data_source(cache_data_source $datasource): void {
protected function set_data_source(data_source_interface $datasource): void {
$this->datasource = $datasource;
}
@ -298,9 +302,9 @@ class cache implements cache_loader {
if ($this->definition->set_identifiers($identifiers)) {
// As static acceleration uses input keys and not parsed keys
// it much be cleared when the identifier set is changed.
$this->staticaccelerationarray = array();
$this->staticaccelerationarray = [];
if ($this->staticaccelerationsize !== false) {
$this->staticaccelerationkeys = array();
$this->staticaccelerationkeys = [];
$this->staticaccelerationcount = 0;
}
}
@ -354,7 +358,7 @@ class cache implements cache_loader {
*/
$cache = self::make('core', 'eventinvalidation');
$events = $cache->get_many($this->definition->get_invalidation_events());
$todelete = array();
$todelete = [];
$purgeall = false;
// Iterate the returned data for the events.
@ -456,7 +460,7 @@ class cache implements cache_loader {
}
} else {
// If there's no result, obviously it doesn't meet the required version.
if (!cache_helper::result_found($result)) {
if (!helper::result_found($result)) {
return false;
}
if (!($result instanceof \core_cache\version_wrapper)) {
@ -489,7 +493,7 @@ class cache implements cache_loader {
if ($usesstaticacceleration) {
$result = $this->static_acceleration_get($key);
if (cache_helper::result_found($result) && self::check_version($result, $requiredversion)) {
if (helper::result_found($result) && self::check_version($result, $requiredversion)) {
if ($requiredversion === self::VERSION_NONE) {
return $result;
} else {
@ -504,7 +508,7 @@ class cache implements cache_loader {
// 3. Get it from the store. Obviously wasn't in the static acceleration array.
$result = $this->store->get($parsedkey);
if (cache_helper::result_found($result)) {
if (helper::result_found($result)) {
// Check the result has at least the required version.
try {
$validversion = self::check_version($result, $requiredversion);
@ -534,14 +538,14 @@ class cache implements cache_loader {
$this->store->delete($parsedkey);
}
}
if (cache_helper::result_found($result)) {
if (helper::result_found($result)) {
// Look to see if there's a TTL wrapper. It might be inside a version wrapper.
if ($requiredversion !== self::VERSION_NONE) {
$ttlconsider = $result->data;
} else {
$ttlconsider = $result;
}
if ($ttlconsider instanceof cache_ttl_wrapper) {
if ($ttlconsider instanceof ttl_wrapper) {
if ($ttlconsider->has_expired()) {
$this->store->delete($parsedkey);
$result = false;
@ -561,16 +565,16 @@ class cache implements cache_loader {
$actualversion = $result->version;
$result = $result->data;
}
if ($result instanceof cache_cached_object) {
if ($result instanceof cached_object) {
$result = $result->restore_object();
}
}
// 4. Load if from the loader/datasource if we don't already have it.
$setaftervalidation = false;
if (!cache_helper::result_found($result)) {
if (!helper::result_found($result)) {
if ($this->perfdebug) {
cache_helper::record_cache_miss($this->store, $this->definition);
helper::record_cache_miss($this->store, $this->definition);
}
if ($this->loader !== false) {
// We must pass the original (unparsed) key to the next loader in the chain.
@ -585,7 +589,7 @@ class cache implements cache_loader {
if ($requiredversion === self::VERSION_NONE) {
$result = $this->datasource->load_for_cache($key);
} else {
if (!$this->datasource instanceof cache_data_source_versionable) {
if (!$this->datasource instanceof versionable_data_source_interface) {
throw new \coding_exception('Data source is not versionable');
}
$result = $this->datasource->load_for_cache_versioned($key, $requiredversion, $actualversion);
@ -594,13 +598,13 @@ class cache implements cache_loader {
}
}
}
$setaftervalidation = (cache_helper::result_found($result));
$setaftervalidation = (helper::result_found($result));
} else if ($this->perfdebug) {
$readbytes = $this->store->get_last_io_bytes();
cache_helper::record_cache_hit($this->store, $this->definition, 1, $readbytes);
helper::record_cache_hit($this->store, $this->definition, 1, $readbytes);
}
// 5. Validate strictness.
if ($strictness === MUST_EXIST && !cache_helper::result_found($result)) {
if ($strictness === MUST_EXIST && !helper::result_found($result)) {
throw new coding_exception('Requested key did not exist in any cache stores and could not be loaded.');
}
// 6. Set it to the store if we got it from the loader/datasource. Only set to this direct
@ -625,7 +629,7 @@ class cache implements cache_loader {
}
}
// 7. Make sure we don't pass back anything that could be a reference.
// We don't want people modifying the data in the cache.
// We don't want people modifying the data in the cache.
if (!$this->store->supports_dereferencing_objects() && !is_scalar($result)) {
// If data is an object it will be a reference.
// If data is an array if may contain references.
@ -656,12 +660,12 @@ class cache implements cache_loader {
*/
public function get_many(array $keys, $strictness = IGNORE_MISSING) {
$keysparsed = array();
$parsedkeys = array();
$resultpersist = array();
$resultstore = array();
$keystofind = array();
$readbytes = cache_store::IO_BYTES_NOT_SUPPORTED;
$keysparsed = [];
$parsedkeys = [];
$resultpersist = [];
$resultstore = [];
$keystofind = [];
$readbytes = store::IO_BYTES_NOT_SUPPORTED;
// First up check the persist cache for each key.
$isusingpersist = $this->use_static_acceleration();
@ -690,7 +694,7 @@ class cache implements cache_loader {
}
// Process each item in the result to "unwrap" it.
foreach ($resultstore as $key => $value) {
if ($value instanceof cache_ttl_wrapper) {
if ($value instanceof ttl_wrapper) {
if ($value->has_expired()) {
$value = false;
} else {
@ -700,7 +704,7 @@ class cache implements cache_loader {
if ($value !== false && $this->use_static_acceleration()) {
$this->static_acceleration_set($keystofind[$key], $value);
}
if ($value instanceof cache_cached_object) {
if ($value instanceof cached_object) {
$value = $value->restore_object();
}
$resultstore[$key] = $value;
@ -716,7 +720,7 @@ class cache implements cache_loader {
$usingloader = ($this->loader !== false);
$usingsource = (!$usingloader && ($this->datasource !== false));
if ($usingloader || $usingsource) {
$missingkeys = array();
$missingkeys = [];
foreach ($result as $key => $value) {
if ($value === false) {
$missingkeys[] = $parsedkeys[$key];
@ -751,7 +755,7 @@ class cache implements cache_loader {
}
// Create an array with the original keys and the found values. This will be what we return.
$fullresult = array();
$fullresult = [];
foreach ($result as $key => $value) {
if (!is_scalar($value)) {
// If data is an object it will be a reference.
@ -783,8 +787,8 @@ class cache implements cache_loader {
$hits++;
}
}
cache_helper::record_cache_hit($this->store, $this->definition, $hits, $readbytes);
cache_helper::record_cache_miss($this->store, $this->definition, $misses);
helper::record_cache_hit($this->store, $this->definition, $hits, $readbytes);
helper::record_cache_miss($this->store, $this->definition, $misses);
}
// Return the result. Phew!
@ -858,8 +862,8 @@ class cache implements cache_loader {
}
$usestaticacceleration = $this->use_static_acceleration();
if (is_object($data) && $data instanceof cacheable_object) {
$data = new cache_cached_object($data);
if (is_object($data) && $data instanceof cacheable_object_interface) {
$data = new cached_object($data);
} else if (!$this->store->supports_dereferencing_objects() && !is_scalar($data)) {
// If data is an object it will be a reference.
// If data is an array if may contain references.
@ -878,7 +882,7 @@ class cache implements cache_loader {
}
if ($this->has_a_ttl() && !$this->store_supports_native_ttl()) {
$data = new cache_ttl_wrapper($data, $this->definition->get_ttl());
$data = new ttl_wrapper($data, $this->definition->get_ttl());
}
$parsedkey = $this->parse_key($key);
@ -888,8 +892,12 @@ class cache implements cache_loader {
$success = $this->store->set($parsedkey, $data);
if ($this->perfdebug) {
cache_helper::record_cache_set($this->store, $this->definition, 1,
$this->store->get_last_io_bytes());
helper::record_cache_set(
$this->store,
$this->definition,
1,
$this->store->get_last_io_bytes()
);
}
return $success;
}
@ -996,8 +1004,8 @@ class cache implements cache_loader {
$usestaticaccelerationarray = $this->use_static_acceleration();
$needsdereferencing = !$this->store->supports_dereferencing_objects();
foreach ($keyvaluearray as $key => $value) {
if (is_object($value) && $value instanceof cacheable_object) {
$value = new cache_cached_object($value);
if (is_object($value) && $value instanceof cacheable_object_interface) {
$value = new cached_object($value);
} else if ($needsdereferencing && !is_scalar($value)) {
// If data is an object it will be a reference.
// If data is an array if may contain references.
@ -1009,17 +1017,21 @@ class cache implements cache_loader {
$this->static_acceleration_set($key, $value);
}
if ($simulatettl) {
$value = new cache_ttl_wrapper($value, $this->definition->get_ttl());
$value = new ttl_wrapper($value, $this->definition->get_ttl());
}
$data[$key] = array(
$data[$key] = [
'key' => $this->parse_key($key),
'value' => $value
);
'value' => $value,
];
}
$successfullyset = $this->store->set_many($data);
if ($this->perfdebug && $successfullyset) {
cache_helper::record_cache_set($this->store, $this->definition, $successfullyset,
$this->store->get_last_io_bytes());
helper::record_cache_set(
$this->store,
$this->definition,
$successfullyset,
$this->store->get_last_io_bytes()
);
}
return $successfullyset;
}
@ -1056,7 +1068,7 @@ class cache implements cache_loader {
// The data has a TTL and the store doesn't support it natively.
// We must fetch the data and expect a ttl wrapper.
$data = $this->store->get($parsedkey);
$has = ($data instanceof cache_ttl_wrapper && !$data->has_expired());
$has = ($data instanceof ttl_wrapper && !$data->has_expired());
} else if (!$this->store_supports_key_awareness()) {
// The store doesn't support key awareness, get the data and check it manually... puke.
// Either no TTL is set of the store supports its handling natively.
@ -1103,7 +1115,7 @@ class cache implements cache_loader {
}
return true;
}
$parsedkeys = array_map(array($this, 'parse_key'), $keys);
$parsedkeys = array_map([$this, 'parse_key'], $keys);
return $this->store->has_all($parsedkeys);
}
@ -1137,7 +1149,7 @@ class cache implements cache_loader {
}
}
}
$parsedkeys = array_map(array($this, 'parse_key'), $keys);
$parsedkeys = array_map([$this, 'parse_key'], $keys);
return $this->store->has_any($parsedkeys);
}
@ -1177,7 +1189,7 @@ class cache implements cache_loader {
// Delete from the bottom of the stack first.
$this->loader->delete_many($keys, $recurse);
}
$parsedkeys = array_map(array($this, 'parse_key'), $keys);
$parsedkeys = array_map([$this, 'parse_key'], $keys);
return $this->store->delete_many($parsedkeys);
}
@ -1211,8 +1223,8 @@ class cache implements cache_loader {
$result['key'] = $key;
return $result;
}
// If not we need to generate a hash and to for that we use the cache_helper.
return cache_helper::hash_key($key, $this->definition);
// If not we need to generate a hash and to for that we use the helper.
return helper::hash_key($key, $this->definition);
}
/**
@ -1237,7 +1249,7 @@ class cache implements cache_loader {
/**
* Returns the cache definition.
*
* @return cache_definition
* @return definition
*/
protected function get_definition() {
return $this->definition;
@ -1246,7 +1258,7 @@ class cache implements cache_loader {
/**
* Returns the cache store
*
* @return cache_store
* @return store
*/
protected function get_store() {
return $this->store;
@ -1266,7 +1278,7 @@ class cache implements cache_loader {
* Returns the data source associated with this cache.
*
* @since Moodle 2.4.4
* @return cache_data_source|false
* @return data_source_interface|false
*/
protected function get_datasource() {
return $this->datasource;
@ -1279,7 +1291,7 @@ class cache implements cache_loader {
*/
protected function store_supports_key_awareness() {
if ($this->supportskeyawareness === null) {
$this->supportskeyawareness = ($this->store instanceof cache_is_key_aware);
$this->supportskeyawareness = ($this->store instanceof key_aware_cache_interface);
}
return $this->supportskeyawareness;
}
@ -1291,7 +1303,7 @@ class cache implements cache_loader {
*/
protected function store_supports_native_locking() {
if ($this->nativelocking === null) {
$this->nativelocking = ($this->store instanceof cache_is_lockable);
$this->nativelocking = ($this->store instanceof lockable_cache_interface);
}
return $this->nativelocking;
}
@ -1359,7 +1371,7 @@ class cache implements cache_loader {
} else {
$data = $this->staticaccelerationarray[$key]['data'];
if ($data instanceof cache_cached_object) {
if ($data instanceof cached_object) {
$result = $data->restore_object();
} else if ($this->staticaccelerationarray[$key]['serialized']) {
$result = unserialize($data);
@ -1367,9 +1379,9 @@ class cache implements cache_loader {
$result = $data;
}
}
if (cache_helper::result_found($result)) {
if (helper::result_found($result)) {
if ($this->perfdebug) {
cache_helper::record_cache_hit(cache_store::STATIC_ACCEL, $this->definition);
helper::record_cache_hit(store::STATIC_ACCEL, $this->definition);
}
if ($this->staticaccelerationsize > 1 && $this->staticaccelerationcount > 1) {
// Check to see if this is the last item on the static acceleration keys array.
@ -1383,7 +1395,7 @@ class cache implements cache_loader {
return $result;
} else {
if ($this->perfdebug) {
cache_helper::record_cache_miss(cache_store::STATIC_ACCEL, $this->definition);
helper::record_cache_miss(store::STATIC_ACCEL, $this->definition);
}
return false;
}
@ -1415,8 +1427,10 @@ class cache implements cache_loader {
// 1. A known scalar safe value.
// 2. A definition that says it's simpledata. We trust it that it doesn't contain dangerous references.
// 3. An object that handles dereferencing by itself.
if (is_scalar($data) || $this->definition->uses_simple_data()
|| $data instanceof cache_cached_object) {
if (
is_scalar($data) || $this->definition->uses_simple_data()
|| $data instanceof cached_object
) {
$this->staticaccelerationarray[$key]['data'] = $data;
$this->staticaccelerationarray[$key]['serialized'] = false;
} else {
@ -1463,9 +1477,9 @@ class cache implements cache_loader {
* Purge the static acceleration cache.
*/
protected function static_acceleration_purge() {
$this->staticaccelerationarray = array();
$this->staticaccelerationarray = [];
if ($this->staticaccelerationsize !== false) {
$this->staticaccelerationkeys = array();
$this->staticaccelerationkeys = [];
$this->staticaccelerationcount = 0;
}
}
@ -1528,10 +1542,10 @@ class cache implements cache_loader {
}
// The token for when the cache was last invalidated.
list($atime) = explode('-', "{$tokena}-", 2);
[$atime] = explode('-', "{$tokena}-", 2);
// The token for this cache.
list($btime) = explode('-', "{$tokenb}-", 2);
[$btime] = explode('-', "{$tokenb}-", 2);
if ($atime >= $btime) {
// Token A is newer.
@ -1549,3 +1563,8 @@ class cache implements cache_loader {
public function purge_current_user() {
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache::class, \cache::class);

View file

@ -14,10 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache lock interface
* Cache lock interface.
*
* This interface needs to be inherited by all cache lock plugins.
*
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_lock_interface {
/**
@ -26,7 +32,7 @@ interface cache_lock_interface {
* @param string $name The unique name of the lock instance
* @param array $configuration
*/
public function __construct($name, array $configuration = array());
public function __construct($name, array $configuration = []);
/**
* Acquires a lock on a given key.
@ -72,3 +78,8 @@ interface cache_lock_interface {
*/
public function __destruct();
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_lock_interface::class, \cache_lock_interface::class);

View file

@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use ArrayObject;
/**
* An array of cacheable objects.
*
@ -41,28 +46,28 @@
*
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core_cache
*/
class cacheable_object_array extends ArrayObject implements cacheable_object {
class cacheable_object_array extends ArrayObject implements cacheable_object_interface {
/**
* Constructs a new array object instance.
* @param array $items
*/
final public function __construct(array $items = array()) {
final public function __construct(array $items = []) {
parent::__construct($items, ArrayObject::STD_PROP_LIST);
}
/**
* Returns the data to cache for this object.
*
* @return array An array of cache_cached_object instances.
* @return cached_object[] An array of cached_object instances.
* @throws coding_exception
*/
final public function prepare_to_cache() {
$result = array();
$result = [];
foreach ($this as $key => $value) {
if ($value instanceof cacheable_object) {
$value = new cache_cached_object($value);
if ($value instanceof cacheable_object_interface) {
$value = new cached_object($value);
} else {
throw new coding_exception('Only cacheable_object instances can be added to a cacheable_array');
}
@ -75,14 +80,14 @@ class cacheable_object_array extends ArrayObject implements cacheable_object {
* Returns the cacheable_object_array that was originally sent to the cache.
*
* @param array $data
* @return cacheable_object_array
* @return self
* @throws coding_exception
*/
final public static function wake_from_cache($data) {
if (!is_array($data)) {
throw new coding_exception('Invalid data type when reviving cacheable_array data');
}
$result = array();
$result = [];
foreach ($data as $key => $value) {
$result[$key] = $value->restore_object();
}
@ -90,3 +95,8 @@ class cacheable_object_array extends ArrayObject implements cacheable_object {
return new $class($result);
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cacheable_object_array::class, \cacheable_object_array::class);

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cacheable object.
*
@ -22,9 +24,12 @@
* Think of it like serialisation and the __sleep and __wakeup methods.
* This is used because cache stores are responsible for how they interact with data and what they do when storing it. This
* interface ensures there is always a guaranteed action.
*
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cacheable_object {
interface cacheable_object_interface {
/**
* Prepares the object for caching. Works like the __sleep method.
*
@ -41,3 +46,8 @@ interface cacheable_object {
*/
public static function wake_from_cache($data);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cacheable_object_interface::class, \cacheable_object::class);

View file

@ -14,18 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* A cached object wrapper.
*
* This class gets used when the data is an object that has implemented the cacheable_object interface.
* This class gets used when the data is an object that has implemented the cacheable_object_interface interface.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_cached_object {
class cached_object {
/**
* The class of the cacheable object
* @var string
@ -33,22 +34,22 @@ class cache_cached_object {
protected $class;
/**
* The data returned by the cacheable_object prepare_to_cache method.
* The data returned by the cacheable_object_interface prepare_to_cache method.
* @var mixed
*/
protected $data;
/**
* Constructs a cached object wrapper.
* @param cacheable_object $obj
* @param cacheable_object_interface $obj
*/
public function __construct(cacheable_object $obj) {
public function __construct(cacheable_object_interface $obj) {
$this->class = get_class($obj);
$this->data = $obj->prepare_to_cache();
}
/**
* Restores the data as an instance of the cacheable_object class.
* Restores the data as an instance of the cacheable_object_interface class.
* @return object
*/
public function restore_object() {
@ -56,3 +57,8 @@ class cache_cached_object {
return $class::wake_from_cache($this->data);
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cached_object::class, \cache_cached_object::class);

View file

@ -14,48 +14,54 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core_cache\exception\cache_exception;
use cache_factory as factory;
use cache_helper as helper;
use cache_store as store;
/**
* Cache configuration reader.
*
* This class is used to interact with the cache's configuration.
* The configuration is stored in the Moodle data directory.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_config {
class config {
/**
* The configured stores
* @var array
*/
protected $configstores = array();
protected $configstores = [];
/**
* The configured mode mappings
* @var array
*/
protected $configmodemappings = array();
protected $configmodemappings = [];
/**
* The configured definitions as picked up from cache.php files
* @var array
*/
protected $configdefinitions = array();
protected $configdefinitions = [];
/**
* The definition mappings that have been configured.
* @var array
*/
protected $configdefinitionmappings = array();
protected $configdefinitionmappings = [];
/**
* An array of configured cache lock instances.
* @var array
*/
protected $configlocks = array();
protected $configlocks = [];
/**
* The site identifier used when the cache config was last saved.
@ -71,12 +77,12 @@ class cache_config {
}
/**
* Gets an instance of the cache_configuration class.
* Gets an instance of the cache config class.
*
* @return cache_config
* @return self
*/
public static function instance() {
$factory = cache_factory::instance();
$factory = factory::instance();
return $factory->create_config_instance();
}
@ -101,14 +107,14 @@ class cache_config {
$path = $CFG->altcacheconfigpath;
if (is_dir($path) && is_writable($path)) {
// Its a writable directory, thats fine.
return $path.'/cacheconfig.php';
return $path . '/cacheconfig.php';
} else if (is_writable(dirname($path)) && (!file_exists($path) || is_writable($path))) {
// Its a file, either it doesn't exist and the directory is writable or the file exists and is writable.
return $path;
}
}
// Return the default location within dataroot.
return $CFG->dataroot.'/muc/config.php';
return $CFG->dataroot . '/muc/config.php';
}
/**
@ -124,11 +130,11 @@ class cache_config {
$configuration = $this->include_configuration();
}
$this->configstores = array();
$this->configdefinitions = array();
$this->configlocks = array();
$this->configmodemappings = array();
$this->configdefinitionmappings = array();
$this->configstores = [];
$this->configdefinitions = [];
$this->configlocks = [];
$this->configmodemappings = [];
$this->configdefinitionmappings = [];
$siteidentifier = 'unknown';
if (array_key_exists('siteidentifier', $configuration)) {
@ -160,7 +166,7 @@ class cache_config {
}
// Filter the stores.
$availableplugins = cache_helper::early_get_cache_plugins();
$availableplugins = helper::early_get_cache_plugins();
foreach ($configuration['stores'] as $store) {
if (!is_array($store) || !array_key_exists('name', $store) || !array_key_exists('plugin', $store)) {
// Not a valid instance configuration.
@ -168,25 +174,25 @@ class cache_config {
continue;
}
$plugin = $store['plugin'];
$class = 'cachestore_'.$plugin;
$class = 'cachestore_' . $plugin;
$exists = array_key_exists($plugin, $availableplugins);
if (!$exists) {
// Not a valid plugin, or has been uninstalled, just skip it an carry on.
debugging('Invalid cache store in config. Not an available plugin.', DEBUG_DEVELOPER);
continue;
}
$file = $CFG->dirroot.'/cache/stores/'.$plugin.'/lib.php';
$file = $CFG->dirroot . '/cache/stores/' . $plugin . '/lib.php';
if (!class_exists($class) && file_exists($file)) {
require_once($file);
}
if (!class_exists($class)) {
continue;
}
if (!array_key_exists('cache_store', class_parents($class))) {
if (!array_key_exists(store::class, class_parents($class))) {
continue;
}
if (!array_key_exists('configuration', $store) || !is_array($store['configuration'])) {
$store['configuration'] = array();
$store['configuration'] = [];
}
$store['class'] = $class;
$store['default'] = !empty($store['default']);
@ -285,8 +291,8 @@ class cache_config {
$this->configdefinitionmappings[] = $mapping;
}
usort($this->configmodemappings, array($this, 'sort_mappings'));
usort($this->configdefinitionmappings, array($this, 'sort_mappings'));
usort($this->configmodemappings, [$this, 'sort_mappings']);
usort($this->configdefinitionmappings, [$this, 'sort_mappings']);
return true;
}
@ -324,19 +330,19 @@ class cache_config {
throw new cache_exception('Invalid cache configuration file');
}
if (!array_key_exists('stores', $configuration) || !is_array($configuration['stores'])) {
$configuration['stores'] = array();
$configuration['stores'] = [];
}
if (!array_key_exists('modemappings', $configuration) || !is_array($configuration['modemappings'])) {
$configuration['modemappings'] = array();
$configuration['modemappings'] = [];
}
if (!array_key_exists('definitions', $configuration) || !is_array($configuration['definitions'])) {
$configuration['definitions'] = array();
$configuration['definitions'] = [];
}
if (!array_key_exists('definitionmappings', $configuration) || !is_array($configuration['definitionmappings'])) {
$configuration['definitionmappings'] = array();
$configuration['definitionmappings'] = [];
}
if (!array_key_exists('locks', $configuration) || !is_array($configuration['locks'])) {
$configuration['locks'] = array();
$configuration['locks'] = [];
}
return $configuration;
@ -387,7 +393,7 @@ class cache_config {
* @return array Associative array of definitions, id=>definition
*/
public function get_definitions_by_store($storename) {
$definitions = array();
$definitions = [];
// This function was accidentally made static at some stage in the past.
// It was converted to an instance method but to be backwards compatible
@ -406,18 +412,18 @@ class cache_config {
$defmappings = $config->get_definition_mappings();
// Create an associative array for the definition mappings.
$thedefmappings = array();
$thedefmappings = [];
foreach ($defmappings as $defmapping) {
$thedefmappings[$defmapping['definition']] = $defmapping;
}
// Search for matches in default mappings.
$defs = $config->get_definitions();
foreach($config->get_mode_mappings() as $modemapping) {
foreach ($config->get_mode_mappings() as $modemapping) {
if ($modemapping['store'] !== $storename) {
continue;
}
foreach($defs as $id => $definition) {
foreach ($defs as $id => $definition) {
if ($definition['mode'] !== $modemapping['mode']) {
continue;
}
@ -429,7 +435,7 @@ class cache_config {
}
}
// Search for matches in the custom definitions mapping
// Search for matches in the custom definitions mapping.
foreach ($defmappings as $defmapping) {
if ($defmapping['store'] !== $storename) {
continue;
@ -451,7 +457,7 @@ class cache_config {
* @return array An array of suitable stores.
*/
public function get_stores($mode, $requirements = 0) {
$stores = array();
$stores = [];
foreach ($this->configstores as $name => $store) {
// If the mode is supported and all of the requirements are provided features.
if (($store['modes'] & $mode) && ($store['features'] & $requirements) === $requirements) {
@ -469,18 +475,18 @@ class cache_config {
*/
public function get_stores_for_definition(definition $definition) {
// Check if MUC has been disabled.
$factory = cache_factory::instance();
$factory = factory::instance();
if ($factory->stores_disabled()) {
// Yip its been disabled.
// To facilitate this we are going to always return an empty array of stores to use.
// This will force all cache instances to use the cachestore_dummy.
// MUC will still be used essentially so that code using it will still continue to function but because no cache stores
// are being used interaction with MUC will be purely based around a static var.
return array();
return [];
}
$availablestores = $this->get_stores($definition->get_mode(), $definition->get_requirements_bin());
$stores = array();
$stores = [];
$id = $definition->get_id();
// Now get any mappings and give them priority.
@ -580,3 +586,8 @@ class cache_config {
throw new cache_exception('ex_nodefaultlock');
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(config::class, \cache_config::class);

View file

@ -14,20 +14,29 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use core_cache\exception\cache_exception;
use cachestore_static;
use cachestore_session;
use cachestore_file;
use core_component;
use ReflectionClass;
/**
* Cache configuration writer.
*
* This class should only be used when you need to write to the config, all read operations exist within the cache_config.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_config_writer extends cache_config {
class config_writer extends config {
/**
* Switch that gets set to true when ever a cache_config_writer instance is saving the cache configuration file.
* Switch that gets set to true when ever a config_writer instance is saving the cache configuration file.
* If this is set to true when save is next called we must avoid the trying to save and instead return the
* generated config so that is may be used instead of the file.
* @var bool
@ -37,10 +46,10 @@ class cache_config_writer extends cache_config {
/**
* Returns an instance of the configuration writer.
*
* @return cache_config_writer
* @return config_writer
*/
public static function instance() {
$factory = cache_factory::instance();
$factory = factory::instance();
return $factory->create_config_instance(true);
}
@ -70,7 +79,7 @@ class cache_config_writer extends cache_config {
$configuration = $this->generate_configuration_array();
// Prepare the file content.
$content = "<?php defined('MOODLE_INTERNAL') || die();\n \$configuration = ".var_export($configuration, true).";";
$content = "<?php defined('MOODLE_INTERNAL') || die();\n \$configuration = " . var_export($configuration, true) . ";";
// Do both file content and hash based detection because this might be called
// many times within a single request.
@ -87,14 +96,14 @@ class cache_config_writer extends cache_config {
if ($lockconf === false) {
debugging('Your cache configuration file is out of date and needs to be refreshed.', DEBUG_DEVELOPER);
// Use the default
$lockconf = array(
$lockconf = [
'name' => 'cachelock_file_default',
'type' => 'cachelock_file',
'dir' => 'filelocks',
'default' => true
);
'default' => true,
];
}
$factory = cache_factory::instance();
$factory = factory::instance();
$locking = $factory->create_lock_instance($lockconf);
if ($locking->lock('configwrite', 'config', true)) {
$tempcachefile = "{$cachefile}.tmp";
@ -118,7 +127,7 @@ class cache_config_writer extends cache_config {
* @return array
*/
protected function generate_configuration_array() {
$configuration = array();
$configuration = [];
$configuration['siteidentifier'] = $this->siteidentifier;
$configuration['stores'] = $this->configstores;
$configuration['modemappings'] = $this->configmodemappings;
@ -140,11 +149,11 @@ class cache_config_writer extends cache_config {
* @return bool
* @throws cache_exception
*/
public function add_store_instance($name, $plugin, array $configuration = array()) {
public function add_store_instance($name, $plugin, array $configuration = []) {
if (array_key_exists($name, $this->configstores)) {
throw new cache_exception('Duplicate name specificed for cache plugin instance. You must provide a unique name.');
}
$class = 'cachestore_'.$plugin;
$class = 'cachestore_' . $plugin;
if (!class_exists($class)) {
$plugins = core_component::get_plugin_list_with_file('cachestore', 'lib.php');
if (!array_key_exists($plugin, $plugins)) {
@ -159,13 +168,13 @@ class cache_config_writer extends cache_config {
}
}
$reflection = new ReflectionClass($class);
if (!$reflection->isSubclassOf('cache_store')) {
if (!$reflection->isSubclassOf(store::class)) {
throw new cache_exception('Invalid cache plugin specified. The plugin does not extend the required class.');
}
if (!$class::are_requirements_met()) {
throw new cache_exception('Unable to add new cache plugin instance. The requested plugin type is not supported.');
}
$this->configstores[$name] = array(
$this->configstores[$name] = [
'name' => $name,
'plugin' => $plugin,
'configuration' => $configuration,
@ -173,8 +182,8 @@ class cache_config_writer extends cache_config {
'modes' => $class::get_supported_modes($configuration),
'mappingsonly' => !empty($configuration['mappingsonly']),
'class' => $class,
'default' => false
);
'default' => false,
];
if (array_key_exists('lock', $configuration)) {
$this->configstores[$name]['lock'] = $configuration['lock'];
unset($this->configstores[$name]['configuration']['lock']);
@ -195,11 +204,11 @@ class cache_config_writer extends cache_config {
* @param string $configuration Configuration data from the config instance.
* @throws cache_exception
*/
public function add_lock_instance($name, $plugin, $configuration = array()) {
public function add_lock_instance($name, $plugin, $configuration = []) {
if (array_key_exists($name, $this->configlocks)) {
throw new cache_exception('Duplicate name specificed for cache lock instance. You must provide a unique name.');
}
$class = 'cachelock_'.$plugin;
$class = 'cachelock_' . $plugin;
if (!class_exists($class)) {
$plugins = core_component::get_plugin_list_with_file('cachelock', 'lib.php');
if (!array_key_exists($plugin, $plugins)) {
@ -214,14 +223,14 @@ class cache_config_writer extends cache_config {
}
}
$reflection = new ReflectionClass($class);
if (!$reflection->implementsInterface('cache_lock_interface')) {
if (!$reflection->implementsInterface(lockable_cache_interface::class)) {
throw new cache_exception('Invalid lock plugin specified. The plugin does not implement the required interface.');
}
$this->configlocks[$name] = array_merge($configuration, array(
$this->configlocks[$name] = array_merge($configuration, [
'name' => $name,
'type' => 'cachelock_'.$plugin,
'default' => false
));
'type' => 'cachelock_' . $plugin,
'default' => false,
]);
$this->config_save();
}
@ -261,11 +270,11 @@ class cache_config_writer extends cache_config {
* @throws cache_exception
*/
public function set_mode_mappings(array $modemappings) {
$mappings = array(
cache_store::MODE_APPLICATION => array(),
cache_store::MODE_SESSION => array(),
cache_store::MODE_REQUEST => array(),
);
$mappings = [
store::MODE_APPLICATION => [],
store::MODE_SESSION => [],
store::MODE_REQUEST => [],
];
foreach ($modemappings as $mode => $stores) {
if (!array_key_exists($mode, $mappings)) {
throw new cache_exception('The cache mode for the new mapping does not exist');
@ -278,17 +287,17 @@ class cache_config_writer extends cache_config {
if (array_key_exists($store, $mappings[$mode])) {
throw new cache_exception('This cache mapping already exists');
}
$mappings[$mode][] = array(
$mappings[$mode][] = [
'store' => $store,
'mode' => $mode,
'sort' => $sort++
);
'sort' => $sort++,
];
}
}
$this->configmodemappings = array_merge(
$mappings[cache_store::MODE_APPLICATION],
$mappings[cache_store::MODE_SESSION],
$mappings[cache_store::MODE_REQUEST]
$mappings[store::MODE_APPLICATION],
$mappings[store::MODE_SESSION],
$mappings[store::MODE_REQUEST]
);
$this->config_save();
@ -316,17 +325,19 @@ class cache_config_writer extends cache_config {
if (!array_key_exists($plugin, $plugins)) {
throw new cache_exception('Invalid plugin name specified. The plugin either does not exist or is not valid.');
}
$class = 'cachestore_'.$plugin;
$class = 'cachestore_' . $plugin;
$file = $plugins[$plugin];
if (!class_exists($class)) {
if (file_exists($file)) {
require_once($file);
}
if (!class_exists($class)) {
throw new cache_exception('Invalid cache plugin specified. The plugin does not contain the required class.'.$class);
throw new cache_exception(
"Invalid cache plugin specified. The plugin does not contain the required class {$class}",
);
}
}
$this->configstores[$name] = array(
$this->configstores[$name] = [
'name' => $name,
'plugin' => $plugin,
'configuration' => $configuration,
@ -334,8 +345,8 @@ class cache_config_writer extends cache_config {
'modes' => $class::get_supported_modes($configuration),
'mappingsonly' => !empty($configuration['mappingsonly']),
'class' => $class,
'default' => $this->configstores[$name]['default'] // Can't change the default.
);
'default' => $this->configstores[$name]['default'], // Can't change the default.
];
if (array_key_exists('lock', $configuration)) {
$this->configstores[$name]['lock'] = $configuration['lock'];
unset($this->configstores[$name]['configuration']['lock']);
@ -373,7 +384,7 @@ class cache_config_writer extends cache_config {
}
// Call instance_deleted()
$class = 'cachestore_'.$this->configstores[$name]['plugin'];
$class = 'cachestore_' . $this->configstores[$name]['plugin'];
$store = new $class($name, $this->configstores[$name]['configuration']);
$store->instance_deleted();
@ -396,42 +407,42 @@ class cache_config_writer extends cache_config {
// HACK ALERT.
// We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
// default store plugins are protected from deletion.
$writer = new self;
$writer = new self();
$writer->configstores = self::get_default_stores();
$writer->configdefinitions = self::locate_definitions();
$writer->configmodemappings = array(
array(
'mode' => cache_store::MODE_APPLICATION,
$writer->configmodemappings = [
[
'mode' => store::MODE_APPLICATION,
'store' => 'default_application',
'sort' => -1
),
array(
'mode' => cache_store::MODE_SESSION,
'sort' => -1,
],
[
'mode' => store::MODE_SESSION,
'store' => 'default_session',
'sort' => -1
),
array(
'mode' => cache_store::MODE_REQUEST,
'sort' => -1,
],
[
'mode' => store::MODE_REQUEST,
'store' => 'default_request',
'sort' => -1
)
);
$writer->configlocks = array(
'default_file_lock' => array(
'sort' => -1,
],
];
$writer->configlocks = [
'default_file_lock' => [
'name' => 'cachelock_file_default',
'type' => 'cachelock_file',
'dir' => 'filelocks',
'default' => true
)
);
'default' => true,
],
];
$factory = cache_factory::instance();
$factory = factory::instance();
// We expect the cache to be initialising presently. If its not then something has gone wrong and likely
// we are now in a loop.
if (!$forcesave && $factory->get_state() !== cache_factory::STATE_INITIALISING) {
if (!$forcesave && $factory->get_state() !== factory::STATE_INITIALISING) {
return $writer->generate_configuration_array();
}
$factory->set_state(cache_factory::STATE_SAVING);
$factory->set_state(factory::STATE_SAVING);
$writer->config_save();
return true;
}
@ -444,43 +455,43 @@ class cache_config_writer extends cache_config {
protected static function get_default_stores() {
global $CFG;
require_once($CFG->dirroot.'/cache/stores/file/lib.php');
require_once($CFG->dirroot.'/cache/stores/session/lib.php');
require_once($CFG->dirroot.'/cache/stores/static/lib.php');
require_once($CFG->dirroot . '/cache/stores/file/lib.php');
require_once($CFG->dirroot . '/cache/stores/session/lib.php');
require_once($CFG->dirroot . '/cache/stores/static/lib.php');
return array(
'default_application' => array(
return [
'default_application' => [
'name' => 'default_application',
'plugin' => 'file',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_file::get_supported_features(),
'modes' => cachestore_file::get_supported_modes(),
'default' => true,
),
'default_session' => array(
],
'default_session' => [
'name' => 'default_session',
'plugin' => 'session',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_session::get_supported_features(),
'modes' => cachestore_session::get_supported_modes(),
'default' => true,
),
'default_request' => array(
],
'default_request' => [
'name' => 'default_request',
'plugin' => 'static',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_static::get_supported_features(),
'modes' => cachestore_static::get_supported_modes(),
'default' => true,
)
);
],
];
}
/**
* Updates the default stores within the MUC config file.
*/
public static function update_default_config_stores() {
$factory = cache_factory::instance();
$factory = factory::instance();
$factory->updating_started();
$config = $factory->create_config_instance(true);
$config->configstores = array_merge($config->configstores, self::get_default_stores());
@ -496,7 +507,7 @@ class cache_config_writer extends cache_config {
* @param bool $coreonly If set to true only core definitions will be updated.
*/
public static function update_definitions($coreonly = false) {
$factory = cache_factory::instance();
$factory = factory::instance();
$factory->updating_started();
$config = $factory->create_config_instance(true);
$config->write_definitions_to_cache(self::locate_definitions($coreonly));
@ -512,9 +523,9 @@ class cache_config_writer extends cache_config {
protected static function locate_definitions($coreonly = false) {
global $CFG;
$files = array();
if (file_exists($CFG->dirroot.'/lib/db/caches.php')) {
$files['core'] = $CFG->dirroot.'/lib/db/caches.php';
$files = [];
if (file_exists($CFG->dirroot . '/lib/db/caches.php')) {
$files['core'] = $CFG->dirroot . '/lib/db/caches.php';
}
if (!$coreonly) {
@ -522,22 +533,22 @@ class cache_config_writer extends cache_config {
foreach ($plugintypes as $type => $location) {
$plugins = core_component::get_plugin_list_with_file($type, 'db/caches.php');
foreach ($plugins as $plugin => $filepath) {
$component = clean_param($type.'_'.$plugin, PARAM_COMPONENT); // Standardised plugin name.
$component = clean_param($type . '_' . $plugin, PARAM_COMPONENT); // Standardised plugin name.
$files[$component] = $filepath;
}
}
}
$definitions = array();
$definitions = [];
foreach ($files as $component => $file) {
$filedefs = self::load_caches_file($file);
foreach ($filedefs as $area => $definition) {
$area = clean_param($area, PARAM_AREA);
$id = $component.'/'.$area;
$id = $component . '/' . $area;
$definition['component'] = $component;
$definition['area'] = $area;
if (array_key_exists($id, $definitions)) {
debugging('Error: duplicate cache definition found with id: '.$id, DEBUG_DEVELOPER);
debugging('Error: duplicate cache definition found with id: ' . $id, DEBUG_DEVELOPER);
continue;
}
$definitions[$id] = $definition;
@ -582,9 +593,9 @@ class cache_config_writer extends cache_config {
*/
private static function load_caches_file($file) {
if (!file_exists($file)) {
return array();
return [];
}
$definitions = array();
$definitions = [];
include($file);
return $definitions;
}
@ -612,11 +623,11 @@ class cache_config_writer extends cache_config {
}
$sort = count($mappings);
foreach ($mappings as $store) {
$this->configdefinitionmappings[] = array(
$this->configdefinitionmappings[] = [
'store' => $store,
'definition' => $definition,
'sort' => $sort
);
'sort' => $sort,
];
$sort--;
}
@ -657,3 +668,8 @@ class cache_config_writer extends cache_config {
$this->config_save();
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(config_writer::class, \cache_config_writer::class);

View file

@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use moodleform;
/**
* Cache store feature: configurable.
*
@ -23,9 +27,11 @@
* data for the edit form.
*
* Can be implemented by classes already implementing cache_store.
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_is_configurable {
interface configurable_cache_interface {
/**
* Given the data from the add instance form this function creates a configuration array.
*
@ -42,3 +48,8 @@ interface cache_is_configurable {
*/
public static function config_set_edit_form_data(moodleform $editform, array $config);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(configurable_cache_interface::class, \cache_is_configurable::class);

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache Data Source.
*
@ -26,13 +28,12 @@
*
* Can be implemented by any class.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_data_source {
interface data_source_interface {
/**
* Returns an instance of the data source class that the cache can use for loading data using the other methods
* specified by this interface.
@ -58,3 +59,8 @@ interface cache_data_source {
*/
public function load_many_for_cache(array $keys);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(data_source_interface::class, \cache_data_source::class);

View file

@ -14,6 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use cache_helper as helper;
use cache_store as store;
use lang_string;
/**
* The cache definition class.
*
@ -22,7 +29,7 @@
*
* Required settings:
* + mode
* [int] Sets the mode for the definition. Must be one of cache_store::MODE_*
* [int] Sets the mode for the definition. Must be one of store::MODE_*
*
* Optional settings:
* + simplekeys
@ -89,13 +96,12 @@
*
* For examples take a look at lib/db/caches.php
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_definition {
class definition {
/** The cache can be shared with everyone */
const SHARING_ALL = 1;
/** The cache can be shared with other sites using the same siteid. */
@ -123,7 +129,7 @@ class cache_definition {
protected $id;
/**
* The mode for the defintion. One of cache_store::MODE_*
* The mode for the defintion. One of store::MODE_*
* @var int
*/
protected $mode;
@ -156,7 +162,7 @@ class cache_definition {
* An array of identifiers that must be provided when the definition is used to create a cache.
* @var array
*/
protected $requireidentifiers = array();
protected $requireidentifiers = [];
/**
* If set to true then only stores that guarantee data may be used with this definition.
@ -249,7 +255,7 @@ class cache_definition {
* An array of events that should cause this cache to invalidate.
* @var array
*/
protected $invalidationevents = array();
protected $invalidationevents = [];
/**
* An array of identifiers provided to this cache when it was initialised.
@ -305,7 +311,7 @@ class cache_definition {
* @param string $id
* @param array $definition
* @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
* @return cache_definition
* @return definition
* @throws coding_exception
*/
public static function load($id, array $definition, $unused = null) {
@ -327,11 +333,11 @@ class cache_definition {
// Set the defaults.
$simplekeys = false;
$simpledata = false;
$requireidentifiers = array();
$requireidentifiers = [];
$requiredataguarantee = false;
$requiremultipleidentifiers = false;
$requirelockingbeforewrite = false;
$requiresearchable = ($mode === cache_store::MODE_SESSION) ? true : false;
$requiresearchable = ($mode === store::MODE_SESSION) ? true : false;
$maxsize = null;
$overrideclass = null;
$overrideclassfile = null;
@ -341,7 +347,7 @@ class cache_definition {
$staticaccelerationsize = false;
$ttl = 0;
$mappingsonly = false;
$invalidationevents = array();
$invalidationevents = [];
$sharingoptions = self::SHARING_DEFAULT;
$selectedsharingoption = self::SHARING_DEFAULT;
$userinputsharingkey = '';
@ -364,13 +370,17 @@ class cache_definition {
}
if (array_key_exists('requirelockingread', $definition)) {
debugging('The cache option requirelockingread is deprecated and now has no effect.',
DEBUG_DEVELOPER);
debugging(
'The cache option requirelockingread is deprecated and now has no effect.',
DEBUG_DEVELOPER
);
}
if (array_key_exists('requirelockingwrite', $definition)) {
debugging('The cache option requirelockingwrite is deprecated and now has no effect. ' .
debugging(
'The cache option requirelockingwrite is deprecated and now has no effect. ' .
"Consider removing the option, or using requirelockingbeforewrite for the $component:$area definition",
DEBUG_DEVELOPER);
DEBUG_DEVELOPER
);
}
if (array_key_exists('requirelockingbeforewrite', $definition)) {
$requirelockingbeforewrite = (bool)$definition['requirelockingbeforewrite'];
@ -451,7 +461,7 @@ class cache_definition {
if (!is_null($overrideclass)) {
if (!is_null($overrideclassfile)) {
if (strpos($overrideclassfile, $CFG->dirroot) !== 0) {
$overrideclassfile = $CFG->dirroot.'/'.$overrideclassfile;
$overrideclassfile = $CFG->dirroot . '/' . $overrideclassfile;
}
if (strpos($overrideclassfile, '../') !== false) {
throw new coding_exception('No path craziness allowed within override class file path.');
@ -466,7 +476,7 @@ class cache_definition {
}
// Make sure that the provided class extends the default class for the mode.
if (get_parent_class($overrideclass) !== cache_helper::get_class_for_mode($mode)) {
if (get_parent_class($overrideclass) !== helper::get_class_for_mode($mode)) {
throw new coding_exception('The override class does not immediately extend the relevant cache class.');
}
}
@ -474,7 +484,7 @@ class cache_definition {
if (!is_null($datasource)) {
if (!is_null($datasourcefile)) {
if (strpos($datasourcefile, $CFG->dirroot) !== 0) {
$datasourcefile = $CFG->dirroot.'/'.$datasourcefile;
$datasourcefile = $CFG->dirroot . '/' . $datasourcefile;
}
if (strpos($datasourcefile, '../') !== false) {
throw new coding_exception('No path craziness allowed within data source file path.');
@ -492,7 +502,7 @@ class cache_definition {
}
}
$cachedefinition = new cache_definition();
$cachedefinition = new self();
$cachedefinition->id = $id;
$cachedefinition->mode = $mode;
$cachedefinition->component = $component;
@ -529,7 +539,7 @@ class cache_definition {
* Please note that when using an adhoc definition you cannot set any of the optional params.
* This is because we cannot guarantee consistent access and we don't want to mislead people into thinking that.
*
* @param int $mode One of cache_store::MODE_*
* @param int $mode One of store::MODE_*
* @param string $component The component this definition relates to.
* @param string $area The area this definition relates to.
* @param array $options An array of options, available options are:
@ -538,15 +548,15 @@ class cache_definition {
* - overrideclass : The class to use as the loader.
* - staticacceleration : If set to true the cache will hold onto data passing through it.
* - staticaccelerationsize : Set it to an int to limit the size of the staticacceleration cache.
* @return cache_application|cache_session|cache_request
* @return self
*/
public static function load_adhoc($mode, $component, $area, array $options = array()) {
$id = 'adhoc/'.$component.'_'.$area;
$definition = array(
public static function load_adhoc($mode, $component, $area, array $options = []) {
$id = 'adhoc/' . $component . '_' . $area;
$definition = [
'mode' => $mode,
'component' => $component,
'area' => $area,
);
];
if (!empty($options['simplekeys'])) {
$definition['simplekeys'] = $options['simplekeys'];
}
@ -580,7 +590,7 @@ class cache_definition {
if (!is_null($this->overrideclass)) {
return $this->overrideclass;
}
return cache_helper::get_class_for_mode($this->mode);
return helper::get_class_for_mode($this->mode);
}
/**
@ -596,7 +606,7 @@ class cache_definition {
* @return string
*/
public function get_name() {
$identifier = 'cachedef_'.clean_param($this->area, PARAM_STRINGID);
$identifier = 'cachedef_' . clean_param($this->area, PARAM_STRINGID);
$component = $this->component;
if ($component === 'core') {
$component = 'cache';
@ -606,7 +616,7 @@ class cache_definition {
/**
* Returns the mode of this definition
* @return int One more cache_store::MODE_
* @return int One more store::MODE_
*/
public function get_mode() {
return $this->mode;
@ -645,7 +655,7 @@ class cache_definition {
*/
public function get_identifiers() {
if (!isset($this->identifiers)) {
return array();
return [];
}
return $this->identifiers;
}
@ -743,14 +753,14 @@ class cache_definition {
/**
* Returns an instance of the data source class used for this definition.
*
* @return cache_data_source
* @return data_source_interface
* @throws coding_exception
*/
public function get_data_source() {
if (!$this->has_data_source()) {
throw new coding_exception('This cache does not use a data source.');
}
return forward_static_call(array($this->datasource, 'get_instance_for_cache'), $this);
return forward_static_call([$this->datasource, 'get_instance_for_cache'], $this);
}
/**
@ -760,7 +770,7 @@ class cache_definition {
* @return bool false if no identifiers where changed, true otherwise.
* @throws coding_exception
*/
public function set_identifiers(array $identifiers = array()) {
public function set_identifiers(array $identifiers = []) {
if ($this->identifiers !== null) {
throw new coding_exception("You can only set identifiers on initial definition creation." .
" Define a new cache to set different identifiers.");
@ -771,11 +781,11 @@ class cache_definition {
foreach ($this->requireidentifiers as $identifier) {
if (!isset($identifiers[$identifier])) {
throw new coding_exception('Identifier required for cache has not been provided: '.$identifier);
throw new coding_exception('Identifier required for cache has not been provided: ' . $identifier);
}
}
$this->identifiers = array();
$this->identifiers = [];
foreach ($identifiers as $name => $value) {
$this->identifiers[$name] = (string)$value;
@ -794,13 +804,13 @@ class cache_definition {
public function get_requirements_bin() {
$requires = 0;
if ($this->require_data_guarantee()) {
$requires += cache_store::SUPPORTS_DATA_GUARANTEE;
$requires += store::SUPPORTS_DATA_GUARANTEE;
}
if ($this->require_multiple_identifiers()) {
$requires += cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS;
$requires += store::SUPPORTS_MULTIPLE_IDENTIFIERS;
}
if ($this->require_searchable()) {
$requires += cache_store::IS_SEARCHABLE;
$requires += store::IS_SEARCHABLE;
}
return $requires;
}
@ -808,11 +818,11 @@ class cache_definition {
/**
* Please call {@link cache_definition::use_static_acceleration()} instead.
*
* @see cache_definition::use_static_acceleration()
* @see definition::use_static_acceleration()
* @deprecated since 2.6
*/
public function should_be_persistent() {
throw new coding_exception('cache_definition::should_be_persistent() can not be used anymore.' .
throw new coding_exception('definition::should_be_persistent() can not be used anymore.' .
' Please use cache_definition::use_static_acceleration() instead.');
}
@ -825,7 +835,7 @@ class cache_definition {
* @return bool
*/
public function use_static_acceleration() {
if ($this->mode === cache_store::MODE_REQUEST) {
if ($this->mode === store::MODE_REQUEST) {
// Request caches should never use static acceleration - it just doesn't make sense.
return false;
}
@ -869,12 +879,12 @@ class cache_definition {
*/
public function generate_single_key_prefix() {
if ($this->keyprefixsingle === null) {
$this->keyprefixsingle = $this->mode.'/'.$this->component.'/'.$this->area;
$this->keyprefixsingle .= '/'.$this->get_cache_identifier();
$this->keyprefixsingle = $this->mode . '/' . $this->component . '/' . $this->area;
$this->keyprefixsingle .= '/' . $this->get_cache_identifier();
$identifiers = $this->get_identifiers();
if ($identifiers) {
foreach ($identifiers as $key => $value) {
$this->keyprefixsingle .= '/'.$key.'='.$value;
$this->keyprefixsingle .= '/' . $key . '=' . $value;
}
}
$this->keyprefixsingle = md5($this->keyprefixsingle);
@ -889,16 +899,16 @@ class cache_definition {
*/
public function generate_multi_key_parts() {
if ($this->keyprefixmulti === null) {
$this->keyprefixmulti = array(
$this->keyprefixmulti = [
'mode' => $this->mode,
'component' => $this->component,
'area' => $this->area,
'siteidentifier' => $this->get_cache_identifier()
);
'siteidentifier' => $this->get_cache_identifier(),
];
if (isset($this->identifiers) && !empty($this->identifiers)) {
$identifiers = array();
$identifiers = [];
foreach ($this->identifiers as $key => $value) {
$identifiers[] = htmlentities($key, ENT_QUOTES, 'UTF-8').'='.htmlentities($value, ENT_QUOTES, 'UTF-8');
$identifiers[] = htmlentities($key, ENT_QUOTES, 'UTF-8') . '=' . htmlentities($value, ENT_QUOTES, 'UTF-8');
}
$this->keyprefixmulti['identifiers'] = join('&', $identifiers);
}
@ -940,15 +950,15 @@ class cache_definition {
* @return string A string to be used as part of keys.
*/
protected function get_cache_identifier() {
$identifiers = array();
$identifiers = [];
if ($this->selectedsharingoption & self::SHARING_ALL) {
// Nothing to do here.
} else {
if ($this->selectedsharingoption & self::SHARING_SITEID) {
$identifiers[] = cache_helper::get_site_identifier();
$identifiers[] = helper::get_site_identifier();
}
if ($this->selectedsharingoption & self::SHARING_VERSION) {
$identifiers[] = cache_helper::get_site_version();
$identifiers[] = helper::get_site_version();
}
if ($this->selectedsharingoption & self::SHARING_INPUT && !empty($this->userinputsharingkey)) {
$identifiers[] = $this->userinputsharingkey;
@ -993,3 +1003,8 @@ class cache_definition {
return $this->selectedsharingoption;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(definition::class, \cache_definition::class);

View file

@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
/**
* The cache loader class used when the Cache has been disabled.
*
@ -21,17 +25,16 @@
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_disabled extends cache implements cache_loader_with_locking {
class disabled_cache extends cache implements loader_with_locking_interface {
/**
* Constructs the cache.
*
* @param cache_definition $definition
* @param cache_store $store
* @param definition $definition
* @param store $store
* @param null $loader Unused.
*/
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
if ($loader instanceof cache_data_source) {
public function __construct(definition $definition, store $store, $loader = null) {
if ($loader instanceof data_source_interface) {
// Set the data source to allow data sources to work when caching is entirely disabled.
$this->set_data_source($loader);
}
@ -54,12 +57,12 @@ class cache_disabled extends cache implements cache_loader_with_locking {
if ($requiredversion === cache::VERSION_NONE) {
return $datasource->load_for_cache($key);
} else {
if (!$datasource instanceof cache_data_source_versionable) {
throw new \coding_exception('Data source is not versionable');
if (!$datasource instanceof versionable_data_source_interface) {
throw new coding_exception('Data source is not versionable');
}
$result = $datasource->load_for_cache_versioned($key, $requiredversion, $actualversion);
if ($result && $actualversion < $requiredversion) {
throw new \coding_exception('Data source returned outdated version');
throw new coding_exception('Data source returned outdated version');
}
return $result;
}
@ -213,3 +216,8 @@ class cache_disabled extends cache implements cache_loader_with_locking {
return true;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(disabled_cache::class, \cache_disabled::class);

View file

@ -14,6 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use core_cache\exception\cache_exception;
use cachestore_static;
use cachestore_session;
use cachestore_file;
/**
* The cache config class used when the Cache has been disabled.
*
@ -21,15 +29,14 @@
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_config_disabled extends config_writer {
class disabled_config extends config_writer {
/**
* Returns an instance of the configuration writer.
*
* @return cache_config_disabled
* @return disabled_config
*/
public static function instance() {
$factory = cache_factory::instance();
$factory = factory::instance();
return $factory->create_config_instance(true);
}
@ -46,7 +53,7 @@ class cache_config_disabled extends config_writer {
* @return array
*/
protected function generate_configuration_array() {
$configuration = array();
$configuration = [];
$configuration['stores'] = $this->configstores;
$configuration['modemappings'] = $this->configmodemappings;
$configuration['definitions'] = $this->configdefinitions;
@ -64,7 +71,7 @@ class cache_config_disabled extends config_writer {
* @return bool
* @throws cache_exception
*/
public function add_store_instance($name, $plugin, array $configuration = array()) {
public function add_store_instance($name, $plugin, array $configuration = []) {
return false;
}
@ -115,63 +122,63 @@ class cache_config_disabled extends config_writer {
// HACK ALERT.
// We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
// default store plugins are protected from deletion.
require_once($CFG->dirroot.'/cache/stores/file/lib.php');
require_once($CFG->dirroot.'/cache/stores/session/lib.php');
require_once($CFG->dirroot.'/cache/stores/static/lib.php');
require_once($CFG->dirroot . '/cache/stores/file/lib.php');
require_once($CFG->dirroot . '/cache/stores/session/lib.php');
require_once($CFG->dirroot . '/cache/stores/static/lib.php');
$writer = new self;
$writer->configstores = array(
'default_application' => array(
$writer = new self();
$writer->configstores = [
'default_application' => [
'name' => 'default_application',
'plugin' => 'file',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_file::get_supported_features(),
'modes' => cache_store::MODE_APPLICATION,
'modes' => store::MODE_APPLICATION,
'default' => true,
),
'default_session' => array(
],
'default_session' => [
'name' => 'default_session',
'plugin' => 'session',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_session::get_supported_features(),
'modes' => cache_store::MODE_SESSION,
'modes' => store::MODE_SESSION,
'default' => true,
),
'default_request' => array(
],
'default_request' => [
'name' => 'default_request',
'plugin' => 'static',
'configuration' => array(),
'configuration' => [],
'features' => cachestore_static::get_supported_features(),
'modes' => cache_store::MODE_REQUEST,
'modes' => store::MODE_REQUEST,
'default' => true,
)
);
$writer->configdefinitions = array();
$writer->configmodemappings = array(
array(
'mode' => cache_store::MODE_APPLICATION,
],
];
$writer->configdefinitions = [];
$writer->configmodemappings = [
[
'mode' => store::MODE_APPLICATION,
'store' => 'default_application',
'sort' => -1
),
array(
'mode' => cache_store::MODE_SESSION,
'sort' => -1,
],
[
'mode' => store::MODE_SESSION,
'store' => 'default_session',
'sort' => -1
),
array(
'mode' => cache_store::MODE_REQUEST,
'sort' => -1,
],
[
'mode' => store::MODE_REQUEST,
'store' => 'default_request',
'sort' => -1
)
);
$writer->configlocks = array(
'default_file_lock' => array(
'sort' => -1,
],
];
$writer->configlocks = [
'default_file_lock' => [
'name' => 'cachelock_file_default',
'type' => 'cachelock_file',
'dir' => 'filelocks',
'default' => true
)
);
'default' => true,
],
];
return $writer->generate_configuration_array();
}
@ -192,7 +199,7 @@ class cache_config_disabled extends config_writer {
* @return array
*/
protected static function locate_definitions($coreonly = false) {
return array();
return [];
}
/**
@ -206,3 +213,8 @@ class cache_config_disabled extends config_writer {
// Nothing to do here.
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(disabled_config::class, \cache_config_disabled::class);

View file

@ -14,6 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use cache_factory as factory;
use cache_store as store;
use core_cache\definition;
use cache_application as application_cache;
use cache_session as session_cache;
use cachestore_static;
use core\exception\coding_exception;
/**
* The cache factory class used when the Cache has been disabled.
*
@ -21,7 +31,7 @@
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_factory_disabled extends cache_factory {
class disabled_factory extends factory {
/** @var array Array of temporary caches in use. */
protected static $tempcaches = [];
@ -29,7 +39,7 @@ class cache_factory_disabled extends cache_factory {
* Returns an instance of the cache_factor method.
*
* @param bool $forcereload Unused.
* @return cache_factory
* @return factory
* @throws coding_exception
*/
public static function instance($forcereload = false) {
@ -42,7 +52,7 @@ class cache_factory_disabled extends cache_factory {
* @param string $component
* @param string $area
* @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
* @return cache_definition
* @return definition
*/
public function create_definition($component, $area, $unused = null) {
$definition = parent::create_definition($component, $area);
@ -50,22 +60,22 @@ class cache_factory_disabled extends cache_factory {
return $definition;
}
return cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area);
return definition::load_adhoc(store::MODE_REQUEST, $component, $area);
}
/**
* Common public method to create a cache instance given a definition.
*
* @param cache_definition $definition
* @return cache_application|cache_session|cache_store
* @param definition $definition
* @return application_cache|session_cache|store
* @throws coding_exception
*/
public function create_cache(cache_definition $definition) {
public function create_cache(definition $definition) {
$loader = null;
if ($definition->has_data_source()) {
$loader = $definition->get_data_source();
}
return new cache_disabled($definition, $this->create_dummy_store($definition), $loader);
return new disabled_cache($definition, $this->create_dummy_store($definition), $loader);
}
/**
@ -75,9 +85,9 @@ class cache_factory_disabled extends cache_factory {
* @param string $area
* @param array $identifiers
* @param string $unused Used to be datasourceaggregate but that was removed and this is now unused.
* @return cache_application|cache_session|request_cache
* @return application_cache|session_cache|request_cache
*/
public function create_cache_from_definition($component, $area, array $identifiers = array(), $unused = null) {
public function create_cache_from_definition($component, $area, array $identifiers = [], $unused = null) {
// Temporary in-memory caches are sometimes allowed when caching is disabled.
if (\core_cache\allow_temporary_caches::is_allowed() && !$identifiers) {
$key = $component . '/' . $area;
@ -93,7 +103,7 @@ class cache_factory_disabled extends cache_factory {
// or it wouldn't have support for versioning. The cache_application class is used
// (rather than cache_request which might make more sense logically) because it
// includes support for locking, which might be necessary for some caches.
$cache = new cache_application($definition, $store);
$cache = new application_cache($definition, $store);
self::$tempcaches[$key] = $cache;
}
return $cache;
@ -129,13 +139,13 @@ class cache_factory_disabled extends cache_factory {
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
* - staticacceleration : If set to true the cache will hold onto all data passing through it.
* - staticaccelerationsize : Sets the max size of the static acceleration array.
* @return cache_application|cache_session|request_cache
* @return application_cache|session_cache|request_cache
*/
public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
public function create_cache_from_params($mode, $component, $area, array $identifiers = [], array $options = []) {
// Regular cache definitions are cached inside create_definition(). This is not the case for disabledlib.php
// definitions as they use load_adhoc(). They are built as a new object on each call.
// We do not need to clone the definition because we know it's new.
$definition = cache_definition::load_adhoc($mode, $component, $area, $options);
$definition = definition::load_adhoc($mode, $component, $area, $options);
$definition->set_identifiers($identifiers);
$cache = $this->create_cache($definition);
return $cache;
@ -146,10 +156,10 @@ class cache_factory_disabled extends cache_factory {
*
* @param string $name Unused.
* @param array $details Unused.
* @param cache_definition $definition
* @return boolean|cache_store
* @param definition $definition
* @return boolean|store
*/
public function create_store_from_config($name, array $details, cache_definition $definition) {
public function create_store_from_config($name, array $details, definition $definition) {
return $this->create_dummy_store($definition);
}
@ -157,7 +167,7 @@ class cache_factory_disabled extends cache_factory {
* Creates a cache config instance with the ability to write if required.
*
* @param bool $writer Unused.
* @return cache_config_disabled|config_writer
* @return disabled_config|config_writer
*/
public function create_config_instance($writer = false) {
// We are always going to use the cache_config_disabled class for all regular request.
@ -170,10 +180,10 @@ class cache_factory_disabled extends cache_factory {
$class = 'cache_config_writer';
}
if (!array_key_exists($class, $this->configs)) {
self::set_state(self::STATE_INITIALISING);
self::set_state(factory::STATE_INITIALISING);
if ($class === 'cache_config_disabled') {
$configuration = $class::create_default_configuration();
$this->configs[$class] = new $class;
$this->configs[$class] = new $class();
} else {
$configuration = false;
// If we need a writer, we should get the classname from the generic factory.
@ -182,7 +192,7 @@ class cache_factory_disabled extends cache_factory {
}
$this->configs[$class]->load($configuration);
}
self::set_state(self::STATE_READY);
self::set_state(factory::STATE_READY);
// Return the instance.
return $this->configs[$class];
@ -197,3 +207,7 @@ class cache_factory_disabled extends cache_factory {
return true;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(disabled_factory::class, \cache_factory_disabled::class);

View file

@ -16,31 +16,14 @@
namespace core_cache;
/**
* Cache dummy store.
*
* This dummy store is used when a load has no other stores that it can make use of.
* This shouldn't happen in normal operation... I think.
*
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are requried in order to use caching.
*
* @package core
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* The cache dummy store.
*
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core_cache
*/
class cachestore_dummy extends cache_store {
class dummy_cachestore extends store {
/**
* The name of this store.
* @var string
@ -59,7 +42,7 @@ class cachestore_dummy extends cache_store {
* The stored data array
* @var array
*/
protected $store = array();
protected $store = [];
/**
* Cache definition
@ -72,7 +55,7 @@ class cachestore_dummy extends cache_store {
* @param string $name
* @param array $configuration
*/
public function __construct($name = 'Dummy store', array $configuration = array()) {
public function __construct($name = 'Dummy store', array $configuration = []) {
$this->name = $name;
}
@ -97,8 +80,8 @@ class cachestore_dummy extends cache_store {
* @param array $configuration
* @return int
*/
public static function get_supported_features(array $configuration = array()) {
return self::SUPPORTS_NATIVE_TTL;
public static function get_supported_features(array $configuration = []) {
return store::SUPPORTS_NATIVE_TTL;
}
/**
@ -106,8 +89,8 @@ class cachestore_dummy extends cache_store {
* @param array $configuration
* @return int
*/
public static function get_supported_modes(array $configuration = array()) {
return self::MODE_APPLICATION + self::MODE_REQUEST + self::MODE_SESSION;
public static function get_supported_modes(array $configuration = []) {
return store::MODE_APPLICATION + store::MODE_REQUEST + store::MODE_SESSION;
}
/**
@ -117,11 +100,11 @@ class cachestore_dummy extends cache_store {
public function initialise(definition $definition) {
// If the definition isn't using static acceleration then we need to be store data here.
// The reasoning behind this is that:
// - If the definition is using static acceleration then the cache loader is going to
// store things in its static array.
// - If the definition is not using static acceleration then the cache loader won't try to store anything
// and we will need to store it here in order to make sure it is accessible.
if ($definition->get_mode() !== self::MODE_APPLICATION) {
// - If the definition is using static acceleration then the cache loader is going to
// store things in its static array.
// - If the definition is not using static acceleration then the cache loader won't try to store anything
// and we will need to store it here in order to make sure it is accessible.
if ($definition->get_mode() !== store::MODE_APPLICATION) {
// Neither the request cache nor the session cache provide static acceleration.
$this->persist = true;
} else {
@ -166,7 +149,7 @@ class cachestore_dummy extends cache_store {
* @return bool
*/
public function get_many($keys) {
$return = array();
$return = [];
foreach ($keys as $key) {
if ($this->persist && array_key_exists($key, $this->store)) {
$return[$key] = $this->store[$key];
@ -200,7 +183,6 @@ class cachestore_dummy extends cache_store {
foreach ($keyvaluearray as $pair) {
$this->store[$pair['key']] = $pair['value'];
}
}
return count($keyvaluearray);
}
@ -233,7 +215,7 @@ class cachestore_dummy extends cache_store {
* @return bool
*/
public function purge() {
$this->store = array();
$this->store = [];
return true;
}
@ -241,11 +223,13 @@ class cachestore_dummy extends cache_store {
* Performs any necessary clean up when the store instance is being deleted.
*
* @deprecated since 3.2
* @see cachestore_dummy::instance_deleted()
* @see dummy_cachestore::instance_deleted()
*/
public function cleanup() {
debugging('cachestore_dummy::cleanup() is deprecated. Please use cachestore_dummy::instance_deleted() instead.',
DEBUG_DEVELOPER);
debugging(
'dummy_cachestore::cleanup() is deprecated. Please use dummy_cachestore::instance_deleted() instead.',
DEBUG_DEVELOPER
);
$this->instance_deleted();
}
@ -264,10 +248,10 @@ class cachestore_dummy extends cache_store {
* Generates an instance of the cache store that can be used for testing.
*
* @param definition $definition
* @return false
* @return self
*/
public static function initialise_test_instance(definition $definition) {
$cache = new cachestore_dummy('Dummy store test');
$cache = new dummy_cachestore('Dummy store test');
if ($cache->is_ready()) {
$cache->initialise($definition);
}

View file

@ -14,10 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\exception;
use core\exception\moodle_exception;
/**
* A cache exception class. Just allows people to catch cache exceptions.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -37,3 +41,8 @@ class cache_exception extends moodle_exception {
parent::__construct($errorcode, $module, $link, $a, $debuginfo);
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_exception::class, \cache_exception::class);

View file

@ -14,6 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
use cache_config_testing;
use cache_phpunit_factory;
/**
* The cache factory class.
*
@ -23,9 +29,9 @@
*
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package core_cache
*/
class cache_factory {
class factory {
/** The cache has not been initialised yet. */
const STATE_UNINITIALISED = 0;
/** The cache is in the process of initialising itself. */
@ -44,8 +50,8 @@ class cache_factory {
const STATE_STORES_DISABLED = 11;
/**
* An instance of the cache_factory class created upon the first request.
* @var cache_factory
* An instance of the factory class created upon the first request.
* @var factory
*/
protected static $instance;
@ -53,43 +59,43 @@ class cache_factory {
* An array containing caches created for definitions
* @var array
*/
protected $cachesfromdefinitions = array();
protected $cachesfromdefinitions = [];
/**
* Array of caches created by parameters, ad-hoc definitions will have been used.
* @var array
*/
protected $cachesfromparams = array();
protected $cachesfromparams = [];
/**
* An array of stores organised by definitions.
* @var array
*/
protected $definitionstores = array();
protected $definitionstores = [];
/**
* An array of instantiated stores.
* @var array
*/
protected $stores = array();
protected $stores = [];
/**
* An array of configuration instances
* @var array
*/
protected $configs = array();
protected $configs = [];
/**
* An array of initialised definitions
* @var array
*/
protected $definitions = array();
protected $definitions = [];
/**
* An array of lock plugins.
* @var array
*/
protected $lockplugins = array();
protected $lockplugins = [];
/**
* The current state of the cache API.
@ -104,10 +110,10 @@ class cache_factory {
protected static $displayhelper = null;
/**
* Returns an instance of the cache_factory class.
* Returns an instance of the factory class.
*
* @param bool $forcereload If set to true a new cache_factory instance will be created and used.
* @return cache_factory
* @param bool $forcereload If set to true a new factory instance will be created and used.
* @return factory
*/
public static function instance($forcereload = false) {
global $CFG;
@ -116,22 +122,21 @@ class cache_factory {
if (defined('CACHE_DISABLE_ALL') && CACHE_DISABLE_ALL !== false) {
// The cache has been disabled. Load disabledlib and start using the factory designed to handle this
// situation. It will use disabled alternatives where available.
self::$instance = new cache_factory_disabled();
self::$instance = new disabled_factory();
} else if ((defined('PHPUNIT_TEST') && PHPUNIT_TEST) || defined('BEHAT_SITE_RUNNING')) {
// We're using the test factory.
require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
require_once($CFG->dirroot . '/cache/tests/fixtures/lib.php');
self::$instance = new cache_phpunit_factory();
if (defined('CACHE_DISABLE_STORES') && CACHE_DISABLE_STORES !== false) {
// The cache stores have been disabled.
self::$instance->set_state(self::STATE_STORES_DISABLED);
}
} else if (!empty($CFG->alternative_cache_factory_class)) {
$factoryclass = $CFG->alternative_cache_factory_class;
self::$instance = new $factoryclass();
} else {
// We're using the regular factory.
self::$instance = new cache_factory();
self::$instance = new factory();
if (defined('CACHE_DISABLE_STORES') && CACHE_DISABLE_STORES !== false) {
// The cache stores have been disabled.
self::$instance->set_state(self::STATE_STORES_DISABLED);
@ -154,10 +159,10 @@ class cache_factory {
public static function reset() {
$factory = self::instance();
$factory->reset_cache_instances();
$factory->configs = array();
$factory->definitions = array();
$factory->definitionstores = array();
$factory->lockplugins = array(); // MUST be null in order to force its regeneration.
$factory->configs = [];
$factory->definitions = [];
$factory->definitionstores = [];
$factory->lockplugins = []; // MUST be null in order to force its regeneration.
// Reset the state to uninitialised.
$factory->state = self::STATE_UNINITIALISED;
}
@ -169,9 +174,9 @@ class cache_factory {
* however all future requests for a cache/store will lead to a new instance being re-initialised.
*/
public function reset_cache_instances() {
$this->cachesfromdefinitions = array();
$this->cachesfromparams = array();
$this->stores = array();
$this->cachesfromdefinitions = [];
$this->cachesfromparams = [];
$this->stores = [];
}
/**
@ -183,11 +188,11 @@ class cache_factory {
* @param string $area
* @param array $identifiers
* @param string $unused Used to be data source aggregate however that was removed and this is now unused.
* @return cache_application|cache_session|cache_request
* @return application_cache|session_cache|request_cache
*/
public function create_cache_from_definition($component, $area, array $identifiers = array(), $unused = null) {
$identifierstring = empty($identifiers) ? '' : '/'.http_build_query($identifiers);
$definitionname = $component.'/'.$area.$identifierstring;
public function create_cache_from_definition($component, $area, array $identifiers = [], $unused = null) {
$identifierstring = empty($identifiers) ? '' : '/' . http_build_query($identifiers);
$definitionname = $component . '/' . $area . $identifierstring;
if (isset($this->cachesfromdefinitions[$definitionname])) {
$cache = $this->cachesfromdefinitions[$definitionname];
return $cache;
@ -217,10 +222,10 @@ class cache_factory {
* - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
* - staticacceleration : If set to true the cache will hold onto data passing through it.
* - staticaccelerationsize : The maximum number of items to hold onto for acceleration purposes.
* @return cache_application|cache_session|cache_request
* @return application_cache|session_cache|request_cache
*/
public function create_cache_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) {
$identifierstring = empty($identifiers) ? '' : '_'.http_build_query($identifiers);
public function create_cache_from_params($mode, $component, $area, array $identifiers = [], array $options = []) {
$identifierstring = empty($identifiers) ? '' : '_' . http_build_query($identifiers);
$key = "{$mode}_{$component}_{$area}{$identifierstring}";
if (isset($this->cachesfromparams[$key])) {
return $this->cachesfromparams[$key];
@ -228,7 +233,7 @@ class cache_factory {
// Regular cache definitions are cached inside create_definition(). This is not the case for Adhoc definitions
// using load_adhoc(). They are built as a new object on each call.
// We do not need to clone the definition because we know it's new.
$definition = cache_definition::load_adhoc($mode, $component, $area, $options);
$definition = definition::load_adhoc($mode, $component, $area, $options);
$definition->set_identifiers($identifiers);
$cache = $this->create_cache($definition);
$this->cachesfromparams[$key] = $cache;
@ -240,13 +245,13 @@ class cache_factory {
*
* This is used by the static make methods.
*
* @param cache_definition $definition
* @return cache_application|cache_session|cache_store
* @param definition $definition
* @return application_cache|session_cache|store
* @throws coding_exception
*/
public function create_cache(cache_definition $definition) {
public function create_cache(definition $definition) {
$class = $definition->get_cache_class();
$stores = cache_helper::get_stores_suitable_for_definition($definition);
$stores = helper::get_stores_suitable_for_definition($definition);
foreach ($stores as $key => $store) {
if (!$store::are_requirements_met()) {
unset($stores[$key]);
@ -273,10 +278,10 @@ class cache_factory {
*
* @param string $name The name of the store (must be unique remember)
* @param array $details
* @param cache_definition $definition The definition to instantiate it for.
* @return boolean|cache_store
* @param definition $definition The definition to instantiate it for.
* @return boolean|store
*/
public function create_store_from_config($name, array $details, cache_definition $definition) {
public function create_store_from_config($name, array $details, definition $definition) {
if (!array_key_exists($name, $this->stores)) {
// Properties: name, plugin, configuration, class.
$class = $details['class'];
@ -286,7 +291,7 @@ class cache_factory {
$store = new $class($details['name'], $details['configuration']);
$this->stores[$name] = $store;
}
/* @var cache_store $store */
/* @var store $store */
$store = $this->stores[$name];
// We check are_requirements_met although we expect is_ready is going to check as well.
if (!$store::are_requirements_met() || !$store->is_ready() || !$store->is_supported_mode($definition->get_mode())) {
@ -302,7 +307,7 @@ class cache_factory {
$store->initialise($definition);
$definitionid = $definition->get_id();
if (!isset($this->definitionstores[$definitionid])) {
$this->definitionstores[$definitionid] = array();
$this->definitionstores[$definitionid] = [];
}
$this->definitionstores[$definitionid][] = $store;
return $store;
@ -310,13 +315,13 @@ class cache_factory {
/**
* Returns an array of cache stores that have been initialised for use in definitions.
* @param cache_definition $definition
* @param definition $definition
* @return array
*/
public function get_store_instances_in_use(cache_definition $definition) {
public function get_store_instances_in_use(definition $definition) {
$id = $definition->get_id();
if (!isset($this->definitionstores[$id])) {
return array();
return [];
}
return $this->definitionstores[$id];
}
@ -333,7 +338,7 @@ class cache_factory {
/**
* Gets all adhoc caches that have been used within this request.
*
* @return cache_store[] Caches currently in use
* @return store[] Caches currently in use
*/
public function get_adhoc_caches_in_use() {
return $this->cachesfromparams;
@ -343,23 +348,23 @@ class cache_factory {
* Creates a cache config instance with the ability to write if required.
*
* @param bool $writer If set to true an instance that can update the configuration will be returned.
* @return cache_config|cache_config_writer
* @return config|config_writer
*/
public function create_config_instance($writer = false) {
global $CFG;
// The class to use.
$class = 'cache_config';
$class = config::class;
// Are we running tests of some form?
$testing = (defined('PHPUNIT_TEST') && PHPUNIT_TEST) || defined('BEHAT_SITE_RUNNING');
// Check if this is a PHPUnit test and redirect to the phpunit config classes if it is.
if ($testing) {
require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
require_once($CFG->dirroot . '/cache/tests/fixtures/lib.php');
// We have just a single class for PHP unit tests. We don't care enough about its
// performance to do otherwise and having a single method allows us to inject things into it
// while testing.
$class = 'cache_config_testing';
$class = cache_config_testing::class;
}
// Check if we need to create a config file with defaults.
@ -376,12 +381,12 @@ class cache_factory {
// Create the default configuration.
// Update the state, we are now initialising the cache.
self::set_state(self::STATE_INITIALISING);
/** @var cache_config_writer $class */
/** @var config_writer $class */
$configuration = $class::create_default_configuration();
if ($configuration !== true) {
// Failed to create the default configuration. Disable the cache stores and update the state.
self::set_state(self::STATE_ERROR_INITIALISING);
$this->configs[$class] = new $class;
$this->configs[$class] = new $class();
$this->configs[$class]->load($configuration);
$error = true;
}
@ -389,7 +394,7 @@ class cache_factory {
if (!array_key_exists($class, $this->configs)) {
// Create a new instance and call it to load it.
$this->configs[$class] = new $class;
$this->configs[$class] = new $class();
$this->configs[$class]->load();
}
@ -408,17 +413,17 @@ class cache_factory {
* @param string $area
* @param string $unused This used to be data source aggregate - however that functionality has been removed and
* this argument is now unused.
* @return cache_definition
* @return definition
* @throws coding_exception If the definition cannot be found.
*/
public function create_definition($component, $area, $unused = null) {
$id = $component.'/'.$area;
$id = $component . '/' . $area;
if (!isset($this->definitions[$id])) {
// This is the first time this definition has been requested.
if ($this->is_initialising()) {
// We're initialising the cache right now. Don't try to create another config instance.
// We'll just use an ad-hoc cache for the time being.
$definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area);
$definition = definition::load_adhoc(store::MODE_REQUEST, $component, $area);
} else {
// Load all the known definitions and find the desired one.
$instance = $this->create_config_instance();
@ -433,7 +438,7 @@ class cache_factory {
// This means that the cache initialisation has requested something from a cache (I had recursive nightmares about this).
// To serve this purpose and avoid errors we are going to make use of an ad-hoc cache rather than
// search for the definition which would possibly cause an infitite loop trying to initialise the cache.
$definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area);
$definition = definition::load_adhoc(store::MODE_REQUEST, $component, $area);
} else {
// Either a typo of the developer has just created the definition and is using it for the first time.
$this->reset();
@ -441,16 +446,16 @@ class cache_factory {
$instance->update_definitions();
$definition = $instance->get_definition_by_id($id);
if (!$definition) {
throw new coding_exception('The requested cache definition does not exist.'. $id, $id);
throw new coding_exception('The requested cache definition does not exist.' . $id, $id);
}
if (!$this->is_disabled()) {
debugging('Cache definitions reparsed causing cache reset in order to locate definition.
You should bump the version number to ensure definitions are reprocessed.', DEBUG_DEVELOPER);
}
$definition = cache_definition::load($id, $definition);
$definition = definition::load($id, $definition);
}
} else {
$definition = cache_definition::load($id, $definition);
$definition = definition::load($id, $definition);
}
}
$this->definitions[$id] = $definition;
@ -464,8 +469,8 @@ class cache_factory {
* @param definition $definition
* @return dummy_cachestore
*/
protected function create_dummy_store(cache_definition $definition) {
$store = new cachestore_dummy();
protected function create_dummy_store(definition $definition) {
$store = new dummy_cachestore();
$store->initialise($definition);
return $store;
}
@ -474,7 +479,7 @@ class cache_factory {
* Returns a lock instance ready for use.
*
* @param array $config
* @return cache_lock_interface
* @return lockable_cache_interface
*/
public function create_lock_instance(array $config) {
global $CFG;
@ -488,7 +493,7 @@ class cache_factory {
if (!isset($this->lockplugins[$type])) {
$pluginname = substr($type, 10);
$file = $CFG->dirroot."/cache/locks/{$pluginname}/lib.php";
$file = $CFG->dirroot . "/cache/locks/{$pluginname}/lib.php";
if (file_exists($file) && is_readable($file)) {
require_once($file);
}
@ -592,7 +597,7 @@ class cache_factory {
* MUC it was decided that this was just to risky and abusable.
*/
protected static function disable() {
self::$instance = new cache_factory_disabled();
self::$instance = new disabled_factory();
}
/**
@ -614,9 +619,9 @@ class cache_factory {
* In order to re-enable the cache you must call the cache factories static reset method:
* <code>
* // Disable the cache factory.
* cache_factory::disable_stores();
* factory::disable_stores();
* // Re-enable the cache factory by resetting it.
* cache_factory::reset();
* factory::reset();
* </code>
*/
public static function disable_stores() {
@ -629,9 +634,9 @@ class cache_factory {
/**
* Returns an instance of the current display_helper.
*
* @return core_cache\administration_helper
* @return administration_helper
*/
public static function get_administration_display_helper(): core_cache\administration_helper {
public static function get_administration_display_helper(): administration_helper {
if (is_null(self::$displayhelper)) {
self::$displayhelper = new \core_cache\local\administration_display_helper();
}
@ -639,12 +644,12 @@ class cache_factory {
}
/**
* Gets the cache_config_writer to use when caching is disabled.
* This should only be called from cache_factory_disabled.
* Gets the config_writer to use when caching is disabled.
* This should only be called from disabled_factory.
*
* @return cache_config_writer
* @return config_writer
*/
public static function get_disabled_writer(): cache_config_writer {
public static function get_disabled_writer(): config_writer {
global $CFG;
// Figure out if we are in a recursive loop using late static binding.
@ -659,14 +664,19 @@ class cache_factory {
$factoryinstance = new $CFG->alternative_cache_factory_class();
return $factoryinstance::get_disabled_writer();
} else {
// We got here from cache_factory_disabled.
// We got here from disabled_factory.
// We should use the default writer here.
// Make sure we have a default config if needed.
if (!cache_config::config_file_exists()) {
cache_config_writer::create_default_configuration(true);
if (!config::config_file_exists()) {
config_writer::create_default_configuration(true);
}
return new cache_config_writer();
return new config_writer();
}
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(factory::class, \cache_factory::class);

View file

@ -14,10 +14,17 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\form;
use core_cache\administration_helper;
use cache_store as store;
use html_writer;
use moodleform;
/**
* Form to set definition mappings
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -32,11 +39,11 @@ class cache_definition_mappings_form extends moodleform {
$definition = $this->_customdata['definition'];
$form = $this->_form;
list($component, $area) = explode('/', $definition, 2);
list($currentstores, $storeoptions, $defaults) =
core_cache\administration_helper::get_definition_store_options($component, $area);
[$component, $area] = explode('/', $definition, 2);
[$currentstores, $storeoptions, $defaults] =
administration_helper::get_definition_store_options($component, $area);
$storedata = core_cache\administration_helper::get_definition_summaries();
$storedata = administration_helper::get_definition_summaries();
if ($storedata[$definition]['mode'] != store::MODE_REQUEST) {
if (isset($storedata[$definition]['canuselocalstore']) && $storedata[$definition]['canuselocalstore']) {
$form->addElement('html', $OUTPUT->notification(get_string('localstorenotification', 'cache'), 'notifymessage'));
@ -49,14 +56,14 @@ class cache_definition_mappings_form extends moodleform {
$form->addElement('hidden', 'action', 'editdefinitionmapping');
$form->setType('action', PARAM_ALPHA);
$requiredoptions = max(3, count($currentstores)+1);
$requiredoptions = max(3, count($currentstores) + 1);
$requiredoptions = min($requiredoptions, count($storeoptions));
$options = array('' => get_string('none'));
$options = ['' => get_string('none')];
foreach ($storeoptions as $option => $def) {
$options[$option] = $option;
if ($def['default']) {
$options[$option] .= ' '.get_string('mappingdefault', 'cache');
$options[$option] .= ' ' . get_string('mappingdefault', 'cache');
}
}
@ -64,23 +71,32 @@ class cache_definition_mappings_form extends moodleform {
$title = '...';
if ($i === 0) {
$title = get_string('mappingprimary', 'cache');
} else if ($i === $requiredoptions-1) {
} else if ($i === $requiredoptions - 1) {
$title = get_string('mappingfinal', 'cache');
}
$form->addElement('select', 'mappings['.$i.']', $title, $options);
$form->addElement('select', 'mappings[' . $i . ']', $title, $options);
}
$i = 0;
foreach ($currentstores as $store => $def) {
$form->setDefault('mappings['.$i.']', $store);
$form->setDefault('mappings[' . $i . ']', $store);
$i++;
}
if (!empty($defaults)) {
$form->addElement('static', 'defaults', get_string('defaultmappings', 'cache'),
html_writer::tag('strong', join(', ', $defaults)));
$form->addElement(
'static',
'defaults',
get_string('defaultmappings', 'cache'),
html_writer::tag('strong', join(', ', $defaults))
);
$form->addHelpButton('defaults', 'defaultmappings', 'cache');
}
$this->add_action_buttons();
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_definition_mappings_form::class, \cache_definition_mappings_form::class);

View file

@ -14,10 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\form;
use core_cache\administration_helper;
use core_cache\definition;
use moodleform;
/**
* Form to set definition sharing option
*
* @package core
* @package core_cache
* @category cache
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -38,7 +44,7 @@ class cache_definition_sharing_form extends moodleform {
// We use a group here for validation.
$count = 0;
$group = array();
$group = [];
foreach ($sharingoptions as $value => $text) {
$count++;
$group[] = $form->createElement('checkbox', $value, null, $text);
@ -48,16 +54,16 @@ class cache_definition_sharing_form extends moodleform {
$form->addElement('text', 'userinputsharingkey', get_string('userinputsharingkey', 'cache'));
$form->addHelpButton('userinputsharingkey', 'userinputsharingkey', 'cache');
$form->disabledIf('userinputsharingkey', 'sharing['.\core_cache\definition::SHARING_INPUT.']', 'notchecked');
$form->disabledIf('userinputsharingkey', 'sharing[' . definition::SHARING_INPUT . ']', 'notchecked');
$form->setType('userinputsharingkey', PARAM_ALPHANUMEXT);
$values = array_keys($sharingoptions);
if (in_array(\core_cache\definition::SHARING_ALL, $values)) {
if (in_array(definition::SHARING_ALL, $values)) {
// If you share with all thenthe other options don't really make sense.
foreach ($values as $value) {
$form->disabledIf('sharing['.$value.']', 'sharing['.\core_cache\definition::SHARING_ALL.']', 'checked');
$form->disabledIf('sharing[' . $value . ']', 'sharing[' . definition::SHARING_ALL . ']', 'checked');
}
$form->disabledIf('userinputsharingkey', 'sharing['.\core_cache\definition::SHARING_ALL.']', 'checked');
$form->disabledIf('userinputsharingkey', 'sharing[' . definition::SHARING_ALL . ']', 'checked');
}
$this->add_action_buttons();
@ -71,7 +77,7 @@ class cache_definition_sharing_form extends moodleform {
public function set_data($data) {
if (!isset($data['sharing'])) {
// Set the default value here. mforms doesn't handle defaults very nicely.
$data['sharing'] = core_cache\administration_helper::get_definition_sharing_options(\core_cache\definition::SHARING_DEFAULT);
$data['sharing'] = administration_helper::get_definition_sharing_options(definition::SHARING_DEFAULT);
}
parent::set_data($data);
}
@ -92,3 +98,8 @@ class cache_definition_sharing_form extends moodleform {
return $errors;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_definition_sharing_form::class, \cache_definition_sharing_form::class);

View file

@ -14,19 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\form;
use cache_config;
use moodleform;
/**
* Form to add a cache lock instance.
*
* All cache lock plugins that wish to have custom configuration should override
* this form, and more explicitly the plugin_definition and plugin_validation methods.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_lock_form extends moodleform {
/**
* Defines this form.
*/
@ -85,3 +89,8 @@ class cache_lock_form extends moodleform {
return $errors;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_lock_form::class, \cache_lock_form::class);

View file

@ -14,10 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\form;
use cache_store as store;
use moodleform;
/**
* Form to set the mappings for a mode.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -30,18 +35,18 @@ class cache_mode_mappings_form extends moodleform {
$form = $this->_form;
$stores = $this->_customdata;
$options = array(
store::MODE_APPLICATION => array(),
store::MODE_SESSION => array(),
store::MODE_REQUEST => array()
);
$options = [
store::MODE_APPLICATION => [],
store::MODE_SESSION => [],
store::MODE_REQUEST => [],
];
foreach ($stores as $storename => $store) {
foreach ($store['modes'] as $mode => $enabled) {
if ($enabled && ($mode !== store::MODE_SESSION || $store['supports']['searchable'])) {
if (empty($store['default'])) {
$options[$mode][$storename] = $store['name'];
} else {
$options[$mode][$storename] = get_string('store_'.$store['name'], 'cache');
$options[$mode][$storename] = get_string('store_' . $store['name'], 'cache');
}
}
}
@ -50,9 +55,14 @@ class cache_mode_mappings_form extends moodleform {
$form->addElement('hidden', 'action', 'editmodemappings');
$form->setType('action', PARAM_ALPHA);
foreach ($options as $mode => $optionset) {
$form->addElement('select', 'mode_'.$mode, get_string('mode_'.$mode, 'cache'), $optionset);
$form->addElement('select', 'mode_' . $mode, get_string('mode_' . $mode, 'cache'), $optionset);
}
$this->add_action_buttons();
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cache_mode_mappings_form::class, \cache_mode_mappings_form::class);

View file

@ -14,19 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache\form;
use core_cache\administration_helper;
use moodleform;
/**
* Add store instance form.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cachestore_addinstance_form extends moodleform {
/**
* The definition of the add instance form
*/
#[\Override]
final protected function definition() {
$form = $this->_form;
$store = $this->_customdata['store'];
@ -56,8 +58,12 @@ class cachestore_addinstance_form extends moodleform {
} else {
$form->addElement('hidden', 'lock', '');
$form->setType('lock', PARAM_ALPHANUMEXT);
$form->addElement('static', 'lock-value', get_string('locking', 'cache'),
'<em>'.get_string('nativelocking', 'cache').'</em>');
$form->addElement(
'static',
'lock-value',
get_string('locking', 'cache'),
'<em>' . get_string('nativelocking', 'cache') . '</em>'
);
}
if (method_exists($this, 'configuration_definition')) {
@ -68,13 +74,7 @@ class cachestore_addinstance_form extends moodleform {
$this->add_action_buttons();
}
/**
* Validates the add instance form data
*
* @param array $data
* @param array $files
* @return array
*/
#[\Override]
public function validation($data, $files) {
$errors = parent::validation($data, $files);
@ -82,7 +82,7 @@ class cachestore_addinstance_form extends moodleform {
if (!preg_match('#^[a-zA-Z0-9\-_ ]+$#', $data['name'])) {
$errors['name'] = get_string('storenameinvalid', 'cache');
} else if (empty($this->_customdata['store'])) {
$stores = core_cache\administration_helper::get_store_instance_summaries();
$stores = administration_helper::get_store_instance_summaries();
if (array_key_exists($data['name'], $stores)) {
$errors['name'] = get_string('storenamealreadyused', 'cache');
}
@ -91,7 +91,7 @@ class cachestore_addinstance_form extends moodleform {
if (method_exists($this, 'configuration_validation')) {
$newerrors = $this->configuration_validation($data, $files, $errors);
// We need to selectiviliy merge here
// We need to selectiviliy merge here.
foreach ($newerrors as $element => $error) {
if (!array_key_exists($element, $errors)) {
$errors[$element] = $error;
@ -102,3 +102,8 @@ class cachestore_addinstance_form extends moodleform {
return $errors;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(cachestore_addinstance_form::class, \cachestore_addinstance_form::class);

View file

@ -14,29 +14,34 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core_cache\administration_helper;
use core\exception\coding_exception;
use DirectoryIterator;
/**
* The cache helper class.
*
* The cache helper class provides common functionality to the cache API and is useful to developers within to interact with
* the cache API in a general way.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_helper {
class helper {
/**
* Statistics gathered by the cache API during its operation will be used here.
* @static
* @var array
*/
protected static $stats = array();
protected static $stats = [];
/**
* The instance of the cache helper.
* @var cache_helper
* @var self
*/
protected static $instance;
@ -56,25 +61,25 @@ class cache_helper {
* @return bool
*/
public static function ready_for_early_init() {
return cache_config::config_file_exists();
return config::config_file_exists();
}
/**
* Returns an instance of the cache_helper.
* Returns an instance of the helper.
*
* This is designed for internal use only and acts as a static store.
* @staticvar null $instance
* @return cache_helper
* @return self
*/
protected static function instance() {
if (is_null(self::$instance)) {
self::$instance = new cache_helper();
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructs an instance of the cache_helper class. Again for internal use only.
* Constructs an instance of the helper class. Again for internal use only.
*/
protected function __construct() {
// Nothing to do here, just making sure you can't get an instance of this.
@ -84,41 +89,41 @@ class cache_helper {
* Used as a data store for initialised definitions.
* @var array
*/
protected $definitions = array();
protected $definitions = [];
/**
* Used as a data store for initialised cache stores
* We use this because we want to avoid establishing multiple instances of a single store.
* @var array
*/
protected $stores = array();
protected $stores = [];
/**
* Returns the class for use as a cache loader for the given mode.
*
* @param int $mode One of cache_store::MODE_
* @param int $mode One of store::MODE_
* @return string
* @throws coding_exception
*/
public static function get_class_for_mode($mode) {
switch ($mode) {
case cache_store::MODE_APPLICATION :
return 'cache_application';
case cache_store::MODE_REQUEST :
return 'cache_request';
case cache_store::MODE_SESSION :
return 'cache_session';
case store::MODE_APPLICATION:
return application_cache::class;
case store::MODE_REQUEST:
return request_cache::class;
case store::MODE_SESSION:
return session_cache::class;
}
throw new coding_exception('Unknown cache mode passed. Must be one of cache_store::MODE_*');
throw new coding_exception('Unknown cache mode passed. Must be one of store::MODE_*');
}
/**
* Returns the cache stores to be used with the given definition.
* @param cache_definition $definition
* @param definition $definition
* @return array
*/
public static function get_cache_stores(cache_definition $definition) {
$instance = cache_config::instance();
public static function get_cache_stores(definition $definition) {
$instance = config::instance();
$stores = $instance->get_stores_for_definition($definition);
$stores = self::initialise_cachestore_instances($stores, $definition);
return $stores;
@ -128,12 +133,12 @@ class cache_helper {
* Internal function for initialising an array of stores against a given cache definition.
*
* @param array $stores
* @param cache_definition $definition
* @return cache_store[]
* @param definition $definition
* @return store[]
*/
protected static function initialise_cachestore_instances(array $stores, cache_definition $definition) {
$return = array();
$factory = cache_factory::instance();
protected static function initialise_cachestore_instances(array $stores, definition $definition) {
$return = [];
$factory = factory::instance();
foreach ($stores as $name => $details) {
$store = $factory->create_store_from_config($name, $details, $definition);
if ($store !== false) {
@ -146,13 +151,13 @@ class cache_helper {
/**
* Returns a cache_lock instance suitable for use with the store.
*
* @param cache_store $store
* @return cache_lock_interface
* @param store $store
* @return lockable_cache_interface
*/
public static function get_cachelock_for_store(cache_store $store) {
$instance = cache_config::instance();
public static function get_cachelock_for_store(store $store) {
$instance = config::instance();
$lockconf = $instance->get_lock_for_store($store->my_name());
$factory = cache_factory::instance();
$factory = factory::instance();
return $factory->create_lock_instance($lockconf);
}
@ -166,9 +171,9 @@ class cache_helper {
*/
public static function early_get_cache_plugins() {
global $CFG;
$result = array();
$ignored = array('CVS', '_vti_cnf', 'simpletest', 'db', 'yui', 'tests');
$fulldir = $CFG->dirroot.'/cache/stores';
$result = [];
$ignored = ['CVS', '_vti_cnf', 'simpletest', 'db', 'yui', 'tests'];
$fulldir = $CFG->dirroot . '/cache/stores';
$items = new DirectoryIterator($fulldir);
foreach ($items as $item) {
if ($item->isDot() or !$item->isDir()) {
@ -182,7 +187,7 @@ class cache_helper {
// Better ignore plugins with problematic names here.
continue;
}
$result[$pluginname] = $fulldir.'/'.$pluginname;
$result[$pluginname] = $fulldir . '/' . $pluginname;
unset($item);
}
unset($items);
@ -201,14 +206,14 @@ class cache_helper {
* @return boolean
* @throws coding_exception
*/
public static function invalidate_by_definition($component, $area, array $identifiers = array(), $keys = array()) {
public static function invalidate_by_definition($component, $area, array $identifiers = [], $keys = []) {
$cache = cache::make($component, $area, $identifiers);
if (is_array($keys)) {
$cache->delete_many($keys);
} else if (is_scalar($keys)) {
$cache->delete($keys);
} else {
throw new coding_exception('cache_helper::invalidate_by_definition only accepts $keys as array, or scalar.');
throw new coding_exception('helper::invalidate_by_definition only accepts $keys as array, or scalar.');
}
return true;
}
@ -223,17 +228,17 @@ class cache_helper {
* @param array $keys
*/
public static function invalidate_by_event($event, array $keys) {
$instance = cache_config::instance();
$instance = config::instance();
$invalidationeventset = false;
$factory = cache_factory::instance();
$factory = factory::instance();
$inuse = $factory->get_caches_in_use();
$purgetoken = null;
foreach ($instance->get_definitions() as $name => $definitionarr) {
$definition = cache_definition::load($name, $definitionarr);
$definition = definition::load($name, $definitionarr);
if ($definition->invalidates_on_event($event)) {
// First up check if there is a cache loader for this definition already.
// If there is we need to invalidate the keys from there.
$definitionkey = $definition->get_component().'/'.$definition->get_area();
$definitionkey = $definition->get_component() . '/' . $definition->get_area();
if (isset($inuse[$definitionkey])) {
$inuse[$definitionkey]->delete_many($keys);
}
@ -242,7 +247,7 @@ class cache_helper {
// Request caches shouldn't have events as all data is lost at the end of the request.
// Events should only be logged once of course and likely several definitions are watching so we
// track its logging with $invalidationeventset.
$logevent = ($invalidationeventset === false && $definition->get_mode() !== cache_store::MODE_REQUEST);
$logevent = ($invalidationeventset === false && $definition->get_mode() !== store::MODE_REQUEST);
if ($logevent) {
// Get the event invalidation cache.
@ -251,7 +256,7 @@ class cache_helper {
$data = $cache->get($event);
if ($data === false) {
// There are none.
$data = array();
$data = [];
}
// Add our keys to them with the current cache timestamp.
if (null === $purgetoken) {
@ -277,12 +282,12 @@ class cache_helper {
* @param array $identifiers
* @return bool
*/
public static function purge_by_definition($component, $area, array $identifiers = array()) {
public static function purge_by_definition($component, $area, array $identifiers = []) {
// Create the cache.
$cache = cache::make($component, $area, $identifiers);
// Initialise, in case of a store.
if ($cache instanceof cache_store) {
$factory = cache_factory::instance();
if ($cache instanceof store) {
$factory = factory::instance();
$definition = $factory->create_definition($component, $area, null);
$cacheddefinition = clone $definition;
$cacheddefinition->set_identifiers($identifiers);
@ -302,17 +307,17 @@ class cache_helper {
* @param string $event
*/
public static function purge_by_event($event) {
$instance = cache_config::instance();
$instance = config::instance();
$invalidationeventset = false;
$factory = cache_factory::instance();
$factory = factory::instance();
$inuse = $factory->get_caches_in_use();
$purgetoken = null;
foreach ($instance->get_definitions() as $name => $definitionarr) {
$definition = cache_definition::load($name, $definitionarr);
$definition = definition::load($name, $definitionarr);
if ($definition->invalidates_on_event($event)) {
// First up check if there is a cache loader for this definition already.
// If there is we need to invalidate the keys from there.
$definitionkey = $definition->get_component().'/'.$definition->get_area();
$definitionkey = $definition->get_component() . '/' . $definition->get_area();
if (isset($inuse[$definitionkey])) {
$inuse[$definitionkey]->purge();
} else {
@ -323,7 +328,7 @@ class cache_helper {
// Request caches shouldn't have events as all data is lost at the end of the request.
// Events should only be logged once of course and likely several definitions are watching so we
// track its logging with $invalidationeventset.
$logevent = ($invalidationeventset === false && $definition->get_mode() !== cache_store::MODE_REQUEST);
$logevent = ($invalidationeventset === false && $definition->get_mode() !== store::MODE_REQUEST);
// We need to flag the event in the "Event invalidation" cache if it hasn't already happened.
if ($logevent && $invalidationeventset === false) {
@ -333,9 +338,9 @@ class cache_helper {
if (null === $purgetoken) {
$purgetoken = cache::get_purge_token(true);
}
$data = array(
$data = [
'purged' => $purgetoken,
);
];
// Set that data back to the cache.
$cache->set($event, $data);
// This only needs to occur once.
@ -350,9 +355,9 @@ class cache_helper {
* @param string $store
* @param string $storeclass
* @param string $definition A string that identifies the definition.
* @param int $mode One of cache_store::MODE_*. Since 2.9.
* @param int $mode One of store::MODE_*. Since 2.9.
*/
protected static function ensure_ready_for_stats($store, $storeclass, $definition, $mode = cache_store::MODE_APPLICATION) {
protected static function ensure_ready_for_stats($store, $storeclass, $definition, $mode = store::MODE_APPLICATION) {
// This function is performance-sensitive, so exit as quickly as possible
// if we do not need to do anything.
if (isset(self::$stats[$definition]['stores'][$store])) {
@ -360,28 +365,28 @@ class cache_helper {
}
if (!array_key_exists($definition, self::$stats)) {
self::$stats[$definition] = array(
self::$stats[$definition] = [
'mode' => $mode,
'stores' => array(
$store => array(
'stores' => [
$store => [
'class' => $storeclass,
'hits' => 0,
'misses' => 0,
'sets' => 0,
'iobytes' => cache_store::IO_BYTES_NOT_SUPPORTED,
'iobytes' => store::IO_BYTES_NOT_SUPPORTED,
'locks' => 0,
)
)
);
],
],
];
} else if (!array_key_exists($store, self::$stats[$definition]['stores'])) {
self::$stats[$definition]['stores'][$store] = array(
self::$stats[$definition]['stores'][$store] = [
'class' => $storeclass,
'hits' => 0,
'misses' => 0,
'sets' => 0,
'iobytes' => cache_store::IO_BYTES_NOT_SUPPORTED,
'iobytes' => store::IO_BYTES_NOT_SUPPORTED,
'locks' => 0,
);
];
}
}
@ -392,47 +397,52 @@ class cache_helper {
* It is backwards compatible when a string is passed but is not accurate.
*
* @since 2.9
* @param cache_definition|string $definition
* @param definition|string $definition
* @return string
*/
protected static function get_definition_stat_id_and_mode($definition) {
if (!($definition instanceof cache_definition)) {
if (!($definition instanceof definition)) {
// All core calls to this method have been updated, this is the legacy state.
// We'll use application as the default as that is the most common, really this is not accurate of course but
// at this point we can only guess and as it only affects calls to cache stat outside of core (of which there should
// be none) I think that is fine.
debugging('Please update you cache stat calls to pass the definition rather than just its ID.', DEBUG_DEVELOPER);
return array((string)$definition, cache_store::MODE_APPLICATION);
return [(string)$definition, store::MODE_APPLICATION];
}
return array($definition->get_id(), $definition->get_mode());
return [$definition->get_id(), $definition->get_mode()];
}
/**
* Record a cache hit in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
* definition instance. It is preferable to pass a cache definition instance.
*
* In Moodle 3.9 the first argument changed to also accept a cache_store.
* In Moodle 3.9 the first argument changed to also accept a store.
*
* @internal
* @param string|cache_store $store
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param string|store $store
* @param definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual definition object now.
* @param int $hits The number of hits to record (by default 1)
* @param int $readbytes Number of bytes read from the cache or cache_store::IO_BYTES_NOT_SUPPORTED
* @param int $readbytes Number of bytes read from the cache or store::IO_BYTES_NOT_SUPPORTED
*/
public static function record_cache_hit($store, $definition, int $hits = 1, int $readbytes = cache_store::IO_BYTES_NOT_SUPPORTED): void {
public static function record_cache_hit(
$store,
$definition,
int $hits = 1,
int $readbytes = store::IO_BYTES_NOT_SUPPORTED,
): void {
$storeclass = '';
if ($store instanceof cache_store) {
if ($store instanceof store) {
$storeclass = get_class($store);
$store = $store->my_name();
}
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
[$definitionstr, $mode] = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $storeclass, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['hits'] += $hits;
if ($readbytes !== cache_store::IO_BYTES_NOT_SUPPORTED) {
if (self::$stats[$definitionstr]['stores'][$store]['iobytes'] === cache_store::IO_BYTES_NOT_SUPPORTED) {
if ($readbytes !== store::IO_BYTES_NOT_SUPPORTED) {
if (self::$stats[$definitionstr]['stores'][$store]['iobytes'] === store::IO_BYTES_NOT_SUPPORTED) {
self::$stats[$definitionstr]['stores'][$store]['iobytes'] = $readbytes;
} else {
self::$stats[$definitionstr]['stores'][$store]['iobytes'] += $readbytes;
@ -444,23 +454,23 @@ class cache_helper {
* Record a cache miss in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
* definition instance. It is preferable to pass a cache definition instance.
*
* In Moodle 3.9 the first argument changed to also accept a cache_store.
* In Moodle 3.9 the first argument changed to also accept a store.
*
* @internal
* @param string|cache_store $store
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param string|store $store
* @param definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual definition object now.
* @param int $misses The number of misses to record (by default 1)
*/
public static function record_cache_miss($store, $definition, $misses = 1) {
$storeclass = '';
if ($store instanceof cache_store) {
if ($store instanceof store) {
$storeclass = get_class($store);
$store = $store->my_name();
}
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
[$definitionstr, $mode] = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $storeclass, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['misses'] += $misses;
}
@ -469,29 +479,33 @@ class cache_helper {
* Record a cache set in the stats for the given store and definition.
*
* In Moodle 2.9 the $definition argument changed from accepting only a string to accepting a string or a
* cache_definition instance. It is preferable to pass a cache definition instance.
* definition instance. It is preferable to pass a cache definition instance.
*
* In Moodle 3.9 the first argument changed to also accept a cache_store.
* In Moodle 3.9 the first argument changed to also accept a store.
*
* @internal
* @param string|cache_store $store
* @param cache_definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual cache_definition object now.
* @param string|store $store
* @param definition $definition You used to be able to pass a string here, however that is deprecated please pass the
* actual definition object now.
* @param int $sets The number of sets to record (by default 1)
* @param int $writebytes Number of bytes written to the cache or cache_store::IO_BYTES_NOT_SUPPORTED
* @param int $writebytes Number of bytes written to the cache or store::IO_BYTES_NOT_SUPPORTED
*/
public static function record_cache_set($store, $definition, int $sets = 1,
int $writebytes = cache_store::IO_BYTES_NOT_SUPPORTED) {
public static function record_cache_set(
$store,
$definition,
int $sets = 1,
int $writebytes = store::IO_BYTES_NOT_SUPPORTED
) {
$storeclass = '';
if ($store instanceof cache_store) {
if ($store instanceof store) {
$storeclass = get_class($store);
$store = $store->my_name();
}
list($definitionstr, $mode) = self::get_definition_stat_id_and_mode($definition);
[$definitionstr, $mode] = self::get_definition_stat_id_and_mode($definition);
self::ensure_ready_for_stats($store, $storeclass, $definitionstr, $mode);
self::$stats[$definitionstr]['stores'][$store]['sets'] += $sets;
if ($writebytes !== cache_store::IO_BYTES_NOT_SUPPORTED) {
if (self::$stats[$definitionstr]['stores'][$store]['iobytes'] === cache_store::IO_BYTES_NOT_SUPPORTED) {
if ($writebytes !== store::IO_BYTES_NOT_SUPPORTED) {
if (self::$stats[$definitionstr]['stores'][$store]['iobytes'] === store::IO_BYTES_NOT_SUPPORTED) {
self::$stats[$definitionstr]['stores'][$store]['iobytes'] = $writebytes;
} else {
self::$stats[$definitionstr]['stores'][$store]['iobytes'] += $writebytes;
@ -514,13 +528,13 @@ class cache_helper {
* anything. This will involve full setup of the cache + the purge operation. On a site using caching heavily this WILL be
* painful.
*
* @param bool $usewriter If set to true the cache_config_writer class is used. This class is special as it avoids
* @param bool $usewriter If set to true the config_writer class is used. This class is special as it avoids
* it is still usable when caches have been disabled.
* Please use this option only if you really must. It's purpose is to allow the cache to be purged when it would be
* otherwise impossible.
*/
public static function purge_all($usewriter = false) {
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance($usewriter);
foreach ($config->get_all_stores() as $store) {
self::purge_store($store['name'], $config);
@ -534,12 +548,12 @@ class cache_helper {
* Purges a store given its name.
*
* @param string $storename
* @param cache_config $config
* @param config|null $config
* @return bool
*/
public static function purge_store($storename, cache_config $config = null) {
public static function purge_store($storename, ?config $config = null) {
if ($config === null) {
$config = cache_config::instance();
$config = config::instance();
}
$stores = $config->get_all_stores();
@ -557,14 +571,14 @@ class cache_helper {
return false;
}
// Found the store: is it ready?
/* @var cache_store $instance */
/* @var store $instance */
$instance = new $class($store['name'], $store['configuration']);
if (!$instance->is_ready()) {
unset($instance);
return false;
}
foreach ($config->get_definitions_by_store($storename) as $id => $definition) {
$definition = cache_definition::load($id, $definition);
$definition = definition::load($id, $definition);
$definitioninstance = clone($instance);
$definitioninstance->initialise($definition);
$definitioninstance->purge();
@ -577,7 +591,7 @@ class cache_helper {
/**
* Purges all of the stores used by a definition.
*
* Unlike cache_helper::purge_by_definition this purges all of the data from the stores not
* Unlike helper::purge_by_definition this purges all of the data from the stores not
* just the data relating to the definition.
* This function is useful when you must purge a definition that requires setup but you don't
* want to set it up.
@ -586,7 +600,7 @@ class cache_helper {
* @param string $area
*/
public static function purge_stores_used_by_definition($component, $area) {
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance();
$definition = $factory->create_definition($component, $area);
$stores = $config->get_stores_for_definition($definition);
@ -598,14 +612,14 @@ class cache_helper {
/**
* Returns the translated name of the definition.
*
* @param cache_definition $definition
* @param definition $definition
* @return lang_string
*/
public static function get_definition_name($definition) {
if ($definition instanceof cache_definition) {
if ($definition instanceof definition) {
return $definition->get_name();
}
$identifier = 'cachedef_'.clean_param($definition['area'], PARAM_STRINGID);
$identifier = 'cachedef_' . clean_param($definition['area'], PARAM_STRINGID);
$component = $definition['component'];
if ($component === 'core') {
$component = 'cache';
@ -616,13 +630,16 @@ class cache_helper {
/**
* Hashes a descriptive key to make it shorter and still unique.
* @param string|int $key
* @param cache_definition $definition
* @param definition $definition
* @return string
*/
public static function hash_key($key, cache_definition $definition) {
public static function hash_key($key, definition $definition) {
if ($definition->uses_simple_keys()) {
if (debugging() && preg_match('#[^a-zA-Z0-9_]#', $key ?? '')) {
throw new coding_exception('Cache definition '.$definition->get_id().' requires simple keys. Invalid key provided.', $key);
throw new coding_exception(
'Cache definition ' . $definition->get_id() . ' requires simple keys. Invalid key provided.',
$key,
);
}
// We put the key first so that we can be sure the start of the key changes.
return (string)$key . '-' . $definition->generate_single_key_prefix();
@ -638,9 +655,9 @@ class cache_helper {
*/
public static function update_definitions($coreonly = false) {
// First update definitions
cache_config_writer::update_definitions($coreonly);
config_writer::update_definitions($coreonly);
// Second reset anything we have already initialised to ensure we're all up to date.
cache_factory::reset();
factory::reset();
}
/**
@ -650,12 +667,12 @@ class cache_helper {
* @return string The new site identifier.
*/
public static function update_site_identifier($siteidentifier) {
$factory = cache_factory::instance();
$factory = factory::instance();
$factory->updating_started();
$config = $factory->create_config_instance(true);
$siteidentifier = $config->update_site_identifier($siteidentifier);
$factory->updating_finished();
cache_factory::reset();
factory::reset();
return $siteidentifier;
}
@ -670,7 +687,7 @@ class cache_helper {
return self::$siteidentifier;
}
// If site identifier hasn't been collected yet attempt to get it from the cache config.
$factory = cache_factory::instance();
$factory = factory::instance();
// If the factory is initialising then we don't want to try to get it from the config or we risk
// causing the cache to enter an infinite initialisation loop.
if (!$factory->is_initialising()) {
@ -719,13 +736,13 @@ class cache_helper {
if ($output) {
mtrace('Cleaning up stale session data from cache stores.');
}
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance();
$definitions = $config->get_definitions();
$purgetime = time() - $CFG->sessiontimeout;
foreach ($definitions as $definitionarray) {
// We are only interested in session caches.
if (!($definitionarray['mode'] & cache_store::MODE_SESSION)) {
if (!($definitionarray['mode'] & store::MODE_SESSION)) {
continue;
}
$definition = $factory->create_definition($definitionarray['component'], $definitionarray['area']);
@ -735,18 +752,18 @@ class cache_helper {
// Initialise all of the stores used for that definition.
foreach ($stores as $store) {
// If the store doesn't support searching we can skip it.
if (!($store instanceof cache_is_searchable)) {
if (!($store instanceof searchable_cache_interface)) {
debugging('Cache stores used for session definitions should ideally be searchable.', DEBUG_DEVELOPER);
continue;
}
// Get all of the last access keys.
$keys = $store->find_by_prefix(cache_session::LASTACCESS);
$keys = $store->find_by_prefix(session_cache::LASTACCESS);
$todelete = [];
foreach ($store->get_many($keys) as $key => $value) {
$expiresvalue = 0;
if ($value instanceof cache_ttl_wrapper) {
$expiresvalue = $value->data;
} else if ($value instanceof cache_cached_object) {
} else if ($value instanceof cached_object) {
$expiresvalue = $value->restore_object();
} else {
$expiresvalue = $value;
@ -754,13 +771,13 @@ class cache_helper {
$expires = (int) $expiresvalue;
if ($expires > 0 && $expires < $purgetime) {
$prefix = substr($key, strlen(cache_session::LASTACCESS));
$prefix = substr($key, strlen(session_cache::LASTACCESS));
$foundbyprefix = $store->find_by_prefix($prefix);
$todelete = array_merge($todelete, [$key], $foundbyprefix);
}
}
if ($todelete) {
$outcome = (int)$store->delete_many($todelete);
$outcome = (int) store->delete_many($todelete);
if ($output) {
$strdef = s($definition->get_id());
$strstore = s($store->my_name());
@ -779,14 +796,14 @@ class cache_helper {
* @return array[] An array of stores, keys are the store names.
*/
public static function get_stores_suitable_for_mode_default() {
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance();
$requirements = 0;
foreach ($config->get_definitions() as $definition) {
$definition = cache_definition::load($definition['component'].'/'.$definition['area'], $definition);
$definition = definition::load($definition['component'] . '/' . $definition['area'], $definition);
$requirements = $requirements | $definition->get_requirements_bin();
}
$stores = array();
$stores = [];
foreach ($config->get_all_stores() as $name => $store) {
if (!empty($store['features']) && ($store['features'] & $requirements)) {
$stores[$name] = $store;
@ -798,12 +815,12 @@ class cache_helper {
/**
* Returns stores suitable for use with a given definition.
*
* @param cache_definition $definition
* @return cache_store[]
* @param definition $definition
* @return store[]
*/
public static function get_stores_suitable_for_definition(cache_definition $definition) {
$factory = cache_factory::instance();
$stores = array();
public static function get_stores_suitable_for_definition(definition $definition) {
$factory = factory::instance();
$stores = [];
if ($factory->is_initialising() || $factory->stores_disabled()) {
// No suitable stores here.
return $stores;
@ -838,10 +855,9 @@ class cache_helper {
*/
public static function warnings(array $stores = null) {
if ($stores === null) {
$stores = core_cache\administration_helper::get_store_instance_summaries();
$stores = administration_helper::get_store_instance_summaries();
}
$warnings = array();
$warnings = [];
foreach ($stores as $store) {
if (!empty($store['warnings'])) {
$warnings = array_merge($warnings, $store['warnings']);
@ -871,3 +887,8 @@ class cache_helper {
return class_exists('RedisCluster');
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(helper::class, \cache_helper::class);

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache store feature: key awareness.
*
@ -26,9 +28,12 @@
* means of performing these tests than the handling that would otherwise take place in the cache_loader.
*
* Can be implemented by classes already implementing cache_store.
*
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_is_key_aware {
interface key_aware_cache_interface {
/**
* Test is a cache has a key.
*
@ -80,3 +85,8 @@ interface cache_is_key_aware {
*/
public function has_all(array $keys);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(key_aware_cache_interface::class, \cache_is_key_aware::class);

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache Loader.
*
@ -21,9 +23,11 @@
* means of accessing and interacting with a cache.
*
* Can be implemented by any class wishing to be a cache loader.
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_loader {
interface loader_interface {
/**
* Retrieves the value for the given key from the cache.
*
@ -215,3 +219,8 @@ interface cache_loader {
*/
public function delete_many(array $keys, $recurse = true);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(loader_interface::class, \cache_loader::class);

View file

@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\moodle_exception;
/**
* Cache Loader supporting locking.
*
@ -21,8 +25,11 @@
* It outlines the required structure for utilising locking functionality when using a cache.
*
* Can be implemented by any class already implementing the cache_loader interface.
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_loader_with_locking {
interface loader_with_locking_interface {
/**
* Acquires a lock for the given key.
*
@ -67,3 +74,8 @@ interface cache_loader_with_locking {
*/
public function release_lock($key);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(loader_with_locking_interface::class, \cache_loader_with_locking::class);

View file

@ -20,7 +20,7 @@
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are requried in order to use caching.
*
* @package core
* @package core_cache
* @category cache
* @author Peter Burnett <peterburnett@catalyst-au.net>
* @copyright 2020 Catalyst IT
@ -30,8 +30,30 @@
namespace core_cache\local;
use cache_store, cache_factory, cache_config_writer, cache_helper;
use cache_store as store;
use cache_config_writer as config_writer;
use cache_factory as factory;
use cache_helper;
use core_cache\cache;
use core_cache\config;
use core_cache\configurable_cache_interface;
use core_cache\exception\cache_exception;
use core_cache\form\cache_lock_form;
use core_cache\form\cache_mode_mappings_form;
use core_cache\form\cache_definition_sharing_form;
use core_cache\form\cache_definition_mappings_form;
use core_cache\form\cachestore_addinstance_form;
use core_cache\lockable_cache_interface;
use core_component;
use core\context;
use core\context\system as context_system;
use core\exception\coding_exception;
use core\exception\moodle_exception;
use core\output\notification;
use core\output\single_button;
use core\url;
use html_writer;
use stdClass;
/**
* A cache helper for administration tasks
@ -42,9 +64,8 @@ use core\output\notification;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class administration_display_helper extends \core_cache\administration_helper {
/**
* Please do not call constructor directly. Use cache_factory::get_administration_display_helper() instead.
* Please do not call constructor directly. Use factory::get_administration_display_helper() instead.
*/
public function __construct() {
// Nothing to do here.
@ -59,33 +80,33 @@ class administration_display_helper extends \core_cache\administration_helper {
* element is used.
* @return array of actions. Each action is an action_url.
*/
public function get_definition_actions(\context $context, array $definitionsummary): array {
public function get_definition_actions(context $context, array $definitionsummary): array {
global $OUTPUT;
if (has_capability('moodle/site:config', $context)) {
$actions = array();
$actions = [];
// Edit mappings.
$actions[] = $OUTPUT->action_link(
new \moodle_url('/cache/admin.php', array('action' => 'editdefinitionmapping',
'definition' => $definitionsummary['id'])),
new url('/cache/admin.php', ['action' => 'editdefinitionmapping',
'definition' => $definitionsummary['id'], ]),
get_string('editmappings', 'cache')
);
// Edit sharing.
if (count($definitionsummary['sharingoptions']) > 1) {
$actions[] = $OUTPUT->action_link(
new \moodle_url('/cache/admin.php', array('action' => 'editdefinitionsharing',
'definition' => $definitionsummary['id'])),
new url('/cache/admin.php', ['action' => 'editdefinitionsharing',
'definition' => $definitionsummary['id'], ]),
get_string('editsharing', 'cache')
);
}
// Purge.
$actions[] = $OUTPUT->action_link(
new \moodle_url('/cache/admin.php', array('action' => 'purgedefinition',
'definition' => $definitionsummary['id'], 'sesskey' => sesskey())),
new url('/cache/admin.php', ['action' => 'purgedefinition',
'definition' => $definitionsummary['id'], 'sesskey' => sesskey(), ]),
get_string('purge', 'cache')
);
return $actions;
}
return array();
return [];
}
/**
@ -98,24 +119,24 @@ class administration_display_helper extends \core_cache\administration_helper {
*/
public function get_store_instance_actions(string $name, array $storedetails): array {
global $OUTPUT;
$actions = array();
if (has_capability('moodle/site:config', \context_system::instance())) {
$baseurl = new \moodle_url('/cache/admin.php', array('store' => $name));
$actions = [];
if (has_capability('moodle/site:config', context_system::instance())) {
$baseurl = new url('/cache/admin.php', ['store' => $name]);
if (empty($storedetails['default'])) {
// Edit store.
$actions[] = $OUTPUT->action_link(
new \moodle_url($baseurl, array('action' => 'editstore', 'plugin' => $storedetails['plugin'])),
new url($baseurl, ['action' => 'editstore', 'plugin' => $storedetails['plugin']]),
get_string('editstore', 'cache')
);
// Delete store.
$actions[] = $OUTPUT->action_link(
new \moodle_url($baseurl, array('action' => 'deletestore')),
new url($baseurl, ['action' => 'deletestore']),
get_string('deletestore', 'cache')
);
}
// Purge store.
$actions[] = $OUTPUT->action_link(
new \moodle_url($baseurl, array('action' => 'purgestore', 'sesskey' => sesskey())),
new url($baseurl, ['action' => 'purgestore', 'sesskey' => sesskey()]),
get_string('purge', 'cache')
);
}
@ -132,11 +153,13 @@ class administration_display_helper extends \core_cache\administration_helper {
*/
public function get_store_plugin_actions(string $name, array $plugindetails): array {
global $OUTPUT;
$actions = array();
if (has_capability('moodle/site:config', \context_system::instance())) {
$actions = [];
if (has_capability('moodle/site:config', context_system::instance())) {
if (!empty($plugindetails['canaddinstance'])) {
$url = new \moodle_url('/cache/admin.php',
array('action' => 'addstore', 'plugin' => $name));
$url = new url(
'/cache/admin.php',
['action' => 'addstore', 'plugin' => $name]
);
$actions[] = $OUTPUT->action_link(
$url,
get_string('addinstance', 'cache')
@ -153,28 +176,28 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return cachestore_addinstance_form
* @throws coding_exception
*/
public function get_add_store_form(string $plugin): \cachestore_addinstance_form {
public function get_add_store_form(string $plugin): cachestore_addinstance_form {
global $CFG; // Needed for includes.
$plugins = \core_component::get_plugin_list('cachestore');
$plugins = core_component::get_plugin_list('cachestore');
if (!array_key_exists($plugin, $plugins)) {
throw new \coding_exception('Invalid cache plugin used when trying to create an edit form.');
throw new coding_exception('Invalid cache plugin used when trying to create an edit form.');
}
$plugindir = $plugins[$plugin];
$class = 'cachestore_addinstance_form';
if (file_exists($plugindir.'/addinstanceform.php')) {
require_once($plugindir.'/addinstanceform.php');
if (class_exists('cachestore_'.$plugin.'_addinstance_form')) {
$class = 'cachestore_'.$plugin.'_addinstance_form';
if (!array_key_exists('cachestore_addinstance_form', class_parents($class))) {
throw new \coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form');
if (file_exists($plugindir . '/addinstanceform.php')) {
require_once($plugindir . '/addinstanceform.php');
if (class_exists('cachestore_' . $plugin . '_addinstance_form')) {
$class = 'cachestore_' . $plugin . '_addinstance_form';
if (!array_key_exists(cachestore_addinstance_form::class, class_parents($class))) {
throw new coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form');
}
}
}
$locks = $this->get_possible_locks_for_stores($plugindir, $plugin);
$url = new \moodle_url('/cache/admin.php', array('action' => 'addstore'));
return new $class($url, array('plugin' => $plugin, 'store' => null, 'locks' => $locks));
$url = new url('/cache/admin.php', ['action' => 'addstore']);
return new $class($url, ['plugin' => $plugin, 'store' => null, 'locks' => $locks]);
}
/**
@ -185,43 +208,45 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return cachestore_addinstance_form
* @throws coding_exception
*/
public function get_edit_store_form(string $plugin, string $store): \cachestore_addinstance_form {
public function get_edit_store_form(string $plugin, string $store): cachestore_addinstance_form {
global $CFG; // Needed for includes.
$plugins = \core_component::get_plugin_list('cachestore');
$plugins = core_component::get_plugin_list('cachestore');
if (!array_key_exists($plugin, $plugins)) {
throw new \coding_exception('Invalid cache plugin used when trying to create an edit form.');
throw new coding_exception('Invalid cache plugin used when trying to create an edit form.');
}
$factory = \cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance();
$stores = $config->get_all_stores();
if (!array_key_exists($store, $stores)) {
throw new \coding_exception('Invalid store name given when trying to create an edit form.');
throw new coding_exception('Invalid store name given when trying to create an edit form.');
}
$plugindir = $plugins[$plugin];
$class = 'cachestore_addinstance_form';
if (file_exists($plugindir.'/addinstanceform.php')) {
require_once($plugindir.'/addinstanceform.php');
if (class_exists('cachestore_'.$plugin.'_addinstance_form')) {
$class = 'cachestore_'.$plugin.'_addinstance_form';
if (!array_key_exists('cachestore_addinstance_form', class_parents($class))) {
throw new \coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form');
if (file_exists($plugindir . '/addinstanceform.php')) {
require_once($plugindir . '/addinstanceform.php');
if (class_exists('cachestore_' . $plugin . '_addinstance_form')) {
$class = 'cachestore_' . $plugin . '_addinstance_form';
if (!array_key_exists(cachestore_addinstance_form::class, class_parents($class))) {
throw new coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form');
}
}
}
$locks = $this->get_possible_locks_for_stores($plugindir, $plugin);
$url = new \moodle_url('/cache/admin.php', array('action' => 'editstore', 'plugin' => $plugin, 'store' => $store));
$editform = new $class($url, array('plugin' => $plugin, 'store' => $store, 'locks' => $locks));
$url = new url('/cache/admin.php', ['action' => 'editstore', 'plugin' => $plugin, 'store' => $store]);
$editform = new $class($url, ['plugin' => $plugin, 'store' => $store, 'locks' => $locks]);
if (isset($stores[$store]['lock'])) {
$editform->set_data(array('lock' => $stores[$store]['lock']));
$editform->set_data(['lock' => $stores[$store]['lock']]);
}
// See if the cachestore is going to want to load data for the form.
// If it has a customised add instance form then it is going to want to.
$storeclass = 'cachestore_'.$plugin;
$storeclass = 'cachestore_' . $plugin;
$storedata = $stores[$store];
if (array_key_exists('configuration', $storedata) &&
array_key_exists('cache_is_configurable', class_implements($storeclass))) {
if (
array_key_exists('configuration', $storedata) &&
array_key_exists(configurable_cache_interface::class, class_implements($storeclass))
) {
$storeclass::config_set_edit_form_data($editform, $storedata['configuration']);
}
return $editform;
@ -237,17 +262,17 @@ class administration_display_helper extends \core_cache\administration_helper {
protected function get_possible_locks_for_stores(string $plugindir, string $plugin) {
global $CFG; // Needed for includes.
$supportsnativelocking = false;
if (file_exists($plugindir.'/lib.php')) {
require_once($plugindir.'/lib.php');
$pluginclass = 'cachestore_'.$plugin;
if (file_exists($plugindir . '/lib.php')) {
require_once($plugindir . '/lib.php');
$pluginclass = 'cachestore_' . $plugin;
if (class_exists($pluginclass)) {
$supportsnativelocking = array_key_exists('cache_is_lockable', class_implements($pluginclass));
$supportsnativelocking = array_key_exists(lockable_cache_interface::class, class_implements($pluginclass));
}
}
if (!$supportsnativelocking) {
$config = \cache_config::instance();
$locks = array();
$config = config::instance();
$locks = [];
foreach ($config->get_locks() as $lock => $conf) {
if (!empty($conf['default'])) {
$name = get_string($lock, 'cache');
@ -271,21 +296,21 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return array
* @throws coding_exception
*/
public function get_store_configuration_from_data(\stdClass $data): array {
public function get_store_configuration_from_data(stClass $data): array {
global $CFG;
$file = $CFG->dirroot.'/cache/stores/'.$data->plugin.'/lib.php';
$file = $CFG->dirroot . '/cache/stores/' . $data->plugin . '/lib.php';
if (!file_exists($file)) {
throw new \coding_exception('Invalid cache plugin provided. '.$file);
throw new coding_exception('Invalid cache plugin provided. ' . $file);
}
require_once($file);
$class = 'cachestore_'.$data->plugin;
$class = 'cachestore_' . $data->plugin;
if (!class_exists($class)) {
throw new \coding_exception('Invalid cache plugin provided.');
throw new coding_exception('Invalid cache plugin provided.');
}
if (array_key_exists('cache_is_configurable', class_implements($class))) {
if (array_key_exists(configurable_cache_interface::class, class_implements($class))) {
return $class::config_get_configuration_array($data);
}
return array();
return [];
}
/**
@ -296,8 +321,8 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return array
*/
public function get_addable_lock_options(): array {
$plugins = \core_component::get_plugin_list_with_class('cachelock', '', 'lib.php');
$options = array();
$plugins = core_component::get_plugin_list_with_class('cachelock', '', 'lib.php');
$options = [];
$len = strlen('cachelock_');
foreach ($plugins as $plugin => $class) {
$method = "$class::can_add_instance";
@ -314,28 +339,28 @@ class administration_display_helper extends \core_cache\administration_helper {
* Gets the form to use when adding a lock instance.
*
* @param string $plugin
* @param array $lockplugin
* @param array|null $lockplugin
* @return cache_lock_form
* @throws coding_exception
*/
public function get_add_lock_form(string $plugin, array $lockplugin = null): \cache_lock_form {
public function get_add_lock_form(string $plugin, ?array $lockplugin = null): cache_lock_form {
global $CFG; // Needed for includes.
$plugins = \core_component::get_plugin_list('cachelock');
$plugins = core_component::get_plugin_list('cachelock');
if (!array_key_exists($plugin, $plugins)) {
throw new \coding_exception('Invalid cache lock plugin requested when trying to create a form.');
throw new coding_exception('Invalid cache lock plugin requested when trying to create a form.');
}
$plugindir = $plugins[$plugin];
$class = 'cache_lock_form';
if (file_exists($plugindir.'/addinstanceform.php') && in_array('cache_is_configurable', class_implements($class))) {
require_once($plugindir.'/addinstanceform.php');
if (class_exists('cachelock_'.$plugin.'_addinstance_form')) {
$class = 'cachelock_'.$plugin.'_addinstance_form';
if (!array_key_exists('cache_lock_form', class_parents($class))) {
throw new \coding_exception('Cache lock plugin add instance forms must extend cache_lock_form');
if (file_exists($plugindir . '/addinstanceform.php') && in_array(configurable_cache_interface::class, class_implements($class))) {
require_once($plugindir . '/addinstanceform.php');
if (class_exists('cachelock_' . $plugin . '_addinstance_form')) {
$class = 'cachelock_' . $plugin . '_addinstance_form';
if (!array_key_exists(cache_lock_form::class, class_parents($class))) {
throw new coding_exception('Cache lock plugin add instance forms must extend cache_lock_form');
}
}
}
return new $class(null, array('lock' => $plugin));
return new $class(null, ['lock' => $plugin]);
}
/**
@ -346,21 +371,21 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return array
* @throws coding_exception
*/
public function get_lock_configuration_from_data(string $plugin, \stdClass $data): array {
public function get_lock_configuration_from_data(string $plugin, stClass $data): array {
global $CFG;
$file = $CFG->dirroot.'/cache/locks/'.$plugin.'/lib.php';
$file = $CFG->dirroot . '/cache/locks/' . $plugin . '/lib.php';
if (!file_exists($file)) {
throw new \coding_exception('Invalid cache plugin provided. '.$file);
throw new coding_exception('Invalid cache plugin provided. ' . $file);
}
require_once($file);
$class = 'cachelock_'.$plugin;
$class = 'cachelock_' . $plugin;
if (!class_exists($class)) {
throw new \coding_exception('Invalid cache plugin provided.');
throw new coding_exception('Invalid cache plugin provided.');
}
if (array_key_exists('cache_is_configurable', class_implements($class))) {
if (array_key_exists(configurable_cache_interface::class, class_implements($class))) {
return $class::config_get_configuration_array($data);
}
return array();
return [];
}
/**
@ -372,27 +397,27 @@ class administration_display_helper extends \core_cache\administration_helper {
*/
public function perform_cache_actions(string $action, array $forminfo): array {
switch ($action) {
case 'rescandefinitions' : // Rescan definitions.
case 'rescandefinitions': // Rescan definitions.
$this->action_rescan_definition();
break;
case 'addstore' : // Add the requested store.
case 'addstore': // Add the requested store.
$forminfo = $this->action_addstore();
break;
case 'editstore' : // Edit the requested store.
case 'editstore': // Edit the requested store.
$forminfo = $this->action_editstore();
break;
case 'deletestore' : // Delete a given store.
case 'deletestore': // Delete a given store.
$this->action_deletestore($action);
break;
case 'editdefinitionmapping' : // Edit definition mappings.
case 'editdefinitionmapping': // Edit definition mappings.
$forminfo = $this->action_editdefinitionmapping();
break;
case 'editdefinitionsharing' : // Edit definition sharing.
case 'editdefinitionsharing': // Edit definition sharing.
$forminfo = $this->action_editdefinitionsharing();
break;
@ -431,7 +456,7 @@ class administration_display_helper extends \core_cache\administration_helper {
global $PAGE;
require_sesskey();
\cache_config_writer::update_definitions();
config_writer::update_definitions();
redirect($PAGE->url);
}
@ -446,7 +471,7 @@ class administration_display_helper extends \core_cache\administration_helper {
$plugin = required_param('plugin', PARAM_PLUGIN);
if (!$storepluginsummaries[$plugin]['canaddinstance']) {
throw new \moodle_exception('ex_unmetstorerequirements', 'cache');
throw new moodle_exception('ex_unmetstorerequirements', 'cache');
}
$mform = $this->get_add_store_form($plugin);
$title = get_string('addstore', 'cache', $storepluginsummaries[$plugin]['name']);
@ -454,7 +479,7 @@ class administration_display_helper extends \core_cache\administration_helper {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$config = $this->get_store_configuration_from_data($data);
$writer = \cache_config_writer::instance();
$writer = config_writer::instance();
unset($config['lock']);
foreach ($writer->get_locks() as $lock => $lockconfig) {
if ($lock == $data->lock) {
@ -466,7 +491,7 @@ class administration_display_helper extends \core_cache\administration_helper {
}
$PAGE->navbar->add(get_string('addstore', 'cache', 'cache'), $PAGE->url);
return array('form' => $mform, 'title' => $title);
return ['form' => $mform, 'title' => $title];
}
/**
@ -486,7 +511,7 @@ class administration_display_helper extends \core_cache\administration_helper {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$config = $this->get_store_configuration_from_data($data);
$writer = \cache_config_writer::instance();
$writer = config_writer::instance();
unset($config['lock']);
foreach ($writer->get_locks() as $lock => $lockconfig) {
@ -498,7 +523,7 @@ class administration_display_helper extends \core_cache\administration_helper {
redirect($PAGE->url, get_string('editstoresuccess', 'cache', $storepluginsummaries[$plugin]['name']), 5);
}
return array('form' => $mform, 'title' => $title);
return ['form' => $mform, 'title' => $title];
}
/**
@ -525,9 +550,9 @@ class administration_display_helper extends \core_cache\administration_helper {
if ($notifysuccess) {
if (!$confirm) {
$title = get_string('confirmstoredeletion', 'cache');
$params = array('store' => $store, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey());
$url = new \moodle_url($PAGE->url, $params);
$button = new \single_button($url, get_string('deletestore', 'cache'));
$params = ['store' => $store, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey()];
$url = new url($PAGE->url, $params);
$button = new single_button($url, get_string('deletestore', 'cache'));
$PAGE->set_title($title);
$PAGE->set_heading($SITE->fullname);
@ -539,7 +564,7 @@ class administration_display_helper extends \core_cache\administration_helper {
exit;
} else {
require_sesskey();
$writer = \cache_config_writer::instance();
$writer = config_writer::instance();
$writer->delete_store_instance($store);
redirect($PAGE->url, get_string('deletestoresuccess', 'cache'), 5);
}
@ -560,15 +585,15 @@ class administration_display_helper extends \core_cache\administration_helper {
$definition = required_param('definition', PARAM_SAFEPATH);
if (!array_key_exists($definition, $definitionsummaries)) {
throw new \cache_exception('Invalid cache definition requested');
throw new cache_exception('Invalid cache definition requested');
}
$title = get_string('editdefinitionmappings', 'cache', $definition);
$mform = new \cache_definition_mappings_form($PAGE->url, array('definition' => $definition));
$mform = new cache_definition_mappings_form($PAGE->url, ['definition' => $definition]);
if ($mform->is_cancelled()) {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$writer = \cache_config_writer::instance();
$mappings = array();
$writer = config_writer::instance();
$mappings = [];
foreach ($data->mappings as $mapping) {
if (!empty($mapping)) {
$mappings[] = $mapping;
@ -579,7 +604,7 @@ class administration_display_helper extends \core_cache\administration_helper {
}
$PAGE->navbar->add(get_string('updatedefinitionmapping', 'cache'), $PAGE->url);
return array('form' => $mform, 'title' => $title);
return ['form' => $mform, 'title' => $title];
}
/**
@ -593,24 +618,24 @@ class administration_display_helper extends \core_cache\administration_helper {
$definition = required_param('definition', PARAM_SAFEPATH);
if (!array_key_exists($definition, $definitionsummaries)) {
throw new \cache_exception('Invalid cache definition requested');
throw new cache_exception('Invalid cache definition requested');
}
$title = get_string('editdefinitionsharing', 'cache', $definition);
$sharingoptions = $definitionsummaries[$definition]['sharingoptions'];
$customdata = array('definition' => $definition, 'sharingoptions' => $sharingoptions);
$mform = new \cache_definition_sharing_form($PAGE->url, $customdata);
$mform->set_data(array(
$customdata = ['definition' => $definition, 'sharingoptions' => $sharingoptions];
$mform = new cache_definition_sharing_form($PAGE->url, $customdata);
$mform->set_data([
'sharing' => $definitionsummaries[$definition]['selectedsharingoption'],
'userinputsharingkey' => $definitionsummaries[$definition]['userinputsharingkey']
));
'userinputsharingkey' => $definitionsummaries[$definition]['userinputsharingkey'],
]);
if ($mform->is_cancelled()) {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$component = $definitionsummaries[$definition]['component'];
$area = $definitionsummaries[$definition]['area'];
// Purge the stores removing stale data before we alter the sharing option.
\cache_helper::purge_stores_used_by_definition($component, $area);
$writer = \cache_config_writer::instance();
cache_helper::purge_stores_used_by_definition($component, $area);
$writer = config_writer::instance();
$sharing = array_sum(array_keys($data->sharing));
$userinputsharingkey = $data->userinputsharingkey;
$writer->set_definition_sharing($definition, $sharing, $userinputsharingkey);
@ -618,7 +643,7 @@ class administration_display_helper extends \core_cache\administration_helper {
}
$PAGE->navbar->add(get_string('updatedefinitionsharing', 'cache'), $PAGE->url);
return array('form' => $mform, 'title' => $title);
return ['form' => $mform, 'title' => $title];
}
/**
@ -631,26 +656,26 @@ class administration_display_helper extends \core_cache\administration_helper {
$storeinstancesummaries = $this->get_store_instance_summaries();
$defaultmodestores = $this->get_default_mode_stores();
$mform = new \cache_mode_mappings_form(null, $storeinstancesummaries);
$mform->set_data(array(
'mode_'.cache_store::MODE_APPLICATION => key($defaultmodestores[cache_store::MODE_APPLICATION]),
'mode_'.cache_store::MODE_SESSION => key($defaultmodestores[cache_store::MODE_SESSION]),
'mode_'.cache_store::MODE_REQUEST => key($defaultmodestores[cache_store::MODE_REQUEST]),
));
$mform = new cache_mode_mappings_form(null, $storeinstancesummaries);
$mform->set_data([
'mode_' . store::MODE_APPLICATION => key($defaultmodestores[store::MODE_APPLICATION]),
'mode_' . store::MODE_SESSION => key($defaultmodestores[store::MODE_SESSION]),
'mode_' . store::MODE_REQUEST => key($defaultmodestores[store::MODE_REQUEST]),
]);
if ($mform->is_cancelled()) {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$mappings = array(
cache_store::MODE_APPLICATION => array($data->{'mode_'.cache_store::MODE_APPLICATION}),
cache_store::MODE_SESSION => array($data->{'mode_'.cache_store::MODE_SESSION}),
cache_store::MODE_REQUEST => array($data->{'mode_'.cache_store::MODE_REQUEST}),
);
$writer = cache_config_writer::instance();
$mappings = [
store::MODE_APPLICATION => [$data->{'mode_' . store::MODE_APPLICATION}],
store::MODE_SESSION => [$data->{'mode_' . store::MODE_SESSION}],
store::MODE_REQUEST => [$data->{'mode_' . store::MODE_REQUEST}],
];
$writer = config_writer::instance();
$writer->set_mode_mappings($mappings);
redirect($PAGE->url);
}
return array('form' => $mform);
return ['form' => $mform];
}
/**
@ -663,8 +688,8 @@ class administration_display_helper extends \core_cache\administration_helper {
require_sesskey();
$id = required_param('definition', PARAM_SAFEPATH);
list($component, $area) = explode('/', $id, 2);
$factory = cache_factory::instance();
[$component, $area] = explode('/', $id, 2);
$factory = factory::instance();
$definition = $factory->create_definition($component, $area);
if ($definition->has_required_identifiers()) {
// We will have to purge the stores used by this definition.
@ -679,9 +704,11 @@ class administration_display_helper extends \core_cache\administration_helper {
'component' => $component,
'area' => $area,
]);
$purgeagainlink = \html_writer::link(new \moodle_url('/cache/admin.php', [
'action' => 'purgedefinition', 'sesskey' => sesskey(), 'definition' => $id]),
get_string('purgeagain', 'cache'));
$purgeagainlink = html_writer::link(
new url('/cache/admin.php', [
'action' => 'purgedefinition', 'sesskey' => sesskey(), 'definition' => $id, ]),
get_string('purgeagain', 'cache')
);
redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5);
}
@ -697,9 +724,11 @@ class administration_display_helper extends \core_cache\administration_helper {
$store = required_param('store', PARAM_TEXT);
cache_helper::purge_store($store);
$message = get_string('purgexstoresuccess', 'cache', ['store' => $store]);
$purgeagainlink = \html_writer::link(new \moodle_url('/cache/admin.php', [
'action' => 'purgestore', 'sesskey' => sesskey(), 'store' => $store]),
get_string('purgeagain', 'cache'));
$purgeagainlink = html_writer::link(
new url('/cache/admin.php', [
'action' => 'purgestore', 'sesskey' => sesskey(), 'store' => $store, ]),
get_string('purgeagain', 'cache')
);
redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5);
}
@ -717,7 +746,7 @@ class administration_display_helper extends \core_cache\administration_helper {
if ($mform->is_cancelled()) {
redirect($PAGE->url);
} else if ($data = $mform->get_data()) {
$factory = cache_factory::instance();
$factory = factory::instance();
$config = $factory->create_config_instance(true);
$name = $data->name;
$data = $this->get_lock_configuration_from_data($lock, $data);
@ -725,7 +754,7 @@ class administration_display_helper extends \core_cache\administration_helper {
redirect($PAGE->url, get_string('addlocksuccess', 'cache', $name), 5);
}
return array('form' => $mform);
return ['form' => $mform];
}
/**
@ -750,9 +779,9 @@ class administration_display_helper extends \core_cache\administration_helper {
if ($notifysuccess) {
if (!$confirm) {
$title = get_string('confirmlockdeletion', 'cache');
$params = array('lock' => $lock, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey());
$url = new \moodle_url($PAGE->url, $params);
$button = new \single_button($url, get_string('deletelock', 'cache'));
$params = ['lock' => $lock, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey()];
$url = new url($PAGE->url, $params);
$button = new single_button($url, get_string('deletelock', 'cache'));
$PAGE->set_title($title);
$PAGE->set_heading($SITE->fullname);
@ -764,7 +793,7 @@ class administration_display_helper extends \core_cache\administration_helper {
exit;
} else {
require_sesskey();
$writer = cache_config_writer::instance();
$writer = config_writer::instance();
$writer->delete_lock_instance($lock);
redirect($PAGE->url, get_string('deletelocksuccess', 'cache'), 5);
}
@ -780,7 +809,7 @@ class administration_display_helper extends \core_cache\administration_helper {
* @return string the HTML for the admin page.
*/
public function generate_admin_page(\core_cache\output\renderer $renderer): string {
$context = \context_system::instance();
$context = context_system::instance();
$html = '';
$storepluginsummaries = $this->get_store_plugin_summaries();
@ -795,10 +824,10 @@ class administration_display_helper extends \core_cache\administration_helper {
$html .= $renderer->lock_summaries($locks);
$html .= $renderer->additional_lock_actions();
$applicationstore = join(', ', $defaultmodestores[cache_store::MODE_APPLICATION]);
$sessionstore = join(', ', $defaultmodestores[cache_store::MODE_SESSION]);
$requeststore = join(', ', $defaultmodestores[cache_store::MODE_REQUEST]);
$editurl = new \moodle_url('/cache/admin.php', array('action' => 'editmodemappings'));
$applicationstore = join(', ', $defaultmodestores[store::MODE_APPLICATION]);
$sessionstore = join(', ', $defaultmodestores[store::MODE_SESSION]);
$requeststore = join(', ', $defaultmodestores[store::MODE_REQUEST]);
$editurl = new url('/cache/admin.php', ['action' => 'editmodemappings']);
$html .= $renderer->mode_mappings($applicationstore, $sessionstore, $requeststore, $editurl);
return $html;
@ -829,7 +858,7 @@ class administration_display_helper extends \core_cache\administration_helper {
public function get_usage(int $samplekeys): array {
$results = [];
$factory = cache_factory::instance();
$factory = factory::instance();
// Check the caches we already have an instance of, so we don't make another one...
$got = $factory->get_caches_in_use();
@ -849,7 +878,7 @@ class administration_display_helper extends \core_cache\administration_helper {
// Where possible (if it doesn't need identifiers), make an instance of the cache, otherwise
// we can't get the store instances for it (and it won't show up in the list).
if (empty($configdetails['requireidentifiers'])) {
\cache::make($configdetails['component'], $configdetails['area']);
cache::make($configdetails['component'], $configdetails['area']);
}
}
$definition = $factory->create_definition($configdetails['component'], $configdetails['area']);
@ -859,7 +888,7 @@ class administration_display_helper extends \core_cache\administration_helper {
$currentresult = (object)['cacheid' => $definition->get_id(), 'stores' => []];
$results[$currentresult->cacheid] = $currentresult;
/** @var cache_store $store */
/** @var store $store */
foreach ($stores as $store) {
// Skip static cache.
if ($store instanceof \cachestore_static) {

View file

@ -14,16 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache store feature: locking
* Cache store feature: locking.
*
* This is a feature that cache stores can implement if they wish to support locking themselves rather
* than having the cache loader handle it for them.
*
* Can be implemented by classes already implementing cache_store.
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_is_lockable {
interface lockable_cache_interface {
/**
* Acquires a lock on the given key for the given identifier.
*
@ -54,3 +58,8 @@ interface cache_is_lockable {
*/
public function release_lock($key, $ownerid);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(lockable_cache_interface::class, \cache_is_lockable::class);

View file

@ -36,7 +36,6 @@ use single_select;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends \plugin_renderer_base {
/**
* Displays store summaries.
*
@ -48,7 +47,7 @@ class renderer extends \plugin_renderer_base {
*/
public function store_instance_summariers(array $storeinstancesummaries, array $storepluginsummaries) {
$table = new html_table();
$table->head = array(
$table->head = [
get_string('storename', 'cache'),
get_string('plugin', 'cache'),
get_string('storeready', 'cache'),
@ -57,8 +56,8 @@ class renderer extends \plugin_renderer_base {
get_string('supports', 'cache'),
get_string('locking', 'cache') . ' ' . $this->output->help_icon('locking', 'cache'),
get_string('actions', 'cache'),
);
$table->colclasses = array(
];
$table->colclasses = [
'storename',
'plugin',
'storeready',
@ -66,42 +65,42 @@ class renderer extends \plugin_renderer_base {
'modes',
'supports',
'locking',
'actions'
);
$table->data = array();
'actions',
];
$table->data = [];
$defaultstoreactions = get_string('defaultstoreactions', 'cache');
foreach ($storeinstancesummaries as $name => $storesummary) {
$htmlactions = cache_factory::get_administration_display_helper()->get_store_instance_actions($name, $storesummary);
$modes = array();
$modes = [];
foreach ($storesummary['modes'] as $mode => $enabled) {
if ($enabled) {
$modes[] = get_string('mode_'.$mode, 'cache');
$modes[] = get_string('mode_' . $mode, 'cache');
}
}
$supports = array();
$supports = [];
foreach ($storesummary['supports'] as $support => $enabled) {
if ($enabled) {
$supports[] = get_string('supports_'.$support, 'cache');
$supports[] = get_string('supports_' . $support, 'cache');
}
}
$info = '';
if (!empty($storesummary['default'])) {
$info = $this->output->pix_icon('i/info', $defaultstoreactions, '', array('class' => 'icon'));
$info = $this->output->pix_icon('i/info', $defaultstoreactions, '', ['class' => 'icon']);
}
$isready = $storesummary['isready'] && $storesummary['requirementsmet'];
$readycell = new html_table_cell;
$readycell = new html_table_cell();
if ($isready) {
$readycell->text = $this->output->pix_icon('i/valid', '1');
}
$storename = $storesummary['name'];
if (!empty($storesummary['default'])) {
$storename = get_string('store_'.$storesummary['name'], 'cache');
$storename = get_string('store_' . $storesummary['name'], 'cache');
}
if (!$isready && (int)$storesummary['mappings'] > 0) {
$readycell->text = $this->output->help_icon('storerequiresattention', 'cache');
@ -113,24 +112,24 @@ class renderer extends \plugin_renderer_base {
$lock = get_string($storesummary['lock']['name'], 'cache');
}
$row = new html_table_row(array(
$row = new html_table_row([
$storename,
get_string('pluginname', 'cachestore_'.$storesummary['plugin']),
get_string('pluginname', 'cachestore_' . $storesummary['plugin']),
$readycell,
$storesummary['mappings'],
join(', ', $modes),
join(', ', $supports),
$lock,
$info.join(', ', $htmlactions)
));
$row->attributes['class'] = 'store-'.$name;
$info . join(', ', $htmlactions),
]);
$row->attributes['class'] = 'store-' . $name;
if ($storesummary['default']) {
$row->attributes['class'] .= ' default-store';
}
$table->data[] = $row;
}
$html = html_writer::start_tag('div', array('id' => 'core-cache-store-summaries'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-store-summaries']);
$html .= $this->output->heading(get_string('storesummaries', 'cache'), 3);
$html .= html_writer::table($table);
$html .= html_writer::end_tag('div');
@ -146,55 +145,55 @@ class renderer extends \plugin_renderer_base {
*/
public function store_plugin_summaries(array $storepluginsummaries) {
$table = new html_table();
$table->head = array(
$table->head = [
get_string('plugin', 'cache'),
get_string('storeready', 'cache'),
get_string('stores', 'cache'),
get_string('modes', 'cache'),
get_string('supports', 'cache'),
get_string('actions', 'cache'),
);
$table->colclasses = array(
];
$table->colclasses = [
'plugin',
'storeready',
'stores',
'modes',
'supports',
'actions'
);
$table->data = array();
'actions',
];
$table->data = [];
foreach ($storepluginsummaries as $name => $plugin) {
$htmlactions = cache_factory::get_administration_display_helper()->get_store_plugin_actions($name, $plugin);
$modes = array();
$modes = [];
foreach ($plugin['modes'] as $mode => $enabled) {
if ($enabled) {
$modes[] = get_string('mode_'.$mode, 'cache');
$modes[] = get_string('mode_' . $mode, 'cache');
}
}
$supports = array();
$supports = [];
foreach ($plugin['supports'] as $support => $enabled) {
if ($enabled) {
$supports[] = get_string('supports_'.$support, 'cache');
$supports[] = get_string('supports_' . $support, 'cache');
}
}
$row = new html_table_row(array(
$row = new html_table_row([
$plugin['name'],
($plugin['requirementsmet']) ? $this->output->pix_icon('i/valid', '1') : '',
$plugin['instances'],
join(', ', $modes),
join(', ', $supports),
join(', ', $htmlactions)
));
join(', ', $htmlactions),
]);
$row->attributes['class'] = 'plugin-'.$name;
$row->attributes['class'] = 'plugin-' . $name;
$table->data[] = $row;
}
$html = html_writer::start_tag('div', array('id' => 'core-cache-plugin-summaries'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-plugin-summaries']);
$html .= $this->output->heading(get_string('pluginsummaries', 'cache'), 3);
$html .= html_writer::table($table);
$html .= html_writer::end_tag('div');
@ -212,7 +211,7 @@ class renderer extends \plugin_renderer_base {
*/
public function definition_summaries(array $definitionsummaries, context $context) {
$table = new html_table();
$table->head = array(
$table->head = [
get_string('definition', 'cache'),
get_string('mode', 'cache'),
get_string('component', 'cache'),
@ -220,9 +219,9 @@ class renderer extends \plugin_renderer_base {
get_string('mappings', 'cache'),
get_string('sharing', 'cache'),
get_string('canuselocalstore', 'cache'),
get_string('actions', 'cache')
);
$table->colclasses = array(
get_string('actions', 'cache'),
];
$table->colclasses = [
'definition',
'mode',
'component',
@ -230,9 +229,9 @@ class renderer extends \plugin_renderer_base {
'mappings',
'sharing',
'canuselocalstore',
'actions'
);
$table->data = array();
'actions',
];
$table->data = [];
core_collator::asort_array_of_arrays_by_key($definitionsummaries, 'name');
@ -242,7 +241,7 @@ class renderer extends \plugin_renderer_base {
if (!empty($definition['mappings'])) {
$mapping = join(', ', $definition['mappings']);
} else {
$mapping = '<em>'.$none.'</em>';
$mapping = '<em>' . $none . '</em>';
}
$uselocalcachecol = get_string('no');
@ -252,27 +251,27 @@ class renderer extends \plugin_renderer_base {
}
}
$row = new html_table_row(array(
$row = new html_table_row([
$definition['name'],
get_string('mode_'.$definition['mode'], 'cache'),
get_string('mode_' . $definition['mode'], 'cache'),
$definition['component'],
$definition['area'],
$mapping,
join(', ', $definition['selectedsharingoption']),
$uselocalcachecol,
join(', ', $htmlactions)
));
$row->attributes['class'] = 'definition-'.$definition['component'].'-'.$definition['area'];
join(', ', $htmlactions),
]);
$row->attributes['class'] = 'definition-' . $definition['component'] . '-' . $definition['area'];
$table->data[] = $row;
}
$html = html_writer::start_tag('div', array('id' => 'core-cache-definition-summaries'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-definition-summaries']);
$html .= $this->output->heading(get_string('definitionsummaries', 'cache'), 3);
$html .= html_writer::table($table);
$url = new moodle_url('/cache/admin.php', array('action' => 'rescandefinitions', 'sesskey' => sesskey()));
$url = new moodle_url('/cache/admin.php', ['action' => 'rescandefinitions', 'sesskey' => sesskey()]);
$link = html_writer::link($url, get_string('rescandefinitions', 'cache'));
$html .= html_writer::tag('div', $link, array('id' => 'core-cache-rescan-definitions'));
$html .= html_writer::tag('div', $link, ['id' => 'core-cache-rescan-definitions']);
$html .= html_writer::end_tag('div');
return $html;
@ -289,30 +288,30 @@ class renderer extends \plugin_renderer_base {
*/
public function mode_mappings($applicationstore, $sessionstore, $requeststore, moodle_url $editurl) {
$table = new html_table();
$table->colclasses = array(
$table->colclasses = [
'mode',
'mapping',
);
$table->rowclasses = array(
];
$table->rowclasses = [
'mode_application',
'mode_session',
'mode_request'
);
$table->head = array(
'mode_request',
];
$table->head = [
get_string('mode', 'cache'),
get_string('mappings', 'cache'),
);
$table->data = array(
array(get_string('mode_'.cache_store::MODE_APPLICATION, 'cache'), $applicationstore),
array(get_string('mode_'.cache_store::MODE_SESSION, 'cache'), $sessionstore),
array(get_string('mode_'.cache_store::MODE_REQUEST, 'cache'), $requeststore)
);
];
$table->data = [
[get_string('mode_' . cache_store::MODE_APPLICATION, 'cache'), $applicationstore],
[get_string('mode_' . cache_store::MODE_SESSION, 'cache'), $sessionstore],
[get_string('mode_' . cache_store::MODE_REQUEST, 'cache'), $requeststore],
];
$html = html_writer::start_tag('div', array('id' => 'core-cache-mode-mappings'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-mode-mappings']);
$html .= $this->output->heading(get_string('defaultmappings', 'cache'), 3);
$html .= html_writer::table($table);
$link = html_writer::link($editurl, get_string('editmappings', 'cache'));
$html .= html_writer::tag('div', $link, array('class' => 'edit-link'));
$html .= html_writer::tag('div', $link, ['class' => 'edit-link']);
$html .= html_writer::end_tag('div');
return $html;
}
@ -327,45 +326,45 @@ class renderer extends \plugin_renderer_base {
*/
public function lock_summaries(array $locks) {
$table = new html_table();
$table->colclasses = array(
$table->colclasses = [
'name',
'type',
'default',
'uses',
'actions'
);
$table->rowclasses = array(
'actions',
];
$table->rowclasses = [
'lock_name',
'lock_type',
'lock_default',
'lock_uses',
'lock_actions',
);
$table->head = array(
];
$table->head = [
get_string('lockname', 'cache'),
get_string('locktype', 'cache'),
get_string('lockdefault', 'cache'),
get_string('lockuses', 'cache'),
get_string('actions', 'cache')
);
$table->data = array();
get_string('actions', 'cache'),
];
$table->data = [];
$tick = $this->output->pix_icon('i/valid', '');
foreach ($locks as $lock) {
$actions = array();
$actions = [];
if ($lock['uses'] === 0 && !$lock['default']) {
$url = new moodle_url('/cache/admin.php', array('lock' => $lock['name'], 'action' => 'deletelock'));
$url = new moodle_url('/cache/admin.php', ['lock' => $lock['name'], 'action' => 'deletelock']);
$actions[] = html_writer::link($url, get_string('delete', 'cache'));
}
$table->data[] = new html_table_row(array(
$table->data[] = new html_table_row([
new html_table_cell($lock['name']),
new html_table_cell($lock['type']),
new html_table_cell($lock['default'] ? $tick : ''),
new html_table_cell($lock['uses']),
new html_table_cell(join(' ', $actions))
));
new html_table_cell(join(' ', $actions)),
]);
}
$html = html_writer::start_tag('div', array('id' => 'core-cache-lock-summary'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-lock-summary']);
$html .= $this->output->heading(get_string('locksummary', 'cache'), 3);
$html .= html_writer::table($table);
$html .= html_writer::end_tag('div');
@ -378,12 +377,12 @@ class renderer extends \plugin_renderer_base {
* @return string
*/
public function additional_lock_actions(): string {
$url = new moodle_url('/cache/admin.php', array('action' => 'newlockinstance'));
$url = new moodle_url('/cache/admin.php', ['action' => 'newlockinstance']);
$select = new single_select($url, 'lock', cache_factory::get_administration_display_helper()->get_addable_lock_options());
$select->label = get_string('addnewlockinstance', 'cache');
$html = html_writer::start_tag('div', array('id' => 'core-cache-lock-additional-actions'));
$html .= html_writer::tag('div', $this->output->render($select), array('class' => 'new-instance'));
$html = html_writer::start_tag('div', ['id' => 'core-cache-lock-additional-actions']);
$html .= html_writer::tag('div', $this->output->render($select), ['class' => 'new-instance']);
$html .= html_writer::end_tag('div');
return $html;
}
@ -400,14 +399,14 @@ class renderer extends \plugin_renderer_base {
* @param array $notifications
* @return string
*/
public function notifications(array $notifications = array()) {
public function notifications(array $notifications = []) {
if (count($notifications) === 0) {
// There are no notifications to render.
return '';
}
$html = html_writer::start_div('notifications');
foreach ($notifications as $notification) {
list($message, $notifysuccess) = $notification;
[$message, $notifysuccess] = $notification;
$html .= $this->notification($message, ($notifysuccess) ? 'notifysuccess' : 'notifyproblem');
}
$html .= html_writer::end_div();
@ -432,10 +431,10 @@ class renderer extends \plugin_renderer_base {
get_string('usage_mean', 'cache'),
get_string('usage_sd', 'cache'),
get_string('usage_total', 'cache'),
get_string('usage_totalmargin', 'cache')];
get_string('usage_totalmargin', 'cache'), ];
$table->align = [
'left', 'left', 'left',
'right', 'right', 'right', 'right', 'right'
'right', 'right', 'right', 'right', 'right',
];
$table->data = [];
@ -445,7 +444,7 @@ class renderer extends \plugin_renderer_base {
get_string('storename', 'cache'),
get_string('plugin', 'cache'),
get_string('usage_total', 'cache'),
get_string('usage_realtotal', 'cache')
get_string('usage_realtotal', 'cache'),
];
$summarytable->align = [
'left', 'left',
@ -542,7 +541,7 @@ class renderer extends \plugin_renderer_base {
$data = [
'maintable' => \html_writer::table($maintable),
'summarytable' => \html_writer::table($summarytable),
'samplesform' => $samplesform->render()
'samplesform' => $samplesform->render(),
];
return $this->render_from_template('core_cache/usage', $data);

View file

@ -24,9 +24,7 @@
namespace core_cache\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use core_privacy\local\metadata\collection;
/**
* Privacy Subsystem implementation for core_cache.
@ -36,13 +34,12 @@ use \core_privacy\local\metadata\collection;
*/
class provider implements
// Caches store data.
\core_privacy\local\metadata\provider,
\core_privacy\local\metadata\provider,
// The cache subsystem stores data on behalf of other components.
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\shared_userlist_provider
{
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\shared_userlist_provider
{
/**
* Returns meta data about this system.
*

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* An request cache.
*
@ -25,11 +27,16 @@
*
* @internal don't use me directly.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_request extends cache {
class request_cache extends cache {
// This comment appeases code pre-checker ;) !
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(request_cache::class, \cache_request::class);

View file

@ -14,15 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache store feature: keys are searchable.
*
* Cache stores can choose to implement this interface.
* In order for a store to be usable as a session cache it must implement this interface.
*
* @since Moodle 2.4.4
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_is_searchable {
interface searchable_cache_interface {
/**
* Finds all of the keys being used by the cache store.
*
@ -37,3 +41,8 @@ interface cache_is_searchable {
*/
public function find_by_prefix($prefix);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(searchable_cache_interface::class, \cache_is_searchable::class);

View file

@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
use core\exception\coding_exception;
/**
* A session cache.
*
@ -27,7 +31,7 @@
* Along with this we embed a lastaccessed time with the data. This way we can
* check sessions for a last access time.
* 3. Session stores are required to support key searching and must
* implement cache_is_searchable. This ensures stores used for the cache can be
* implement searchable_cache_interface. This ensures stores used for the cache can be
* targetted for garbage collection of session data.
*
* This cache class should never be interacted with directly. Instead you should always use the cache::make methods.
@ -37,14 +41,15 @@
* @todo we should support locking in the session as well. Should be pretty simple to set up.
*
* @internal don't use me directly.
* @method cache_store|cache_is_searchable get_store() Returns the cache store which must implement both cache_is_searchable.
* @method store|searchable_cache_interface get_store() Returns the cache store which must implement
* both searchable_cache_interface.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_session extends cache {
class session_cache extends cache {
/**
* The user the session has been established for.
* @var int
@ -89,11 +94,11 @@ class cache_session extends cache {
*
* You should not call this method from your code, instead you should use the cache::make methods.
*
* @param cache_definition $definition
* @param cache_store $store
* @param cache_loader|cache_data_source $loader
* @param definition $definition
* @param store $store
* @param loader_interface|data_source_interface $loader
*/
public function __construct(cache_definition $definition, cache_store $store, $loader = null) {
public function __construct(definition $definition, store $store, $loader = null) {
// First up copy the loadeduserid to the current user id.
$this->currentuserid = self::$loadeduserid;
$this->set_session_id();
@ -117,7 +122,7 @@ class cache_session extends cache {
* @return string
*/
protected function get_key_prefix() {
return 'u'.$this->currentuserid.'_'.$this->sessionid;
return 'u' . $this->currentuserid . '_' . $this->sessionid;
}
/**
@ -134,9 +139,9 @@ class cache_session extends cache {
protected function parse_key($key) {
$prefix = $this->get_key_prefix();
if ($key === self::LASTACCESS) {
return $key.$prefix;
return $key . $prefix;
}
return $prefix.'_'.parent::parse_key($key);
return $prefix . '_' . parent::parse_key($key);
}
/**
@ -219,8 +224,8 @@ class cache_session extends cache {
// We have to let the loader do its own parsing of data as it may be unique.
$loader->set($key, $data);
}
if (is_object($data) && $data instanceof cacheable_object) {
$data = new cache_cached_object($data);
if (is_object($data) && $data instanceof cacheable_object_interface) {
$data = new cached_object($data);
} else if (!$this->get_store()->supports_dereferencing_objects() && !is_scalar($data)) {
// If data is an object it will be a reference.
// If data is an array if may contain references.
@ -230,12 +235,16 @@ class cache_session extends cache {
}
// We dont' support native TTL here as we consolidate data for sessions.
if ($this->has_a_ttl() && !$this->store_supports_native_ttl()) {
$data = new cache_ttl_wrapper($data, $this->get_definition()->get_ttl());
$data = new ttl_wrapper($data, $this->get_definition()->get_ttl());
}
$success = $this->get_store()->set($this->parse_key($key), $data);
if ($this->perfdebug) {
cache_helper::record_cache_set($this->get_store(), $this->get_definition(), 1,
$this->get_store()->get_last_io_bytes());
helper::record_cache_set(
$this->get_store(),
$this->get_definition(),
1,
$this->get_store()->get_last_io_bytes()
);
}
return $success;
}
@ -277,8 +286,8 @@ class cache_session extends cache {
*/
public function get_many(array $keys, $strictness = IGNORE_MISSING) {
$this->check_tracked_user();
$parsedkeys = array();
$keymap = array();
$parsedkeys = [];
$keymap = [];
foreach ($keys as $key) {
$parsedkey = $this->parse_key($key);
$parsedkeys[$key] = $parsedkey;
@ -288,13 +297,13 @@ class cache_session extends cache {
if ($this->perfdebug) {
$readbytes = $this->get_store()->get_last_io_bytes();
}
$return = array();
$missingkeys = array();
$return = [];
$missingkeys = [];
$hasmissingkeys = false;
foreach ($result as $parsedkey => $value) {
$key = $keymap[$parsedkey];
if ($value instanceof cache_ttl_wrapper) {
/* @var cache_ttl_wrapper $value */
if ($value instanceof ttl_wrapper) {
/* @var ttl_wrapper $value */
if ($value->has_expired()) {
$this->delete($keymap[$parsedkey]);
$value = false;
@ -302,8 +311,8 @@ class cache_session extends cache {
$value = $value->data;
}
}
if ($value instanceof cache_cached_object) {
/* @var cache_cached_object $value */
if ($value instanceof cached_object) {
/* @var cached_object $value */
$value = $value->restore_object();
} else if (!$this->get_store()->supports_dereferencing_objects() && !is_scalar($value)) {
// If data is an object it will be a reference.
@ -355,11 +364,10 @@ class cache_session extends cache {
$hits++;
}
}
cache_helper::record_cache_hit($this->get_store(), $this->get_definition(), $hits, $readbytes);
cache_helper::record_cache_miss($this->get_store(), $this->get_definition(), $misses);
helper::record_cache_hit($this->get_store(), $this->get_definition(), $hits, $readbytes);
helper::record_cache_miss($this->get_store(), $this->get_definition(), $misses);
}
return $return;
}
/**
@ -371,7 +379,7 @@ class cache_session extends cache {
* @return int The number of items successfully deleted.
*/
public function delete_many(array $keys, $recurse = true) {
$parsedkeys = array_map(array($this, 'parse_key'), $keys);
$parsedkeys = array_map([$this, 'parse_key'], $keys);
if ($recurse && $this->get_loader() !== false) {
// Delete from the bottom of the stack first.
$this->get_loader()->delete_many($keys, $recurse);
@ -410,12 +418,12 @@ class cache_session extends cache {
// We have to let the loader do its own parsing of data as it may be unique.
$loader->set_many($keyvaluearray);
}
$data = array();
$data = [];
$definitionid = $this->get_definition()->get_ttl();
$simulatettl = $this->has_a_ttl() && !$this->store_supports_native_ttl();
foreach ($keyvaluearray as $key => $value) {
if (is_object($value) && $value instanceof cacheable_object) {
$value = new cache_cached_object($value);
if (is_object($value) && $value instanceof cacheable_object_interface) {
$value = new cached_object($value);
} else if (!$this->get_store()->supports_dereferencing_objects() && !is_scalar($value)) {
// If data is an object it will be a reference.
// If data is an array if may contain references.
@ -424,17 +432,21 @@ class cache_session extends cache {
$value = $this->unref($value);
}
if ($simulatettl) {
$value = new cache_ttl_wrapper($value, $definitionid);
$value = new ttl_wrapper($value, $definitionid);
}
$data[$key] = array(
$data[$key] = [
'key' => $this->parse_key($key),
'value' => $value
);
'value' => $value,
];
}
$successfullyset = $this->get_store()->set_many($data);
if ($this->perfdebug && $successfullyset) {
cache_helper::record_cache_set($this->get_store(), $this->get_definition(), $successfullyset,
$this->get_store()->get_last_io_bytes());
helper::record_cache_set(
$this->get_store(),
$this->get_definition(),
$successfullyset,
$this->get_store()->get_last_io_bytes()
);
}
return $successfullyset;
}
@ -481,7 +493,7 @@ class cache_session extends cache {
// The data has a TTL and the store doesn't support it natively.
// We must fetch the data and expect a ttl wrapper.
$data = $store->get($parsedkey);
$has = ($data instanceof cache_ttl_wrapper && !$data->has_expired());
$has = ($data instanceof ttl_wrapper && !$data->has_expired());
} else if (!$this->store_supports_key_awareness()) {
// The store doesn't support key awareness, get the data and check it manually... puke.
// Either no TTL is set of the store supports its handling natively.
@ -490,7 +502,7 @@ class cache_session extends cache {
} else {
// The store supports key awareness, this is easy!
// Either no TTL is set of the store supports its handling natively.
/* @var cache_store|cache_is_key_aware $store */
/* @var store|key_aware_cache_interface $store */
$has = $store->has($parsedkey);
}
if (!$has && $tryloadifpossible) {
@ -532,9 +544,9 @@ class cache_session extends cache {
return true;
}
// The cache must be key aware and if support native ttl if it a ttl is set.
/* @var cache_store|cache_is_key_aware $store */
/* @var store|key_aware_cache_interface $store */
$store = $this->get_store();
return $store->has_all(array_map(array($this, 'parse_key'), $keys));
return $store->has_all(array_map([$this, 'parse_key'], $keys));
}
/**
@ -559,9 +571,9 @@ class cache_session extends cache {
}
return false;
}
/* @var cache_store|cache_is_key_aware $store */
/* @var store|key_aware_cache_interface $store */
$store = $this->get_store();
return $store->has_any(array_map(array($this, 'parse_key'), $keys));
return $store->has_any(array_map([$this, 'parse_key'], $keys));
}
/**
@ -574,3 +586,8 @@ class cache_session extends cache {
return false;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(session_cache::class, \cache_session::class);

View file

@ -14,17 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Cache store - base class
*
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are required in order to use caching.
*
* @package core
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_cache;
use core\exception\coding_exception;
use stdClass;
/**
* Abstract cache store class.
@ -33,13 +26,12 @@
* It lays down the foundation for what is required of a cache store plugin.
*
* @since Moodle 2.4
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class cache_store implements cache_store_interface {
abstract class store implements store_interface {
// Constants for features a cache store can support
/**
@ -109,7 +101,7 @@ abstract class cache_store implements cache_store_interface {
* @param string $name The name of the cache store
* @param array $configuration The configuration for this store instance.
*/
abstract public function __construct($name, array $configuration = array());
abstract public function __construct($name, array $configuration = []);
/**
* Returns the name of this store instance.
@ -127,9 +119,9 @@ abstract class cache_store implements cache_store_interface {
* If there are setup tasks that may fail they should be done within the __construct method
* and should they fail is_ready should return false.
*
* @param cache_definition $definition
* @param definition $definition
*/
abstract public function initialise(cache_definition $definition);
abstract public function initialise(definition $definition);
/**
* Returns true if this cache store instance has been initialised.
@ -142,7 +134,7 @@ abstract class cache_store implements cache_store_interface {
* @return bool
*/
public function is_ready() {
return forward_static_call(array($this, 'are_requirements_met'));
return forward_static_call([$this, 'are_requirements_met']);
}
/**
@ -208,11 +200,11 @@ abstract class cache_store implements cache_store_interface {
/**
* @deprecated since 2.5
* @see \cache_store::instance_deleted()
* @see store::instance_deleted()
*/
public function cleanup() {
throw new coding_exception('cache_store::cleanup() can not be used anymore.' .
' Please use cache_store::instance_deleted() instead.');
throw new coding_exception('store::cleanup() can not be used anymore.' .
' Please use store::instance_deleted() instead.');
}
/**
@ -282,7 +274,7 @@ abstract class cache_store implements cache_store_interface {
* @return bool
*/
public function is_searchable() {
return in_array('cache_is_searchable', class_implements($this));
return in_array(searchable_cache_interface::class, class_implements($this));
}
/**
@ -304,9 +296,9 @@ abstract class cache_store implements cache_store_interface {
* you can override this method to handle any situations you want before cloning.
*
* @param array $details An array containing the details of the store from the cache config.
* @return cache_store
* @return store
*/
public function create_clone(array $details = array()) {
public function create_clone(array $details = []) {
// By default we just run clone.
// Any stores that have an issue with this will need to override the create_clone method.
return clone($this);
@ -321,7 +313,7 @@ abstract class cache_store implements cache_store_interface {
* @return string[] An array of warning strings from the store instance.
*/
public function get_warnings() {
return array();
return [];
}
/**
@ -384,7 +376,7 @@ abstract class cache_store implements cache_store_interface {
'items' => 0,
'mean' => 0,
'sd' => 0,
'margin' => 0
'margin' => 0,
];
// If this cache isn't searchable, we don't know the answer.
@ -472,3 +464,8 @@ abstract class cache_store implements cache_store_interface {
return self::IO_BYTES_NOT_SUPPORTED;
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(store::class, \cache_store::class);

View file

@ -14,18 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Cache store interface.
*
* This interface defines the static methods that must be implemented by every cache store plugin.
* To ensure plugins implement this class the abstract cache_store class implements this interface.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_store_interface {
interface store_interface {
/**
* Static method to check if the store requirements are met.
*
@ -46,7 +48,7 @@ interface cache_store_interface {
* @param array $configuration The configuration of a store to consider specifically.
* @return int The supported features.
*/
public static function get_supported_features(array $configuration = array());
public static function get_supported_features(array $configuration = []);
/**
* Returns the supported modes as a binary flag.
@ -54,17 +56,17 @@ interface cache_store_interface {
* @param array $configuration The configuration of a store to consider specifically.
* @return int The supported modes.
*/
public static function get_supported_modes(array $configuration = array());
public static function get_supported_modes(array $configuration = []);
/**
* Generates an instance of the cache store that can be used for testing.
*
* Returns an instance of the cache store, or false if one cannot be created.
*
* @param cache_definition $definition
* @return cache_store|false
* @param definition $definition
* @return store_interface|false
*/
public static function initialise_test_instance(cache_definition $definition);
public static function initialise_test_instance(definition $definition);
/**
* Generates the appropriate configuration required for unit testing.
@ -73,3 +75,8 @@ interface cache_store_interface {
*/
public static function unit_test_configuration();
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(store_interface::class, \cache_store_interface::class);

View file

@ -14,18 +14,19 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* A wrapper class used to handle ttl when the cache store doesn't natively support it.
*
* This class is exactly why you should use event driving invalidation of cache data rather than relying on ttl.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_ttl_wrapper {
class ttl_wrapper {
/**
* The data being stored.
* @var mixed
@ -57,3 +58,8 @@ class cache_ttl_wrapper {
return ($this->expires < cache::now());
}
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(ttl_wrapper::class, \cache_ttl_wrapper::class);

View file

@ -24,7 +24,6 @@ namespace core_cache;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class version_wrapper {
/**
* The data being stored.
* @var mixed

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace core_cache;
/**
* Versionable cache data source.
*
@ -21,8 +23,10 @@
* the data source is to be used for a versioned cache.
*
* @package core_cache
* @copyright Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
interface cache_data_source_versionable extends cache_data_source {
interface versionable_data_source_interface extends cache_data_source {
/**
* Loads the data for the key provided ready formatted for caching.
*
@ -39,3 +43,8 @@ interface cache_data_source_versionable extends cache_data_source {
*/
public function load_for_cache_versioned($key, int $requiredversion, &$actualversion);
}
// Alias this class to the old name.
// This file will be autoloaded by the legacyclasses autoload system.
// In future all uses of this class will be corrected and the legacy references will be removed.
class_alias(versionable_data_source_interface::class, \cache_data_source_versionable::class);

View file

@ -17,14 +17,14 @@
/**
* Store performance test run + output script.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->dirroot.'/lib/adminlib.php');
require_once($CFG->dirroot . '/lib/adminlib.php');
$count = optional_param('count', 100, PARAM_INT);
$count = min($count, 100000);
@ -33,15 +33,15 @@ $count = max($count, 0);
admin_externalpage_setup('cachetestperformance');
$applicationtable = new html_table();
$applicationtable->head = array(
$applicationtable->head = [
get_string('plugin', 'cache'),
get_string('result', 'cache'),
get_string('set', 'cache'),
get_string('gethit', 'cache'),
get_string('getmiss', 'cache'),
get_string('delete', 'cache'),
);
$applicationtable->data = array();
];
$applicationtable->data = [];
$sessiontable = clone($applicationtable);
$requesttable = clone($applicationtable);
@ -57,48 +57,47 @@ $strtested = new lang_string('tested', 'cache');
$strnotready = new lang_string('storenotready', 'cache');
foreach (core_component::get_plugin_list_with_file('cachestore', 'lib.php', true) as $plugin => $path) {
$class = 'cachestore_'.$plugin;
$plugin = get_string('pluginname', 'cachestore_'.$plugin);
$class = 'cachestore_' . $plugin;
$plugin = get_string('pluginname', 'cachestore_' . $plugin);
if (!class_exists($class) || !method_exists($class, 'initialise_test_instance') || !$class::are_requirements_met()) {
$applicationtable->data[] = array($plugin, $strinvalidplugin, '-', '-', '-', '-');
$sessiontable->data[] = array($plugin, $strinvalidplugin, '-', '-', '-', '-');
$requesttable->data[] = array($plugin, $strinvalidplugin, '-', '-', '-', '-');
$applicationtable->data[] = [$plugin, $strinvalidplugin, '-', '-', '-', '-'];
$sessiontable->data[] = [$plugin, $strinvalidplugin, '-', '-', '-', '-'];
$requesttable->data[] = [$plugin, $strinvalidplugin, '-', '-', '-', '-'];
continue;
}
if (!$class::is_supported_mode(cache_store::MODE_APPLICATION)) {
$applicationtable->data[] = array($plugin, $strunsupportedmode, '-', '-', '-', '-');
$applicationtable->data[] = [$plugin, $strunsupportedmode, '-', '-', '-', '-'];
} else {
$store = $class::initialise_test_instance($application);
if ($store === false) {
$applicationtable->data[] = array($plugin, $struntestable, '-', '-', '-', '-');
$applicationtable->data[] = [$plugin, $struntestable, '-', '-', '-', '-'];
} else if (!$store->is_ready()) {
$applicationtable->data[] = array($plugin, $strnotready, '-', '-', '-', '-');
$applicationtable->data[] = [$plugin, $strnotready, '-', '-', '-', '-'];
} else {
$result = array($plugin, $strtested, 0, 0, 0);
$result = [$plugin, $strtested, 0, 0, 0];
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->set('key'.$i, 'test data '.$i);
$store->set('key' . $i, 'test data ' . $i);
}
$result[2] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('key'.$i);
$store->get('key' . $i);
}
$result[3] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('fake'.$i);
$store->get('fake' . $i);
}
$result[4] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->delete('key'.$i);
$store->delete('key' . $i);
}
$result[5] = sprintf('%01.4f', microtime(true) - $start);
$applicationtable->data[] = $result;
@ -107,36 +106,36 @@ foreach (core_component::get_plugin_list_with_file('cachestore', 'lib.php', true
}
if (!$class::is_supported_mode(cache_store::MODE_SESSION)) {
$sessiontable->data[] = array($plugin, $strunsupportedmode, '-', '-', '-', '-');
$sessiontable->data[] = [$plugin, $strunsupportedmode, '-', '-', '-', '-'];
} else {
$store = $class::initialise_test_instance($session);
if ($store === false) {
$sessiontable->data[] = array($plugin, $struntestable, '-', '-', '-', '-');
$sessiontable->data[] = [$plugin, $struntestable, '-', '-', '-', '-'];
} else if (!$store->is_ready()) {
$sessiontable->data[] = array($plugin, $strnotready, '-', '-', '-', '-');
$sessiontable->data[] = [$plugin, $strnotready, '-', '-', '-', '-'];
} else {
$result = array($plugin, $strtested, 0, 0, 0);
$result = [$plugin, $strtested, 0, 0, 0];
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->set('key'.$i, 'test data '.$i);
$store->set('key' . $i, 'test data ' . $i);
}
$result[2] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('key'.$i);
$store->get('key' . $i);
}
$result[3] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('fake'.$i);
$store->get('fake' . $i);
}
$result[4] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->delete('key'.$i);
$store->delete('key' . $i);
}
$result[5] = sprintf('%01.4f', microtime(true) - $start);
$sessiontable->data[] = $result;
@ -145,52 +144,51 @@ foreach (core_component::get_plugin_list_with_file('cachestore', 'lib.php', true
}
if (!$class::is_supported_mode(cache_store::MODE_REQUEST)) {
$requesttable->data[] = array($plugin, $strunsupportedmode, '-', '-', '-', '-');
$requesttable->data[] = [$plugin, $strunsupportedmode, '-', '-', '-', '-'];
} else {
$store = $class::initialise_test_instance($request);
if ($store === false) {
$requesttable->data[] = array($plugin, $struntestable, '-', '-', '-', '-');
$requesttable->data[] = [$plugin, $struntestable, '-', '-', '-', '-'];
} else if (!$store->is_ready()) {
$requesttable->data[] = array($plugin, $strnotready, '-', '-', '-', '-');
$requesttable->data[] = [$plugin, $strnotready, '-', '-', '-', '-'];
} else {
$result = array($plugin, $strtested, 0, 0, 0);
$result = [$plugin, $strtested, 0, 0, 0];
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->set('key'.$i, 'test data '.$i);
$store->set('key' . $i, 'test data ' . $i);
}
$result[2] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('key'.$i);
$store->get('key' . $i);
}
$result[3] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->get('fake'.$i);
$store->get('fake' . $i);
}
$result[4] = sprintf('%01.4f', microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < $count; $i++) {
$store->delete('key'.$i);
$store->delete('key' . $i);
}
$result[5] = sprintf('%01.4f', microtime(true) - $start);
$requesttable->data[] = $result;
$store->instance_deleted();
}
}
}
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('storeperformance', 'cache', $count));
$possiblecounts = array(1, 10, 100, 500, 1000, 5000, 10000, 50000, 100000);
$links = array();
$possiblecounts = [1, 10, 100, 500, 1000, 5000, 10000, 50000, 100000];
$links = [];
foreach ($possiblecounts as $pcount) {
$links[] = html_writer::link(new moodle_url($PAGE->url, array('count' => $pcount)), $pcount);
$links[] = html_writer::link(new moodle_url($PAGE->url, ['count' => $pcount]), $pcount);
}
echo $OUTPUT->box_start('generalbox performance-test-counts');
echo get_string('requestcount', 'cache', join(', ', $links));

View file

@ -17,18 +17,6 @@
namespace core_cache;
use cache_config_testing;
use cache_config_writer;
use cache_factory;
use cache_helper;
use cache_store;
defined('MOODLE_INTERNAL') || die();
// Include the necessary evils.
global $CFG;
require_once($CFG->dirroot.'/cache/locallib.php');
require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
/**
* PHPunit tests for the cache API and in particular the core_cache\administration_helper
@ -37,24 +25,34 @@ require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
* @category test
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_cache\administration_helper
*/
class administration_helper_test extends \advanced_testcase {
final class administration_helper_test extends \advanced_testcase {
/**
* Set things back to the default before each test.
*/
public function setUp(): void {
parent::setUp();
cache_factory::reset();
factory::reset();
cache_config_testing::create_default_configuration();
}
/**
* Require all test dependencies not auto-loadable.
*/
public static function setUpBeforeClass(): void {
global $CFG;
parent::setUpBeforeClass();
require_once($CFG->dirroot . '/cache/tests/fixtures/lib.php');
}
/**
* Final task is to reset the cache system
*/
public static function tearDownAfterClass(): void {
parent::tearDownAfterClass();
cache_factory::reset();
factory::reset();
}
/**
@ -62,20 +60,20 @@ class administration_helper_test extends \advanced_testcase {
*/
public function test_get_summaries(): void {
// First the preparation.
$config = cache_config_writer::instance();
$config = config_writer::instance();
$this->assertTrue($config->add_store_instance('summariesstore', 'file'));
$config->set_definition_mappings('core/eventinvalidation', array('summariesstore'));
$this->assertTrue($config->set_mode_mappings(array(
cache_store::MODE_APPLICATION => array('summariesstore'),
cache_store::MODE_SESSION => array('default_session'),
cache_store::MODE_REQUEST => array('default_request'),
)));
$config->set_definition_mappings('core/eventinvalidation', ['summariesstore']);
$this->assertTrue($config->set_mode_mappings([
store::MODE_APPLICATION => ['summariesstore'],
store::MODE_SESSION => ['default_session'],
store::MODE_REQUEST => ['default_request'],
]));
$storesummaries = administration_helper::get_store_instance_summaries();
$this->assertIsArray($storesummaries);
$this->assertArrayHasKey('summariesstore', $storesummaries);
$summary = $storesummaries['summariesstore'];
// Check the keys
// Check the keys.
$this->assertArrayHasKey('name', $summary);
$this->assertArrayHasKey('plugin', $summary);
$this->assertArrayHasKey('default', $summary);
@ -84,7 +82,7 @@ class administration_helper_test extends \advanced_testcase {
$this->assertArrayHasKey('mappings', $summary);
$this->assertArrayHasKey('modes', $summary);
$this->assertArrayHasKey('supports', $summary);
// Check the important/known values
// Check the important/known values.
$this->assertEquals('summariesstore', $summary['name']);
$this->assertEquals('file', $summary['plugin']);
$this->assertEquals(0, $summary['default']);
@ -92,8 +90,8 @@ class administration_helper_test extends \advanced_testcase {
$this->assertEquals(1, $summary['requirementsmet']);
// Find the number of mappings to sessionstore.
$mappingcount = count(array_filter($config->get_definitions(), function($element) {
return $element['mode'] === cache_store::MODE_APPLICATION;
$mappingcount = count(array_filter($config->get_definitions(), function ($element) {
return $element['mode'] === store::MODE_APPLICATION;
}));
$this->assertEquals($mappingcount, $summary['mappings']);
@ -101,17 +99,17 @@ class administration_helper_test extends \advanced_testcase {
$this->assertIsArray($definitionsummaries);
$this->assertArrayHasKey('core/eventinvalidation', $definitionsummaries);
$summary = $definitionsummaries['core/eventinvalidation'];
// Check the keys
// Check the keys.
$this->assertArrayHasKey('id', $summary);
$this->assertArrayHasKey('name', $summary);
$this->assertArrayHasKey('mode', $summary);
$this->assertArrayHasKey('component', $summary);
$this->assertArrayHasKey('area', $summary);
$this->assertArrayHasKey('mappings', $summary);
// Check the important/known values
// Check the important/known values.
$this->assertEquals('core/eventinvalidation', $summary['id']);
$this->assertInstanceOf('lang_string', $summary['name']);
$this->assertEquals(cache_store::MODE_APPLICATION, $summary['mode']);
$this->assertEquals(store::MODE_APPLICATION, $summary['mode']);
$this->assertEquals('core', $summary['component']);
$this->assertEquals('eventinvalidation', $summary['area']);
$this->assertIsArray($summary['mappings']);
@ -121,7 +119,7 @@ class administration_helper_test extends \advanced_testcase {
$this->assertIsArray($pluginsummaries);
$this->assertArrayHasKey('file', $pluginsummaries);
$summary = $pluginsummaries['file'];
// Check the keys
// Check the keys.
$this->assertArrayHasKey('name', $summary);
$this->assertArrayHasKey('requirementsmet', $summary);
$this->assertArrayHasKey('instances', $summary);
@ -136,12 +134,12 @@ class administration_helper_test extends \advanced_testcase {
$mappings = administration_helper::get_default_mode_stores();
$this->assertIsArray($mappings);
$this->assertCount(3, $mappings);
$this->assertArrayHasKey(cache_store::MODE_APPLICATION, $mappings);
$this->assertIsArray($mappings[cache_store::MODE_APPLICATION]);
$this->assertContains('summariesstore', $mappings[cache_store::MODE_APPLICATION]);
$this->assertArrayHasKey(store::MODE_APPLICATION, $mappings);
$this->assertIsArray($mappings[store::MODE_APPLICATION]);
$this->assertContains('summariesstore', $mappings[store::MODE_APPLICATION]);
$potentials = administration_helper::get_definition_store_options('core', 'eventinvalidation');
$this->assertIsArray($potentials); // Currently used, suitable, default
$this->assertIsArray($potentials); // Currently used, suitable, default.
$this->assertCount(3, $potentials);
$this->assertArrayHasKey('summariesstore', $potentials[0]);
$this->assertArrayHasKey('summariesstore', $potentials[1]);
@ -152,14 +150,14 @@ class administration_helper_test extends \advanced_testcase {
* Test instantiating an add store form.
*/
public function test_get_add_store_form(): void {
$form = cache_factory::get_administration_display_helper()->get_add_store_form('file');
$form = factory::get_administration_display_helper()->get_add_store_form('file');
$this->assertInstanceOf('moodleform', $form);
try {
$form = cache_factory::get_administration_display_helper()->get_add_store_form('somethingstupid');
$form = factory::get_administration_display_helper()->get_add_store_form('somethingstupid');
$this->fail('You should not be able to create an add form for a store plugin that does not exist.');
} catch (\moodle_exception $e) {
$this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' .get_class($e)." ::: ".$e->getMessage());
$this->assertInstanceOf('coding_exception', $e, 'Needs to be: ' . get_class($e) . " ::: " . $e->getMessage());
}
}
@ -168,8 +166,8 @@ class administration_helper_test extends \advanced_testcase {
*/
public function test_get_edit_store_form(): void {
// Always instantiate a new core display helper here.
$administrationhelper = new local\administration_display_helper;
$config = cache_config_writer::instance();
$administrationhelper = new local\administration_display_helper();
$config = config_writer::instance();
$this->assertTrue($config->add_store_instance('test_get_edit_store_form', 'file'));
$form = $administrationhelper->get_edit_store_form('file', 'test_get_edit_store_form');
@ -197,41 +195,41 @@ class administration_helper_test extends \advanced_testcase {
$this->resetAfterTest();
set_debugging(DEBUG_ALL);
// First with simplekeys
// First with simplekeys.
$instance = cache_config_testing::instance(true);
$instance->phpunit_add_definition('phpunit/hashtest', array(
'mode' => cache_store::MODE_APPLICATION,
$instance->phpunit_add_definition('phpunit/hashtest', [
'mode' => store::MODE_APPLICATION,
'component' => 'phpunit',
'area' => 'hashtest',
'simplekeys' => true
));
$factory = cache_factory::instance();
'simplekeys' => true,
]);
$factory = factory::instance();
$definition = $factory->create_definition('phpunit', 'hashtest');
$result = cache_helper::hash_key('test', $definition);
$this->assertEquals('test-'.$definition->generate_single_key_prefix(), $result);
$result = helper::hash_key('test', $definition);
$this->assertEquals('test-' . $definition->generate_single_key_prefix(), $result);
try {
cache_helper::hash_key('test/test', $definition);
helper::hash_key('test/test', $definition);
$this->fail('Invalid key was allowed, you should see this.');
} catch (\coding_exception $e) {
$this->assertEquals('test/test', $e->debuginfo);
}
// Second without simple keys
$instance->phpunit_add_definition('phpunit/hashtest2', array(
'mode' => cache_store::MODE_APPLICATION,
// Second without simple keys.
$instance->phpunit_add_definition('phpunit/hashtest2', [
'mode' => store::MODE_APPLICATION,
'component' => 'phpunit',
'area' => 'hashtest2',
'simplekeys' => false
));
'simplekeys' => false,
]);
$definition = $factory->create_definition('phpunit', 'hashtest2');
$result = cache_helper::hash_key('test', $definition);
$this->assertEquals(sha1($definition->generate_single_key_prefix().'-test'), $result);
$result = helper::hash_key('test', $definition);
$this->assertEquals(sha1($definition->generate_single_key_prefix() . '-test'), $result);
$result = cache_helper::hash_key('test/test', $definition);
$this->assertEquals(sha1($definition->generate_single_key_prefix().'-test/test'), $result);
$result = helper::hash_key('test/test', $definition);
$this->assertEquals(sha1($definition->generate_single_key_prefix() . '-test/test'), $result);
}
/**
@ -241,17 +239,17 @@ class administration_helper_test extends \advanced_testcase {
// Create a test cache definition and put items in it.
$instance = cache_config_testing::instance(true);
$instance->phpunit_add_definition('phpunit/test', [
'mode' => cache_store::MODE_APPLICATION,
'mode' => store::MODE_APPLICATION,
'component' => 'phpunit',
'area' => 'test',
'simplekeys' => true
'simplekeys' => true,
]);
$cache = \cache::make('phpunit', 'test');
for ($i = 0; $i < 100; $i++) {
$cache->set('key' . $i, str_repeat('x', $i));
}
$factory = cache_factory::instance();
$factory = factory::instance();
$adminhelper = $factory->get_administration_display_helper();
$usage = $adminhelper->get_usage(10)['phpunit/test'];

View file

@ -25,8 +25,7 @@ namespace core_cache;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_cache\allow_temporary_caches
*/
class allow_temporary_caches_test extends \advanced_testcase {
final class allow_temporary_caches_test extends \advanced_testcase {
/**
* Tests whether temporary caches are allowed.
*/
@ -92,8 +91,8 @@ class allow_temporary_caches_test extends \advanced_testcase {
get_fast_modinfo($course);
} finally {
// You have to do this after phpunit_disable or it breaks later tests.
\cache_factory::reset();
\cache_factory::instance(true);
factory::reset();
factory::instance(true);
}
}
}

View file

@ -19,23 +19,22 @@ namespace core_cache;
/**
* PHPunit tests for the cache_helper class.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2023 Andrew Lyons <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @coversDefaultClass \cache_helper
* @covers \core_cache\helper
*/
class cache_helper_test extends \advanced_testcase {
final class cache_helper_test extends \advanced_testcase {
/**
* Test the result_found method.
*
* @param mixed $value
* @param bool $expected
* @dataProvider result_found_provider
* @covers ::result_found
*/
public function test_result_found($value, bool $expected): void {
$this->assertEquals($expected, \cache_helper::result_found($value));
$this->assertEquals($expected, helper::result_found($value));
}
/**
@ -43,7 +42,7 @@ class cache_helper_test extends \advanced_testcase {
*
* @return array
*/
public function result_found_provider(): array {
public static function result_found_provider(): array {
return [
// Only false values are considered as not found.
[false, false],

File diff suppressed because it is too large Load diff

View file

@ -17,16 +17,6 @@
namespace core_cache;
use cache_config_testing;
use cache_config_writer;
use cache_factory;
use cache_store;
defined('MOODLE_INTERNAL') || die();
// Include the necessary evils.
global $CFG;
require_once($CFG->dirroot.'/cache/locallib.php');
require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
/**
* PHPunit tests for the cache API and in particular the cache config writer.
@ -35,15 +25,25 @@ require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php');
* @category test
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_cache\config_writer
*/
class config_writer_test extends \advanced_testcase {
final class config_writer_test extends \advanced_testcase {
/**
* Load required libraries and fixtures.
*/
public static function setUpBeforeClass(): void {
global $CFG;
require_once($CFG->dirroot . '/cache/tests/fixtures/lib.php');
parent::setUpBeforeClass();
}
/**
* Set things back to the default before each test.
*/
public function setUp(): void {
parent::setUp();
cache_factory::reset();
factory::reset();
cache_config_testing::create_default_configuration();
}
@ -52,22 +52,22 @@ class config_writer_test extends \advanced_testcase {
*/
public static function tearDownAfterClass(): void {
parent::tearDownAfterClass();
cache_factory::reset();
factory::reset();
}
/**
* Test getting an instance. Pretty basic.
*/
public function test_instance(): void {
$config = cache_config_writer::instance();
$this->assertInstanceOf('cache_config_writer', $config);
$config = config_writer::instance();
$this->assertInstanceOf(config_writer::class, $config);
}
/**
* Test the default configuration.
*/
public function test_default_configuration(): void {
$config = cache_config_writer::instance();
$config = config_writer::instance();
// First check stores.
$stores = $config->get_all_stores();
@ -82,13 +82,13 @@ class config_writer_test extends \advanced_testcase {
$this->assertArrayHasKey('default', $store);
// Check the mode, we need at least one default store of each mode.
if (!empty($store['default'])) {
if ($store['modes'] & cache_store::MODE_APPLICATION) {
if ($store['modes'] & store::MODE_APPLICATION) {
$hasapplication = true;
}
if ($store['modes'] & cache_store::MODE_SESSION) {
if ($store['modes'] & store::MODE_SESSION) {
$hassession = true;
}
if ($store['modes'] & cache_store::MODE_REQUEST) {
if ($store['modes'] & store::MODE_REQUEST) {
$hasrequest = true;
}
}
@ -111,7 +111,7 @@ class config_writer_test extends \advanced_testcase {
}
$this->assertTrue($eventinvalidation, 'Missing the event invalidation definition.');
// Next mode mappings
// Next mode mappings.
$mappings = $config->get_mode_mappings();
$hasapplication = false;
$hassession = false;
@ -121,13 +121,13 @@ class config_writer_test extends \advanced_testcase {
$this->assertArrayHasKey('mode', $mode);
$this->assertArrayHasKey('store', $mode);
if ($mode['mode'] === cache_store::MODE_APPLICATION) {
if ($mode['mode'] === store::MODE_APPLICATION) {
$hasapplication = true;
}
if ($mode['mode'] === cache_store::MODE_SESSION) {
if ($mode['mode'] === store::MODE_SESSION) {
$hassession = true;
}
if ($mode['mode'] === cache_store::MODE_REQUEST) {
if ($mode['mode'] === store::MODE_REQUEST) {
$hasrequest = true;
}
}
@ -135,7 +135,7 @@ class config_writer_test extends \advanced_testcase {
$this->assertTrue($hassession, 'There is no mapping for the session mode.');
$this->assertTrue($hasrequest, 'There is no mapping for the request mode.');
// Finally check config locks
// Finally check config locks.
$locks = $config->get_locks();
foreach ($locks as $lock) {
$this->assertArrayHasKey('name', $lock);
@ -150,14 +150,14 @@ class config_writer_test extends \advanced_testcase {
* Test updating the definitions.
*/
public function test_update_definitions(): void {
$config = cache_config_writer::instance();
$config = config_writer::instance();
// Remove the definition.
$config->phpunit_remove_definition('core/string');
$definitions = $config->get_definitions();
// Check it is gone.
$this->assertFalse(array_key_exists('core/string', $definitions));
// Update definitions. This should re-add it.
cache_config_writer::update_definitions();
config_writer::update_definitions();
$definitions = $config->get_definitions();
// Check it is back again.
$this->assertTrue(array_key_exists('core/string', $definitions));
@ -167,18 +167,18 @@ class config_writer_test extends \advanced_testcase {
* Test adding/editing/deleting store instances.
*/
public function test_add_edit_delete_plugin_instance(): void {
$config = cache_config_writer::instance();
$config = config_writer::instance();
$this->assertArrayNotHasKey('addplugintest', $config->get_all_stores());
$this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
// Add a default file instance.
$config->add_store_instance('addplugintest', 'file');
cache_factory::reset();
$config = cache_config_writer::instance();
factory::reset();
$config = config_writer::instance();
$this->assertArrayHasKey('addplugintest', $config->get_all_stores());
// Add a store with a lock described.
$config->add_store_instance('addplugintestwlock', 'file', array('lock' => 'default_file_lock'));
$config->add_store_instance('addplugintestwlock', 'file', ['lock' => 'default_file_lock']);
$this->assertArrayHasKey('addplugintestwlock', $config->get_all_stores());
$config->delete_store_instance('addplugintest');
@ -190,7 +190,7 @@ class config_writer_test extends \advanced_testcase {
$this->assertArrayNotHasKey('addplugintestwlock', $config->get_all_stores());
// Add a default file instance.
$config->add_store_instance('storeconfigtest', 'file', array('test' => 'a', 'one' => 'two'));
$config->add_store_instance('storeconfigtest', 'file', ['test' => 'a', 'one' => 'two']);
$stores = $config->get_all_stores();
$this->assertArrayHasKey('storeconfigtest', $stores);
$this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
@ -199,7 +199,7 @@ class config_writer_test extends \advanced_testcase {
$this->assertEquals('a', $stores['storeconfigtest']['configuration']['test']);
$this->assertEquals('two', $stores['storeconfigtest']['configuration']['one']);
$config->edit_store_instance('storeconfigtest', 'file', array('test' => 'b', 'one' => 'three'));
$config->edit_store_instance('storeconfigtest', 'file', ['test' => 'b', 'one' => 'three']);
$stores = $config->get_all_stores();
$this->assertArrayHasKey('storeconfigtest', $stores);
$this->assertArrayHasKey('configuration', $stores['storeconfigtest']);
@ -214,22 +214,22 @@ class config_writer_test extends \advanced_testcase {
$config->delete_store_instance('default_application');
$this->fail('Default store deleted. This should not be possible!');
} catch (\Exception $e) {
$this->assertInstanceOf('cache_exception', $e);
$this->assertInstanceOf(\core_cache\exception\cache_exception::class, $e);
}
try {
$config->delete_store_instance('some_crazy_store');
$this->fail('You should not be able to delete a store that does not exist.');
} catch (\Exception $e) {
$this->assertInstanceOf('cache_exception', $e);
$this->assertInstanceOf(\core_cache\exception\cache_exception::class, $e);
}
try {
// Try with a plugin that does not exist.
$config->add_store_instance('storeconfigtest', 'shallowfail', array('test' => 'a', 'one' => 'two'));
$config->add_store_instance('storeconfigtest', 'shallowfail', ['test' => 'a', 'one' => 'two']);
$this->fail('You should not be able to add an instance of a store that does not exist.');
} catch (\Exception $e) {
$this->assertInstanceOf('cache_exception', $e);
$this->assertInstanceOf(\core_cache\exception\cache_exception::class, $e);
}
}
@ -237,17 +237,17 @@ class config_writer_test extends \advanced_testcase {
* Test setting some mode mappings.
*/
public function test_set_mode_mappings(): void {
$config = cache_config_writer::instance();
$config = config_writer::instance();
$this->assertTrue($config->add_store_instance('setmodetest', 'file'));
$this->assertTrue($config->set_mode_mappings(array(
cache_store::MODE_APPLICATION => array('setmodetest', 'default_application'),
cache_store::MODE_SESSION => array('default_session'),
cache_store::MODE_REQUEST => array('default_request'),
)));
$this->assertTrue($config->set_mode_mappings([
store::MODE_APPLICATION => ['setmodetest', 'default_application'],
store::MODE_SESSION => ['default_session'],
store::MODE_REQUEST => ['default_request'],
]));
$mappings = $config->get_mode_mappings();
$setmodetestfound = false;
foreach ($mappings as $mapping) {
if ($mapping['store'] == 'setmodetest' && $mapping['mode'] == cache_store::MODE_APPLICATION) {
if ($mapping['store'] == 'setmodetest' && $mapping['mode'] == store::MODE_APPLICATION) {
$setmodetestfound = true;
}
}
@ -258,30 +258,30 @@ class config_writer_test extends \advanced_testcase {
* Test setting some definition mappings.
*/
public function test_set_definition_mappings(): void {
$config = cache_config_testing::instance(true);
$config->phpunit_add_definition('phpunit/testdefinition', array(
'mode' => cache_store::MODE_APPLICATION,
$config = cache_config_testing::instance();
$config->phpunit_add_definition('phpunit/testdefinition', [
'mode' => store::MODE_APPLICATION,
'component' => 'phpunit',
'area' => 'testdefinition'
));
'area' => 'testdefinition',
]);
$config = cache_config_writer::instance();
$config = config_writer::instance();
$this->assertTrue($config->add_store_instance('setdefinitiontest', 'file'));
$this->assertIsArray($config->get_definition_by_id('phpunit/testdefinition'));
$config->set_definition_mappings('phpunit/testdefinition', array('setdefinitiontest', 'default_application'));
$config->set_definition_mappings('phpunit/testdefinition', ['setdefinitiontest', 'default_application']);
try {
$config->set_definition_mappings('phpunit/testdefinition', array('something that does not exist'));
$config->set_definition_mappings('phpunit/testdefinition', ['something that does not exist']);
$this->fail('You should not be able to set a mapping for a store that does not exist.');
} catch (\Exception $e) {
$this->assertInstanceOf('coding_exception', $e);
$this->assertInstanceOf(\core\exception\coding_exception::class, $e);
}
try {
$config->set_definition_mappings('something/crazy', array('setdefinitiontest'));
$config->set_definition_mappings('something/crazy', ['setdefinitiontest']);
$this->fail('You should not be able to set a mapping for a definition that does not exist.');
} catch (\Exception $e) {
$this->assertInstanceOf('coding_exception', $e);
$this->assertInstanceOf(\core\exception\coding_exception::class, $e);
}
}
}

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use core_cache\versionable_data_source_interface;
/**
* A dummy datasource which supports versioning.
*
@ -21,8 +23,9 @@
* @copyright 2021 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_phpunit_dummy_datasource_versionable extends cache_phpunit_dummy_datasource
implements cache_data_source_versionable {
class cache_phpunit_dummy_datasource_versionable extends cache_phpunit_dummy_datasource implements
versionable_data_source_interface
{
/** @var array Data in cache */
protected $data = [];
@ -35,8 +38,7 @@ class cache_phpunit_dummy_datasource_versionable extends cache_phpunit_dummy_dat
* @param cache_definition $definition
* @return cache_phpunit_dummy_datasource New object
*/
public static function get_instance_for_cache(cache_definition $definition):
cache_phpunit_dummy_datasource_versionable {
public static function get_instance_for_cache(cache_definition $definition): cache_phpunit_dummy_datasource_versionable {
self::$lastinstance = new cache_phpunit_dummy_datasource_versionable();
return self::$lastinstance;
}
@ -81,4 +83,3 @@ class cache_phpunit_dummy_datasource_versionable extends cache_phpunit_dummy_dat
return $value->data;
}
}

View file

@ -30,8 +30,7 @@ class cachestore_file_with_ttl_wrappers extends cachestore_file {
* @param array $configuration Configuration
* @return int Supported features
*/
public static function get_supported_features(array $configuration = array()) {
public static function get_supported_features(array $configuration = []) {
return parent::get_supported_features($configuration) - self::SUPPORTS_NATIVE_TTL;
}
}

View file

@ -20,7 +20,7 @@
* This file is part of Moodle's cache API, affectionately called MUC.
* It contains the components that are requried in order to use caching.
*
* @package core
* @package core_cache
* @category cache
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -28,6 +28,8 @@
defined('MOODLE_INTERNAL') || die();
use core_cache\store;
/**
* Override the default cache configuration for our own maniacal purposes.
*
@ -39,7 +41,6 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_config_testing extends cache_config_writer {
/**
* Creates the default configuration and saves it.
*
@ -55,7 +56,7 @@ class cache_config_testing extends cache_config_writer {
// HACK ALERT.
// We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
// default store plugins are protected from deletion.
$writer = new self;
$writer = new self();
$writer->configstores = self::get_default_stores();
$writer->configdefinitions = self::locate_definitions();
$defaultapplication = 'default_application';
@ -63,50 +64,50 @@ class cache_config_testing extends cache_config_writer {
$appdefine = defined('TEST_CACHE_USING_APPLICATION_STORE') ? TEST_CACHE_USING_APPLICATION_STORE : false;
if ($appdefine !== false && preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/', $appdefine)) {
$expectedstore = $appdefine;
$file = $CFG->dirroot.'/cache/stores/'.$appdefine.'/lib.php';
$class = 'cachestore_'.$appdefine;
$file = $CFG->dirroot . '/cache/stores/' . $appdefine . '/lib.php';
$class = 'cachestore_' . $appdefine;
if (file_exists($file)) {
require_once($file);
}
if (class_exists($class) && $class::ready_to_be_used_for_testing()) {
/* @var cache_store $class */
$writer->configstores['test_application'] = array(
/* @var store $class */
$writer->configstores['test_application'] = [
'name' => 'test_application',
'plugin' => $expectedstore,
'modes' => $class::get_supported_modes(),
'features' => $class::get_supported_features(),
'configuration' => $class::unit_test_configuration()
);
'configuration' => $class::unit_test_configuration(),
];
$defaultapplication = 'test_application';
}
}
$writer->configmodemappings = array(
array(
'mode' => cache_store::MODE_APPLICATION,
$writer->configmodemappings = [
[
'mode' => store::MODE_APPLICATION,
'store' => $defaultapplication,
'sort' => -1
),
array(
'mode' => cache_store::MODE_SESSION,
'sort' => -1,
],
[
'mode' => store::MODE_SESSION,
'store' => 'default_session',
'sort' => -1
),
array(
'mode' => cache_store::MODE_REQUEST,
'sort' => -1,
],
[
'mode' => store::MODE_REQUEST,
'store' => 'default_request',
'sort' => -1
)
);
$writer->configlocks = array(
'default_file_lock' => array(
'sort' => -1,
],
];
$writer->configlocks = [
'default_file_lock' => [
'name' => 'cachelock_file_default',
'type' => 'cachelock_file',
'dir' => 'filelocks',
'default' => true
)
);
'default' => true,
],
];
$factory = cache_factory::instance();
// We expect the cache to be initialising presently. If its not then something has gone wrong and likely
@ -133,13 +134,12 @@ class cache_config_testing extends cache_config_writer {
protected static function get_config_file_path() {
global $CFG;
// We always use this path.
$configpath = $CFG->dataroot.'/muc/config.php';
$configpath = $CFG->dataroot . '/muc/config.php';
if (!empty($CFG->altcacheconfigpath)) {
// No need to check we are within a test here, this is the cache config class that gets used
// only when one of those is true.
if (!defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') || !TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) {
if (!defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') || !TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) {
// TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH has not being defined or is false, we want to use the default.
return $configpath;
}
@ -147,7 +147,7 @@ class cache_config_testing extends cache_config_writer {
$path = $CFG->altcacheconfigpath;
if (is_dir($path) && is_writable($path)) {
// Its a writable directory, thats fine. Convert it to a file.
$path = $CFG->altcacheconfigpath.'/cacheconfig.php';
$path = $CFG->altcacheconfigpath . '/cacheconfig.php';
}
if (is_readable($path)) {
$directory = dirname($configpath);
@ -178,13 +178,13 @@ class cache_config_testing extends cache_config_writer {
public function phpunit_add_definition($area, array $properties, $addmapping = true) {
if (!array_key_exists('overrideclass', $properties)) {
switch ($properties['mode']) {
case cache_store::MODE_APPLICATION:
case store::MODE_APPLICATION:
$properties['overrideclass'] = 'cache_phpunit_application';
break;
case cache_store::MODE_SESSION:
case store::MODE_SESSION:
$properties['overrideclass'] = 'cache_phpunit_session';
break;
case cache_store::MODE_REQUEST:
case store::MODE_REQUEST:
$properties['overrideclass'] = 'cache_phpunit_request';
break;
}
@ -192,13 +192,13 @@ class cache_config_testing extends cache_config_writer {
$this->configdefinitions[$area] = $properties;
if ($addmapping) {
switch ($properties['mode']) {
case cache_store::MODE_APPLICATION:
case store::MODE_APPLICATION:
$this->phpunit_add_definition_mapping($area, 'default_application', 0);
break;
case cache_store::MODE_SESSION:
case store::MODE_SESSION:
$this->phpunit_add_definition_mapping($area, 'default_session', 0);
break;
case cache_store::MODE_REQUEST:
case store::MODE_REQUEST:
$this->phpunit_add_definition_mapping($area, 'default_request', 0);
break;
}
@ -217,7 +217,7 @@ class cache_config_testing extends cache_config_writer {
* Removes the configured stores so that there are none available.
*/
public function phpunit_remove_stores() {
$this->configstores = array();
$this->configstores = [];
}
/**
@ -232,19 +232,19 @@ class cache_config_testing extends cache_config_writer {
if (!$nativettl) {
require_once(__DIR__ . '/cachestore_file_with_ttl_wrappers.php');
}
$this->configstores[$name] = array(
$this->configstores[$name] = [
'name' => $name,
'plugin' => 'file',
'configuration' => array(
'path' => ''
),
'configuration' => [
'path' => '',
],
'features' => 6,
'modes' => 3,
'mappingsonly' => false,
'class' => $nativettl ? 'cachestore_file' : 'cachestore_file_with_ttl_wrappers',
'default' => false,
'lock' => 'cachelock_file_default'
);
'lock' => 'cachelock_file_default',
];
}
/**
@ -265,16 +265,16 @@ class cache_config_testing extends cache_config_writer {
* @param string $name
*/
public function phpunit_add_session_store($name) {
$this->configstores[$name] = array(
$this->configstores[$name] = [
'name' => $name,
'plugin' => 'session',
'configuration' => array(),
'configuration' => [],
'features' => 14,
'modes' => 2,
'default' => true,
'class' => 'cachestore_session',
'lock' => 'cachelock_file_default',
);
];
}
/**
@ -288,11 +288,11 @@ class cache_config_testing extends cache_config_writer {
* @param int $sort
*/
public function phpunit_add_definition_mapping($definition, $store, $sort) {
$this->configdefinitionmappings[] = array(
$this->configdefinitionmappings[] = [
'store' => $store,
'definition' => $definition,
'sort' => (int)$sort
);
'sort' => (int)$sort,
];
}
/**
@ -302,7 +302,7 @@ class cache_config_testing extends cache_config_writer {
*/
public function get_site_identifier() {
global $CFG;
return $CFG->wwwroot.'phpunit';
return $CFG->wwwroot . 'phpunit';
}
/**
@ -361,7 +361,7 @@ class cache_phpunit_dummy_object extends stdClass implements cacheable_object {
* @return array
*/
public function prepare_to_cache() {
return array($this->property1.'_ptc', $this->property2.'_ptc', $this->propertytime);
return [$this->property1 . '_ptc', $this->property2 . '_ptc', $this->propertytime];
}
/**
* Returns this object from the cache
@ -375,9 +375,8 @@ class cache_phpunit_dummy_object extends stdClass implements cacheable_object {
do {
$time = microtime(true);
} while ($time == $data[2]);
}
return new cache_phpunit_dummy_object(array_shift($data).'_wfc', array_shift($data).'_wfc', $time);
return new cache_phpunit_dummy_object(array_shift($data) . '_wfc', array_shift($data) . '_wfc', $time);
}
}
@ -405,7 +404,7 @@ class cache_phpunit_dummy_datasource implements cache_data_source {
* @return string
*/
public function load_for_cache($key) {
return $key.' has no value really.';
return $key . ' has no value really.';
}
/**
@ -415,9 +414,9 @@ class cache_phpunit_dummy_datasource implements cache_data_source {
* @return array
*/
public function load_many_for_cache(array $keys) {
$return = array();
$return = [];
foreach ($keys as $key) {
$return[$key] = $key.' has no value really.';
$return[$key] = $key . ' has no value really.';
}
return $return;
}
@ -432,6 +431,10 @@ class cache_phpunit_dummy_datasource implements cache_data_source {
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_phpunit_application extends cache_application {
#[\Override]
public function get_store() {
return parent::get_store();
}
/**
* Returns the class of the store immediately associated with this cache.
@ -480,10 +483,14 @@ class cache_phpunit_application extends cache_application {
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_phpunit_session extends cache_session {
/** @var Static member used for emulating the behaviour of session_id() during the tests. */
protected static $sessionidmockup = 'phpunitmockupsessionid';
#[\Override]
public function get_store() {
return parent::get_store();
}
/**
* Returns the class of the store immediately associated with this cache.
* @return string
@ -535,6 +542,10 @@ class cache_phpunit_session extends cache_session {
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cache_phpunit_request extends cache_request {
#[\Override]
public function get_store() {
return parent::get_store();
}
/**
* Returns the class of the store immediately associated with this cache.

View file

@ -14,17 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Cache store test fixtures.
*
* @package core
* @category cache
* @copyright 2013 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* An abstract class to make writing unit tests for cache stores very easy.
*
@ -34,7 +23,6 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class cachestore_tests extends advanced_testcase {
/**
* Returns the class name for the store.
*
@ -49,7 +37,7 @@ abstract class cachestore_tests extends advanced_testcase {
public function setUp(): void {
$class = $this->get_class_name();
if (!class_exists($class) || !$class::are_requirements_met()) {
$this->markTestSkipped('Could not test '.$class.'. Requirements are not met.');
$this->markTestSkipped('Could not test ' . $class . '. Requirements are not met.');
}
parent::setUp();
}
@ -62,10 +50,10 @@ abstract class cachestore_tests extends advanced_testcase {
$modes = $class::get_supported_modes();
if ($modes & cache_store::MODE_APPLICATION) {
$definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, $class, 'phpunit_test');
$instance = new $class($class.'_test', $class::unit_test_configuration());
$instance = new $class($class . '_test', $class::unit_test_configuration());
if (!$instance->is_ready()) {
$this->markTestSkipped('Could not test '.$class.'. No test instance configured for application caches.');
$this->markTestSkipped('Could not test ' . $class . '. No test instance configured for application caches.');
} else {
$instance->initialise($definition);
$this->run_tests($instance);
@ -73,10 +61,10 @@ abstract class cachestore_tests extends advanced_testcase {
}
if ($modes & cache_store::MODE_SESSION) {
$definition = cache_definition::load_adhoc(cache_store::MODE_SESSION, $class, 'phpunit_test');
$instance = new $class($class.'_test', $class::unit_test_configuration());
$instance = new $class($class . '_test', $class::unit_test_configuration());
if (!$instance->is_ready()) {
$this->markTestSkipped('Could not test '.$class.'. No test instance configured for session caches.');
$this->markTestSkipped('Could not test ' . $class . '. No test instance configured for session caches.');
} else {
$instance->initialise($definition);
$this->run_tests($instance);
@ -84,10 +72,10 @@ abstract class cachestore_tests extends advanced_testcase {
}
if ($modes & cache_store::MODE_REQUEST) {
$definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $class, 'phpunit_test');
$instance = new $class($class.'_test', $class::unit_test_configuration());
$instance = new $class($class . '_test', $class::unit_test_configuration());
if (!$instance->is_ready()) {
$this->markTestSkipped('Could not test '.$class.'. No test instance configured for request caches.');
$this->markTestSkipped('Could not test ' . $class . '. No test instance configured for request caches.');
} else {
$instance->initialise($definition);
$this->run_tests($instance);
@ -99,7 +87,7 @@ abstract class cachestore_tests extends advanced_testcase {
* Test the store for basic functionality.
*/
public function run_tests(cache_store $instance) {
$object = new stdClass;
$object = new stdClass();
$object->data = 1;
// Test set with a string.
@ -163,31 +151,31 @@ abstract class cachestore_tests extends advanced_testcase {
$this->assertFalse($instance->get('test2'));
// Test set_many.
$outcome = $instance->set_many(array(
array('key' => 'many1', 'value' => 'many1'),
array('key' => 'many2', 'value' => 'many2'),
array('key' => 'many3', 'value' => 'many3'),
array('key' => 'many4', 'value' => 'many4'),
array('key' => 'many5', 'value' => 'many5')
));
$outcome = $instance->set_many([
['key' => 'many1', 'value' => 'many1'],
['key' => 'many2', 'value' => 'many2'],
['key' => 'many3', 'value' => 'many3'],
['key' => 'many4', 'value' => 'many4'],
['key' => 'many5', 'value' => 'many5'],
]);
$this->assertSame(5, $outcome);
$this->assertSame('many1', $instance->get('many1'));
$this->assertSame('many5', $instance->get('many5'));
$this->assertFalse($instance->get('many6'));
// Test get_many.
$result = $instance->get_many(array('many1', 'many3', 'many5', 'many6'));
$result = $instance->get_many(['many1', 'many3', 'many5', 'many6']);
$this->assertIsArray($result);
$this->assertCount(4, $result);
$this->assertSame(array(
$this->assertSame([
'many1' => 'many1',
'many3' => 'many3',
'many5' => 'many5',
'many6' => false,
), $result);
], $result);
// Test delete_many.
$this->assertSame(3, $instance->delete_many(array('many2', 'many3', 'many4')));
$this->assertSame(2, $instance->delete_many(array('many1', 'many5', 'many6')));
$this->assertSame(3, $instance->delete_many(['many2', 'many3', 'many4']));
$this->assertSame(2, $instance->delete_many(['many1', 'many5', 'many6']));
}
}

View file

@ -17,14 +17,14 @@
namespace core_cache;
/**
* Unit tests for cache_store functionality.
* Unit tests for \core_cache\store functionality.
*
* @package core_cache
* @copyright 2021 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_cache\store
*/
class store_test extends \advanced_testcase {
final class store_test extends \advanced_testcase {
/**
* Tests the default implementation of cache_size_details, which does some
* complicated statistics.
@ -67,11 +67,11 @@ class store_test extends \advanced_testcase {
protected static function create_static_store(): \cachestore_static {
require_once(__DIR__ . '/../stores/static/lib.php');
$store = new \cachestore_static('frog');
$definition = \cache_definition::load('zombie', [
'mode' => \cache_store::MODE_REQUEST,
'component' => 'phpunit',
'area' => 'store_test',
'simplekeys' => true
$definition = definition::load('zombie', [
'mode' => store::MODE_REQUEST,
'component' => 'phpunit',
'area' => 'store_test',
'simplekeys' => true,
]);
$store->initialise($definition);
return $store;

View file

@ -51,40 +51,142 @@ $legacyclasses = [
\webservice_parameter_exception::class => 'exception/webservice_parameter_exception.php',
// Cache API.
\cache::class => 'cache.php',
\cache_application::class => 'application_cache.php',
\cache_definition::class => 'definition.php',
\cache_request::class => 'request_cache.php',
\cache_session::class => 'session_cache.php',
\cache_cached_object::class => 'cached_object.php',
\cache_config::class => 'config.php',
\cache_config_writer::class => 'config_writer.php',
\cache_config_disabled::class => 'disabled_config.php',
\cache_disabled::class => 'disabled_cache.php',
\config_writer::class => 'config_writer.php',
\cache_data_source::class => 'data_source_interface.php',
\cache_data_source_versionable::class => 'versionable_data_source_interface.php',
\cache_exception::class => 'exception/cache_exception.php',
\cache_factory::class => 'factory.php',
\cache_factory_disabled::class => 'disabled_factory.php',
\cache_helper::class => 'helper.php',
\cache_is_key_aware::class => 'key_aware_cache_interface.php',
\cache_is_lockable::class => 'lockable_cache_interface.php',
\cache_is_searchable::class => 'searchable_cache_interface.php',
\cache_is_configurable::class => 'configurable_cache_interface.php',
\cache_loader::class => 'loader_interface.php',
\cache_loader_with_locking::class => 'loader_with_locking_interface.php',
\cache_lock_interface::class => 'cache_lock_interface.php',
\cache_store::class => 'store.php',
\cache_store_interface::class => 'store_interface.php',
\cache_ttl_wrapper::class => 'ttl_wrapper.php',
\cacheable_object::class => 'cacheable_object_interface.php',
\cacheable_object_array::class => 'cacheable_object_array.php',
\cache_definition_mappings_form::class => 'form/cache_definition_mappings_form.php',
\cache_definition_sharing_form::class => 'form/cache_definition_sharing_form.php',
\cache_lock_form::class => 'form/cache_lock_form.php',
\cache_mode_mappings_form::class => 'form/cache_mode_mappings_form.php',
\cache::class => [
'core_cache',
'cache.php',
],
\cache_application::class => [
'core_cache',
'application_cache.php',
],
\cache_definition::class => [
'core_cache',
'definition.php',
],
\cache_request::class => [
'core_cache',
'request_cache.php',
],
\cache_session::class => [
'core_cache',
'session_cache.php',
],
\cache_cached_object::class => [
'core_cache',
'cached_object.php',
],
\cache_config::class => [
'core_cache',
'config.php',
],
\cache_config_writer::class => [
'core_cache',
'config_writer.php',
],
\cache_config_disabled::class => [
'core_cache',
'disabled_config.php',
],
\cache_disabled::class => [
'core_cache',
'disabled_cache.php',
],
\config_writer::class => [
'core_cache',
'config_writer.php',
],
\cache_data_source::class => [
'core_cache',
'data_source_interface.php',
],
\cache_data_source_versionable::class => [
'core_cache',
'versionable_data_source_interface.php',
],
\cache_exception::class => [
'core_cache',
'exception/cache_exception.php',
],
\cache_factory::class => [
'core_cache',
'factory.php',
],
\cache_factory_disabled::class => [
'core_cache',
'disabled_factory.php',
],
\cache_helper::class => [
'core_cache',
'helper.php',
],
\cache_is_key_aware::class => [
'core_cache',
'key_aware_cache_interface.php',
],
\cache_is_lockable::class => [
'core_cache',
'lockable_cache_interface.php',
],
\cache_is_searchable::class => [
'core_cache',
'searchable_cache_interface.php',
],
\cache_is_configurable::class => [
'core_cache',
'configurable_cache_interface.php',
],
\cache_loader::class => [
'core_cache',
'loader_interface.php',
],
\cache_loader_with_locking::class => [
'core_cache',
'loader_with_locking_interface.php',
],
\cache_lock_interface::class => [
'core_cache',
'cache_lock_interface.php',
],
\cache_store::class => [
'core_cache',
'store.php',
],
\cache_store_interface::class => [
'core_cache',
'store_interface.php',
],
\cache_ttl_wrapper::class => [
'core_cache',
'ttl_wrapper.php',
],
\cacheable_object::class => [
'core_cache',
'cacheable_object_interface.php',
],
\cacheable_object_array::class => [
'core_cache',
'cacheable_object_array.php',
],
\cache_definition_mappings_form::class => [
'core_cache',
'form/cache_definition_mappings_form.php',
],
\cache_definition_sharing_form::class => [
'core_cache',
'form/cache_definition_sharing_form.php',
],
\cache_lock_form::class => [
'core_cache',
'form/cache_lock_form.php',
],
\cache_mode_mappings_form::class => [
'core_cache',
'form/cache_mode_mappings_form.php',
],
\cachestore_addinstance_form::class => [
'core_cache',
'form/cachestore_addinstance_form.php',
],
// Output API.
\theme_config::class => 'output/theme_config.php',

View file

@ -313,7 +313,7 @@ if (!defined('CACHE_DISABLE_ALL')) {
}
// When set to true MUC (Moodle caching) will not use any of the defined or default stores.
// The Cache API will continue to function however this will force the use of the cachestore_dummy so all requests
// The Cache API will continue to function however this will force the use of the dummy_cachestore so all requests
// will be interacting with a static property and will never go to the proper cache stores.
// Useful if you need to avoid the stores for one reason or another.
if (!defined('CACHE_DISABLE_STORES')) {