summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2021-09-01 06:53:14 +0300
committerAndrew Dolgov <[email protected]>2021-09-01 06:53:14 +0300
commit7499d01abdf9e0584686bb99146de588a0402a8f (patch)
tree0fe78f6af8f6b2b1d3d9f0e3f37fba6b3005ed5e
parent6636bdde1b1b5af77b0429bef4bdd1ff72e3b12f (diff)
optionally prepare images of specific widths in HOOK_ARTICLE_FILTER
-rw-r--r--init.php132
1 files changed, 127 insertions, 5 deletions
diff --git a/init.php b/init.php
index 2ff877e..11ffd6f 100644
--- a/init.php
+++ b/init.php
@@ -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 ?>">
&nbsp;
- <?= $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 ?>">
+ &nbsp;
+ <?= $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);