Files
yogibook_aury_new/public/apiwp/events.php
T
2026-09-18 15:36:44 +02:00

134 lines
5.1 KiB
PHP

<?php
require_once __DIR__ . '/bootstrap.php';
/**
* Endpoint pubblico LISTA eventi (sola lettura).
* Ritorna gli eventi PUBBLICATI e NON ancora terminati, con posti/prezzo/gallery.
*
* Parametri (query string):
* ?id=12 -> un solo evento
* ?ids=12,15,20 -> solo questi eventi (nell'ordine per data)
* ?limit=3 -> massimo N eventi
* Senza parametri: tutti i pubblicati futuri, per data crescente.
*
* Regole di visibilità:
* status = 'published' AND COALESCE(ends_at, starts_at) >= NOW()
* (l'evento sparisce da solo quando è terminato)
*/
try {
$pdo = pdo_conn();
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$idsParam = trim($_GET['ids'] ?? '');
$limit = isset($_GET['limit']) ? max(1, min(50, (int) $_GET['limit'])) : 0;
$where = ["e.status IN ('published','scheduled')", "COALESCE(e.ends_at, e.starts_at) >= NOW()"];
$params = [];
if ($id > 0) {
$where[] = 'e.id = ?';
$params[] = $id;
} elseif ($idsParam !== '') {
$ids = array_values(array_filter(array_map('intval', explode(',', $idsParam)), function ($v) {
return $v > 0;
}));
if (!empty($ids)) {
$where[] = 'e.id IN (' . implode(',', array_fill(0, count($ids), '?')) . ')';
foreach ($ids as $v) {
$params[] = $v;
}
} else {
send_json(['ok' => true, 'count' => 0, 'events' => []]);
}
}
$sql = "SELECT e.*, u.first_name AS cf, u.last_name AS cl,
COALESCE(b.occupied, 0) AS occupied,
COALESCE(w.waiting, 0) AS waiting
FROM events e
LEFT JOIN auth_users u ON u.id = e.user_id
LEFT JOIN (
SELECT event_id, SUM(seats) AS occupied
FROM event_bookings WHERE status IN ('confirmed','pending','offered')
GROUP BY event_id
) b ON b.event_id = e.id
LEFT JOIN (
SELECT event_id, SUM(seats) AS waiting
FROM event_bookings WHERE status = 'waiting'
GROUP BY event_id
) w ON w.event_id = e.id
WHERE " . implode(' AND ', $where) . "
ORDER BY e.starts_at ASC";
if ($limit > 0) {
$sql .= ' LIMIT ' . (int) $limit;
}
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$symbols = ['EUR' => '€', 'USD' => '$', 'GBP' => '£', 'CHF' => 'CHF'];
$events = [];
foreach ($rows as $r) {
$maxSeats = (int) $r['max_seats'];
$occupied = (int) $r['occupied'];
$remaining = max(0, $maxSeats - $occupied);
$gallery = [];
if (!empty($r['gallery'])) {
$g = json_decode($r['gallery'], true);
if (is_array($g)) {
foreach ($g as $path) {
if (is_string($path) && $path !== '') {
$gallery[] = public_url($path);
}
}
}
}
$organizer = trim((string) $r['organizer_name']) !== ''
? $r['organizer_name']
: trim(($r['cf'] ?? '') . ' ' . ($r['cl'] ?? ''));
$events[] = [
'id' => (int) $r['id'],
'title' => $r['title'],
'slug' => $r['slug'],
'status' => $r['status'],
'scheduled' => $r['status'] === 'scheduled',
'bookable' => $r['status'] === 'published',
'publish_at' => $r['publish_at'],
'description' => $r['description'], // HTML (sanificare al rendering in WP)
'instructions' => $r['instructions'],
'what_to_bring' => $r['what_to_bring'],
'suitable_for' => $r['suitable_for'],
'organizer' => $organizer !== '' ? $organizer : null,
'starts_at' => $r['starts_at'],
'ends_at' => $r['ends_at'],
'address' => $r['address'],
'lat' => $r['lat'] !== null ? (float) $r['lat'] : null,
'lng' => $r['lng'] !== null ? (float) $r['lng'] : null,
'cost' => (float) $r['cost'],
'currency' => $r['currency'],
'currency_symbol' => $symbols[$r['currency']] ?? $r['currency'],
'color' => $r['color'],
'cover_image' => public_url($r['cover_image']),
'gallery' => $gallery,
'max_seats' => $maxSeats,
'max_per_booking' => (int) $r['max_per_booking'],
'occupied' => $occupied,
'remaining' => $remaining,
'sold_out' => $remaining <= 0,
'waitlist_enabled' => ($r['waitlist_enabled'] ?? 'N') === 'Y',
'waiting' => (int) $r['waiting'],
];
}
send_json(['ok' => true, 'count' => count($events), 'events' => $events]);
} catch (Throwable $ex) {
error_log('[api/events] ' . $ex->getMessage());
send_json(['ok' => false, 'error' => 'Errore nel recupero degli eventi.'], 500);
}