Schüler-Session mit students.easy_language=1 > normal if (session_status() === PHP_SESSION_NONE) session_start(); $easy = false; if (isset($_GET['easy'])) { $easy = $_GET['easy'] === '1'; } elseif (!empty($_SESSION['student_id'])) { if (!isset($_SESSION['_easy_cache']) || ($_SESSION['_easy_cache']['id'] ?? null) !== $_SESSION['student_id']) { $stmt = $db->prepare('SELECT easy_language FROM students WHERE id = ?'); $stmt->execute([$_SESSION['student_id']]); $r = $stmt->fetch(PDO::FETCH_ASSOC); $_SESSION['_easy_cache'] = ['id' => $_SESSION['student_id'], 'val' => !empty($r['easy_language'])]; } $easy = $_SESSION['_easy_cache']['val']; } // Cache pro Variante header($easy ? 'Cache-Control: private, max-age=60' : 'Cache-Control: public, max-age=600'); /** Liefert Easy-Variante, sonst Fallback auf normal */ function pickText(array $row, string $normalKey, string $easyKey, bool $easy) { if ($easy && !empty($row[$easyKey])) return $row[$easyKey]; return $row[$normalKey] ?? null; } try { $method = $_SERVER['REQUEST_METHOD']; if ($method === 'GET') { // Graph-Endpoint: alle Nodes + Edges für die Mindmap if (!empty($_GET['graph'])) { // Nodes inkl. Module-Zuordnung $nodes = $db->query(' SELECT g.id, g.key_slug, g.title, g.short, g.category, g.image_path, GROUP_CONCAT(m.module_id) AS modules FROM glossar g LEFT JOIN glossar_modules m ON m.glossar_id = g.id GROUP BY g.id ORDER BY g.title ')->fetchAll(PDO::FETCH_ASSOC); foreach ($nodes as &$n) { $n['modules'] = $n['modules'] ? explode(',', $n['modules']) : []; $n['id'] = (int) $n['id']; } unset($n); // Edges: related-Tabelle — jede Kante einmal (kleinere id → grössere id) $edges = $db->query(' SELECT LEAST(glossar_id, related_id) AS a, GREATEST(glossar_id, related_id) AS b FROM glossar_related GROUP BY a, b ')->fetchAll(PDO::FETCH_ASSOC); foreach ($edges as &$e) { $e['a'] = (int) $e['a']; $e['b'] = (int) $e['b']; } unset($e); echo json_encode(['nodes' => $nodes, 'edges' => $edges], JSON_UNESCAPED_UNICODE); exit; } // Einzelner Eintrag per key_slug if (!empty($_GET['key'])) { $key = $_GET['key']; $entry = $db->prepare('SELECT * FROM glossar WHERE key_slug = ?'); $entry->execute([$key]); $row = $entry->fetch(PDO::FETCH_ASSOC); if (!$row) { http_response_code(404); echo json_encode(['error' => 'not found']); exit; } // Leichte Sprache: falls aktiv, short/text durch easy-Varianten ersetzen (Fallback auf normal) $row['short'] = pickText($row, 'short', 'short_easy', $easy); $row['text'] = pickText($row, 'text', 'text_easy', $easy); $row['_easy'] = $easy; // Meta-Info fürs Frontend // Roh-Easy-Felder entfernen, damit JSON schlank bleibt unset($row['short_easy'], $row['text_easy']); // Module $mods = $db->prepare('SELECT module_id FROM glossar_modules WHERE glossar_id = ?'); $mods->execute([$row['id']]); $row['modules'] = $mods->fetchAll(PDO::FETCH_COLUMN); // Beispiele (inkl. optionaler Quellen-Referenz + Easy-Variante) $ex = $db->prepare('SELECT text, text_easy, source_ref FROM glossar_examples WHERE glossar_id = ? ORDER BY sort_order'); $ex->execute([$row['id']]); $examples = $ex->fetchAll(PDO::FETCH_ASSOC); foreach ($examples as &$e) { $e['text'] = pickText($e, 'text', 'text_easy', $easy); unset($e['text_easy']); } unset($e); $row['examples'] = $examples; // Quellen $sr = $db->prepare('SELECT ref_num, label, url, access_date FROM glossar_sources WHERE glossar_id = ? ORDER BY ref_num'); $sr->execute([$row['id']]); $row['sources'] = $sr->fetchAll(PDO::FETCH_ASSOC); // Links $lk = $db->prepare('SELECT label, url FROM glossar_links WHERE glossar_id = ? ORDER BY sort_order'); $lk->execute([$row['id']]); $row['links'] = $lk->fetchAll(PDO::FETCH_ASSOC); // Related (mit title + key) $rel = $db->prepare(' SELECT g.key_slug, g.title FROM glossar_related r JOIN glossar g ON g.id = r.related_id WHERE r.glossar_id = ? '); $rel->execute([$row['id']]); $row['related'] = $rel->fetchAll(PDO::FETCH_ASSOC); echo json_encode($row, JSON_UNESCAPED_UNICODE); exit; } // Alle Einträge eines Moduls if (!empty($_GET['module'])) { $mod = $_GET['module']; $stmt = $db->prepare(' SELECT g.id, g.key_slug, g.title, g.short, g.short_easy, g.text, g.text_easy, g.unit, g.category, g.image_path, g.animation_path FROM glossar g JOIN glossar_modules m ON m.glossar_id = g.id WHERE m.module_id = ? ORDER BY g.title '); $stmt->execute([$mod]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as &$r) { $r['short'] = pickText($r, 'short', 'short_easy', $easy); $r['text'] = pickText($r, 'text', 'text_easy', $easy); unset($r['short_easy'], $r['text_easy']); } unset($r); echo json_encode($rows, JSON_UNESCAPED_UNICODE); exit; } // Volltextsuche if (!empty($_GET['search'])) { $q = '%' . $_GET['search'] . '%'; $stmt = $db->prepare(' SELECT id, key_slug, title, short, category FROM glossar WHERE title LIKE ? OR short LIKE ? OR text LIKE ? ORDER BY title LIMIT 50 '); $stmt->execute([$q, $q, $q]); echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC), JSON_UNESCAPED_UNICODE); exit; } // Alle Einträge (Übersicht) mit Modul-Zuordnungen $stmt = $db->query(' SELECT g.id, g.key_slug, g.title, g.short, g.category, g.image_path, GROUP_CONCAT(m.module_id) AS modules FROM glossar g LEFT JOIN glossar_modules m ON m.glossar_id = g.id GROUP BY g.id ORDER BY g.title '); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as &$r) { $r['modules'] = $r['modules'] ? explode(',', $r['modules']) : []; } echo json_encode($rows, JSON_UNESCAPED_UNICODE); exit; } http_response_code(405); echo json_encode(['error' => 'method not allowed']); } catch (Throwable $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]); }