NanoGal/app/Cache.php
2024-10-04 16:25:50 +02:00

209 lines
7.4 KiB
PHP

<?php
namespace App;
use Utils\Utils;
class Cache {
private $currentDir;
private $counter = [];
private $fileName = '../cache/cache.json';
private $fileCache;
static $atomFileName = '../cache/feed.atom';
private $currentConfig;
private $saveConfig;
/**
* Initializes the object with a directory path and configuration settings, managing cache as needed.
*
* This constructor checks if the provided directory path is authorized. If it is, the constructor
* proceeds to handle caching based on the provided configuration. If caching is disabled, any existing
* cache file is deleted. The method also compares the current configuration with a saved version
* to detect changes.
*
* @param string $dir The current directory path to be set.
* @param array $config Configuration settings to be used by the object, including cache management options.
*
* @throws \Exception If an unauthorized access attempt is detected.
*/
function __construct(string $dir, array $config) {
if (!Utils::isPathAuthorized($dir)) {
die("ERROR 03: Unauthorized access!");
}
$this->currentDir = $dir;
if (!is_dir('../cache/html')) {
mkdir('../cache/html', 0700);
}
if ($config['disableCache'] && file_exists($this->fileName)) {
unlink($this->fileName);
}
if (file_exists($this->fileName)) {
$cacheFile = json_decode(file_get_contents($this->fileName), true);
} else {
$cacheFile = [];
}
$this->currentConfig = md5(json_encode($config));
if (isset($cacheFile['config'])) {
$this->saveConfig = $cacheFile['config'];
}
$this->fileCache = $cacheFile;
}
/**
* Counts the number of files and directories in the current directory.
*
* This method iterates over the contents of the current directory, counting
* both files and subdirectories (excluding `.` and `..`). The total count is
* stored in an internal array indexed by the directory path and is also returned.
* If the directory cannot be opened, an exception is thrown.
*
* @return array An associative array where the key is the directory path and the value is the count of files and directories.
*
* @throws \Exception If the directory cannot be opened for reading.
*/
public function countDirsAndFiles(): array {
$counter = 0;
if (is_dir($this->currentDir) && $handle = opendir($this->currentDir)) {
while (false !== ($file = readdir($handle))) {
if ($file === "." || $file === "..") {
continue;
}
if (is_file($this->currentDir . '/' . $file) || is_dir($this->currentDir . '/' . $file)) {
$counter++;
}
}
closedir($handle);
$this->counter[$this->currentDir] = $counter;
return $this->counter;
} else {
throw new \Exception("ERROR: Could not open directory for reading: " . $this->currentDir);
}
}
/**
* Checks if the number of files and directories in the current directory has changed.
*
* This method compares the current count of files and directories with a cached count.
* If the counts differ, it updates the cache with the new count and returns `true`,
* indicating that a change has occurred. Otherwise, it returns `false`.
*
* @return bool `true` if the count of files and directories has changed and the cache is updated; `false` otherwise.
*/
public function changeFile(): bool {
if (!isset($this->fileCache[$this->currentDir])) {
$this->fileCache[$this->currentDir] = -1;
}
if (!empty($this->counter[$this->currentDir]) && ($this->counter[$this->currentDir] !== $this->fileCache[$this->currentDir])) {
$this->fileCache = array_merge($this->fileCache, $this->counter);
return true;
}
return false;
}
/**
* Checks if the current configuration has changed compared to the saved configuration.
*
* This method compares the current configuration with a previously saved configuration.
* If they differ, it updates the cache with the current configuration and returns `true`,
* indicating that a change has occurred. Otherwise, it returns `false`.
*
* @return bool `true` if the configuration has changed and the cache is updated; `false` otherwise.
*/
public function changeConf(): bool {
if ($this->currentConfig !== $this->saveConfig) {
$this->fileCache['config'] = $this->currentConfig;
return true;
}
return false;
}
/**
* Saves the current file cache to a file in JSON format.
*
* This method serializes the file cache to a JSON string with pretty printing, unescaped slashes,
* and unescaped Unicode characters. It then writes this JSON data to the specified file.
* If the JSON encoding fails or if the file write operation fails, an exception is thrown.
*
* @throws \Exception If JSON encoding fails or if writing to the file fails.
*
* @return void
*/
public function save(): void {
$jsonData = json_encode($this->fileCache, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if ($jsonData === false) {
throw new \Exception("Failed to encode data to JSON: " . json_last_error_msg());
}
if (file_put_contents($this->fileName, $jsonData) === false) {
throw new \Exception("Failed to write data to file: " . $this->fileName);
}
}
/**
* Clears the HTML cache by deleting all cached files.
*
* This method retrieves all `.html` files in the cache directory and deletes them.
* If the cache directory cannot be read or if any file deletion fails, an exception is thrown.
*
* @throws \Exception If the cache directory cannot be read or if a file cannot be deleted.
*
* @return void
*/
public function clearCache(): void {
$files = glob("../cache/html/*.html");
if ($files === false) {
throw new \Exception("Failed to read cache directory.");
}
foreach ($files as $file) {
if (is_file($file)) {
if (!unlink($file)) {
throw new \Exception("Failed to delete file: " . $file);
}
}
}
}
/**
* Deleting the Atom feed cache file if exists.
*
* @return void
*/
static function clearAtomFeed(): void {
if (file_exists(self::$atomFileName)) {
unlink(self::$atomFileName);
}
}
/**
* Retrieves the Atom feed cache content if file exists.
*
* @return string|false Returns the content of the Atom feed cache file, or false if the file does not exist.
*/
static function getAtomFeed(): string|false {
if (file_exists(self::$atomFileName)) {
return file_get_contents(self::$atomFileName);
}
return false;
}
/**
* Writes content to the Atom feed cache file.
*
* @param string $content The content to be written to the Atom feed file.
* @return void
*/
static function setAtomFeed(string $content): void {
file_put_contents(self::$atomFileName, $content);
}
}