update schema and so on
This commit is contained in:
@@ -172,7 +172,7 @@ class ApiKernel
|
||||
private function resolveAction(): void { /* ... Logik bleibt unverändert ... */
|
||||
$action = $this->val($this->in, 'action', '');
|
||||
$resource = $this->val($this->in, 'resource', null);
|
||||
$allowedResources = ['templates', 'sections', 'blocks', 'snippets', 'content', 'sections_config'];
|
||||
$allowedResources = ['templates', 'sections', 'blocks', 'snippets', 'content', 'sections_config', 'content_versions'];
|
||||
if ($resource && in_array($resource, $allowedResources, true) && strpos((string)$action, '.') === false) {
|
||||
$verb = strtolower((string)$action);
|
||||
if (in_array($verb, ['list', 'get', 'create', 'update', 'delete'], true)) $action = $resource . '.' . $verb;
|
||||
@@ -188,6 +188,7 @@ class ApiKernel
|
||||
'snippets' => $tables['snippets'] ?? 'emailtemplate_snippets',
|
||||
'content_items' => $tables['content_items'] ?? 'emailtemplate_content_items',
|
||||
'content_sections' => $tables['content_sections'] ?? 'emailtemplate_content_sections',
|
||||
'content_versions' => $tables['content_versions'] ?? 'emailtemplate_content_versions',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -342,6 +343,11 @@ class ApiKernel
|
||||
return $this->tableMap['content_sections'] ?? $this->lookupTableName('content_sections', 'emailtemplate_content_sections');
|
||||
}
|
||||
|
||||
private function contentVersionsTable(): string
|
||||
{
|
||||
return $this->tableMap['content_versions'] ?? $this->lookupTableName('content_versions', 'emailtemplate_content_versions');
|
||||
}
|
||||
|
||||
private function resolveContentItemColumns(string $table): array
|
||||
{
|
||||
$cols = $this->tableColumns($table);
|
||||
@@ -360,6 +366,59 @@ class ApiKernel
|
||||
return $this->tableExists($this->contentItemsTable()) && $this->tableExists($this->contentSectionsTable());
|
||||
}
|
||||
|
||||
private function createContentVersion(array $current, array $itemCols, int $customerId, int $sectionId): void
|
||||
{
|
||||
$table = $this->contentVersionsTable();
|
||||
if (!$this->tableExists($table)) return;
|
||||
$contentId = (int)($current['id'] ?? 0);
|
||||
if ($contentId <= 0) return;
|
||||
|
||||
$jsonCol = $itemCols['json'] ?? null;
|
||||
$htmlCol = $itemCols['html'] ?? null;
|
||||
$editorCol = $itemCols['editor'] ?? null;
|
||||
$craftCol = $itemCols['craft'] ?? null;
|
||||
$settingsCol = $itemCols['settings'] ?? null;
|
||||
|
||||
$json = $jsonCol ? ($current[$jsonCol] ?? null) : null;
|
||||
$html = $htmlCol ? ($current[$htmlCol] ?? null) : null;
|
||||
$editorType = $editorCol ? ($current[$editorCol] ?? null) : null;
|
||||
$craftJson = $craftCol ? ($current[$craftCol] ?? null) : null;
|
||||
$settings = $settingsCol ? ($current[$settingsCol] ?? null) : null;
|
||||
|
||||
try {
|
||||
$stmt = $this->pdo->prepare("SELECT MAX(`version_no`) FROM `$table` WHERE `content_id` = :cid");
|
||||
$stmt->execute([':cid' => $contentId]);
|
||||
$nextVersion = (int)($stmt->fetchColumn() ?: 0) + 1;
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"INSERT INTO `$table` (`customer_id`,`content_id`,`section_id`,`version_no`,`editor_type`,`json_content`,`html`,`craft_json`,`settings_json`)
|
||||
VALUES (:cust,:content,:section,:ver,:editor,:json,:html,:craft,:settings)"
|
||||
);
|
||||
$stmt->execute([
|
||||
':cust' => $customerId,
|
||||
':content' => $contentId,
|
||||
':section' => $sectionId,
|
||||
':ver' => $nextVersion,
|
||||
':editor' => $editorType,
|
||||
':json' => $json,
|
||||
':html' => $html,
|
||||
':craft' => $craftJson,
|
||||
':settings' => $settings,
|
||||
]);
|
||||
|
||||
$cleanup = $this->pdo->prepare(
|
||||
"DELETE FROM `$table` WHERE `id` IN (
|
||||
SELECT `id` FROM (
|
||||
SELECT `id` FROM `$table` WHERE `content_id` = :cid ORDER BY `id` DESC LIMIT 10, 1000000
|
||||
) t
|
||||
)"
|
||||
);
|
||||
$cleanup->execute([':cid' => $contentId]);
|
||||
} catch (Throwable $e) {
|
||||
// Versioning darf nicht das Speichern blockieren.
|
||||
}
|
||||
}
|
||||
|
||||
private function isLegacyContentKind(string $kind): bool
|
||||
{
|
||||
return in_array($kind, ['templates', 'sections', 'blocks', 'snippets'], true);
|
||||
@@ -843,6 +902,20 @@ class ApiKernel
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($section['is_template'])) {
|
||||
$versionCols = array_filter([$jsonCol, $htmlCol, $craftCol, $settingsCol, $editorCol]);
|
||||
$shouldSnapshot = false;
|
||||
foreach ($versionCols as $col) {
|
||||
if (array_key_exists($col, $data)) {
|
||||
$shouldSnapshot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($shouldSnapshot) {
|
||||
$this->createContentVersion($current, $itemCols, $customerId, (int)($section['id'] ?? 0));
|
||||
}
|
||||
}
|
||||
|
||||
$set = implode(',', array_map(static fn($c) => "`$c` = :$c", array_keys($data)));
|
||||
$data['id'] = $id;
|
||||
$data['customer_id'] = $customerId;
|
||||
@@ -880,6 +953,121 @@ class ApiKernel
|
||||
$this->respond(['ok' => true, 'kind' => 'content', 'id' => $id, 'deleted' => true]);
|
||||
}
|
||||
|
||||
private function handleContentVersionsList(): void
|
||||
{
|
||||
$auth = $this->requireAuth();
|
||||
$customerId = (int)($auth['customer_id'] ?? 0);
|
||||
if ($customerId <= 0) $this->fail('Customer context missing', null, 500);
|
||||
$contentId = (int)$this->val($this->in, ['content_id', 'id'], 0);
|
||||
if ($contentId <= 0) $this->fail('content_id required', null, 422);
|
||||
|
||||
$table = $this->contentVersionsTable();
|
||||
if (!$this->tableExists($table)) {
|
||||
$this->respond(['ok' => true, 'items' => [], 'data' => []]);
|
||||
return;
|
||||
}
|
||||
|
||||
$itemsTable = $this->contentItemsTable();
|
||||
if ($this->tableExists($itemsTable)) {
|
||||
$stmt = $this->pdo->prepare("SELECT `id` FROM `$itemsTable` WHERE `id` = :id AND `customer_id` = :cid LIMIT 1");
|
||||
$stmt->execute([':id' => $contentId, ':cid' => $customerId]);
|
||||
if (!$stmt->fetch()) $this->fail('Not found', ['id' => $contentId], 404);
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
"SELECT `id`,`content_id`,`section_id`,`version_no`,`editor_type`,`created_at`
|
||||
FROM `$table` WHERE `customer_id` = :cid AND `content_id` = :content
|
||||
ORDER BY `id` DESC LIMIT 10"
|
||||
);
|
||||
$stmt->execute([':cid' => $customerId, ':content' => $contentId]);
|
||||
$rows = $stmt->fetchAll() ?: [];
|
||||
$items = array_map(static function ($row) {
|
||||
return [
|
||||
'id' => (int)($row['id'] ?? 0),
|
||||
'content_id' => (int)($row['content_id'] ?? 0),
|
||||
'section_id' => (int)($row['section_id'] ?? 0),
|
||||
'version_no' => (int)($row['version_no'] ?? 0),
|
||||
'editor_type' => $row['editor_type'] ?? null,
|
||||
'created_at' => $row['created_at'] ?? null,
|
||||
];
|
||||
}, $rows);
|
||||
$this->respond(['ok' => true, 'items' => $items, 'data' => $items]);
|
||||
}
|
||||
|
||||
private function handleContentVersionsGet(): void
|
||||
{
|
||||
$auth = $this->requireAuth();
|
||||
$customerId = (int)($auth['customer_id'] ?? 0);
|
||||
if ($customerId <= 0) $this->fail('Customer context missing', null, 500);
|
||||
$id = (int)$this->pullId($this->in);
|
||||
if ($id <= 0) $this->fail('id required', null, 422);
|
||||
$contentId = (int)$this->val($this->in, ['content_id', 'content'], 0);
|
||||
|
||||
$table = $this->contentVersionsTable();
|
||||
if (!$this->tableExists($table)) $this->fail('Versions table not available', null, 500);
|
||||
|
||||
$sql = "SELECT * FROM `$table` WHERE `id` = :id AND `customer_id` = :cid";
|
||||
$params = [':id' => $id, ':cid' => $customerId];
|
||||
if ($contentId > 0) {
|
||||
$sql .= " AND `content_id` = :content";
|
||||
$params[':content'] = $contentId;
|
||||
}
|
||||
$sql .= " LIMIT 1";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$row = $stmt->fetch();
|
||||
if (!$row) $this->fail('Not found', ['id' => $id], 404);
|
||||
$this->respond(['ok' => true, 'item' => $row, 'data' => $row]);
|
||||
}
|
||||
|
||||
private function handleContentVersionsRestore(): void
|
||||
{
|
||||
$auth = $this->requireAuth();
|
||||
$customerId = (int)($auth['customer_id'] ?? 0);
|
||||
if ($customerId <= 0) $this->fail('Customer context missing', null, 500);
|
||||
$versionId = (int)$this->val($this->in, ['id', 'version_id', 'version'], 0);
|
||||
if ($versionId <= 0) $this->fail('version id required', null, 422);
|
||||
$contentId = (int)$this->val($this->in, ['content_id', 'content'], 0);
|
||||
|
||||
$versionsTable = $this->contentVersionsTable();
|
||||
$itemsTable = $this->contentItemsTable();
|
||||
if (!$this->tableExists($versionsTable) || !$this->tableExists($itemsTable)) {
|
||||
$this->fail('Content tables not available', null, 500);
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM `$versionsTable` WHERE `id` = :id AND `customer_id` = :cid";
|
||||
$params = [':id' => $versionId, ':cid' => $customerId];
|
||||
if ($contentId > 0) {
|
||||
$sql .= " AND `content_id` = :content";
|
||||
$params[':content'] = $contentId;
|
||||
}
|
||||
$sql .= " LIMIT 1";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$version = $stmt->fetch();
|
||||
if (!$version) $this->fail('Not found', ['id' => $versionId], 404);
|
||||
|
||||
$itemCols = $this->resolveContentItemColumns($itemsTable);
|
||||
$data = [];
|
||||
if (!empty($itemCols['json'])) $data[$itemCols['json']] = $version['json_content'] ?? null;
|
||||
if (!empty($itemCols['html'])) $data[$itemCols['html']] = $version['html'] ?? null;
|
||||
if (!empty($itemCols['craft'])) $data[$itemCols['craft']] = $version['craft_json'] ?? null;
|
||||
if (!empty($itemCols['settings'])) $data[$itemCols['settings']] = $version['settings_json'] ?? null;
|
||||
if (!empty($itemCols['editor'])) $data[$itemCols['editor']] = $version['editor_type'] ?? null;
|
||||
|
||||
if ($data) {
|
||||
$set = implode(',', array_map(static fn($c) => "`$c` = :$c", array_keys($data)));
|
||||
$data['id'] = (int)($version['content_id'] ?? 0);
|
||||
$data['customer_id'] = $customerId;
|
||||
$sql = "UPDATE `$itemsTable` SET $set WHERE `id` = :id AND `customer_id` = :customer_id LIMIT 1";
|
||||
$stmt = $this->pdo->prepare($sql);
|
||||
foreach ($data as $k => $v) $stmt->bindValue(":$k", $v);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$this->respond(['ok' => true, 'restored' => true, 'content_id' => (int)($version['content_id'] ?? 0)]);
|
||||
}
|
||||
|
||||
private function handleSectionsConfigList(): void
|
||||
{
|
||||
$auth = $this->requireAuth();
|
||||
@@ -2072,19 +2260,24 @@ class ApiKernel
|
||||
case 'sections_config.reorder':
|
||||
$this->handleSectionsConfigReorder();
|
||||
break;
|
||||
case 'content_versions.restore':
|
||||
$this->handleContentVersionsRestore();
|
||||
break;
|
||||
|
||||
/* ---------- CRUD HANDLER ---------- */
|
||||
default:
|
||||
if (in_array($kind, ['templates', 'sections', 'blocks', 'snippets', 'content', 'sections_config'])) {
|
||||
if (in_array($kind, ['templates', 'sections', 'blocks', 'snippets', 'content', 'sections_config', 'content_versions'])) {
|
||||
switch ($operation) {
|
||||
case 'list':
|
||||
if ($kind === 'content') $this->handleContentList();
|
||||
elseif ($kind === 'sections_config') $this->handleSectionsConfigList();
|
||||
elseif ($kind === 'content_versions') $this->handleContentVersionsList();
|
||||
else $this->handleList($kind);
|
||||
break;
|
||||
case 'get':
|
||||
if ($kind === 'content') $this->handleContentGet();
|
||||
elseif ($kind === 'sections_config') $this->handleSectionsConfigGet();
|
||||
elseif ($kind === 'content_versions') $this->handleContentVersionsGet();
|
||||
else $this->handleGet($kind);
|
||||
break;
|
||||
case 'create':
|
||||
|
||||
Reference in New Issue
Block a user