prepare('SELECT id FROM users WHERE username = ?'); $user_stmt->execute([$_GET['username']]); $user_row = $user_stmt->fetch(); if (!$user_row) { http_response_code(404); die('User not found.'); } // Try sessions first $ses_stmt = $pdo->prepare('SELECT id FROM sessions WHERE user_id = ? AND slug = ? AND is_public = 1'); $ses_stmt->execute([$user_row['id'], $_GET['slug']]); $ses_row = $ses_stmt->fetch(); if ($ses_row) { $_GET['id'] = $ses_row['id']; } else { // Try novena group — find first day session $grp_stmt = $pdo->prepare('SELECT id FROM novena_groups WHERE user_id = ? AND slug = ? AND is_public = 1'); $grp_stmt->execute([$user_row['id'], $_GET['slug']]); $grp_row = $grp_stmt->fetch(); if ($grp_row) { // Show day-picker instead of jumping straight to Day 1 header('Location: ' . BASE_URL . '/novena_public.php?group_id=' . (int)$grp_row['id']); exit; } else { http_response_code(404); die('Rosary not found.'); } } } // Load session $id = isset($_GET['id']) ? (int)$_GET['id'] : 0; if ($id < 1) { die('Missing session ID. Please use a valid presentation link.'); } $stmt = get_pdo()->prepare('SELECT * FROM sessions WHERE id = ?'); $stmt->execute([$id]); $session = $stmt->fetch(); if (!$session) { die('Session not found.'); } // Resolve "by_day_of_week" mystery set to the actual set for today if ($session['mystery_set'] === 'by_day_of_week') { $dow_map = [ 0 => 'glorious', // Sunday 1 => 'joyful', // Monday 2 => 'sorrowful', // Tuesday 3 => 'glorious', // Wednesday 4 => 'luminous', // Thursday 5 => 'sorrowful', // Friday 6 => 'joyful', // Saturday ]; $session['mystery_set'] = $dow_map[(int)date('w')]; } // "all_sorrowful" is stored as-is but maps to sorrowful if ($session['mystery_set'] === 'all_sorrowful') { $session['mystery_set'] = 'sorrowful'; } // Build slide array $slides = build_slides($session); // Prepare JSON for JavaScript (HTML-safe) $slides_json = json_encode($slides, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); // Session display info $mystery_labels = [ 'sorrowful' => 'Sorrowful Mysteries', 'joyful' => 'Joyful Mysteries', 'glorious' => 'Glorious Mysteries', 'luminous' => 'Luminous Mysteries', ]; $mystery_label = $mystery_labels[$session['mystery_set']] ?? ucfirst($session['mystery_set']); $site_name = get_setting('site_name', APP_NAME); // Back URL — novena sessions return to day-picker; others return home $back_url = BASE_URL . '/'; if (!empty($session['novena_group_id'])) { $back_url = BASE_URL . '/novena_public.php?group_id=' . (int)$session['novena_group_id']; } // Build audio manifest: scan uploads/audio/ for available files $audio_manifest = []; $audio_dir = UPLOADS_DIR . 'audio/'; if (is_dir($audio_dir)) { foreach (glob($audio_dir . '*.*') ?: [] as $f) { $base = basename($f); $dot = strrpos($base, '.'); if ($dot !== false) { $k = substr($base, 0, $dot); $e = strtolower(substr($base, $dot + 1)); if (preg_match('/^[a-z0-9_]+$/', $k)) { $audio_manifest[$k] = $e; } } } } $has_audio = !empty($audio_manifest); ?>