diff options
author | Andrew Dolgov <[email protected]> | 2021-09-01 06:53:14 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2021-09-01 06:53:14 +0300 |
commit | 7499d01abdf9e0584686bb99146de588a0402a8f (patch) | |
tree | 0fe78f6af8f6b2b1d3d9f0e3f37fba6b3005ed5e | |
parent | 6636bdde1b1b5af77b0429bef4bdd1ff72e3b12f (diff) |
optionally prepare images of specific widths in HOOK_ARTICLE_FILTER
-rw-r--r-- | init.php | 132 |
1 files changed, 127 insertions, 5 deletions
@@ -28,11 +28,11 @@ class Api_Resize_Media extends Plugin { $host->add_hook($host::HOOK_RENDER_ARTICLE_API, $this, 999); $host->add_hook($host::HOOK_ARTICLE_IMAGE, $this, 999); - $host->add_hook($host::HOOK_PREFS_TAB, $this); $host->add_hook($host::HOOK_RENDER_ARTICLE_CDM, $this, 999); $host->add_hook($host::HOOK_RENDER_ARTICLE, $this, 999); $host->add_hook($host::HOOK_ENCLOSURE_ENTRY, $this, 999); + $host->add_hook($host::HOOK_ARTICLE_FILTER, $this, 999); } private function make_thumbnail($input_filename, $output_filename, $dim_max_x = 600, $dim_max_y = 600, @@ -108,12 +108,68 @@ class Api_Resize_Media extends Plugin { } } + function prepare_thumbnails(string $url, array $widths, bool $force_stamp) { + Debug::log("[api_resize_media] checking URL $url (force_stamp=$force_stamp)...", + Debug::LOG_VERBOSE); + + $url = validate_url($url); + + if (!$url) { + Debug::log("[api_resize_media] URL failed validation, skipping.", Debug::LOG_VERBOSE); + return; + } + + $local_filename = sha1($url); + $quality = $this->host->get($this, "quality", self::DEFAULT_QUALITY); + + if (!$this->cache->exists($local_filename)) { + $data = fetch_file_contents(["url" => $url, "max_size" => Config::get(Config::MAX_CACHE_FILE_SIZE)]); + + if ($data) { + if (!$this->cache->put($local_filename, $data)) { + Debug::log("[api_resize_media] error: could not save URL to local cache.", + Debug::LOG_VERBOSE); + return; + } + } + } + + foreach ($widths as $width) { + if ($width <= 0) + continue; + + if ($width > self::MAX_WIDTH) + $width = self::MAX_WIDTH; + + $resized_filename = sha1($url) . "-$width"; + + if (!$this->cache->exists($resized_filename)) { + Debug::log("[api_resize_media] preparing width: $resized_filename (q=$quality)", + Debug::LOG_VERBOSE); + + if ($this->cache->exists($local_filename)) { + $this->make_thumbnail( + $this->cache->get_full_path($local_filename), + $this->cache->get_full_path($resized_filename), + $width, + $width, + $this->cache->get_mime_type($local_filename), + $force_stamp, + $quality); + } + } + } + } + public function api_resize() { $url = validate_url($_REQUEST["url"]); $width = (int) $_REQUEST["width"]; $force_stamp = sql_bool_to_bool($_REQUEST["force_stamp"]); + if ($width > self::MAX_WIDTH) + $width = self::MAX_WIDTH; + $local_filename = sha1($url); $flag_filename = sha1($url) . ".flag"; $resized_filename = sha1($url) . "-$width"; @@ -125,8 +181,6 @@ class Api_Resize_Media extends Plugin { return; } - if ($width > self::MAX_WIDTH) $width = self::MAX_WIDTH; - if ($this->cache->exists($local_filename)) { if ($this->cache->exists($resized_filename)) { @@ -321,6 +375,57 @@ class Api_Resize_Media extends Plugin { return $enc; } + function hook_article_filter($article) { + $widths = array_unique( + array_map("intval", + $this->host->get_array($this, "prepare_widths"))); + + if (count($widths) == 0) + return $article; + + $site_url = $article["feed"]["site_url"] ?? ""; + + $doc = new DOMDocument(); + if (@$doc->loadHTML('<?xml encoding="UTF-8">' . $article["content"])) { + $xpath = new DOMXPath($doc); + $imgs = $xpath->query("//img[@src]"); + + foreach ($imgs as $img) { + $this->prepare_thumbnails( + UrlHelper::rewrite_relative($site_url, $img->getAttribute("src")), + $widths, false); + } + + $vids = $xpath->query("//video[@poster]"); + + foreach ($vids as $vid) { + $this->prepare_thumbnails( + UrlHelper::rewrite_relative($site_url, $vid->getAttribute("poster")), + $widths, false); + } + + $posters = $xpath->query("//picture/source[@src]"); + + foreach ($posters as $poster) { + $this->prepare_thumbnails( + UrlHelper::rewrite_relative($site_url, $poster->getAttribute("src")), + $widths, true); + } + + if (isset($article["enclosures"]) && is_array($article["enclosures"])) { + for ($i = 0; $i < count($article["enclosures"]); $i++) { + if (preg_match("/image/", $article["enclosures"][$i][1])) { + $this->prepare_thumbnails( + UrlHelper::rewrite_relative($site_url, $article["enclosures"][$i][0]), + $widths, false); + } + } + } + } + + return $article; + } + function hook_render_article_cdm($row) { $force_width = (int) $this->host->profile_get($this, "force_width", 0); @@ -374,6 +479,7 @@ class Api_Resize_Media extends Plugin { if ($args != "prefFeeds") return; $force_width = (int) $this->host->profile_get($this, "force_width", 0); + $prepare_widths = implode(", ", $this->host->get_array($this, "prepare_widths")); $quality = (int) $this->host->profile_get($this, "quality", self::DEFAULT_QUALITY); ?> @@ -394,12 +500,23 @@ class Api_Resize_Media extends Plugin { </script> <fieldset class='prefs'> - <label><?= $this->__( "Also resize in web UI (width, 0 - disables):") ?></label> + <label><?= $this->__("Also resize in web UI (width, 0 - disables):") ?></label> <input dojoType='dijit.form.NumberSpinner' title="<?= $this->__("This setting is local to current preference profile.") ?>" required='1' name='force_width' value="<?= $force_width ?>"> - <?= $this->__('pixels') ?> + <?= $this->__('(pixels)') ?> + </fieldset> + + <fieldset class='prefs'> + <label><?= $this->__("Prepare images of specific widths:") ?></label> + <input dojoType='dijit.form.ValidationTextBox' + regexp='[0-9, ]*' + placeholder='810, 900, 1200' + title="<?= $this->__("This is a global setting.") ?>" + name='prepare_widths' value="<?= $prepare_widths ?>"> + + <?= $this->__('(comma-separated list, disabled if empty)') ?> </fieldset> <fieldset class='prefs'> @@ -421,6 +538,11 @@ class Api_Resize_Media extends Plugin { function save() { $force_width = (int) $_POST["force_width"]; $quality = (int) $_POST["quality"]; + $prepare_widths = array_map("intval", + array_map("trim", + explode(",", $_POST["prepare_widths"]))); + + $this->host->set($this, "prepare_widths", $prepare_widths); $this->host->profile_set($this, "force_width", $force_width); $this->host->profile_set($this, "quality", $quality); |