From 610389a5e683f4c4e4efa6c212d68f0c986842d5 Mon Sep 17 00:00:00 2001
From: Lars Gebhardt-Kusche
Date: Sun, 7 Dec 2025 01:51:03 +0100
Subject: [PATCH] clean
---
src/ApiKernel.php | 121 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
diff --git a/src/ApiKernel.php b/src/ApiKernel.php
index fc1ff29..40a0346 100644
--- a/src/ApiKernel.php
+++ b/src/ApiKernel.php
@@ -1,6 +1,8 @@
(Dieses Template enthält noch keine HTML-Inhalte.)
';
}
+
+ $renderCache = [];
+ $renderStack = [];
+ $html = $this->renderHtmlWithReferences($html, $auth, $renderCache, $renderStack);
$html = $this->prepareEmailHtml($html);
if (!$this->dispatchTestMail($recipient, $subject, $html)) {
@@ -867,4 +873,119 @@ class ApiKernel
$summary['total'] = array_sum($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 = '' . $html . '
';
+ $loaded = @$doc->loadHTML('' . $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;
+ }
}