1
0
mirror of https://tt-rss.org/git/tt-rss.git synced 2024-06-29 12:20:51 +02:00
ttrss/classes/cache/local.php
wn_ 8b129626cd Only touch on send for expirable cache files.
With d373b7b452 feed icon modification times get used for cache-busting, but 'Cache_Local' updates that
value on each send.  This change makes it so the modification time only gets updated on files in expirable caches, keeping the value
consistent between sends for files in non-expiring caches.

Also, marking 'Cache_Local::send_local_file()' private since it's unique to that adapter.
2022-12-20 02:16:47 +00:00

149 lines
3.9 KiB
PHP

<?php
class Cache_Local implements Cache_Adapter {
private string $dir;
public function remove(string $filename): bool {
return unlink($this->get_full_path($filename));
}
public function get_mtime(string $filename) {
return filemtime($this->get_full_path($filename));
}
public function set_dir(string $dir) : void {
$this->dir = Config::get(Config::CACHE_DIR) . "/" . basename(clean($dir));
$this->make_dir();
}
public function get_dir(): string {
return $this->dir;
}
public function make_dir(): bool {
if (!is_dir($this->dir)) {
return mkdir($this->dir);
}
return false;
}
public function is_writable(?string $filename = null): bool {
if ($filename) {
if (file_exists($this->get_full_path($filename)))
return is_writable($this->get_full_path($filename));
else
return is_writable($this->dir);
} else {
return is_writable($this->dir);
}
}
public function exists(string $filename): bool {
return file_exists($this->get_full_path($filename));
}
/**
* @return int|false -1 if the file doesn't exist, false if an error occurred, size in bytes otherwise
*/
public function get_size(string $filename) {
if ($this->exists($filename))
return filesize($this->get_full_path($filename));
else
return -1;
}
public function get_full_path(string $filename): string {
return $this->dir . "/" . basename(clean($filename));
}
public function get(string $filename): ?string {
if ($this->exists($filename))
return file_get_contents($this->get_full_path($filename));
else
return null;
}
/**
* @param mixed $data
*
* @return int|false Bytes written or false if an error occurred.
*/
public function put(string $filename, $data) {
return file_put_contents($this->get_full_path($filename), $data);
}
/**
* @return false|null|string false if detection failed, null if the file doesn't exist, string mime content type otherwise
*/
public function get_mime_type(string $filename) {
if ($this->exists($filename))
return mime_content_type($this->get_full_path($filename));
else
return null;
}
/**
* @return bool|int false if the file doesn't exist (or unreadable) or isn't audio/video, true if a plugin handled, otherwise int of bytes sent
*/
public function send(string $filename) {
return $this->send_local_file($this->get_full_path($filename));
}
public function expire_all(): void {
$dirs = array_filter(glob(Config::get(Config::CACHE_DIR) . "/*"), "is_dir");
foreach ($dirs as $cache_dir) {
$num_deleted = 0;
if (is_writable($cache_dir) && !file_exists("$cache_dir/.no-auto-expiry")) {
$files = glob("$cache_dir/*");
if ($files) {
foreach ($files as $file) {
if (time() - filemtime($file) > 86400 * Config::get(Config::CACHE_MAX_DAYS)) {
unlink($file);
++$num_deleted;
}
}
}
Debug::log("Expired $cache_dir: removed $num_deleted files.");
}
}
}
/**
* this is essentially a wrapper for readfile() which allows plugins to hook
* output with httpd-specific "fast" implementation i.e. X-Sendfile or whatever else
*
* hook function should return true if request was handled (or at least attempted to)
*
* note that this can be called without user context so the plugin to handle this
* should be loaded systemwide in config.php
*
* @return bool|int false if the file doesn't exist (or unreadable) or isn't audio/video, true if a plugin handled, otherwise int of bytes sent
*/
private function send_local_file(string $filename) {
if (file_exists($filename)) {
if (is_writable($filename) && !$this->exists('.no-auto-expiry')) {
touch($filename);
}
$tmppluginhost = new PluginHost();
$tmppluginhost->load(Config::get(Config::PLUGINS), PluginHost::KIND_SYSTEM);
//$tmppluginhost->load_data();
if ($tmppluginhost->run_hooks_until(PluginHost::HOOK_SEND_LOCAL_FILE, true, $filename))
return true;
return readfile($filename);
} else {
return false;
}
}
}