diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php index a632b8de7687..9e1377a03aae 100644 --- a/system/Cache/CacheInterface.php +++ b/system/Cache/CacheInterface.php @@ -108,7 +108,10 @@ public function getCacheInfo(); * * @param string $key Cache item name. * - * @return mixed + * @return array|false|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). + * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key); diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php index d184d19f0dd4..4791b3f06a1b 100644 --- a/system/Cache/Handlers/FileHandler.php +++ b/system/Cache/Handlers/FileHandler.php @@ -282,7 +282,10 @@ public function getCacheInfo() * * @param string $key Cache item name. * - * @return mixed + * @return array|false|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). + * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key) { @@ -290,28 +293,36 @@ public function getMetaData(string $key) if (! is_file($this->path . $key)) { - return false; + return false; // This will return null in a future release } $data = @unserialize(file_get_contents($this->path . $key)); - if (is_array($data)) + if (! is_array($data) || ! isset($data['ttl'])) { - $mtime = filemtime($this->path . $key); + return false; // This will return null in a future release + } - if (! isset($data['ttl'])) + // Consider expired items as missing + $expire = $data['time'] + $data['ttl']; + + // @phpstan-ignore-next-line + if ($data['ttl'] > 0 && time() > $expire) + { + // If the file is still there then remove it + if (is_file($this->path . $key)) { - return false; + unlink($this->path . $key); } - return [ - 'expire' => $mtime + $data['ttl'], - 'mtime' => $mtime, - 'data' => $data['data'], - ]; + return false; // This will return null in a future release } - return false; + return [ + 'expire' => $expire, + 'mtime' => filemtime($this->path . $key), + 'data' => $data['data'], + ]; } //-------------------------------------------------------------------- diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index 8758b01423cc..e9a1b919e38b 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -342,7 +342,10 @@ public function getCacheInfo() * * @param string $key Cache item name. * - * @return mixed + * @return array|false|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). + * Some handlers may return false when an item does not exist, which is deprecated. */ public function getMetaData(string $key) { @@ -353,13 +356,16 @@ public function getMetaData(string $key) // if not an array, don't try to count for PHP7.2 if (! is_array($stored) || count($stored) !== 3) { - return false; + return false; // This will return null in a future release } - list($data, $time, $ttl) = $stored; + list($data, $time, $limit) = $stored; + + // Calculate the remaining time to live from the original limit + $ttl = time() - $time - $limit; return [ - 'expire' => $time + $ttl, + 'expire' => $limit > 0 ? $time + $limit : null, 'mtime' => $time, 'data' => $data, ]; diff --git a/system/Cache/Handlers/PredisHandler.php b/system/Cache/Handlers/PredisHandler.php index 5b932733cc88..22c77af27eeb 100644 --- a/system/Cache/Handlers/PredisHandler.php +++ b/system/Cache/Handlers/PredisHandler.php @@ -271,7 +271,9 @@ public function getCacheInfo() * * @param string $key Cache item name. * - * @return mixed + * @return array|false|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). */ public function getMetaData(string $key) { @@ -280,8 +282,10 @@ public function getMetaData(string $key) if (isset($data['__ci_value']) && $data['__ci_value'] !== false) { $time = time(); + $ttl = $this->redis->ttl($key); + return [ - 'expire' => $time + $this->redis->ttl($key), + 'expire' => $ttl > 0 ? time() + $ttl : null, 'mtime' => $time, 'data' => $data['__ci_value'], ]; diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php index d5fad5b86ce8..29c6a6fa8905 100644 --- a/system/Cache/Handlers/RedisHandler.php +++ b/system/Cache/Handlers/RedisHandler.php @@ -317,7 +317,9 @@ public function getCacheInfo() * * @param string $key Cache item name. * - * @return mixed + * @return array|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). */ public function getMetaData(string $key) { @@ -328,8 +330,10 @@ public function getMetaData(string $key) if ($value !== null) { $time = time(); + $ttl = $this->redis->ttl($key); + return [ - 'expire' => $time + $this->redis->ttl($key), + 'expire' => $ttl > 0 ? time() + $ttl : null, 'mtime' => $time, 'data' => $value, ]; diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php index f6ca9d8d5d40..f925a6ea4f6f 100644 --- a/system/Cache/Handlers/WincacheHandler.php +++ b/system/Cache/Handlers/WincacheHandler.php @@ -71,7 +71,7 @@ public function get(string $key) $data = wincache_ucache_get($key, $success); // Success returned by reference from wincache_ucache_get() - return ($success) ? $data : null; + return $success ? $data : null; } //-------------------------------------------------------------------- @@ -147,7 +147,7 @@ public function increment(string $key, int $offset = 1) $success = false; $value = wincache_ucache_inc($key, $offset, $success); - return ($success === true) ? $value : false; // @phpstan-ignore-line + return $success ? $value : false; // @phpstan-ignore-line } //-------------------------------------------------------------------- @@ -169,7 +169,7 @@ public function decrement(string $key, int $offset = 1) $success = false; $value = wincache_ucache_dec($key, $offset, $success); - return ($success === true) ? $value : false; // @phpstan-ignore-line + return $success ? $value : false; // @phpstan-ignore-line } //-------------------------------------------------------------------- @@ -210,7 +210,10 @@ public function getCacheInfo() * * @param string $key Cache item name. * - * @return mixed + * @return array|false|null + * Returns null if the item does not exist, otherwise array + * with at least the 'expires' key for absolute epoch expiry (or null). + * Some handlers may return false when an item does not exist, which is deprecated. * * @codeCoverageIgnore */ @@ -225,14 +228,14 @@ public function getMetaData(string $key) $hitcount = $stored['ucache_entries'][1]['hitcount']; return [ - 'expire' => $ttl - $age, + 'expire' => $ttl > 0 ? time() + $ttl : null, 'hitcount' => $hitcount, 'age' => $age, 'ttl' => $ttl, ]; } - return false; + return false; // This will return null in a future release } //-------------------------------------------------------------------- diff --git a/user_guide_src/source/changelogs/v4.1.2.rst b/user_guide_src/source/changelogs/v4.1.2.rst index e1fd16d01a11..be2004a0ef12 100644 --- a/user_guide_src/source/changelogs/v4.1.2.rst +++ b/user_guide_src/source/changelogs/v4.1.2.rst @@ -26,6 +26,7 @@ Changes: - ``Entity::mutateDate`` uses external cast handler ``DatetimeCast::get``. - In order for ``Config\**`` classes to get their respective properties' values from the ``.env``, it is now necessary to namespace the property with the name of the class. Previously, the property names are enough but now disallowed because it can get system environment variables, like ``PATH``. - The array helper ``_array_search_dot`` is now marked for ``@internal`` use. As this is used by ``dot_array_search``, users should not use ``_array_search_dot`` directly in their code. +- ``CacheInterface::getMetaData()`` returns ``null`` for misses, or an array with at least the "expires" key set to the absolute epoch expiration, or ``null`` for "never expires". The File, Memcached, and Wincache Handlers still return ``false`` which will become ``null`` in a future release. Deprecations: diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst index c3f7720d31bc..9a9f22eb0471 100644 --- a/user_guide_src/source/libraries/caching.rst +++ b/user_guide_src/source/libraries/caching.rst @@ -216,8 +216,8 @@ Class Reference .. php:method:: getMetadata(string $key) :param string $key: Cache item name - :returns: Metadata for the cached item - :rtype: mixed + :returns: Metadata for the cached item. ``null`` for missing items, or an array with at least the "expire" key for absolute epoch expiry (``null`` for never expires). + :rtype: array|null This method will return detailed information on a specific item in the cache. @@ -227,7 +227,8 @@ Class Reference var_dump($cache->getMetadata('my_cached_item')); .. note:: The information returned and the structure of the data is dependent - on which adapter is being used. + on which adapter is being used. Some adapters (File, Memcached, Wincache) + still return ``false`` for missing items. ******* Drivers