diff options
author | 2023-07-06 15:10:30 +0200 | |
---|---|---|
committer | 2023-07-06 15:10:30 +0200 | |
commit | caac7f572cf335e96ee99f8a3af7395df471baf8 (patch) | |
tree | fec5678b9f30d84d0082e1f52764d8f67f671d36 | |
parent | f8801d8cb3d99711808a83176f767b6f6f4ec5a9 (diff) | |
download | rss-bridge-caac7f572cf335e96ee99f8a3af7395df471baf8.tar.gz rss-bridge-caac7f572cf335e96ee99f8a3af7395df471baf8.tar.zst rss-bridge-caac7f572cf335e96ee99f8a3af7395df471baf8.zip |
refacor: improve cache interface (#3492)
* fix: proper typehint on setScope
* refactor: type hint setKey()
* typehint
-rw-r--r-- | actions/DisplayAction.php | 4 | ||||
-rw-r--r-- | actions/SetBridgeCacheAction.php | 4 | ||||
-rw-r--r-- | bridges/SpotifyBridge.php | 2 | ||||
-rw-r--r-- | bridges/TwitterBridge.php | 2 | ||||
-rw-r--r-- | caches/FileCache.php | 28 | ||||
-rw-r--r-- | caches/MemcachedCache.php | 31 | ||||
-rw-r--r-- | caches/NullCache.php | 8 | ||||
-rw-r--r-- | caches/SQLiteCache.php | 31 | ||||
-rw-r--r-- | docs/07_Cache_API/01_How_to_create_a_new_cache.md | 23 | ||||
-rw-r--r-- | docs/07_Cache_API/02_CacheInterface.md | 71 | ||||
-rw-r--r-- | lib/BridgeAbstract.php | 10 | ||||
-rw-r--r-- | lib/CacheInterface.php | 60 | ||||
-rw-r--r-- | lib/contents.php | 2 |
13 files changed, 56 insertions, 220 deletions
diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php index 607ffbfd..18992842 100644 --- a/actions/DisplayAction.php +++ b/actions/DisplayAction.php @@ -91,7 +91,7 @@ class DisplayAction implements ActionInterface $cache = $cacheFactory->create(); $cache->setScope(''); - $cache->purgeCache(86400); // 24 hours + $cache->purgeCache(86400); $cache->setKey($cache_params); $items = []; @@ -215,7 +215,7 @@ class DisplayAction implements ActionInterface $cache = $cacheFactory->create(); $cache->setScope('error_reporting'); $cache->setkey([$bridgeName . '_' . $code]); - $cache->purgeCache(86400); // 24 hours + $cache->purgeCache(86400); if ($report = $cache->loadData()) { $report = Json::decode($report); $report['time'] = time(); diff --git a/actions/SetBridgeCacheAction.php b/actions/SetBridgeCacheAction.php index 324684a3..2f60fbc4 100644 --- a/actions/SetBridgeCacheAction.php +++ b/actions/SetBridgeCacheAction.php @@ -39,6 +39,10 @@ class SetBridgeCacheAction implements ActionInterface $cache = $cacheFactory->create(); $cache->setScope(get_class($bridge)); + if (!is_array($key)) { + // not sure if $key is an array when it comes in from request + $key = [$key]; + } $cache->setKey($key); $cache->saveData($value); diff --git a/bridges/SpotifyBridge.php b/bridges/SpotifyBridge.php index 2a24454b..48d225a7 100644 --- a/bridges/SpotifyBridge.php +++ b/bridges/SpotifyBridge.php @@ -196,7 +196,7 @@ class SpotifyBridge extends BridgeAbstract $cache->setScope('SpotifyBridge'); $cacheKey = sprintf('%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret')); - $cache->setKey($cacheKey); + $cache->setKey([$cacheKey]); $time = null; if ($cache->getTime()) { diff --git a/bridges/TwitterBridge.php b/bridges/TwitterBridge.php index a467f61b..9191c184 100644 --- a/bridges/TwitterBridge.php +++ b/bridges/TwitterBridge.php @@ -228,7 +228,7 @@ EOD $cache->setScope('twitter'); $cache->setKey(['cache']); - $cache->purgeCache(60 * 60 * 3); // 3h + $cache->purgeCache(60 * 60 * 3); $api = new TwitterClient($cache); $screenName = $this->getInput('u'); diff --git a/caches/FileCache.php b/caches/FileCache.php index d25a60da..bb7c1b30 100644 --- a/caches/FileCache.php +++ b/caches/FileCache.php @@ -3,8 +3,8 @@ class FileCache implements CacheInterface { private array $config; - protected $scope; - protected $key; + protected string $scope; + protected string $key; public function __construct(array $config = []) { @@ -39,13 +39,12 @@ class FileCache implements CacheInterface return $data; } - public function saveData($data) + public function saveData($data): void { $writeStream = file_put_contents($this->getCacheFile(), serialize($data)); if ($writeStream === false) { throw new \Exception('The cache path is not writeable. You probably want: chown www-data:www-data cache'); } - return $this; } public function getTime(): ?int @@ -63,7 +62,7 @@ class FileCache implements CacheInterface return null; } - public function purgeCache($seconds) + public function purgeCache(int $seconds): void { if (! $this->config['enable_purge']) { return; @@ -90,27 +89,14 @@ class FileCache implements CacheInterface } } - public function setScope($scope) + public function setScope(string $scope): void { - if (!is_string($scope)) { - throw new \Exception('The given scope is invalid!'); - } - $this->scope = $this->config['path'] . trim($scope, " \t\n\r\0\x0B\\\/") . '/'; - - return $this; } - public function setKey($key) + public function setKey(array $key): void { - $key = json_encode($key); - - if (!is_string($key)) { - throw new \Exception('The given key is invalid!'); - } - - $this->key = $key; - return $this; + $this->key = json_encode($key); } private function getScope() diff --git a/caches/MemcachedCache.php b/caches/MemcachedCache.php index 2255fe96..8cd1932b 100644 --- a/caches/MemcachedCache.php +++ b/caches/MemcachedCache.php @@ -2,8 +2,8 @@ class MemcachedCache implements CacheInterface { - private $scope; - private $key; + private string $scope; + private string $key; private $conn; private $expiration = 0; private $time = null; @@ -58,11 +58,11 @@ class MemcachedCache implements CacheInterface return $result['data']; } - public function saveData($datas) + public function saveData($data): void { $time = time(); $object_to_save = [ - 'data' => $datas, + 'data' => $data, 'time' => $time, ]; $result = $this->conn->set($this->getCacheKey(), $object_to_save, $this->expiration); @@ -72,8 +72,6 @@ class MemcachedCache implements CacheInterface } $this->time = $time; - - return $this; } public function getTime(): ?int @@ -84,32 +82,21 @@ class MemcachedCache implements CacheInterface return $this->time; } - public function purgeCache($duration) + public function purgeCache(int $seconds): void { // Note: does not purges cache right now // Just sets cache expiration and leave cache purging for memcached itself - $this->expiration = $duration; + $this->expiration = $seconds; } - public function setScope($scope) + public function setScope(string $scope): void { $this->scope = $scope; - return $this; } - public function setKey($key) + public function setKey(array $key): void { - if (!empty($key) && is_array($key)) { - $key = array_map('strtolower', $key); - } - $key = json_encode($key); - - if (!is_string($key)) { - throw new \Exception('The given key is invalid!'); - } - - $this->key = $key; - return $this; + $this->key = json_encode($key); } private function getCacheKey() diff --git a/caches/NullCache.php b/caches/NullCache.php index 63917b4f..1a01df2f 100644 --- a/caches/NullCache.php +++ b/caches/NullCache.php @@ -4,11 +4,11 @@ declare(strict_types=1); class NullCache implements CacheInterface { - public function setScope($scope) + public function setScope(string $scope): void { } - public function setKey($key) + public function setKey(array $key): void { } @@ -16,7 +16,7 @@ class NullCache implements CacheInterface { } - public function saveData($data) + public function saveData($data): void { } @@ -25,7 +25,7 @@ class NullCache implements CacheInterface return null; } - public function purgeCache($seconds) + public function purgeCache(int $seconds): void { } } diff --git a/caches/SQLiteCache.php b/caches/SQLiteCache.php index ae531cb6..f8a36ba3 100644 --- a/caches/SQLiteCache.php +++ b/caches/SQLiteCache.php @@ -5,8 +5,8 @@ */ class SQLiteCache implements CacheInterface { - protected $scope; - protected $key; + protected string $scope; + protected string $key; private $db = null; @@ -59,15 +59,13 @@ class SQLiteCache implements CacheInterface return null; } - public function saveData($data) + public function saveData($data): void { $Qupdate = $this->db->prepare('INSERT OR REPLACE INTO storage (key, value, updated) VALUES (:key, :value, :updated)'); $Qupdate->bindValue(':key', $this->getCacheKey()); $Qupdate->bindValue(':value', serialize($data)); $Qupdate->bindValue(':updated', time()); $Qupdate->execute(); - - return $this; } public function getTime(): ?int @@ -85,36 +83,21 @@ class SQLiteCache implements CacheInterface return null; } - public function purgeCache($seconds) + public function purgeCache(int $seconds): void { $Qdelete = $this->db->prepare('DELETE FROM storage WHERE updated < :expired'); $Qdelete->bindValue(':expired', time() - $seconds); $Qdelete->execute(); } - public function setScope($scope) + public function setScope(string $scope): void { - if (is_null($scope) || !is_string($scope)) { - throw new \Exception('The given scope is invalid!'); - } - $this->scope = $scope; - return $this; } - public function setKey($key) + public function setKey(array $key): void { - if (!empty($key) && is_array($key)) { - $key = array_map('strtolower', $key); - } - $key = json_encode($key); - - if (!is_string($key)) { - throw new \Exception('The given key is invalid!'); - } - - $this->key = $key; - return $this; + $this->key = json_encode($key); } private function getCacheKey() diff --git a/docs/07_Cache_API/01_How_to_create_a_new_cache.md b/docs/07_Cache_API/01_How_to_create_a_new_cache.md index fe171718..cfc30308 100644 --- a/docs/07_Cache_API/01_How_to_create_a_new_cache.md +++ b/docs/07_Cache_API/01_How_to_create_a_new_cache.md @@ -1,24 +1,3 @@ Create a new file in the `caches/` folder (see [Folder structure](../04_For_Developers/03_Folder_structure.md)). -The file must be named according to following specification: - -* It starts with the type -* The file name must end with 'Cache' -* The file type must be PHP, written in small letters (seriously!) ".php" - -**Examples:** - -Type | Filename ------|--------- -File | FileCache.php -MySQL | MySQLCache.php - -The file must start with the PHP tags and end with an empty line. The closing tag `?>` is [omitted](http://php.net/basic-syntax.instruction-separation). - -Example: - -```PHP -<?PHP - // PHP code here -// This line is empty (just imagine it!) -```
\ No newline at end of file +See `NullCache` and `SQLiteCache` for examples.
\ No newline at end of file diff --git a/docs/07_Cache_API/02_CacheInterface.md b/docs/07_Cache_API/02_CacheInterface.md index bc343ff1..61127a0d 100644 --- a/docs/07_Cache_API/02_CacheInterface.md +++ b/docs/07_Cache_API/02_CacheInterface.md @@ -1,67 +1,18 @@ -The `CacheInterface` interface defines functions that need to be implemented. To create a new cache that implements `CacheInterface` you must implement following functions: +See `CacheInterface`. -* [loadData](#the-loaddata-function) -* [saveData](#the-savedata-function) -* [getTime](#the-gettime-function) -* [purgeCache](#the-purgecache-function) +```php +interface CacheInterface +{ + public function setScope(string $scope): void; -Find a [template](#template) at the end of this file. + public function setKey(array $key): void; -# Functions + public function loadData(); -## The `loadData` function + public function saveData($data): void; -This function loads data from the cache and returns the data in the same format provided to the [saveData](#the-savedata-function) function. + public function getTime(): ?int; -```PHP -loadData(): mixed -``` - -## The `saveData` function - -This function stores the given data into the cache and returns the object instance. - -```PHP -saveData(mixed $data): self -``` - -## The `getTime` function - -## The `purgeCache` function - -This function removes any data from the cache that is not within the given duration. The duration is specified in seconds and defines the period between now and the oldest item to keep. - -```PHP -purgeCache(int $duration): null -``` - -# Template - -This is the bare minimum template for a new cache: - -```PHP -<?php -class MyTypeCache implements CacheInterface { - public function loadData(){ - // Implement your algorithm here! - return null; - } - - public function saveData($data){ - // Implement your algorithm here! - - return $this; - } - - public function getTime(){ - // Implement your algorithm here! - - return false; - } - - public function purgeCache($duration){ - // Implement your algorithm here! - } + public function purgeCache(int $seconds): void; } -// Imaginary empty line! -``` +```
\ No newline at end of file diff --git a/lib/BridgeAbstract.php b/lib/BridgeAbstract.php index 537e76df..21206a7b 100644 --- a/lib/BridgeAbstract.php +++ b/lib/BridgeAbstract.php @@ -410,11 +410,10 @@ abstract class BridgeAbstract implements BridgeInterface /** * Loads a cached value for the specified key * - * @param string $key Key name * @param int $duration Cache duration (optional) * @return mixed Cached value or null if the key doesn't exist or has expired */ - protected function loadCacheValue($key, $duration = null) + protected function loadCacheValue(string $key, $duration = null) { $cacheFactory = new CacheFactory(); @@ -422,7 +421,7 @@ abstract class BridgeAbstract implements BridgeInterface // Create class name without the namespace part $scope = $this->getShortName(); $cache->setScope($scope); - $cache->setKey($key); + $cache->setKey([$key]); $timestamp = $cache->getTime(); if ( @@ -438,17 +437,16 @@ abstract class BridgeAbstract implements BridgeInterface /** * Stores a value to cache with the specified key * - * @param string $key Key name * @param mixed $value Value to cache */ - protected function saveCacheValue($key, $value) + protected function saveCacheValue(string $key, $value) { $cacheFactory = new CacheFactory(); $cache = $cacheFactory->create(); $scope = $this->getShortName(); $cache->setScope($scope); - $cache->setKey($key); + $cache->setKey([$key]); $cache->saveData($value); } diff --git a/lib/CacheInterface.php b/lib/CacheInterface.php index b332e21b..414a9c84 100644 --- a/lib/CacheInterface.php +++ b/lib/CacheInterface.php @@ -1,68 +1,16 @@ <?php -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * The cache interface - */ interface CacheInterface { - /** - * Set scope of the current cache - * - * If $scope is an empty string, the cache is set to a global context. - * - * @param string $scope The scope the data is related to - */ - public function setScope($scope); + public function setScope(string $scope): void; - /** - * Set key to assign the current data - * - * Since $key can be anything, the cache implementation must ensure to - * assign the related data reliably; most commonly by serializing and - * hashing the key in an appropriate way. - * - * @param array $key The key the data is related to - */ - public function setKey($key); + public function setKey(array $key): void; - /** - * Loads data from cache - * - * @return mixed The cached data or null - */ public function loadData(); - /** - * Stores data to the cache - * - * @param mixed $data The data to store - * @return self The cache object - */ - public function saveData($data); + public function saveData($data): void; - /** - * Returns the modification time of the current cache item. - * In unix timestamp. - * Example: 1688570578 - */ public function getTime(): ?int; - /** - * Removes any data that is older than the specified age from cache - * - * @param int $seconds The cache age in seconds - */ - public function purgeCache($seconds); + public function purgeCache(int $seconds): void; } diff --git a/lib/contents.php b/lib/contents.php index 568d5b92..20e30025 100644 --- a/lib/contents.php +++ b/lib/contents.php @@ -103,7 +103,7 @@ function getContents( $cache = $cacheFactory->create(); $cache->setScope('server'); - $cache->purgeCache(86400); // 24 hours (forced) + $cache->purgeCache(86400); $cache->setKey([$url]); // Snagged from https://github.com/lwthiker/curl-impersonate/blob/main/firefox/curl_ff102 |