Files
esun3d/app/code/Esun3d/LanguageUrlStoreResolver/Model/HtmlLinkProcessor.php
T
2026-09-15 10:35:56 +08:00

77 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
namespace Esun3d\LanguageUrlStoreResolver\Model;
class HtmlLinkProcessor
{
/**
* @var UrlPathConverter
*/
private $urlPathConverter;
/**
* @param UrlPathConverter $urlPathConverter
*/
public function __construct(UrlPathConverter $urlPathConverter)
{
$this->urlPathConverter = $urlPathConverter;
}
/**
* Convert internal anchor URLs in complete page HTML.
*
* @param string $html
* @param string $language
* @return string
*/
public function process(string $html, string $language): string
{
if (stripos($html, '<a') === false) {
return $html;
}
$result = preg_replace_callback(
'~(<a\b[^>]*\bhref\s*=\s*)(["\'])(.*?)\2~is',
function (array $matches) use ($language): string {
$href = $matches[3];
$normalizedHref = trim($href);
if (!$this->isConvertibleHref($normalizedHref)) {
return $matches[0];
}
$convertedHref = $this->urlPathConverter->toLanguageUrl($normalizedHref, $language);
if ($convertedHref === $normalizedHref) {
return $matches[0];
}
return $matches[1] . $matches[2] . $convertedHref . $matches[2];
},
$html
);
return is_string($result) ? $result : $html;
}
/**
* Check whether an href represents a navigational HTTP URL.
*
* @param string $href
* @return bool
*/
private function isConvertibleHref(string $href): bool
{
if ($href === '' || $href[0] === '#' || $href[0] === '?') {
return false;
}
if (strpos($href, '{{') !== false || strpos($href, '${') !== false) {
return false;
}
return !preg_match('~^[a-z][a-z0-9+.-]*:~i', $href)
|| preg_match('~^https?:~i', $href) === 1;
}
}