Files
seatmapv1/seatmap-webapi/src/Tqdev/PhpCrudApi/Cache/TempFileCache.php
2021-01-20 13:13:22 +01:00

147 lines
4.1 KiB
PHP

<?php
namespace Tqdev\PhpCrudApi\Cache;
class TempFileCache implements Cache
{
const SUFFIX = 'cache';
private $path;
private $segments;
public function __construct(string $prefix, string $config)
{
$this->segments = [];
$s = DIRECTORY_SEPARATOR;
$ps = PATH_SEPARATOR;
if ($config == '') {
$this->path = sys_get_temp_dir() . $s . $prefix . self::SUFFIX;
} elseif (strpos($config, $ps) === false) {
$this->path = $config;
} else {
list($path, $segments) = explode($ps, $config);
$this->path = $path;
$this->segments = explode(',', $segments);
}
if (file_exists($this->path) && is_dir($this->path)) {
$this->clean($this->path, array_filter($this->segments), strlen(md5('')), false);
}
}
private function getFileName(string $key): string
{
$s = DIRECTORY_SEPARATOR;
$md5 = md5($key);
$filename = rtrim($this->path, $s) . $s;
$i = 0;
foreach ($this->segments as $segment) {
$filename .= substr($md5, $i, $segment) . $s;
$i += $segment;
}
$filename .= substr($md5, $i);
return $filename;
}
public function set(string $key, string $value, int $ttl = 0): bool
{
$filename = $this->getFileName($key);
$dirname = dirname($filename);
if (!file_exists($dirname)) {
if (!mkdir($dirname, 0755, true)) {
return false;
}
}
$string = $ttl . '|' . $value;
return $this->filePutContents($filename, $string) !== false;
}
private function filePutContents($filename, $string)
{
return file_put_contents($filename, $string, LOCK_EX);
}
private function fileGetContents($filename)
{
$file = fopen($filename, 'rb');
if ($file === false) {
return false;
}
$lock = flock($file, LOCK_SH);
if (!$lock) {
fclose($file);
return false;
}
$string = '';
while (!feof($file)) {
$string .= fread($file, 8192);
}
flock($file, LOCK_UN);
fclose($file);
return $string;
}
private function getString($filename): string
{
$data = $this->fileGetContents($filename);
if ($data === false) {
return '';
}
list($ttl, $string) = explode('|', $data, 2);
if ($ttl > 0 && time() - filemtime($filename) > $ttl) {
return '';
}
return $string;
}
public function get(string $key): string
{
$filename = $this->getFileName($key);
if (!file_exists($filename)) {
return '';
}
$string = $this->getString($filename);
if ($string == null) {
return '';
}
return $string;
}
private function clean(string $path, array $segments, int $len, bool $all) /*: void*/
{
$entries = scandir($path);
foreach ($entries as $entry) {
if ($entry === '.' || $entry === '..') {
continue;
}
$filename = $path . DIRECTORY_SEPARATOR . $entry;
if (count($segments) == 0) {
if (strlen($entry) != $len) {
continue;
}
if (is_file($filename)) {
if ($all || $this->getString($filename) == null) {
unlink($filename);
}
}
} else {
if (strlen($entry) != $segments[0]) {
continue;
}
if (is_dir($filename)) {
$this->clean($filename, array_slice($segments, 1), $len - $segments[0], $all);
rmdir($filename);
}
}
}
}
public function clear(): bool
{
if (!file_exists($this->path) || !is_dir($this->path)) {
return false;
}
$this->clean($this->path, array_filter($this->segments), strlen(md5('')), true);
return true;
}
}