EmbedService.php: refactor

This commit is contained in:
Zankaria 2025-03-17 14:44:57 +01:00
parent cd8d0e060f
commit 01811cb50f

View file

@ -1,26 +1,13 @@
<?php
namespace Vichan\Services\Embed;
use Vichan\Data\Driver\HttpDriver;
use Vichan\Data\Driver\LogDriver;
use Vichan\Services\Embed\OembedExtractor;
use Vichan\Data\Driver\{HttpDriver, LogDriver};
class EmbedService {
private const TMP_FILE_PREFIX = 'oembed-thumb-';
/**
* The input embed text isn't a valid URL.
*/
public const MATCH_EMBED_ERR_NOT_AN_URL = 0;
/**
* The embed url doesn't match any supported url.
*/
public const MATCH_EMBED_ERR_NO_MATCH = 1;
/**
* The embed url doesn't have a thumbnail.
*/
public const MATCH_EMBED_ERR_NO_THUMBNAIL = 2;
private LogDriver $log;
private OembedExtractor $oembed_extractor;
private HttpDriver $http;
@ -62,31 +49,44 @@ class EmbedService {
}
/**
* Matches an alleged embed url and returns the path to the thumbnail, if any.
* Returns the path to the thumbnail from a matched url, if any.
*
* @param string $rawText
* @return ?array Returns the url to the thumbnail and the path to the fallback if any embedding matches, null otherwise.
* @param string $url The url to embed.
* @param int $entry_index The index of the embedding entry.
* @return ?array Returns the url to the thumbnail and the path to the fallback.
*/
private function matchAndExtract(string $rawText) {
foreach ($this->embed_entries as $embed_entry) {
$match_regex = $embed_entry['match_regex'];
private function extractThumb(string $url, int $entry_index) {
$embed_entry = $this->embed_entries[$entry_index];
$match_regex = $embed_entry['match_regex'];
$type = $embed_entry['type'];
if (\preg_match($match_regex, $rawText, $matches)) {
$type = $embed_entry['type'];
if ($type === 'oembed') {
$thumbnail_url_fallback = $embed_entry['thumbnail_url_fallback'] ?? null;
$provider = $embed_entry['provider_url'];
$oembed_resp = $this->oembed_extractor->fetch($provider, $url);
if ($type === 'oembed') {
$thumbnail_url_fallback = $embed_entry['thumbnail_url_fallback'] ?? null;
$provider = $embed_entry['provider'];
$oembed_resp = $this->oembed_extractor->fetch($provider, $rawText);
return [ $oembed_resp->thumbnail_url, $thumbnail_url_fallback ];
} elseif ($type === 'regex') {
$thumbnail_url_regex = $embed_entry['thumbnail_url'];
// Plz somebody review this.
return [ \preg_replace($match_regex, $thumbnail_url_regex, $url), null ];
} else {
$this->log->log(LogDriver::ERROR, "Unknown embed type '$type' in embed entry $entry_index, ignoring the entry");
return [ null, null ];
}
}
return [ $oembed_resp->thumbnail_url, $thumbnail_url_fallback ];
} elseif ($type === 'regex') {
$thumbnail_url_regex = $embed_entry['thumbnail_url'];
// Plz somebody review this.
return [ \preg_replace($match_regex, $thumbnail_url_regex, $rawText), null ];
} else {
$this->log->log(LogDriver::ERROR, "Unknown embed type '$type', ignoring the embed entry");
}
/**
* Find the embed entry matching with the url, if any.
*
* @param string $url Url to embed. MUST BE ALREADY VALIDATED.
* @return int The index of the matched embed entry or null.
*/
public function matchEmbed(string $url): ?int {
for ($i = 0; $i < \count($this->embed_entries); $i++) {
$match_regex = $this->embed_entries[$i]['match_regex'];
if (\preg_match($match_regex, $url, $matches)) {
return $i;
}
}
@ -94,26 +94,22 @@ class EmbedService {
}
/**
* @return array|int Returns the url to the thumbnail and if it should be moved if any embedding matches,
* otherwise it returns a MATCH_EMBED_ERR_* constant.
* Get the embed's thumbnail if possible. May download it from the network into a temporary file, or use a static file.
*
* @param string $url Url to embed. MUST BE ALREADY VALIDATED.
* @param int The index of the matched embed entry.
* @return ?array Null if no thumbnail can be selected, otherwise an array with the local file path to the thumbnail
* and if the the file is a temporary or a static one.
*/
public function matchEmbed(string $rawText) {
$rawText = \trim($rawText);
if (\filter_var($rawText, \FILTER_VALIDATE_URL) === false) {
return self::MATCH_EMBED_ERR_NOT_AN_URL;
}
$ret = $this->matchAndExtract($rawText);
if ($ret === null) {
return self::MATCH_EMBED_ERR_NO_MATCH;
}
public function getEmbedThumb(string $url, int $entry_index): ?array {
$ret = $this->extractThumb($url, $entry_index);
list($thumbnail_url, $thumbnail_url_fallback) = $ret;
if (!isset($thumbnail_url, $thumbnail_url_fallback)) {
return self::MATCH_EMBED_ERR_NO_THUMBNAIL;
return null;
}
if (\filter_var($thumbnail_url, \FILTER_VALIDATE_URL) === false) {
$this->log->log(LogDriver::ERROR, "Thumbnail URL '$thumbnail_url' is not a valid URL, trying fallback");
$this->log->log(LogDriver::ERROR, "Thumbnail URL '$thumbnail_url' from embed entry $entry_index is not a valid URL, trying fallback");
} else {
$tmp_file = $this->fetchThumbnail($thumbnail_url);
if ($tmp_file !== null) {
@ -123,8 +119,23 @@ class EmbedService {
}
if ($thumbnail_url_fallback === null) {
return self::MATCH_EMBED_ERR_NO_THUMBNAIL;
return null;
}
return [ $thumbnail_url_fallback, false ];
}
public function renderEmbed(string $url, int $entry_index, string $thumbnail_path): string {
$embed_entry = $this->embed_entries[$entry_index];
$match_regex = $embed_entry['match_regex'];
$html = $embed_entry['html'];
$ret = \preg_replace($match_regex, $html, $url);
if (!\is_string($ret)) {
throw new \RuntimeException("Error while applying regex replacement for embed entry $entry_index");
}
\str_replace('%%embed_url%%', $url, $ret);
\str_replace('%%thumbnail_path%%', $thumbnail_path, $ret);
return $ret;
}
}