From 57dc40fd46bd67863a90b130d4183865dfe2ef55 Mon Sep 17 00:00:00 2001 From: Lars Gebhardt-Kusche Date: Sun, 1 Feb 2026 01:34:05 +0100 Subject: [PATCH] =?UTF-8?q?L=C3=B6schen/Deaktivierung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/current.ver | 2 +- public/assets/js/ui-editor.js | 5 +- public/assets/js/ui-list.js | 8 +- src/ApiKernel.php | 160 ++++++++++++++++++++++++++++------ 4 files changed, 145 insertions(+), 30 deletions(-) diff --git a/config/current.ver b/config/current.ver index d2d61a7..e2cac26 100644 --- a/config/current.ver +++ b/config/current.ver @@ -1 +1 @@ -1.2.2 \ No newline at end of file +1.2.3 \ No newline at end of file diff --git a/public/assets/js/ui-editor.js b/public/assets/js/ui-editor.js index 340f436..f8d1f31 100644 --- a/public/assets/js/ui-editor.js +++ b/public/assets/js/ui-editor.js @@ -1062,7 +1062,10 @@ export function initEditor() { async function confirmTemplateReferences(actionLabel) { if (!current?.section?.is_template || !current?.id) return true; - const res = await apiAction('templates.references', { method: 'GET', data: { template_id: current.id } }).catch(() => ({})); + const res = await apiAction('templates.references', { method: 'GET', data: { template_id: current.id } }).catch(() => null); + if (!res || res.ok === false) { + return confirm(`Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`); + } const refs = Array.isArray(res?.references) ? res.references : []; if (!refs.length) return true; const preview = refs.slice(0, 6).map(r => `${r.name || 'Template'} #${r.id}`).join(', '); diff --git a/public/assets/js/ui-list.js b/public/assets/js/ui-list.js index 378bf11..cd1370c 100644 --- a/public/assets/js/ui-list.js +++ b/public/assets/js/ui-list.js @@ -89,14 +89,18 @@ async function openTemplateManager(item, section) { let activeId = 0; const fetchTemplateReferences = async () => { - if (!section?.is_template) return []; - const res = await apiAction('templates.references', { method: 'GET', data: { template_id: item.id } }).catch(() => ({})); + if (!section?.is_template) return null; + const res = await apiAction('templates.references', { method: 'GET', data: { template_id: item.id } }).catch(() => null); + if (!res || res.ok === false) return null; return Array.isArray(res?.references) ? res.references : []; }; const confirmTemplateReferences = async (actionLabel) => { if (!section?.is_template) return true; const refs = await fetchTemplateReferences(); + if (refs === null) { + return confirm(`Referenzen konnten nicht geprüft werden. ${actionLabel} trotzdem?`); + } if (!refs.length) return true; const preview = refs.slice(0, 6).map(r => `${r.name || 'Template'} #${r.id}`).join(', '); const more = refs.length > 6 ? ` und ${refs.length - 6} weitere` : ''; diff --git a/src/ApiKernel.php b/src/ApiKernel.php index fb59c45..c25b236 100644 --- a/src/ApiKernel.php +++ b/src/ApiKernel.php @@ -2230,6 +2230,7 @@ class ApiKernel private function findTemplateReferences(int $customerId, int $templateId): array { $out = []; + $seen = []; $matches = function (?string $html) use ($templateId): bool { if (!$html) return false; $id = preg_quote((string)$templateId, '/'); @@ -2246,18 +2247,33 @@ class ApiKernel if (!$this->tableExists($itemsTable)) return []; $itemCols = $this->resolveContentItemColumns($itemsTable); $htmlCol = $itemCols['html']; + $jsonCol = $itemCols['json']; + $craftCol = $itemCols['craft']; $versionsTable = $this->contentVersionsTable(); $versionCols = ($this->tableExists($versionsTable)) ? $this->resolveContentVersionColumns($versionsTable) : null; $versionHtmlCol = $versionCols['html'] ?? null; + $versionJsonCol = $versionCols['json'] ?? null; + $versionCraftCol = $versionCols['craft'] ?? null; $versionActiveCol = $versionCols['is_active'] ?? null; $select = "i.`id` AS id, i.`name` AS name"; if ($htmlCol) $select .= ", i.`$htmlCol` AS item_html"; + if ($jsonCol) $select .= ", i.`$jsonCol` AS item_json"; + if ($craftCol) $select .= ", i.`$craftCol` AS item_craft"; $join = ''; + $hasVersionJoin = $versionActiveCol && ($versionHtmlCol || $versionJsonCol || $versionCraftCol); + if ($hasVersionJoin) { + $join = "LEFT JOIN `$versionsTable` v ON v.`content_id` = i.`id` AND v.`$versionActiveCol` = 1"; + } if ($versionHtmlCol && $versionActiveCol) { $select .= ", v.`$versionHtmlCol` AS version_html"; - $join = "LEFT JOIN `$versionsTable` v ON v.`content_id` = i.`id` AND v.`$versionActiveCol` = 1"; + } + if ($versionJsonCol && $versionActiveCol) { + $select .= ", v.`$versionJsonCol` AS version_json"; + } + if ($versionCraftCol && $versionActiveCol) { + $select .= ", v.`$versionCraftCol` AS version_craft"; } $sql = "SELECT $select FROM `$itemsTable` i $join WHERE i.`customer_id` = :cid AND i.`section_id` = :sid AND i.`id` <> :id"; $stmt = $this->pdo->prepare($sql); @@ -2265,38 +2281,130 @@ class ApiKernel $rows = $stmt->fetchAll() ?: []; foreach ($rows as $row) { - $html = (string)($row['version_html'] ?? $row['item_html'] ?? ''); - if ($matches($html)) { + $blobs = [ + (string)($row['version_html'] ?? ''), + (string)($row['item_html'] ?? ''), + (string)($row['version_json'] ?? ''), + (string)($row['item_json'] ?? ''), + (string)($row['version_craft'] ?? ''), + (string)($row['item_craft'] ?? ''), + ]; + $found = false; + foreach ($blobs as $blob) { + if ($matches($blob)) { $found = true; break; } + } + if ($found) { + $id = (int)($row['id'] ?? 0); + if ($id <= 0 || isset($seen[$id])) continue; + $seen[$id] = true; $out[] = [ - 'id' => (int)($row['id'] ?? 0), + 'id' => $id, 'name' => (string)($row['name'] ?? ''), ]; } } - return $out; + } + if (!$this->useUnifiedContent()) { + $table = $this->tableMap['templates'] ?? null; + if ($table && $this->tableExists($table)) { + [$idCol, $allCols] = $this->resolveIdCol('templates'); + $htmlCol = $this->firstExisting($allCols, ['html', 'body', 'markup', 'content']); + $jsonCol = $this->firstExisting($allCols, ['json_content']); + $craftCol = $this->firstExisting($allCols, ['craft_json', 'craft_content', 'craft_data']); + if ($htmlCol || $jsonCol || $craftCol) { + $nameCol = $this->conf['columns']['templates']['name'] ?? ($this->firstExisting($allCols, ['name']) ?: $idCol); + [$tw, $tp] = $this->tenantWhere(['customer_id' => $customerId]); + $select = "`$idCol` AS id, `$nameCol` AS name"; + if ($htmlCol) $select .= ", `$htmlCol` AS html"; + if ($jsonCol) $select .= ", `$jsonCol` AS json"; + if ($craftCol) $select .= ", `$craftCol` AS craft"; + $sql = "SELECT $select FROM `$table` WHERE `$idCol` <> :id" . $tw; + $stmt = $this->pdo->prepare($sql); + $stmt->bindValue(':id', $templateId, PDO::PARAM_INT); + foreach ($tp as $k => $v) $stmt->bindValue($k, $v); + $stmt->execute(); + $rows = $stmt->fetchAll() ?: []; + foreach ($rows as $row) { + $blobs = [ + (string)($row['html'] ?? ''), + (string)($row['json'] ?? ''), + (string)($row['craft'] ?? ''), + ]; + $found = false; + foreach ($blobs as $blob) { + if ($matches($blob)) { $found = true; break; } + } + if ($found) { + $id = (int)($row['id'] ?? 0); + if ($id <= 0 || isset($seen[$id])) continue; + $seen[$id] = true; + $out[] = [ + 'id' => $id, + 'name' => (string)($row['name'] ?? ''), + ]; + } + } + } + } } - $table = $this->tableMap['templates'] ?? null; - if (!$table || !$this->tableExists($table)) return []; - - [$idCol, $allCols] = $this->resolveIdCol('templates'); - $htmlCol = $this->firstExisting($allCols, ['html', 'body', 'markup', 'content']); - if (!$htmlCol) return []; - $nameCol = $this->conf['columns']['templates']['name'] ?? ($this->firstExisting($allCols, ['name']) ?: $idCol); - - [$tw, $tp] = $this->tenantWhere(['customer_id' => $customerId]); - $sql = "SELECT `$idCol` AS id, `$nameCol` AS name, `$htmlCol` AS html FROM `$table` WHERE `$idCol` <> :id" . $tw; - $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':id', $templateId, PDO::PARAM_INT); - foreach ($tp as $k => $v) $stmt->bindValue($k, $v); - $stmt->execute(); - $rows = $stmt->fetchAll() ?: []; - foreach ($rows as $row) { - if ($matches((string)($row['html'] ?? ''))) { - $out[] = [ - 'id' => (int)($row['id'] ?? 0), - 'name' => (string)($row['name'] ?? ''), - ]; + $templateItemsTable = $this->lookupTableName('template_items', 'emailtemplate_template_items'); + if ($this->tableExists($templateItemsTable)) { + $sql = "SELECT DISTINCT `template_id` FROM `$templateItemsTable` WHERE `customer_id` = :cid AND `ref_type` = :rt AND `ref_id` = :rid"; + $stmt = $this->pdo->prepare($sql); + $stmt->execute([':cid' => $customerId, ':rt' => 'section', ':rid' => $templateId]); + $ids = array_filter(array_map('intval', array_column($stmt->fetchAll() ?: [], 'template_id'))); + if ($ids) { + if ($this->useUnifiedContent()) { + $section = $this->ensureEmailtemplateSection($customerId); + if ($section) { + $itemsTable = $this->contentItemsTable(); + $nameCol = $this->resolveContentItemColumns($itemsTable)['category'] ? 'name' : 'name'; + $placeholders = implode(',', array_fill(0, count($ids), '?')); + $sql = "SELECT `id`, `name` FROM `$itemsTable` WHERE `customer_id` = ? AND `section_id` = ? AND `id` IN ($placeholders)"; + $stmt = $this->pdo->prepare($sql); + $stmt->execute(array_merge([$customerId, (int)$section['id']], $ids)); + $rows = $stmt->fetchAll() ?: []; + foreach ($rows as $row) { + $id = (int)($row['id'] ?? 0); + if ($id <= 0 || isset($seen[$id])) continue; + $seen[$id] = true; + $out[] = [ + 'id' => $id, + 'name' => (string)($row['name'] ?? ''), + ]; + } + } + } else { + $table = $this->tableMap['templates'] ?? null; + if ($table && $this->tableExists($table)) { + [$idCol, $allCols] = $this->resolveIdCol('templates'); + $nameCol = $this->conf['columns']['templates']['name'] ?? ($this->firstExisting($allCols, ['name']) ?: $idCol); + $ph = []; + $params = []; + foreach ($ids as $idx => $val) { + $key = ':id' . $idx; + $ph[] = $key; + $params[$key] = $val; + } + [$tw, $tp] = $this->tenantWhere(['customer_id' => $customerId]); + $sql = "SELECT `$idCol` AS id, `$nameCol` AS name FROM `$table` WHERE `$idCol` IN (" . implode(',', $ph) . ")" . $tw; + $stmt = $this->pdo->prepare($sql); + foreach ($params as $k => $v) $stmt->bindValue($k, $v, PDO::PARAM_INT); + foreach ($tp as $k => $v) $stmt->bindValue($k, $v); + $stmt->execute(); + $rows = $stmt->fetchAll() ?: []; + foreach ($rows as $row) { + $id = (int)($row['id'] ?? 0); + if ($id <= 0 || isset($seen[$id])) continue; + $seen[$id] = true; + $out[] = [ + 'id' => $id, + 'name' => (string)($row['name'] ?? ''), + ]; + } + } + } } } return $out;