clean
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
|
use DOMXPath;
|
||||||
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
|
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
|
||||||
|
|
||||||
// 💡 NEUE KORREKTUR: Starte Output Buffering so früh wie möglich, um Whitespace/Errors
|
// 💡 NEUE KORREKTUR: Starte Output Buffering so früh wie möglich, um Whitespace/Errors
|
||||||
@@ -659,6 +661,10 @@ class ApiKernel
|
|||||||
if ($html === '' && !empty($row['json_content'])) {
|
if ($html === '' && !empty($row['json_content'])) {
|
||||||
$html = '<p>(Dieses Template enthält noch keine HTML-Inhalte.)</p>';
|
$html = '<p>(Dieses Template enthält noch keine HTML-Inhalte.)</p>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$renderCache = [];
|
||||||
|
$renderStack = [];
|
||||||
|
$html = $this->renderHtmlWithReferences($html, $auth, $renderCache, $renderStack);
|
||||||
$html = $this->prepareEmailHtml($html);
|
$html = $this->prepareEmailHtml($html);
|
||||||
|
|
||||||
if (!$this->dispatchTestMail($recipient, $subject, $html)) {
|
if (!$this->dispatchTestMail($recipient, $subject, $html)) {
|
||||||
@@ -867,4 +873,119 @@ class ApiKernel
|
|||||||
$summary['total'] = array_sum($summary);
|
$summary['total'] = array_sum($summary);
|
||||||
return $summary;
|
return $summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function normalizeResourceKind(string $kind): ?string
|
||||||
|
{
|
||||||
|
$kind = strtolower(trim($kind));
|
||||||
|
$map = [
|
||||||
|
'template' => 'templates',
|
||||||
|
'templates' => 'templates',
|
||||||
|
'section' => 'sections',
|
||||||
|
'sections' => 'sections',
|
||||||
|
'block' => 'blocks',
|
||||||
|
'blocks' => 'blocks',
|
||||||
|
'snippet' => 'snippets',
|
||||||
|
'snippets' => 'snippets',
|
||||||
|
];
|
||||||
|
return $map[$kind] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveHtmlColumn(array $columns, string $kindKey): ?string
|
||||||
|
{
|
||||||
|
$candidates = ($kindKey === 'snippets')
|
||||||
|
? ['content', 'html', 'body', 'markup']
|
||||||
|
: ['html', 'body', 'markup', 'content'];
|
||||||
|
return $this->firstExisting($columns, $candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchResourceHtml(string $kind, int $id, array $auth, array &$cache, array &$stack): ?string
|
||||||
|
{
|
||||||
|
$kindKey = $this->normalizeResourceKind($kind);
|
||||||
|
if (!$kindKey || $id <= 0) return null;
|
||||||
|
|
||||||
|
$cacheKey = $kindKey . ':' . $id;
|
||||||
|
if (array_key_exists($cacheKey, $cache)) return $cache[$cacheKey];
|
||||||
|
if (!empty($stack[$cacheKey])) return null;
|
||||||
|
|
||||||
|
$table = $this->tableMap[$kindKey] ?? null;
|
||||||
|
if (!$table) return null;
|
||||||
|
[$idCol, $allCols] = $this->resolveIdCol($kindKey);
|
||||||
|
[$tw, $tp] = $this->tenantWhere($auth);
|
||||||
|
|
||||||
|
$sql = "SELECT * FROM `$table` WHERE `$idCol` = :id" . $tw . " LIMIT 1";
|
||||||
|
$stmt = $this->pdo->prepare($sql);
|
||||||
|
$stmt->bindValue(':id', $id);
|
||||||
|
foreach ($tp as $k => $v) $stmt->bindValue($k, $v);
|
||||||
|
$stmt->execute();
|
||||||
|
$row = $stmt->fetch();
|
||||||
|
if (!$row) {
|
||||||
|
$cache[$cacheKey] = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$htmlCol = $this->resolveHtmlColumn($allCols, $kindKey);
|
||||||
|
$html = $htmlCol && isset($row[$htmlCol]) ? (string)$row[$htmlCol] : '';
|
||||||
|
|
||||||
|
$stack[$cacheKey] = true;
|
||||||
|
$html = $this->renderHtmlWithReferences($html, $auth, $cache, $stack);
|
||||||
|
unset($stack[$cacheKey]);
|
||||||
|
|
||||||
|
$cache[$cacheKey] = $html;
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderHtmlWithReferences(string $html, array $auth, array &$cache, array &$stack): string
|
||||||
|
{
|
||||||
|
$trimmed = trim($html);
|
||||||
|
if ($trimmed === '') return $html;
|
||||||
|
if (!class_exists(DOMDocument::class)) return $html;
|
||||||
|
|
||||||
|
$flags = 0;
|
||||||
|
if (defined('LIBXML_HTML_NOIMPLIED')) {
|
||||||
|
$flags |= LIBXML_HTML_NOIMPLIED;
|
||||||
|
}
|
||||||
|
if (defined('LIBXML_HTML_NODEFDTD')) {
|
||||||
|
$flags |= LIBXML_HTML_NODEFDTD;
|
||||||
|
}
|
||||||
|
|
||||||
|
$doc = new DOMDocument('1.0', 'UTF-8');
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
$wrapper = '<div id="lib-ref-root">' . $html . '</div>';
|
||||||
|
$loaded = @$doc->loadHTML('<?xml encoding="utf-8"?>' . $wrapper, $flags);
|
||||||
|
libxml_clear_errors();
|
||||||
|
if (!$loaded) return $html;
|
||||||
|
|
||||||
|
$xpath = new DOMXPath($doc);
|
||||||
|
$nodes = $xpath->query('//*[@data-lib-kind and @data-lib-id]');
|
||||||
|
if ($nodes !== false) {
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
/** @var \DOMElement $node */
|
||||||
|
$kind = $node->getAttribute('data-lib-kind');
|
||||||
|
$refId = (int)$node->getAttribute('data-lib-id');
|
||||||
|
if (!$kind || $refId <= 0) continue;
|
||||||
|
$replacement = $this->fetchResourceHtml($kind, $refId, $auth, $cache, $stack);
|
||||||
|
if ($replacement === null) continue;
|
||||||
|
|
||||||
|
while ($node->firstChild) {
|
||||||
|
$node->removeChild($node->firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fragment = $doc->createDocumentFragment();
|
||||||
|
if (@$fragment->appendXML($replacement)) {
|
||||||
|
$node->appendChild($fragment);
|
||||||
|
} else {
|
||||||
|
$node->appendChild($doc->createTextNode($replacement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$root = $doc->getElementById('lib-ref-root');
|
||||||
|
if (!$root) return $html;
|
||||||
|
|
||||||
|
$output = '';
|
||||||
|
foreach ($root->childNodes as $child) {
|
||||||
|
$output .= $doc->saveHTML($child);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user