summaryrefslogtreecommitdiff
path: root/classes/Cache_Local.php
diff options
context:
space:
mode:
Diffstat (limited to 'classes/Cache_Local.php')
-rw-r--r--classes/Cache_Local.php148
1 files changed, 148 insertions, 0 deletions
diff --git a/classes/Cache_Local.php b/classes/Cache_Local.php
new file mode 100644
index 000000000..8ac634a3e
--- /dev/null
+++ b/classes/Cache_Local.php
@@ -0,0 +1,148 @@
+<?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;
+ }
+ }
+
+}