'HUB_CONTENT_SECRET não configurado nesta plataforma.']); exit; } $date = (string) ($_SERVER['HTTP_X_HUB_DATE'] ?? ''); $token = (string) ($_SERVER['HTTP_X_HUB_TOKEN'] ?? ''); $path = (string) (parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?? ''); $ts = $date !== '' ? strtotime($date) : false; if ($token === '' || $ts === false || abs(time() - $ts) > 600 || !hash_equals(hash_hmac('sha256', $date . $path, $secret), $token)) { http_response_code(403); echo json_encode(['error' => 'Assinatura inválida.']); exit; } session_write_close(); // not needed past auth; release the session lock $type = (string) ($_GET['type'] ?? ''); // Optional category filter: ?category=segunda or ?categories=segunda,quarta. // For this platform the category dimension is the weekday. Empty = all. $cat_filter = array_filter(array_map( fn($c) => strtolower(trim($c)), preg_split('/[,]/', (string) ($_GET['categories'] ?? $_GET['category'] ?? '')) )); // Weekday enum → display label and ISO day-of-week (1=Mon … 7=Sun). $WEEKDAYS = [ 'segunda' => ['Segunda-feira', 1], 'terça' => ['Terça-feira', 2], 'quarta' => ['Quarta-feira', 3], 'quinta' => ['Quinta-feira', 4], 'sexta' => ['Sexta-feira', 5], 'sábado' => ['Sábado', 6], 'domingo' => ['Domingo', 7], ]; $LOCALS = ['sala1' => 'Sala 1', 'sala2' => 'Sala 2', 'crossfit' => 'CrossFit']; // Next occurrence (today or in the coming week) of a given weekday at $time. $next_occurrence = static function (int $isoDow, string $time): DateTime { $dt = new DateTime('today'); $diff = ($isoDow - (int) $dt->format('N') + 7) % 7; // 0 = today if ($diff > 0) $dt->modify("+{$diff} day"); [$h, $m, $s] = array_pad(explode(':', $time), 3, '0'); $dt->setTime((int) $h, (int) $m, (int) $s); return $dt; }; $items = []; // ── event: weekly class schedule ──────────────────────────────────────────── if ($type === '' || $type === 'event') { // db_horario_list() already joins modalidades and orders segunda→domingo, // then by start time; restrict to live modalidades (not soft-deleted). $rows = $pdo->query(" SELECT h.id, h.dia_semana, h.local, m.nome AS modalidade_nome, TIME_FORMAT(h.hora_inicio, '%H:%i') AS hora_inicio_fmt, TIME_FORMAT(h.hora_fim, '%H:%i') AS hora_fim_fmt FROM horario h JOIN modalidades m ON m.m_id = h.id_modalidade AND m.deleted_at IS NULL ORDER BY FIELD(h.dia_semana,'segunda','terça','quarta','quinta','sexta','sábado','domingo'), h.hora_inicio ASC ")->fetchAll(PDO::FETCH_ASSOC); foreach ($rows as $r) { $dia = (string) $r['dia_semana']; if (!isset($WEEKDAYS[$dia])) continue; // unknown / NULL weekday — skip if ($cat_filter && !in_array($dia, $cat_filter, true)) continue; // category filter [$diaLabel, $isoDow] = $WEEKDAYS[$dia]; $ini = (string) $r['hora_inicio_fmt']; $fim = (string) $r['hora_fim_fmt']; $hora = $fim !== '' ? ($ini . '–' . $fim) : $ini; $local = $LOCALS[(string) $r['local']] ?? ''; $start = $next_occurrence($isoDow, $ini !== '' ? $ini . ':00' : '00:00:00'); $end = $fim !== '' ? $next_occurrence($isoDow, $fim . ':00') : null; $fields = ['Dia' => $diaLabel, 'Hora' => $hora]; if ($local !== '') $fields['Local'] = $local; $items[] = [ 'id' => 'aula-' . (int) $r['id'], 'type' => 'event', 'title' => (string) $r['modalidade_nome'], 'subtitle' => $hora . ($local !== '' ? ' · ' . $local : ''), 'date_start' => $start->format('c'), 'date_end' => $end ? $end->format('c') : '', 'url' => base_url('home/horario'), 'category' => $dia, // machine key (weekday enum value) 'category_label' => $diaLabel, // human label 'fields' => $fields, 'media' => [], ]; } } // Distinct categories present, in item order (segunda→domingo), with counts — // lets the hub offer a category filter without re-deriving it. $categories = []; foreach ($items as $it) { $k = $it['category']; if ($k === '') continue; if (!isset($categories[$k])) { $categories[$k] = ['key' => $k, 'label' => $it['category_label'], 'count' => 0]; } $categories[$k]['count']++; } echo json_encode([ 'app' => 'fitme3070', 'generated_at' => gmdate('c'), 'item_types' => array_values(array_unique(array_column($items, 'type'))), 'category_label'=> 'Dia da semana', // what the category dimension means here 'categories' => array_values($categories), 'items' => $items, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);