/views/sysadmin/index.php must: // 1. Load $pdo (config/db.php + functions.php) // 2. Run require_sysadmin() // 3. Set $repo_root // Optional overrides (same as platform_update.php / backups.php): // $platform_layout_header / $platform_layout_navbar / $platform_layout_footer // $sysadmin_tools — array of card definitions; merged with the defaults below. // Each entry: ['title'=>str, 'description'=>str, 'icon'=>str (bi-*), // 'url'=>str, 'badge'=>?str, 'color'=>str (primary/info/…)] if (!isset($repo_root) || !is_string($repo_root)) { $repo_root = realpath(dirname(__DIR__, 2)) ?: dirname(__DIR__, 2); } $repo_root = rtrim($repo_root, '/'); $base = function (string $path): string { return function_exists('base_url') ? base_url($path) : '/' . ltrim($path, '/'); }; $default_tools = [ [ 'title' => 'Atualizar plataforma', 'description' => 'Git pull/push, OPcache, migrations e log de erros.', 'icon' => 'bi-arrow-repeat', 'url' => platform_admin_url('platform_update.php'), 'color' => 'primary', ], [ 'title' => 'Backups', 'description' => 'Criar e transferir cópias de segurança dos uploads e da base de dados.', 'icon' => 'bi-archive', 'url' => platform_admin_url('backups.php'), 'color' => 'secondary', ], [ 'title' => 'Estado SMTP', 'description' => 'Configuração do envio de email, teste de ligação e mensagem de teste.', 'icon' => 'bi-envelope-check', 'url' => platform_admin_url('smtp_status.php'), 'color' => 'info', ], // Por omissão e não site a site: a partir do momento em que o cliente do hub // é partilhado, uma plataforma que o tenha instalado sem mostrar a página // fica ligada ao hub sem ninguém saber por onde a desligar. [ 'title' => 'Integração com o hub', 'description' => 'Anunciar esta plataforma à Frota e gerir as chaves de leitura e de operações.', 'icon' => 'bi-hdd-network', 'url' => platform_admin_url('hub_integration.php'), 'color' => 'secondary', // Um site que ainda não tenha o stub não deve mostrar um cartão para 404. 'available' => (function_exists('platform_router_enabled') && platform_router_enabled()) || is_file($repo_root . '/public/views/sysadmin/hub_integration.php') || is_file($repo_root . '/public/views/admin/hub_integration.php'), ], ]; // Com o router, todas as páginas partilhadas existem em todos os sites — por // isso aparecem sozinhas, e uma ferramenta nova chega a toda a frota sem cartão // nenhum a escrever site a site. Sem router ficam de fora: cada site tem só os // stubs que tem, e um cartão para 404 é pior do que cartão nenhum. $routed = function_exists('platform_router_enabled') && platform_router_enabled(); $default_tools = array_merge($default_tools, [ [ 'title' => 'Bloqueio de IP', 'description' => 'Endereços recusados à porta por atividade automatizada repetida, e quem está a caminho disso.', 'icon' => 'bi-shield-slash', 'url' => platform_admin_url('ip_bans.php'), 'color' => 'warning', 'available' => $routed, ], [ 'title' => 'Bloqueio por país', 'description' => 'Recusar formulários — ou o site — a quem chega de fora do país.', 'icon' => 'bi-globe-americas', 'url' => platform_admin_url('geo.php'), 'color' => 'warning', 'available' => $routed, ], [ 'title' => 'Restaurar base de dados', 'description' => 'Aplicar um backup de base de dados, com inspecção prévia e cópia de segurança automática do estado actual.', 'icon' => 'bi-arrow-counterclockwise', 'url' => platform_admin_url('restore.php'), 'color' => 'danger', 'available' => $routed, ], [ 'title' => 'Origem das visitas', 'description' => 'De onde vêm as pessoas, com que dispositivo e de que país — e quais dessas origens produzem pedidos.', 'icon' => 'bi-graph-up-arrow', 'url' => platform_admin_url('tracking.php'), 'color' => 'success', 'available' => $routed, ], [ 'title' => 'Registo de auditoria', 'description' => 'Quem fez o quê, a quê e quando — com o antes e o depois de cada alteração.', 'icon' => 'bi-journal-text', 'url' => platform_admin_url('audit.php'), 'color' => 'secondary', 'available' => $routed, ], ]); // Um site pode esconder um cartão por omissão declarando // $platform_hide_tools = ['smtp_status.php'] no seu stub. Serve para quando a // plataforma tem uma página própria que já faz o mesmo -- o dance tem as // Comunicações, que editam a configuração e correm os mesmos testes, e ter os // dois cartões lado a lado só faz hesitar em qual clicar. $hide = array_map('strval', $platform_hide_tools ?? []); if ($hide) { $default_tools = array_filter( $default_tools, fn($t) => !array_filter($hide, fn($h) => str_contains((string) $t['url'], $h)) ); } // Cards podem declarar 'available' => bool para serem escondidos quando o // servidor não suporta a ferramenta (ex.: exige proc_open). Ausente = visível. $tools = array_filter( array_merge($default_tools, $sysadmin_tools ?? []), fn($t) => !isset($t['available']) || $t['available'] ); // Um cartão próprio que aponta para o mesmo sítio que um por omissão não o // repete (um site que ainda declara «Bloqueio de IP» à mão, por exemplo). $seen = []; $tools = array_filter($tools, function ($t) use (&$seen) { $url = (string) ($t['url'] ?? ''); if ($url === '' || isset($seen[$url])) return $url === ''; return $seen[$url] = true; }); $layout_header = $platform_layout_header ?? ($repo_root . '/includes/header.php'); $layout_navbar = $platform_layout_navbar ?? ($repo_root . '/includes/navbar.php'); $layout_footer = $platform_layout_footer ?? ($repo_root . '/includes/footer.php'); $pageTitle = 'Sistema'; if (is_file($layout_header)) include $layout_header; if (is_file($layout_navbar)) include $layout_navbar; ?>
Ferramentas de administração da plataforma.