diff --git a/cache/classes/factory.php b/cache/classes/factory.php index c23a147c6a8..f3d520c51af 100644 --- a/cache/classes/factory.php +++ b/cache/classes/factory.php @@ -263,7 +263,13 @@ class cache_factory { if (!$store->is_ready() || !$store->is_supported_mode($definition->get_mode())) { return false; } - $store = clone($this->stores[$name]); + // We always create a clone of the original store. + // If we were to clone a store that had already been initialised with a definition then + // we'd run into a myriad of issues. + // We use a method of the store to create a clone rather than just creating it ourselves + // so that if any store out there doesn't handle cloning they can override this method in + // order to address the issues. + $store = $this->stores[$name]->create_clone($details); $store->initialise($definition); return $store; } diff --git a/cache/classes/store.php b/cache/classes/store.php index 4130b590f25..5bb26e4d4fd 100644 --- a/cache/classes/store.php +++ b/cache/classes/store.php @@ -306,4 +306,22 @@ abstract class cache_store implements cache_store_interface { public function supports_native_ttl() { return $this::get_supported_features() & self::SUPPORTS_NATIVE_TTL; } + + /** + * Creates a clone of this store instance ready to be initialised. + * + * This method is used so that a cache store needs only be constructed once. + * Future requests for an instance of the store will be given a cloned instance. + * + * If you are writing a cache store that isn't compatible with the clone operation + * 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 + */ + public function create_clone(array $details = array()) { + // 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); + } }