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; } }