Files
geograsim/App/php/api/admin-modules.php
T
Adminator 9a61f55cb1 Atlas: Infrastruktur + Team-Konventionen + Sprachregel Lernarbeit
- Design-System (assets/css/design-system.css) mit 21 Komponenten,
  iPad-Responsive-Breakpoints, Touch-Ziele 36px, Music-Player,
  Glossar-Tooltips
- Templates (sims/template.html + student/teacher-Dashboard)
- Docs: module-interface.md (inkl. 4a Sprachregel, 4b Leichte Sprache,
  4c iPad), content-architecture.md, crash-recovery.md, music-registry.md
- Admin-Infrastruktur: admin-modules.html + api/admin-modules.php
  (Titel, Emoji, Bild, Status, Dauer, Alter pro Modul)
- Inbox-System: _inbox/README.md + _status.md fuer Atlas + Briefings
  an Klima, Glossar, Lehrplan, Fluss
- Zentrale SFX-Pipeline (scripts/generate-sounds.py)
- DALL-E-Bilder: 8 Badges + 5 Glossar-Repraesentationsbilder (Querformat)
- Logo + Inter-Font lokal
- PHP-APIs: admin, glossar, levels, licenses, progress, waypoints,
  assignments, profile, tickets
- Spielsprache entfernt (admin-modules, admin-levels, schueler)
- Landing-Page-Bearbeitungen (Boote sichtbarer, Button-Hintergrund)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 11:51:14 +02:00

94 lines
3.5 KiB
PHP

<?php
/**
* Admin API: Module-Verwaltung
* GET /api/admin-modules → Liste aller Module (mit Emoji, Titel, Bild, Status)
* PUT /api/admin-modules → Ein Modul aktualisieren (Emoji, Titel, Subtitle, Status, Bild)
* POST /api/admin-modules → Upload eines neuen Card-Bildes (multipart)
*
* Auth: Super-Admin Session ($_SESSION['admin_id'])
*/
if (session_status() === PHP_SESSION_NONE) session_start();
if (empty($_SESSION['admin_id'])) {
http_response_code(401);
echo json_encode(['error' => 'Nicht eingeloggt']);
exit;
}
$db = Database::get();
$method = $_SERVER['REQUEST_METHOD'];
try {
// === GET: Liste aller Module ===
if ($method === 'GET') {
$modules = $db->fetchAll('
SELECT module_id, title, subtitle, icon, card_image, status,
duration_min, age_min, age_max, play_url, page_url, sort_order
FROM module_info
ORDER BY sort_order, title
');
Response::json(['modules' => $modules]);
}
// === PUT: Modul aktualisieren ===
if ($method === 'PUT') {
$body = json_decode(file_get_contents('php://input'), true);
$id = trim($body['module_id'] ?? '');
if (!$id) Response::error('module_id fehlt');
$exists = $db->fetchOne('SELECT module_id FROM module_info WHERE module_id = ?', [$id]);
if (!$exists) Response::error('Modul nicht gefunden', 404);
$fields = [];
$params = [];
// Erlaubte Felder
$allowed = ['title', 'subtitle', 'icon', 'card_image', 'status',
'duration_min', 'age_min', 'age_max', 'play_url', 'page_url', 'sort_order'];
foreach ($allowed as $f) {
if (array_key_exists($f, $body)) {
$fields[] = "$f = ?";
$params[] = $body[$f] === '' ? null : $body[$f];
}
}
if (!$fields) Response::error('Keine Felder zum Aktualisieren');
$params[] = $id;
$sql = 'UPDATE module_info SET ' . implode(', ', $fields) . ' WHERE module_id = ?';
$db->execute($sql, $params);
$updated = $db->fetchOne('SELECT * FROM module_info WHERE module_id = ?', [$id]);
Response::json(['ok' => true, 'module' => $updated]);
}
// === POST: Bild-Upload ===
if ($method === 'POST') {
$id = trim($_POST['module_id'] ?? '');
if (!$id) Response::error('module_id fehlt');
if (empty($_FILES['image'])) Response::error('Kein Bild hochgeladen');
$file = $_FILES['image'];
if ($file['error'] !== UPLOAD_ERR_OK) Response::error('Upload-Fehler');
if ($file['size'] > 5 * 1024 * 1024) Response::error('Bild zu gross (max 5 MB)');
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ['png', 'jpg', 'jpeg', 'webp', 'svg'])) Response::error('Nur PNG, JPG, WEBP, SVG');
$targetDir = __DIR__ . '/../../assets/img/';
$filename = 'card-' . preg_replace('/[^a-z0-9]/', '', $id) . '.' . $ext;
$targetPath = $targetDir . $filename;
if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
Response::error('Datei konnte nicht gespeichert werden');
}
$db->execute('UPDATE module_info SET card_image = ? WHERE module_id = ?', [$filename, $id]);
Response::json(['ok' => true, 'card_image' => $filename]);
}
Response::error('Methode nicht unterstützt', 405);
} catch (Throwable $e) {
Response::error('Fehler: ' . $e->getMessage(), 500);
}