[], 'programmes' => [], 'error' => 'PHP DOM/XML extension is not installed']; } libxml_use_internal_errors(true); $dom = new DOMDocument(); if (!$dom->loadXML($xml, LIBXML_NOERROR | LIBXML_NOWARNING)) { return ['channels' => [], 'programmes' => [], 'error' => 'Invalid XMLTV response']; } $xp = new DOMXPath($dom); $channels = []; foreach ($xp->query('/tv/channel') as $channel) { $id = $channel->getAttribute('id'); $name = trim($xp->evaluate('string(display-name[1])', $channel)); $icon = trim($xp->evaluate('string(icon/@src)', $channel)); $channels[$id] = ['id' => $id, 'name' => $name ?: $id, 'icon' => $icon]; } $start_day = new DateTimeImmutable($target_day . ' 00:00:00'); $end_day = $start_day->modify('+1 day'); $rows = []; foreach ($xp->query('/tv/programme') as $programme) { $channel_id = $programme->getAttribute('channel'); $start = DateTimeImmutable::createFromFormat('YmdHis O', $programme->getAttribute('start')); $stop = DateTimeImmutable::createFromFormat('YmdHis O', $programme->getAttribute('stop')); if (!$start || !$stop) continue; if ($stop <= $start_day || $start >= $end_day) continue; $title = trim($xp->evaluate('string(title)', $programme)); $subtitle = trim($xp->evaluate('string(sub-title)', $programme)); $desc = trim($xp->evaluate('string(desc)', $programme)); $rating = trim($xp->evaluate('string(rating/value)', $programme)); $cats = []; foreach ($xp->query('category', $programme) as $cat) { $value = trim($cat->textContent); if ($value !== '') $cats[strtolower($value)] = $value; } $rows[$channel_id][] = [ 'start' => $start, 'stop' => $stop, 'title' => $title, 'subtitle' => $subtitle, 'desc' => $desc, 'rating' => $rating, 'categories' => array_values($cats), ]; } uasort($channels, static function ($a, $b) { preg_match('/^\d+/', $a['name'], $ma); preg_match('/^\d+/', $b['name'], $mb); $na = isset($ma[0]) ? (int) $ma[0] : 9999; $nb = isset($mb[0]) ? (int) $mb[0] : 9999; return $na <=> $nb ?: strcmp($a['name'], $b['name']); }); foreach ($rows as &$programmes) { usort($programmes, static fn($a, $b) => $a['start'] <=> $b['start']); } return ['channels' => $channels, 'programmes' => $rows, 'error' => '']; } $sources = array_values($config['epg_sources'] ?? []); $source_index = max(0, min((int) ($_GET['source'] ?? 0), max(count($sources) - 1, 0))); $source = $sources[$source_index] ?? null; $target_day = preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) ($_GET['day'] ?? '')) ? (string) $_GET['day'] : (new DateTimeImmutable('today'))->format('Y-m-d'); $fetch = $source ? gridtv_fetch_url((string) $source['epg_url'], 25) : ['ok' => false, 'error' => 'No source configured', 'body' => '']; $parsed = $fetch['ok'] ? export_parse_xmltv_programmes($fetch['body'], $target_day) : ['channels' => [], 'programmes' => [], 'error' => $fetch['error'] ?: 'Unable to fetch XMLTV']; $print_channels = []; foreach ($parsed['channels'] as $channel_id => $channel) { if (!empty($parsed['programmes'][$channel_id])) { $print_channels[$channel_id] = $channel; } } $day_label = (new DateTimeImmutable($target_day))->format('l d F Y'); ?> GridTV — Export 24h

Export 24h

Version “programme télé” pensée pour être imprimée proprement en PDF, ou exportée en image pour l’envoyer facilement à quelqu’un.

Health Guide
TV Guide · 24 hours · Printable edition
Le programme télé de la journée
·
24h view channel(s) Generated from XMLTV
Impossible de générer la feuille:
Aucun programme trouvé pour cette journée.
$channel): ?>
modify('+1 hour'); $items = []; foreach ($parsed['programmes'][$channel_id] as $programme) { if ($programme['stop'] <= $hour_start || $programme['start'] >= $hour_end) continue; $items[] = $programme; } ?>
format('H:i') . ' - ' . $programme['stop']->format('H:i'); if ($programme['rating']) $meta .= ' · ' . $programme['rating']; $cats = $programme['categories'] ? implode(' · ', $programme['categories']) : ''; ?>
Astuce: “PDF / Print” donne un export A4/PDF propre. “Image” fabrique un PNG de la feuille affichée.