loadHTML(
'
' . $html . '
',
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
libxml_clear_errors();
libxml_use_internal_errors($previous);
if (!$loaded) {
throw new LocalizedException(__('Unable to parse HTML file: %1', $htmlPath));
}
$xpath = new \DOMXPath($document);
$article = $xpath->query(
'//*[contains(concat(" ", normalize-space(@class), " "), " blog-article ")]'
)->item(0);
$contentRoot = $article instanceof \DOMElement
? $article
: $xpath->query('//*[@id="esun-import-root"]')->item(0);
if (!$contentRoot instanceof \DOMElement) {
throw new LocalizedException(__('No importable HTML content found in %1.', $htmlPath));
}
$removeQueries = [
'.//h1[contains(concat(" ", normalize-space(@class), " "), " news-title ")]',
'.//*[contains(concat(" ", normalize-space(@class), " "), " news-time ")]',
'.//script',
'.//*[contains(concat(" ", normalize-space(@class), " "), " picker ")]',
'./*[contains(concat(" ", normalize-space(@class), " "), " clear ")]',
];
foreach ($removeQueries as $query) {
$nodes = iterator_to_array($xpath->query($query, $contentRoot));
foreach ($nodes as $node) {
$node->parentNode?->removeChild($node);
}
}
$media = [];
$mediaReplacements = [];
foreach (iterator_to_array($xpath->query('.//*', $contentRoot)) as $element) {
if (!$element instanceof \DOMElement) {
continue;
}
foreach (['src', 'href', 'poster'] as $attribute) {
if (!$element->hasAttribute($attribute)) {
continue;
}
$relativeMediaPath = $this->getLegacyMediaPath($element->getAttribute($attribute));
if ($relativeMediaPath === null) {
continue;
}
$media[$relativeMediaPath] = $relativeMediaPath;
$placeholder = sprintf('__ESUN_IMPORTED_MEDIA_%d__', count($mediaReplacements));
$mediaReplacements[$placeholder] = sprintf(
"{{media url='%s/%s'}}",
$mediaSubdirectory,
str_replace("'", ''', $relativeMediaPath)
);
$element->setAttribute($attribute, $placeholder);
}
}
$output = '';
foreach ($contentRoot->childNodes as $child) {
$output .= $document->saveHTML($child);
}
$output = trim(strtr($output, $mediaReplacements));
if ($output === '') {
throw new LocalizedException(__('HTML content became empty after processing: %1', $htmlPath));
}
return ['html' => $output, 'media' => array_values($media)];
}
private function getLegacyMediaPath(string $url): ?string
{
$url = html_entity_decode(trim($url), ENT_QUOTES | ENT_HTML5);
$path = '';
if (str_starts_with($url, '/uploads/')) {
$embeddedUrl = rawurldecode(substr($url, strlen('/uploads/')));
if (preg_match('#^(?:https?:)?//#iu', $embeddedUrl)) {
return null;
}
$path = $url;
} elseif (preg_match(
'#^(?:https?:)?//([^/]+)(/.*)$#iu',
$url,
$matches
)) {
if (!in_array(strtolower($matches[1]), self::ESUN_MEDIA_HOSTS, true)) {
return null;
}
$path = $matches[2];
}
if ($path === '') {
return null;
}
$path = (string)preg_split('/[?#]/', $path, 2)[0];
$filename = rawurldecode(basename($path));
if ($filename === '' || $filename === '.' || $filename === '..') {
return null;
}
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($extension, self::MEDIA_EXTENSIONS, true)) {
return null;
}
return $filename;
}
}