198 lines
8.7 KiB
PHP
198 lines
8.7 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../includes/bootstrap.php';
|
|
$admin = require_admin_or_permission('manage_kb');
|
|
$pdo = get_db();
|
|
|
|
$errors = [];
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
verify_csrf();
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'create_category') {
|
|
$name = trim($_POST['name'] ?? '');
|
|
if ($name === '') {
|
|
$errors[] = 'Bitte einen Kategorienamen angeben.';
|
|
} else {
|
|
$slug = slugify($name);
|
|
$pdo->prepare('INSERT INTO kb_categories (name, slug, sort_order) VALUES (?,?,0)')->execute([$name, $slug]);
|
|
audit_log($admin['id'], "KB-Kategorie erstellt: {$name}");
|
|
flash('success', 'Kategorie erstellt.');
|
|
redirect('/staff/kb_manage.php');
|
|
}
|
|
}
|
|
|
|
if ($action === 'delete_category') {
|
|
$id = (int) $_POST['id'];
|
|
$stmt = $pdo->prepare('SELECT COUNT(*) FROM kb_articles WHERE category_id = ?');
|
|
$stmt->execute([$id]);
|
|
if ((int) $stmt->fetchColumn() > 0) {
|
|
flash('error', 'Diese Kategorie enthält noch Artikel und kann nicht gelöscht werden.');
|
|
} else {
|
|
$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($admin['id'], "KB-Kategorie gelöscht: {$catName}");
|
|
flash('success', 'Kategorie gelöscht.');
|
|
}
|
|
redirect('/staff/kb_manage.php');
|
|
}
|
|
|
|
if ($action === 'save_article') {
|
|
$id = $_POST['id'] ?? '';
|
|
$title = trim($_POST['title'] ?? '');
|
|
$categoryId = (int) ($_POST['category_id'] ?? 0);
|
|
$body = sanitize_staff_html($_POST['body'] ?? '');
|
|
$isPublished = !empty($_POST['is_published']) ? 1 : 0;
|
|
|
|
if ($title === '') $errors[] = 'Bitte einen Titel angeben.';
|
|
if (trim(strip_tags($body)) === '') $errors[] = 'Bitte einen Inhalt angeben.';
|
|
|
|
if (!$errors) {
|
|
if ($id === '') {
|
|
$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, $body, $isPublished, db_now(), db_now()]);
|
|
audit_log($admin['id'], "KB-Artikel erstellt: {$title}");
|
|
flash('success', 'Artikel erstellt.');
|
|
} else {
|
|
$pdo->prepare('UPDATE kb_articles SET category_id=?, title=?, body=?, is_published=?, updated_at=? WHERE id=?')
|
|
->execute([$categoryId, $title, $body, $isPublished, db_now(), (int) $id]);
|
|
audit_log($admin['id'], "KB-Artikel aktualisiert: {$title}");
|
|
flash('success', 'Artikel aktualisiert.');
|
|
}
|
|
redirect('/staff/kb_manage.php');
|
|
}
|
|
}
|
|
|
|
if ($action === 'delete_article') {
|
|
$id = (int) $_POST['id'];
|
|
$titleStmt = $pdo->prepare('SELECT title FROM kb_articles WHERE id = ?');
|
|
$titleStmt->execute([$id]);
|
|
$artTitle = $titleStmt->fetchColumn();
|
|
$pdo->prepare('DELETE FROM kb_articles WHERE id = ?')->execute([$id]);
|
|
audit_log($admin['id'], "KB-Artikel gelöscht: {$artTitle}");
|
|
flash('success', 'Artikel gelöscht.');
|
|
redirect('/staff/kb_manage.php');
|
|
}
|
|
}
|
|
|
|
$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();
|
|
|
|
$editId = $_GET['edit'] ?? null;
|
|
$editArticle = null;
|
|
if ($editId) {
|
|
$stmt = $pdo->prepare('SELECT * FROM kb_articles WHERE id = ?');
|
|
$stmt->execute([$editId]);
|
|
$editArticle = $stmt->fetch();
|
|
}
|
|
$showForm = isset($_GET['new']) || $editArticle;
|
|
|
|
$pageTitle = 'Wissensdatenbank';
|
|
$activePage = 'kb';
|
|
require __DIR__ . '/_header.php';
|
|
?>
|
|
|
|
<h1>Wissensdatenbank verwalten</h1>
|
|
|
|
<?php foreach ($errors as $err): ?>
|
|
<div class="flash error"><?= e($err) ?></div>
|
|
<?php endforeach; ?>
|
|
|
|
<div style="display:flex; gap:24px; align-items:flex-start">
|
|
<div style="flex:2; min-width:0">
|
|
|
|
<?php if ($showForm): ?>
|
|
<div class="card">
|
|
<h3><?= $editArticle ? 'Artikel bearbeiten' : 'Neuer Artikel' ?></h3>
|
|
<form method="post">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="action" value="save_article">
|
|
<?php if ($editArticle): ?><input type="hidden" name="id" value="<?= $editArticle['id'] ?>"><?php endif; ?>
|
|
<label for="title">Titel</label>
|
|
<input type="text" id="title" name="title" value="<?= e($editArticle['title'] ?? '') ?>" required>
|
|
<label for="category_id">Kategorie</label>
|
|
<select name="category_id" id="category_id" required>
|
|
<?php foreach ($categories as $c): ?>
|
|
<option value="<?= $c['id'] ?>" <?= ($editArticle['category_id'] ?? '') == $c['id'] ? 'selected' : '' ?>><?= e($c['name']) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<label for="body">Inhalt (HTML erlaubt)</label>
|
|
<textarea id="body" name="body" data-richtext style="min-height:220px" required><?= e($editArticle['body'] ?? '') ?></textarea>
|
|
<label style="display:flex; align-items:center; gap:8px; margin-top:14px">
|
|
<input type="checkbox" name="is_published" style="width:auto" <?= ($editArticle['is_published'] ?? 1) ? 'checked' : '' ?>>
|
|
Veröffentlicht
|
|
</label>
|
|
<div class="btn-row">
|
|
<button type="submit" class="btn">Speichern</button>
|
|
<a href="/staff/kb_manage.php" class="btn secondary">Abbrechen</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card">
|
|
<div class="topbar" style="margin-bottom:10px"><h3 style="margin:0">Artikel</h3><a href="/staff/kb_manage.php?new=1" class="btn secondary">+ Neuer Artikel</a></div>
|
|
<table>
|
|
<thead><tr><th>Titel</th><th>Kategorie</th><th>Status</th><th>Aufrufe</th><th></th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($articles as $a): ?>
|
|
<tr>
|
|
<td><?= e($a['title']) ?></td>
|
|
<td><?= e($a['category_name']) ?></td>
|
|
<td><?= $a['is_published'] ? '<span class="badge" style="background:#16a34a">Live</span>' : '<span class="badge" style="background:#6b7280">Entwurf</span>' ?></td>
|
|
<td><?= (int) $a['views'] ?></td>
|
|
<td>
|
|
<a href="/staff/kb_manage.php?edit=<?= $a['id'] ?>">Bearbeiten</a> ·
|
|
<form method="post" style="display:inline" onsubmit="return confirm('Artikel wirklich löschen?');">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="action" value="delete_article">
|
|
<input type="hidden" name="id" value="<?= $a['id'] ?>">
|
|
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.9rem">Löschen</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="flex:1; min-width:260px">
|
|
<div class="card">
|
|
<h3>Kategorien</h3>
|
|
<?php foreach ($categories as $c): ?>
|
|
<div style="display:flex; justify-content:space-between; align-items:center; padding:6px 0; border-bottom:1px solid var(--border)">
|
|
<span><?= e($c['name']) ?></span>
|
|
<form method="post" onsubmit="return confirm('Kategorie wirklich löschen?');">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="action" value="delete_category">
|
|
<input type="hidden" name="id" value="<?= $c['id'] ?>">
|
|
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.85rem">Löschen</button>
|
|
</form>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<form method="post" style="margin-top:14px">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="action" value="create_category">
|
|
<label for="name">Neue Kategorie</label>
|
|
<input type="text" id="name" name="name" required>
|
|
<div class="btn-row"><button type="submit" class="btn secondary">Hinzufügen</button></div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require __DIR__ . '/_footer.php'; ?>
|