123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- <?php
-
- namespace Tqdev\PhpCrudApi\Cache;
-
- class TempFileCache implements Cache
- {
- public 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;
- }
- }
|