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; } }