Initial commit
This commit is contained in:
commit
6ffc729cc7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/composer.lock
|
||||||
|
/vendor
|
25
composer.json
Normal file
25
composer.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "noccylabs/local-cache",
|
||||||
|
"description": "A local system-wide always available cache",
|
||||||
|
"type": "library",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Christopher Vagnetoft",
|
||||||
|
"email": "cvagnetoft@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"psr/log": "^1.1",
|
||||||
|
"psr/cache": "^1.0",
|
||||||
|
"psr/simple-cache": "^1.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"NoccyLabs\\LocalCache\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.4"
|
||||||
|
}
|
||||||
|
}
|
176
src/LocalCache.php
Normal file
176
src/LocalCache.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace NoccyLabs\LocalCache;
|
||||||
|
|
||||||
|
use Psr\SimpleCache\InvalidArgumentException;
|
||||||
|
use Psr\SimpleCache\CacheInterface;
|
||||||
|
use Psr\SimpleCache\CacheException;
|
||||||
|
|
||||||
|
class LocalCache implements CacheInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
private $cacheDir;
|
||||||
|
|
||||||
|
private $poolName;
|
||||||
|
|
||||||
|
private $defaultTtl = 3600;
|
||||||
|
|
||||||
|
public function __construct(string $poolName)
|
||||||
|
{
|
||||||
|
$this->poolName = preg_replace("/[^a-zA-Z0-9_\\-]/", "_", $poolName);
|
||||||
|
$this->cacheDir = $this->findCachePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function findCachePath(): string
|
||||||
|
{
|
||||||
|
$candidates = [
|
||||||
|
'/var/cache',
|
||||||
|
getenv("HOME").'/.cache',
|
||||||
|
];
|
||||||
|
while ($candidate = array_shift($candidates)) {
|
||||||
|
if (!is_writable($candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$path = $candidate . DIRECTORY_SEPARATOR . 'php-localcache';
|
||||||
|
/*
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
@mkdir($path);
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
|
throw new CacheException("Couldn't find a usable cache directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hashKey(string $key)
|
||||||
|
{
|
||||||
|
$hash = hash("sha256", $key);
|
||||||
|
return $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getKeyPath(string $key)
|
||||||
|
{
|
||||||
|
$hash = $this->hashKey($key);
|
||||||
|
// $path = substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2, 2) . DIRECTORY_SEPARATOR . $hash;
|
||||||
|
$full = $this->cacheDir . DIRECTORY_SEPARATOR . $this->poolName . DIRECTORY_SEPARATOR . $hash; // $path;
|
||||||
|
return $full;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get($key, $default = null)
|
||||||
|
{
|
||||||
|
if (!$this->has($key)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$path = $this->getKeyPath($key);
|
||||||
|
return file_get_contents($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function set($key, $value, $ttl = null)
|
||||||
|
{
|
||||||
|
$info = [
|
||||||
|
'key' => $key,
|
||||||
|
'ttl' => $ttl ?? $this->defaultTtl
|
||||||
|
];
|
||||||
|
$info['expires'] = time() + $info['ttl'];
|
||||||
|
$path = $this->getKeyPath($key);
|
||||||
|
if (!is_dir(dirname($path))) {
|
||||||
|
mkdir(dirname($path), 0777, true);
|
||||||
|
}
|
||||||
|
file_put_contents($path, $value);
|
||||||
|
file_put_contents($path.".info", serialize($info));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function delete($key)
|
||||||
|
{
|
||||||
|
if (!$this->has($key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$path = $this->getKeyPath($key);
|
||||||
|
@unlink($path);
|
||||||
|
@unlink($path.".info");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function has($key)
|
||||||
|
{
|
||||||
|
$path = $this->getKeyPath($key);
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = unserialize(file_get_contents($path.".info"));
|
||||||
|
if ($info['expires'] < time()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
$items = glob($this->cacheDir.DIRECTORY_SEPARATOR.$this->poolName.DIRECTORY_SEPARATOR."*.info");
|
||||||
|
foreach ($items as $item) {
|
||||||
|
unlink(substr($item, 0, -5));
|
||||||
|
unlink($item);
|
||||||
|
}
|
||||||
|
@rmdir($this->cacheDir . DIRECTORY_SEPARATOR . $this->poolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getMultiple($keys, $default = null)
|
||||||
|
{
|
||||||
|
if (!is_iterable($keys)) {
|
||||||
|
throw new InvalidArgumentException("Argument not iterable");
|
||||||
|
}
|
||||||
|
$ret = [];
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$ret[$key] = $this->get($key, $default);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setMultiple($values, $ttl = null)
|
||||||
|
{
|
||||||
|
if (!is_iterable($values)) {
|
||||||
|
throw new InvalidArgumentException("Argument not iterable");
|
||||||
|
}
|
||||||
|
foreach ($values as $key=>$value) {
|
||||||
|
$this->set($key, $value, $ttl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function deleteMultiple($keys)
|
||||||
|
{
|
||||||
|
if (!is_iterable($keys)) {
|
||||||
|
throw new InvalidArgumentException("Argument not iterable");
|
||||||
|
}
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$this->delete($key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user