['file' => 'index.php'], 'platform_update' => ['file' => 'platform_update.php'], 'backups' => ['file' => 'backups.php', 'needs_db' => true, 'backup_helpers' => true], 'restore' => ['file' => 'restore.php', 'needs_db' => true, 'backup_helpers' => true], 'ip_bans' => ['file' => 'ip_bans.php', 'needs_db' => true], 'geo' => ['file' => 'geo.php'], 'tracking' => ['file' => 'tracking.php', 'needs_db' => true], 'hub_integration' => ['file' => 'hub_integration.php'], 'smtp_status' => ['file' => 'smtp_status.php', 'needs_db' => true], 'audit' => ['file' => 'audit.php', 'needs_db' => true], ]; } /** * Os endpoints partilhados que o public/api/platform.php de um site serve * (api/router.php). Cada um continua a autenticar-se a si próprio — chave de * saúde, chave de operações, HMAC, sessão + CSRF —; o router só despacha. * * Os URLs antigos (api/health.php, api/hub_ops.php, …) ficam onde estão: os * webhooks do Gitea e os caminhos que o hub guarda por plataforma apontam para * eles. Um endpoint NOVO entra só aqui e chega a todos os sites sem stub. */ function platform_api_routes(): array { return [ 'health' => 'api/hub_health.php', 'hub_ops' => 'api/hub_ops.php', 'hub_pair' => 'api/hub_pair.php', 'feedback' => 'api/feedback.php', 'agent' => 'api/agent.php', 'auto_update' => 'api/auto_update.php', 'backup_trigger' => 'api/backup_trigger.php', 'backup_download' => 'api/backup_download.php', ]; } /** O site declarou `'router' => true` no platform_connect() (tem o public/platform.php). */ function platform_router_enabled(): bool { return function_exists('platform_config') && !empty(platform_config()['router']); } /** * URLs sem `.php`? Só quando o site o declara (`'clean_urls' => true`), porque * precisa da regra do .htaccess que serve `/platform` a partir de * `platform.php` — sem ela, o URL limpo dava 404. */ function platform_clean_urls(): bool { return function_exists('platform_config') && !empty(platform_config()['clean_urls']); } /** URL de uma ferramenta pelo router; $query sem o `?` (p. ex. 'tab=db'). */ function platform_route_url(string $tool, string $query = ''): string { $script = platform_clean_urls() ? 'platform' : 'platform.php'; $path = $script . '?tool=' . rawurlencode($tool) . ($query !== '' ? '&' . ltrim($query, '?&') : ''); return platform_route_absolute_url($path); } /** URL de um endpoint pelo router da API. */ function platform_api_url(string $endpoint, string $query = ''): string { $script = platform_clean_urls() ? 'api/platform' : 'api/platform.php'; $path = $script . '?endpoint=' . rawurlencode($endpoint) . ($query !== '' ? '&' . ltrim($query, '?&') : ''); return platform_route_absolute_url($path); } /** Um caminho relativo ao base_url passa a absoluto; um URL ou caminho absoluto fica. */ function platform_route_absolute_url(string $url): string { if ($url === '' || preg_match('#^([a-z][a-z0-9+.-]*:)?//#i', $url) || $url[0] === '/') return $url; if (function_exists('base_url')) return (string) base_url($url); if (function_exists('hub_base_url')) return hub_base_url($url); return '/' . $url; } /** * As ferramentas que este site serve, com o URL de cada uma — anunciadas no * health para o hub poder ligar para a página local. [] sem router: os stubs * antigos variam de site para site, e anunciar um URL que dá 404 é pior do que * não anunciar. */ function platform_routes_announced(): array { if (!platform_router_enabled()) return []; $out = []; foreach (array_keys(platform_routes()) as $tool) $out[$tool] = platform_route_url($tool); return $out; } /** O mesmo para os endpoints, com a mesma condição. */ function platform_api_routes_announced(): array { if (!platform_router_enabled()) return []; $out = []; foreach (array_keys(platform_api_routes()) as $endpoint) $out[$endpoint] = platform_api_url($endpoint); return $out; }