124 lines
4.9 KiB
PHP
124 lines
4.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/common.php';
|
|
|
|
api_require_method('GET', 'POST');
|
|
$staff = api_require_staff();
|
|
api_require_admin_or_permission($staff, 'manage_kb');
|
|
$pdo = get_db();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
$categories = $pdo->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.');
|