Files
dasposchi-de/admin/articles.php
Claude 3c97192386 Initiales CMS: Deutschsprachiges Blog-System mit Admin-Bereich
Vollständiges, schlankes PHP/SQLite-CMS für IT-, KI- und Gaming-Inhalte:

- Core: DB-Singleton, Auth mit Passwort-Hashing, Session-Cookies,
  CSRF-Schutz, Login-Rate-Limit, Bild-Upload mit serverseitiger Validierung
- Admin: Dashboard, Artikel/Seiten-Verwaltung mit Quill WYSIWYG-Editor,
  Kategorien, Navigation (Drag & Drop), Medienbibliothek, Profil
- Frontend: Responsive Dark-Theme, Artikel-Grid, Kategorie-Filter,
  Archiv, Paginierung, SEO-Meta-Tags
- Sicherheit: Prepared Statements, HTML-Sanitizer, .htaccess-Schutz
  für sensible Verzeichnisse, PHP-Ausführungsschutz im Upload-Ordner
- Installation: install.php erstellt DB-Schema und Admin-Account

https://claude.ai/code/session_01Xsg4j2t4S9goMuWVpF3ezG
2026-04-05 20:59:52 +00:00

87 lines
3.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/../core/auth.php';
auth_start_session();
auth_require_login();
$pdo = db();
// Artikel löschen
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_id'])) {
csrf_verify();
$stmt = $pdo->prepare('DELETE FROM articles WHERE id = ?');
$stmt->execute([(int) $_POST['delete_id']]);
flash('success', 'Artikel gelöscht.');
redirect('/admin/articles.php');
}
$page = max(1, (int) ($_GET['page'] ?? 1));
$total = (int) $pdo->query('SELECT COUNT(*) FROM articles')->fetchColumn();
$pag = paginate($total, $page, ITEMS_PER_PAGE);
$stmt = $pdo->prepare(
"SELECT a.id, a.title, a.slug, a.status, a.published_at, a.created_at, c.name as category_name
FROM articles a LEFT JOIN categories c ON a.category_id = c.id
ORDER BY a.created_at DESC LIMIT ? OFFSET ?"
);
$stmt->execute([$pag['limit'], $pag['offset']]);
$articles = $stmt->fetchAll();
$pageTitle = 'Artikel';
$currentPage = 'articles';
ob_start();
?>
<div class="card">
<div class="card-header">
<h3>Alle Artikel (<?= $total ?>)</h3>
<a href="/admin/article-edit.php" class="btn btn-primary btn-sm">Neuer Artikel</a>
</div>
<?php if (empty($articles)): ?>
<p class="empty-state">Noch keine Artikel vorhanden.</p>
<?php else: ?>
<table class="table">
<thead>
<tr>
<th>Titel</th>
<th>Kategorie</th>
<th>Status</th>
<th>Datum</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php foreach ($articles as $article): ?>
<tr>
<td><a href="/admin/article-edit.php?id=<?= $article['id'] ?>"><?= e($article['title']) ?></a></td>
<td><?= e($article['category_name'] ?? '') ?></td>
<td>
<span class="badge badge-<?= $article['status'] === 'published' ? 'success' : 'warning' ?>">
<?= $article['status'] === 'published' ? 'Veröffentlicht' : 'Entwurf' ?>
</span>
</td>
<td><?= format_date($article['published_at'] ?? $article['created_at']) ?></td>
<td class="actions">
<a href="/admin/article-edit.php?id=<?= $article['id'] ?>" class="btn btn-sm">Bearbeiten</a>
<form method="post" class="inline-form" onsubmit="return confirm('Artikel wirklich löschen?')">
<?= csrf_field() ?>
<input type="hidden" name="delete_id" value="<?= $article['id'] ?>">
<button type="submit" class="btn btn-sm btn-danger">Löschen</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ($pag['total_pages'] > 1): ?>
<div class="pagination">
<?php for ($i = 1; $i <= $pag['total_pages']; $i++): ?>
<a href="?page=<?= $i ?>" class="<?= $i === $pag['current_page'] ? 'active' : '' ?>"><?= $i ?></a>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php
$content = ob_get_clean();
include __DIR__ . '/templates/layout.php';