|
|
|
@@ -5985,10 +5985,9 @@ class navigation_json {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The cache class used by global navigation and settings navigation.
|
|
|
|
|
* The navigation_cache class is used for global and settings navigation data.
|
|
|
|
|
*
|
|
|
|
|
* It is basically an easy access point to session with a bit of smarts to make
|
|
|
|
|
* sure that the information that is cached is valid still.
|
|
|
|
|
* It provides an easy access to the session cache with TTL of 1800 seconds.
|
|
|
|
|
*
|
|
|
|
|
* Example use:
|
|
|
|
|
* <code php>
|
|
|
|
@@ -6005,173 +6004,142 @@ class navigation_json {
|
|
|
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
|
|
*/
|
|
|
|
|
class navigation_cache {
|
|
|
|
|
/** @var int represents the time created */
|
|
|
|
|
protected $creation;
|
|
|
|
|
/** @var array An array of session keys */
|
|
|
|
|
protected $session;
|
|
|
|
|
/** @var cache_session The session cache instance */
|
|
|
|
|
protected $cache;
|
|
|
|
|
/** @var array The current cache area data */
|
|
|
|
|
protected $session = [];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The string to use to segregate this particular cache. It can either be
|
|
|
|
|
* unique to start a fresh cache or if you want to share a cache then make
|
|
|
|
|
* it the string used in the original cache.
|
|
|
|
|
* @var string
|
|
|
|
|
* @var string A unique string to segregate this particular cache.
|
|
|
|
|
* It can either be unique to start a fresh cache or shared to use an existing cache.
|
|
|
|
|
*/
|
|
|
|
|
protected $area;
|
|
|
|
|
/** @var int a time that the information will time out */
|
|
|
|
|
protected $timeout;
|
|
|
|
|
/** @var stdClass The current context */
|
|
|
|
|
protected $currentcontext;
|
|
|
|
|
/** @var int cache time information */
|
|
|
|
|
#[\core\attribute\deprecated(null, since: '4.5', reason: 'This constant is no longer needed.', mdl: 'MDL-79628')]
|
|
|
|
|
const CACHETIME = 0;
|
|
|
|
|
/** @var int cache user id */
|
|
|
|
|
#[\core\attribute\deprecated(null, since: '4.5', reason: 'This constant is no longer needed.', mdl: 'MDL-79628')]
|
|
|
|
|
const CACHEUSERID = 1;
|
|
|
|
|
/** @var int cache value */
|
|
|
|
|
const CACHEVALUE = 2;
|
|
|
|
|
/** @var null|array An array of navigation cache areas to expire on shutdown */
|
|
|
|
|
public static $volatilecaches;
|
|
|
|
|
/** @var null|array An array of cache areas to expire on shutdown */
|
|
|
|
|
public static $volatilecaches = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Contructor for the cache. Requires two arguments
|
|
|
|
|
* Contructor for the cache. Requires a area string be passed in.
|
|
|
|
|
*
|
|
|
|
|
* @param string $area The string to use to segregate this particular cache
|
|
|
|
|
* it can either be unique to start a fresh cache or if you want
|
|
|
|
|
* to share a cache then make it the string used in the original
|
|
|
|
|
* cache
|
|
|
|
|
* @param string $area The unique string to segregate this particular cache.
|
|
|
|
|
* @param int $timeout The number of seconds to time the information out after
|
|
|
|
|
*/
|
|
|
|
|
public function __construct($area, $timeout=1800) {
|
|
|
|
|
$this->creation = time();
|
|
|
|
|
$this->area = $area;
|
|
|
|
|
$this->timeout = time() - $timeout;
|
|
|
|
|
if (rand(0,100) === 0) {
|
|
|
|
|
$this->garbage_collection();
|
|
|
|
|
public function __construct($area, $timeout = null) {
|
|
|
|
|
if ($timeout !== null) {
|
|
|
|
|
debugging(
|
|
|
|
|
'The timeout argument has been deprecated. Please remove it from your method calls.',
|
|
|
|
|
DEBUG_DEVELOPER,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
global $USER;
|
|
|
|
|
$this->area = "user_{$USER->id}_{$area}";
|
|
|
|
|
$this->cache = cache::make('core', 'navigation_cache');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Used to set up the cache within the SESSION.
|
|
|
|
|
* Ensure the navigation cache is initialised
|
|
|
|
|
*
|
|
|
|
|
* This is called for each access and ensure that we don't put anything into the session before
|
|
|
|
|
* it is required.
|
|
|
|
|
* This is called for each access and ensures that no data is put into the cache before it is required.
|
|
|
|
|
*/
|
|
|
|
|
protected function ensure_session_cache_initialised() {
|
|
|
|
|
global $SESSION;
|
|
|
|
|
protected function ensure_navigation_cache_initialised() {
|
|
|
|
|
if (empty($this->session)) {
|
|
|
|
|
if (!isset($SESSION->navcache)) {
|
|
|
|
|
$SESSION->navcache = new stdClass;
|
|
|
|
|
$this->session = $this->cache->get($this->area);
|
|
|
|
|
if (!is_array($this->session)) {
|
|
|
|
|
$this->session = [];
|
|
|
|
|
}
|
|
|
|
|
if (!isset($SESSION->navcache->{$this->area})) {
|
|
|
|
|
$SESSION->navcache->{$this->area} = array();
|
|
|
|
|
}
|
|
|
|
|
$this->session = &$SESSION->navcache->{$this->area}; // pointer to array, =& is correct here
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Magic Method to retrieve something by simply calling using = cache->key
|
|
|
|
|
* Magic Method to retrieve a cached item by simply calling using = cache->key
|
|
|
|
|
*
|
|
|
|
|
* @param mixed $key The identifier for the information you want out again
|
|
|
|
|
* @return void|mixed Either void or what ever was put in
|
|
|
|
|
* @param mixed $key The identifier for the cached information
|
|
|
|
|
* @return mixed|void The cached information or void if not found
|
|
|
|
|
*/
|
|
|
|
|
public function __get($key) {
|
|
|
|
|
if (!$this->cached($key)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$information = $this->session[$key][self::CACHEVALUE];
|
|
|
|
|
return unserialize($information);
|
|
|
|
|
return unserialize($this->session[$key][self::CACHEVALUE]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Magic method that simply uses {@link set();} to store something in the cache
|
|
|
|
|
* Magic method that simply uses {@see navigation_cache::set()} to store an item in the cache
|
|
|
|
|
*
|
|
|
|
|
* @param string|int $key
|
|
|
|
|
* @param mixed $information
|
|
|
|
|
* @param string|int $key The key to store the information against
|
|
|
|
|
* @param mixed $information The information to cache
|
|
|
|
|
*/
|
|
|
|
|
public function __set($key, $information) {
|
|
|
|
|
$this->set($key, $information);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets some information against the cache (session) for later retrieval
|
|
|
|
|
* Sets some information in the session cache for later retrieval
|
|
|
|
|
*
|
|
|
|
|
* @param string|int $key
|
|
|
|
|
* @param mixed $information
|
|
|
|
|
*/
|
|
|
|
|
public function set($key, $information) {
|
|
|
|
|
global $USER;
|
|
|
|
|
$this->ensure_session_cache_initialised();
|
|
|
|
|
$this->ensure_navigation_cache_initialised();
|
|
|
|
|
$information = serialize($information);
|
|
|
|
|
$this->session[$key]= array(self::CACHETIME=>time(), self::CACHEUSERID=>$USER->id, self::CACHEVALUE=>$information);
|
|
|
|
|
$this->session[$key] = [self::CACHEVALUE => $information];
|
|
|
|
|
$this->cache->set($this->area, $this->session);
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Check the existence of the identifier in the cache
|
|
|
|
|
*
|
|
|
|
|
* @param string|int $key
|
|
|
|
|
* @return bool
|
|
|
|
|
* @param string|int $key The identifier to check
|
|
|
|
|
* @return bool True if the item exists in the cache, false otherwise
|
|
|
|
|
*/
|
|
|
|
|
public function cached($key) {
|
|
|
|
|
global $USER;
|
|
|
|
|
$this->ensure_session_cache_initialised();
|
|
|
|
|
if (!array_key_exists($key, $this->session) || !is_array($this->session[$key]) || $this->session[$key][self::CACHEUSERID]!=$USER->id || $this->session[$key][self::CACHETIME] < $this->timeout) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
$this->ensure_navigation_cache_initialised();
|
|
|
|
|
return isset($this->session[$key]) &&
|
|
|
|
|
is_array($this->session[$key]);
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Compare something to it's equivilant in the cache
|
|
|
|
|
*
|
|
|
|
|
* @param string $key
|
|
|
|
|
* @param mixed $value
|
|
|
|
|
* @param string $key The key to check
|
|
|
|
|
* @param mixed $value The value to compare
|
|
|
|
|
* @param bool $serialise Whether to serialise the value before comparison
|
|
|
|
|
* this should only be set to false if the value is already
|
|
|
|
|
* serialised
|
|
|
|
|
* @return bool If the value is the same false if it is not set or doesn't match
|
|
|
|
|
* @return bool True if the value is the same as the cached one, false otherwise
|
|
|
|
|
*/
|
|
|
|
|
public function compare($key, $value, $serialise = true) {
|
|
|
|
|
if ($this->cached($key)) {
|
|
|
|
|
if ($serialise) {
|
|
|
|
|
$value = serialize($value);
|
|
|
|
|
}
|
|
|
|
|
if ($this->session[$key][self::CACHEVALUE] === $value) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return $this->session[$key][self::CACHEVALUE] === $value;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Wipes the entire cache, good to force regeneration
|
|
|
|
|
* Deletes the entire cache area, forcing a fresh cache to be created
|
|
|
|
|
*/
|
|
|
|
|
public function clear() {
|
|
|
|
|
global $SESSION;
|
|
|
|
|
unset($SESSION->navcache);
|
|
|
|
|
$this->session = null;
|
|
|
|
|
$this->cache->delete($this->area);
|
|
|
|
|
$this->session = [];
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Checks all cache entries and removes any that have expired, good ole cleanup
|
|
|
|
|
*/
|
|
|
|
|
protected function garbage_collection() {
|
|
|
|
|
if (empty($this->session)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
foreach ($this->session as $key=>$cachedinfo) {
|
|
|
|
|
if (is_array($cachedinfo) && $cachedinfo[self::CACHETIME]<$this->timeout) {
|
|
|
|
|
unset($this->session[$key]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Marks the cache as being volatile (likely to change)
|
|
|
|
|
* Marks the cache as volatile (likely to change)
|
|
|
|
|
*
|
|
|
|
|
* Any caches marked as volatile will be destroyed at the on shutdown by
|
|
|
|
|
* {@link navigation_node::destroy_volatile_caches()} which is registered
|
|
|
|
|
* as a shutdown function if any caches are marked as volatile.
|
|
|
|
|
* Any caches marked as volatile will be destroyed on shutdown by {@see navigation_node::destroy_volatile_caches()}
|
|
|
|
|
*
|
|
|
|
|
* @param bool $setting True to destroy the cache false not too
|
|
|
|
|
* @param bool $setting True to mark the cache as volatile, false to remove the volatile flag
|
|
|
|
|
*/
|
|
|
|
|
public function volatile($setting = true) {
|
|
|
|
|
if (self::$volatilecaches===null) {
|
|
|
|
|
self::$volatilecaches = array();
|
|
|
|
|
core_shutdown_manager::register_function(array('navigation_cache','destroy_volatile_caches'));
|
|
|
|
|
if (self::$volatilecaches === null) {
|
|
|
|
|
self::$volatilecaches = [];
|
|
|
|
|
core_shutdown_manager::register_function(['navigation_cache', 'destroy_volatile_caches']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($setting) {
|
|
|
|
@@ -6184,19 +6152,16 @@ class navigation_cache {
|
|
|
|
|
/**
|
|
|
|
|
* Destroys all caches marked as volatile
|
|
|
|
|
*
|
|
|
|
|
* This function is static and works in conjunction with the static volatilecaches
|
|
|
|
|
* property of navigation cache.
|
|
|
|
|
* Because this function is static it manually resets the cached areas back to an
|
|
|
|
|
* empty array.
|
|
|
|
|
* This function is static and works with the static volatilecaches property of navigation cache.
|
|
|
|
|
* It manually resets the cached areas back to an empty array.
|
|
|
|
|
*/
|
|
|
|
|
public static function destroy_volatile_caches() {
|
|
|
|
|
global $SESSION;
|
|
|
|
|
if (is_array(self::$volatilecaches) && count(self::$volatilecaches)>0) {
|
|
|
|
|
if (is_array(self::$volatilecaches) && count(self::$volatilecaches) > 0) {
|
|
|
|
|
$cache = cache::make('core', 'navigation_cache');
|
|
|
|
|
foreach (self::$volatilecaches as $area) {
|
|
|
|
|
$SESSION->navcache->{$area} = array();
|
|
|
|
|
$cache->delete($area);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$SESSION->navcache = new stdClass;
|
|
|
|
|
self::$volatilecaches = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|