From e5184cac0eff6e2cea7eead6749db81067aab095 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Thu, 2 May 2013 09:56:30 +1200 Subject: [PATCH] MDL-39456 cachestore_file: added reference to global $CFG By holding onto a reference of the global $CFG object we can be sure that it isn't destroyed before we are done with it. This allows for caches to be used within destructors for purposes such as delayed writes. --- cache/stores/file/lib.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/cache/stores/file/lib.php b/cache/stores/file/lib.php index 607a4d22d93..455665817eb 100644 --- a/cache/stores/file/lib.php +++ b/cache/stores/file/lib.php @@ -101,6 +101,19 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i */ protected $definition; + /** + * A reference to the global $CFG object. + * + * You may be asking yourself why on earth this is here, but there is a good reason. + * By holding onto a reference of the $CFG object we can be absolutely sure that it won't be destroyed before + * we are done with it. + * This makes it possible to use a cache within a destructor method for the purposes of + * delayed writes. Like how the session mechanisms work. + * + * @var stdClass + */ + private $cfg = null; + /** * Constructs the store instance. * @@ -111,6 +124,13 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i * @param array $configuration */ public function __construct($name, array $configuration = array()) { + global $CFG; + + if (isset($CFG)) { + // Hold onto a reference of the global $CFG object. + $this->cfg = $CFG; + } + $this->name = $name; if (array_key_exists('path', $configuration) && $configuration['path'] !== '') { $this->custompath = true; @@ -605,13 +625,27 @@ class cachestore_file extends cache_store implements cache_is_key_aware, cache_i * @throws coding_exception */ protected function ensure_path_exists() { + global $CFG; if (!is_writable($this->path)) { if ($this->custompath && !$this->autocreate) { throw new coding_exception('File store path does not exist. It must exist and be writable by the web server.'); } + $createdcfg = false; + if (!isset($CFG)) { + // This can only happen during destruction of objects. + // A cache is being used within a destructor, php is ending a request and $CFG has + // already being cleaned up. + // Rebuild $CFG with directory permissions just to complete this write. + $CFG = $this->cfg; + $createdcfg = true; + } if (!make_writable_directory($this->path, false)) { throw new coding_exception('File store path does not exist and can not be created.'); } + if ($createdcfg) { + // We re-created it so we'll clean it up. + unset($CFG); + } } return true; }