mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-22 01:25:28 +03:00
refacor: improve cache interface (#3492)
* fix: proper typehint on setScope * refactor: type hint setKey() * typehint
This commit is contained in:
parent
f8801d8cb3
commit
caac7f572c
13 changed files with 56 additions and 220 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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!)
|
||||
```
|
||||
See `NullCache` and `SQLiteCache` for examples.
|
|
@ -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!
|
||||
}
|
||||
}
|
||||
// Imaginary empty line!
|
||||
public function purgeCache(int $seconds): void;
|
||||
}
|
||||
```
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue