feat: add config option "path" for file cache (#3297)

This commit is contained in:
Dag 2023-03-20 19:10:01 +01:00 committed by GitHub
parent 4e616c7092
commit 9e9a697b8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 27 deletions

View File

@ -186,6 +186,9 @@ class PixivBridge extends BridgeAbstract
}
}
/**
* todo: remove manual file cache
*/
private function cacheImage($url, $illustId, $isImage)
{
$illustId = preg_replace('/[^0-9]/', '', $illustId);

View File

@ -3,14 +3,18 @@
class FileCache implements CacheInterface
{
private array $config;
protected $path;
protected $scope;
protected $key;
public function __construct(array $config = [])
{
$this->config = $config;
if (!is_writable(PATH_CACHE)) {
throw new \Exception('The cache folder is not writeable');
if (!is_dir($this->config['path'])) {
throw new \Exception('The cache path does not exists. You probably want: mkdir cache && chown www-data:www-data cache');
}
if (!is_writable($this->config['path'])) {
throw new \Exception('The cache path is not writeable. You probably want: chown www-data:www-data cache');
}
}
@ -26,7 +30,7 @@ class FileCache implements CacheInterface
{
$writeStream = file_put_contents($this->getCacheFile(), serialize($data));
if ($writeStream === false) {
throw new \Exception('Cannot write the cache... Do you have the right permissions ?');
throw new \Exception('The cache path is not writeable. You probably want: chown www-data:www-data cache');
}
return $this;
}
@ -52,7 +56,7 @@ class FileCache implements CacheInterface
return;
}
$cachePath = $this->getPath();
$cachePath = $this->getScope();
if (!file_exists($cachePath)) {
return;
}
@ -79,7 +83,7 @@ class FileCache implements CacheInterface
throw new \Exception('The given scope is invalid!');
}
$this->path = PATH_CACHE . trim($scope, " \t\n\r\0\x0B\\\/") . '/';
$this->scope = $this->config['path'] . trim($scope, " \t\n\r\0\x0B\\\/") . '/';
return $this;
}
@ -96,24 +100,24 @@ class FileCache implements CacheInterface
return $this;
}
private function getPath()
private function getScope()
{
if (is_null($this->path)) {
if (is_null($this->scope)) {
throw new \Exception('Call "setScope" first!');
}
if (!is_dir($this->path)) {
if (mkdir($this->path, 0755, true) !== true) {
if (!is_dir($this->scope)) {
if (mkdir($this->scope, 0755, true) !== true) {
throw new \Exception('mkdir: Unable to create file cache folder');
}
}
return $this->path;
return $this->scope;
}
private function getCacheFile()
{
return $this->getPath() . $this->getCacheName();
return $this->getScope() . $this->getCacheName();
}
private function getCacheName()

View File

@ -96,6 +96,9 @@ report_limit = 1
; --- Cache specific configuration ---------------------------------------------
[FileCache]
; The root folder to store files in.
; "" = Use the cache folder in the repository (default)
path = ""
; Whether to actually delete files when purging. Can be useful to turn off to increase performance.
enable_purge = true

View File

@ -39,6 +39,8 @@ class CacheFactory
return new NullCache();
case FileCache::class:
return new FileCache([
// Intentionally checking for "truthy" value
'path' => Configuration::getConfig('FileCache', 'path') ?: PATH_CACHE,
'enable_purge' => Configuration::getConfig('FileCache', 'enable_purge'),
]);
case SQLiteCache::class:

View File

@ -226,3 +226,8 @@ function now(): \DateTimeImmutable
{
return new \DateTimeImmutable();
}
function create_random_string(int $bytes = 16): string
{
return bin2hex(openssl_random_pseudo_bytes($bytes));
}

31
tests/CacheTest.php Normal file
View File

@ -0,0 +1,31 @@
<?php
namespace RssBridge\Tests;
use PHPUnit\Framework\TestCase;
class CacheTest extends TestCase
{
public function testFileCache()
{
$temporaryFolder = sprintf('%s/rss_bridge_%s/', sys_get_temp_dir(), create_random_string());
mkdir($temporaryFolder);
$sut = new \FileCache([
'path' => $temporaryFolder,
'enable_purge' => true,
]);
$sut->setScope('scope');
$sut->purgeCache(-1);
$sut->setKey(['key']);
$this->assertNull($sut->loadData());
$sut->saveData('data');
$this->assertSame('data', $sut->loadData());
$this->assertIsNumeric($sut->getTime());
$sut->purgeCache(-1);
// Intentionally not deleting the temp folder
}
}

View File

@ -26,21 +26,6 @@ final class UtilsTest extends TestCase
$this->assertSame('1 TB', format_bytes(1024 ** 4));
}
public function testFileCache()
{
$sut = new \FileCache(['enable_purge' => true]);
$sut->setScope('scope');
$sut->purgeCache(-1);
$sut->setKey(['key']);
$this->assertNull($sut->loadData());
$sut->saveData('data');
$this->assertSame('data', $sut->loadData());
$this->assertIsNumeric($sut->getTime());
$sut->purgeCache(-1);
}
public function testSanitizePathName()
{
$this->assertSame('index.php', _sanitize_path_name('/home/satoshi/rss-bridge/index.php', '/home/satoshi/rss-bridge'));
@ -54,4 +39,11 @@ final class UtilsTest extends TestCase
$sanitized = 'Error: Argument 1 passed to foo() must be an instance of kk, string given, called in bridges/RumbleBridge.php';
$this->assertSame($sanitized, _sanitize_path_name($raw, '/home/satoshi/rss-bridge'));
}
public function testCreateRandomString()
{
$this->assertSame(2, strlen(create_random_string(1)));
$this->assertSame(4, strlen(create_random_string(2)));
$this->assertSame(6, strlen(create_random_string(3)));
}
}