diff --git a/lib/Cache.php b/lib/Cache.php index 119e2c5..8755fa5 100644 --- a/lib/Cache.php +++ b/lib/Cache.php @@ -1,5 +1,57 @@ prepare($sql); + $result = $stmt->execute(); + + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + self::$resourceCache[$row["name"]] = $row; + } + + } + + public static function hasResourceCache(string $name) { + if (count(self::$resourceCache) == 0) { + self::fillResourceCache(); + } + + return isset(self::$resourceCache[$name]); + } + + public static function setResourceCache(string $name, $data) { + self::$resourceCache[$name] = $data; + } + + public static function getResourceCache(string $name) { + if (count(self::$resourceCache) == 0) { + self::fillResourceCache(); + } + + if (isset(self::$resourceCache[$name])) { + return self::$resourceCache[$name]; + } + + return null; + } + + public static function getResourceCacheByThumbnailUrl(string $url) { + if (count(self::$resourceCache) == 0) { + self::fillResourceCache(); + } + + foreach (self::$resourceCache as $resource) { + if ($resource["url"] == $url) { + return $resource; + } + } + + return null; + } + public static function getCacheFile(string $name, $maxAge = 3600) { $cacheFile = CACHE_DIR . "/" . $name; @@ -18,28 +70,12 @@ class Cache { } public static function publicCacheExists(string $name, bool $skipExtensionCheck = false) { - // For now cache is not reliable since we use a generated name. - return false; - /*if (!$skipExtensionCheck) { - $ext = substr($name, strrpos($name, ".") + 1); - if (strtolower($ext) == "jpg" || strtolower($ext) == "jpeg" || strtolower($ext) == "png") { - $name = str_replace("." . $ext, ".webp", strtolower($name)); - } - } - - $cacheFile = PUBLIC_CACHE_DIR . "/" . $name; - - try { - $fe = file_exists($cacheFile); - } catch (Exception $e) { - $fe = false; - Logger::log("Could not check if public cache file " . $name . " exists: " . $e->getMessage(), Logger::ERROR, "Cache"); - } - - return $fe;*/ + return self::hasResourceCache($name); } public static function savePublicCacheFile(string $name, string $data, int $cacheLevel = 70, bool $skipExtensionCheck = false) { + $originalName = $name; + $name = strtolower($name); $ext = substr($name, strrpos($name, ".") + 1); @@ -55,10 +91,31 @@ class Cache { $cacheFile = PUBLIC_CACHE_DIR . "/" . $name; $blurhash = self::generateBlurHash($cacheFile, $img, $skipExtensionCheck); - if (!empty($blurhash)) { - $name = "BH-" . bin2hex($blurhash) . "-W" . $img->getImageWidth() . "xH" . $img->getImageHeight() . ".webp"; - $cacheFile = PUBLIC_CACHE_DIR . "/" . $name; - } + + $resourceSql = "INSERT INTO `resources` (`name`, `type`, `blurhash`, `url`, `width`, `height`, `hasBeenProcessed`, `modified`) + VALUES (:name,:type,:blurhash,:url,:width,:height,1,strftime('%Y-%m-%d %H:%M:%S','now'))"; + + $db = new Database(); + $resourceStmt = $db::$handle->prepare($resourceSql); + $resourceStmt->bindValue(":name", $originalName); + $resourceStmt->bindValue(":type", "image/webp"); + $resourceStmt->bindValue(":blurhash", $blurhash); + $resourceStmt->bindValue(":url", PUBLIC_CACHE_URL . "/" . $name); + $resourceStmt->bindValue(":width", $img->getImageWidth()); + $resourceStmt->bindValue(":height", $img->getImageHeight()); + $resourceStmt->execute(); + + // Append to the resource cache + self::setResourceCache($originalName, [ + "name" => $originalName, + "type" => "image/webp", + "blurhash" => $blurhash, + "url" => PUBLIC_CACHE_URL . "/" . $name, + "width" => $img->getImageWidth(), + "height" => $img->getImageHeight(), + "hasBeenProcessed" => 1, + "modified" => date("Y-m-d H:i:s") + ]); // For now don't transfer file if its generated name exists if (file_exists($cacheFile)) { @@ -117,4 +174,31 @@ class Cache { return $hash; } } + + public static function getBlurHashImage($blurhash,$width = 269, $height = 173) { + + $hash = \kornrunner\Blurhash\Blurhash::decode($blurhash, $width, $height); + + $img = new Imagick(); + $img->newImage($width, $height, new ImagickPixel("white")); + $img->setImageFormat("webp"); + $img->setImageCompressionQuality(60); + + $pixels = []; + for ($y = 0; $y < $height; ++$y) { + for ($x = 0; $x < $width; ++$x) { + [$r, $g, $b] = $hash[$y][$x]; + $pixels[] = $r; + $pixels[] = $g; + $pixels[] = $b; + } + } + + $img->importImagePixels(0, 0, $width, $height, "RGB", Imagick::PIXEL_CHAR, $pixels); + + $img->stripImage(); + $data = $img->getImageBlob(); + + return "data:image/webp;base64," . base64_encode($data); + } } \ No newline at end of file diff --git a/lib/Database.php b/lib/Database.php index a69f58f..cc2a032 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -71,7 +71,21 @@ class Database if ($run === true) { Logger::log("Found migration for table " . $migrationTable . " version " . $migrationVersion, LOGGER::INFO, "Database"); - $migrationContents = file_get_contents(MIGRATIONS_DIR . "/" . $migration); + $possiblePaths = [LIB_MIGRATIONS_DIR, MIGRATIONS_DIR]; + $migrationFile = null; + foreach ($possiblePaths as $possiblePath) { + if (file_exists($possiblePath . "/" . $migration)) { + $migrationFile = $possiblePath . "/" . $migration; + break; + } + } + + if ($migrationFile === null) { + Logger::log("Could not find migration file for table " . $migrationTable . " version " . $migrationVersion, LOGGER::ERROR, "Database"); + continue; + } + + $migrationContents = file_get_contents($migrationFile); if (@self::$handle->exec($migrationContents)) { self::$handle->exec("INSERT INTO `migrations` (`table`,`version`, `schemafile`, `created`) VALUES ('" . $migrationTable . "'," . $migrationVersion . ",'" . $migration . "', strftime('%Y-%m-%d %H:%M:%S','now'))"); $migrationCount++; diff --git a/schema/resources-000.sql b/schema/resources-000.sql new file mode 100644 index 0000000..7a57c1c --- /dev/null +++ b/schema/resources-000.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS `resources` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, + `name` TEXT NOT NULL, + `type` TEXT NOT NULL, + `blurhash` TEXT DEFAULT NULL, + `url` TEXT NOT NULL, + `width` INTEGER DEFAULT NULL, + `height` INTEGER DEFAULT NULL, + `hasBeenProcessed` INTEGER DEFAULT 0, + `modified` TEXT NOT NULL +); + +CREATE UNIQUE INDEX IF NOT EXISTS `resources_name` ON `resources` (`name`); +CREATE INDEX IF NOT EXISTS `resources_blurhash` ON `resources` (`blurhash`); +CREATE INDEX IF NOT EXISTS `resources_type` ON `resources` (`type`); +CREATE INDEX IF NOT EXISTS `resources_hasBeenProcessed` ON `resources` (`hasBeenProcessed`); +CREATE INDEX IF NOT EXISTS `resources_modified` ON `resources` (`modified`);