query('SELECT * FROM kb_categories ORDER BY sort_order, name')->fetchAll(); $articles = $pdo->query( 'SELECT a.*, c.name AS category_name FROM kb_articles a JOIN kb_categories c ON c.id=a.category_id ORDER BY a.title' )->fetchAll(); api_json([ 'categories' => array_map(fn(array $c) => [ 'id' => (int) $c['id'], 'name' => $c['name'], ], $categories), 'articles' => array_map(fn(array $a) => [ 'id' => (int) $a['id'], 'categoryId' => (int) $a['category_id'], 'categoryName' => $a['category_name'], 'title' => $a['title'], 'body' => $a['body'], 'isPublished' => (bool) $a['is_published'], 'views' => (int) $a['views'], ], $articles), ]); } $body = api_request_body(); $action = $body['action'] ?? ''; if ($action === 'create_category') { $name = trim((string) ($body['name'] ?? '')); if ($name === '') { api_error(422, 'NAME_REQUIRED', 'Bitte einen Kategorienamen angeben.'); } $slug = slugify($name); $pdo->prepare('INSERT INTO kb_categories (name, slug, sort_order) VALUES (?,?,0)')->execute([$name, $slug]); $newId = (int) $pdo->lastInsertId(); audit_log($staff['id'], "KB-Kategorie erstellt: {$name} (Mobile App)"); api_json(['id' => $newId]); } if ($action === 'delete_category') { $id = (int) ($body['id'] ?? 0); $stmt = $pdo->prepare('SELECT COUNT(*) FROM kb_articles WHERE category_id = ?'); $stmt->execute([$id]); if ((int) $stmt->fetchColumn() > 0) { api_error(422, 'CATEGORY_NOT_EMPTY', 'Diese Kategorie enthält noch Artikel und kann nicht gelöscht werden.'); } $nameStmt = $pdo->prepare('SELECT name FROM kb_categories WHERE id = ?'); $nameStmt->execute([$id]); $catName = $nameStmt->fetchColumn(); $pdo->prepare('DELETE FROM kb_categories WHERE id = ?')->execute([$id]); audit_log($staff['id'], "KB-Kategorie gelöscht: {$catName} (Mobile App)"); api_json(['ok' => true]); } if ($action === 'save_article') { $id = (int) ($body['id'] ?? 0); $title = trim((string) ($body['title'] ?? '')); $categoryId = (int) ($body['categoryId'] ?? 0); $articleBody = sanitize_staff_html((string) ($body['body'] ?? '')); $isPublished = !empty($body['isPublished']) ? 1 : 0; if ($title === '') { api_error(422, 'TITLE_REQUIRED', 'Bitte einen Titel angeben.'); } if (trim(strip_tags($articleBody)) === '') { api_error(422, 'BODY_REQUIRED', 'Bitte einen Inhalt angeben.'); } $catCheck = $pdo->prepare('SELECT COUNT(*) FROM kb_categories WHERE id = ?'); $catCheck->execute([$categoryId]); if (!(bool) $catCheck->fetchColumn()) { api_error(422, 'INVALID_CATEGORY', 'Bitte eine gültige Kategorie wählen.'); } if ($id === 0) { $slug = slugify($title); $base = $slug; $i = 2; $check = $pdo->prepare('SELECT COUNT(*) FROM kb_articles WHERE slug = ?'); while (true) { $check->execute([$slug]); if ((int) $check->fetchColumn() === 0) break; $slug = $base . '-' . $i++; } $pdo->prepare('INSERT INTO kb_articles (category_id, title, slug, body, is_published, created_at, updated_at) VALUES (?,?,?,?,?,?,?)') ->execute([$categoryId, $title, $slug, $articleBody, $isPublished, db_now(), db_now()]); $newId = (int) $pdo->lastInsertId(); audit_log($staff['id'], "KB-Artikel erstellt: {$title} (Mobile App)"); } else { $existsStmt = $pdo->prepare('SELECT COUNT(*) FROM kb_articles WHERE id = ?'); $existsStmt->execute([$id]); if (!(bool) $existsStmt->fetchColumn()) { api_error(404, 'ARTICLE_NOT_FOUND', 'Der Artikel wurde nicht gefunden.'); } $pdo->prepare('UPDATE kb_articles SET category_id=?, title=?, body=?, is_published=?, updated_at=? WHERE id=?') ->execute([$categoryId, $title, $articleBody, $isPublished, db_now(), $id]); $newId = $id; audit_log($staff['id'], "KB-Artikel aktualisiert: {$title} (Mobile App)"); } api_json(['id' => $newId]); } if ($action === 'delete_article') { $id = (int) ($body['id'] ?? 0); $titleStmt = $pdo->prepare('SELECT title FROM kb_articles WHERE id = ?'); $titleStmt->execute([$id]); $artTitle = $titleStmt->fetchColumn(); if ($artTitle === false) { api_error(404, 'ARTICLE_NOT_FOUND', 'Der Artikel wurde nicht gefunden.'); } $pdo->prepare('DELETE FROM kb_articles WHERE id = ?')->execute([$id]); audit_log($staff['id'], "KB-Artikel gelöscht: {$artTitle} (Mobile App)"); api_json(['ok' => true]); } api_error(422, 'INVALID_ACTION', 'Unbekannte Aktion.');