Found by testing: unlike news items, the agenda @results batch listing always returns text_fr and items (attachments) as null for events - only description_fr (short teaser) was ever available from it. The site itself works around this by firing a second request per event (@results?UID=<uid>&fullobjects=1) when you open one; we now do the same, with a per-UID cache since a recurring event shares one UID across all its occurrences. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
106 lines
3.6 KiB
PHP
106 lines
3.6 KiB
PHP
<?php
|
|
require __DIR__ . '/common.php';
|
|
|
|
const SITE = 'https://www.silly.be';
|
|
const EVENTS_API = SITE . '/agenda/@results';
|
|
const PAGE_SIZE = 20;
|
|
const MAX_PAGES = 2;
|
|
|
|
function fetch_all_events(): array
|
|
{
|
|
$items = [];
|
|
for ($page = 0; $page < MAX_PAGES; $page++) {
|
|
$bStart = $page * PAGE_SIZE;
|
|
$url = EVENTS_API . '?b_size=' . PAGE_SIZE . '&b_start=' . $bStart;
|
|
$data = json_decode(http_get($url), true);
|
|
$pageItems = $data['items'] ?? [];
|
|
if (empty($pageItems)) {
|
|
break;
|
|
}
|
|
$items = array_merge($items, $pageItems);
|
|
if (count($items) >= ($data['items_total'] ?? 0)) {
|
|
break;
|
|
}
|
|
}
|
|
return $items;
|
|
}
|
|
|
|
/**
|
|
* Contrairement aux actualites, l'API renvoie text_fr/items (texte complet
|
|
* et pieces jointes) a null dans la liste paginee des evenements - il faut
|
|
* une requete par UID pour les recuperer (c'est ce que fait le site
|
|
* lui-meme quand on ouvre un evenement). Un evenement recurrent partage un
|
|
* seul UID sur toutes ses occurrences, donc un cache statique evite de
|
|
* refaire la requete pour chaque occurrence.
|
|
*/
|
|
function fetch_event_detail(string $uid): ?array
|
|
{
|
|
static $cache = [];
|
|
if (array_key_exists($uid, $cache)) {
|
|
return $cache[$uid];
|
|
}
|
|
try {
|
|
$url = EVENTS_API . '?UID=' . rawurlencode($uid) . '&fullobjects=1';
|
|
$data = json_decode(http_get($url), true);
|
|
$cache[$uid] = $data['items'][0] ?? null;
|
|
} catch (Throwable $e) {
|
|
$cache[$uid] = null;
|
|
}
|
|
return $cache[$uid];
|
|
}
|
|
|
|
function format_event_meta(array $item): string
|
|
{
|
|
$parts = [];
|
|
$start = !empty($item['start']) ? new DateTime($item['start']) : null;
|
|
$end = !empty($item['end']) ? new DateTime($item['end']) : null;
|
|
|
|
if ($start) {
|
|
$parts[] = !empty($item['whole_day'])
|
|
? 'Le ' . $start->format('d/m/Y')
|
|
: 'Le ' . $start->format('d/m/Y à H:i');
|
|
}
|
|
if ($end && (!$start || $end->format('Y-m-d') !== $start->format('Y-m-d'))) {
|
|
$parts[] = "jusqu'au " . $end->format('d/m/Y H:i');
|
|
}
|
|
$address = implode(', ', array_filter([$item['street'] ?? null, $item['zipcode'] ?? null, $item['city'] ?? null]));
|
|
if ($address) {
|
|
$parts[] = "Lieu : $address";
|
|
}
|
|
return implode(' — ', $parts);
|
|
}
|
|
|
|
function build_events_feed(): string
|
|
{
|
|
$items = [];
|
|
foreach (fetch_all_events() as $item) {
|
|
$id = basename(rtrim($item['@id'] ?? '', '/'));
|
|
$title = $item['title_fr'] ?? $item['title'] ?? '(sans titre)';
|
|
$uid = $item['UID'] ?? $id;
|
|
$meta = format_event_meta($item);
|
|
$detail = fetch_event_detail($uid);
|
|
$description = ($meta !== '' ? '<p>' . htmlspecialchars($meta, ENT_QUOTES, 'UTF-8') . '</p>' : '')
|
|
. full_body_html($detail ?? $item, $title);
|
|
// Un evenement recurrent partage le meme UID sur toutes ses
|
|
// occurrences (memes UID, dates differentes) : on suffixe le guid
|
|
// avec la date de debut pour rester unique par occurrence, comme
|
|
// l'exige la spec RSS.
|
|
$items[] = [
|
|
'title' => $title,
|
|
'link' => SITE . '/agenda/' . slugify($title) . '?u=' . rawurlencode($uid),
|
|
'guid' => $uid . '-' . ($item['start'] ?? ''),
|
|
'pubDate' => $item['created'] ?? $item['start'] ?? null,
|
|
'description' => $description,
|
|
];
|
|
}
|
|
return build_rss(
|
|
'Silly.be - Agenda',
|
|
SITE . '/agenda',
|
|
"Agenda / événements de la commune de Silly (Belgique)",
|
|
$items,
|
|
'https://sillycone-village.be/silly-rss/agenda.php'
|
|
);
|
|
}
|
|
|
|
serve_cached_feed('agenda', 'build_events_feed');
|