Registo de alterações

NeoFrag Reborn 1.2.0

Luandre 23 set. 2026 52 min de leitura 109
Sumário
Sumário

Adicionado

  • As atualizações do núcleo, com um só clique (2026-09-23). A partir desta versão, Administração → Monitorização assinala as novas versões do NeoFrag Reborn e instala-as: cópia de segurança do site, verificação da impressão do pacote, aplicação do pacote, atualização da base de dados, e regresso à cópia de segurança se algo falhar. É a primeira versão publicada por este caminho; foi testada do princípio ao fim num site novo antes da publicação. Um site na 1.1.0 ainda não tem este botão: passa para a 1.2.0 à mão, substituindo os seus ficheiros. Para os mantenedores: tools/build-release.php produz os três ficheiros a publicar juntos (neofrag-reborn-update-<v>.zip, version.json, checksum.json); o procedimento está em docs/guide/marketplace.md.

  • Os anúncios no Discord (2026-09-23). Um webhook que aponta para um canal do Discord recebe agora uma verdadeira mensagem, com título, ligação e cor: nova notícia, novo artigo, novo membro, novo comentário, novo tópico do fórum. Até agora o Discord recusava o que o módulo enviava, embora a sua descrição prometesse o Discord.

  • «Fulano está em direto» (2026-09-23). Quando um canal do Twitch ou do YouTube seguido pelo widget «Estado ao vivo» entra em direto, os webhooks subscritos ao evento «Canal em direto» anunciam-no, uma só vez por emissão, com a miniatura da emissão.

  • A demonstração fala também inglês no seu conteúdo (2026-09-23): as suas notícias, artigos, páginas, categorias e galerias têm uma versão inglesa, que mostra o multilinguismo.

  • Todo o produto fala as seis línguas (2026-09-23). A administração, os módulos, os widgets, os temas, as definições, os botões, as mensagens e os scripts: perto de 800 cadeias estavam escritas diretamente em francês e ficavam assim num site em inglês, alemão, espanhol, italiano ou português. Passam agora todas pelas traduções, nas seis línguas. Em particular:

    • O assistente de instalação está traduzido, com um seletor de língua; segue no início a língua do navegador. O instalador da linha de comandos aceita --lang=en, ou a língua do terminal.
    • O marketplace mostra o nome e a descrição de cada addon na língua do site.
    • Os países (perfil, adversários) são mostrados na língua do site.
    • Os cargos e os modelos de e-mail incluídos são mostrados traduzidos; um nome mudado pelo administrador fica tal como o administrador o escreveu.
    • A moderação mostra o estado, o motivo e o tipo de uma denúncia, e o tipo de uma sanção, escritos por extenso — mostrava os códigos (pending, forum_message, ban_temp).
    • Um grupo criado numa língua já não desaparece quando o site é mostrado noutra — saía da lista, e as suas permissões com ele.
    • O tema da administração declarava-se escrito em inglês: num site em inglês, as suas cadeias francesas nunca eram traduzidas. Está corrigido, tal como os scripts dos módulos, que procuravam as suas traduções no sítio errado.
    • A confirmação da eliminação da conta pede para escrever a palavra na língua do site («ELIMINAR» em português), e já não «SUPPRIMER» em todo o lado.

    Uma verificação, check-textes-en-dur, recusa agora na CI qualquer texto da interface escrito no código.

  • Os navegadores dos visitantes podem guardar os ficheiros do site, se o pedires (2026-09-22). O manifesto já tornava o site instalável; o site pode agora guardar as suas imagens, estilos e scripts nos navegadores dos visitantes. Desligado por predefinição, liga-se em Administração → Definições → Preferências gerais («Aplicação instalável»).

    As páginas, essas, nunca são guardadas. Uma página guardada em memória sobreviveria a uma nova implementação: a quem já tivesse vindo seria servido um site com dias, sem que nada o indicasse. Uma alteração continua assim visível de imediato.

    Desmarcar desinstala mesmo. É a parte delicada desta técnica: um componente deste tipo, uma vez instalado num navegador, fica lá mesmo que o ficheiro seja retirado do servidor. O interruptor não retira, portanto, nada — serve uma versão que se desinstala sozinha na visita seguinte. Por isso a funcionalidade está desligada por predefinição, e por isso uma atualização do núcleo nunca a liga sozinha.

  • O site pode ser instalado como aplicação (2026-09-21). /manifest.webmanifest é gerado pelo próprio site — nome, descrição, cor do tema, endereço inicial e favicon vêm das definições — em vez de ser colocado como ficheiro, que estaria errado em qualquer outro lado.

  • As pastas sensíveis também estão fechadas com o Apache (2026-09-21). Os .htaccess do pacote protegiam menos do que a configuração do Caddy incluída: com o Apache, o instalador continuava acessível depois de o site estar instalado (só a sua própria verificação o impedia de correr), e num site instalado a partir do repositório git, docs/, tools/ e tests/ também estavam acessíveis — a documentação lia-se em texto simples. cache/, config/, install/, tools/, tests/ e docs/ têm agora cada uma a sua proteção, a raiz bloqueia também os ficheiros .neon e .md, e tools/check-htaccess.php volta a ler a lista em cada execução, com o motivo de cada linha.

  • Um endereço desconhecido já não escreve um erro no registo do site (2026-09-21). O módulo pages, que recebe em último recurso os endereços que mais nada reconhece, escrevia uma linha de erro para cada um — cada robô que sondava acrescentava algumas. Para os programadores de addons: um controlador pode agora declarar uma recusa como corrente (Module_Checker::refus_ordinaire()); o diagnóstico continua a ser mostrado no ecrã em modo de depuração. A verificação check-journal recusa agora qualquer linha que o próprio produto escreva no registo de erros.

  • Duas verificações fazem respeitar as regras do repositório (2026-09-21), para os contribuidores. tools/check-tools.php verifica que cada ferramenta segue as regras comuns: cabeçalho descritivo, recurso à biblioteca comum em vez de código copiado, veredicto e códigos de saída padrão, porta reservada, catálogo atualizado. tools/check-docs.php controla a documentação: números exatos, ligações e âncoras válidas, nenhum documento órfão, nenhuma menção de uma ferramenta que já não existe, nenhuma passagem copiada de um documento para outro, documentos que continuam legíveis. Ambas correm na integração contínua.

  • Oito addons novos, todos opcionais (2026-09-20). Uma atualização não os instala: num site existente, adicionam-se a partir de Administração → Temas & addons, e retiram-se da mesma forma. Uma instalação nova inclui-os com o perfil Completo, oferecido por predefinição, mas não com os outros perfis.

    Addon O que faz
    Efeito sazonal (widget) Neve, confetes ou folhas por todo o ecrã, durante um intervalo de datas. As datas escrevem-se MM-DD sem ano — a estação volta sozinha — e podem passar pelo Ano Novo (de 12-15 a 01-06). Fora de época, a página não recebe absolutamente nada: nem imagem, nem script. A definição do sistema que pede menos movimento (prefers-reduced-motion) é respeitada, e a animação para quando o separador passa para segundo plano.
    Leitor de feeds (widget) Os últimos artigos de um feed RSS ou Atom externo. Uma página quase nunca espera por um site alheio: lê uma cache, e serve até conteúdo desatualizado em vez de fazer esperar os visitantes; a atualização faz-se na tarefa agendada. Só a primeiríssima apresentação, com a cache vazia, espera pelo feed, três segundos no máximo. Um feed em baixo fica de lado dez minutos em vez de ser tentado de novo a cada visita.
    Citações (módulo) Uma coleção por categorias, com autor e fonte.
    Receitas (módulo) Ingredientes e passos introduzidos um por linha, tempos e número de doses, marcação schema.org/Recipe que os motores de pesquisa leem.
    Glossário (módulo) Um léxico ordenado por letra. «Éclaireur» fica no E, «Æther» no A, «1v1» no #. A letra é calculada, nunca introduzida.
    Mapa de locais (módulo) Locais num mapa OpenStreetMap, com endereço, descrição e ligação. A biblioteca do mapa é alojada pelo site; só os mosaicos do mapa de fundo vêm do OpenStreetMap. A página continua útil sem JavaScript — a lista, os endereços e as ligações estão lá.
    Rádio web (módulo) Um leitor de emissão, o que está no ar, e a programação da semana. Um programa pode passar a meia-noite: «sábado 22:00 → 02:00» continua a ser o programa de sábado.
    Área de testes (módulo) Reservado aos membros: experimenta-se lá uma formatação e vê-se a apresentação exata do site. Sobretudo, mostra o que o site retirou — é a única página que responde a «porque é que a minha tabela desapareceu?».

    Os três módulos de conteúdo (citações, receitas, glossário) partilham o padrão da FAQ: categorias, pesquisa, filtro, ordenação e rascunhos.

  • Escolher o conteúdo na instalação. O instalador web oferece agora um perfil do site entre os requisitos e a base de dados: Completo, Gaming / eSports, Comunidade ou Só o núcleo. Os módulos podem sempre ser desmarcados um a um, e os de que um módulo precisa são adicionados automaticamente (o palmarés precisa das equipas), com uma mensagem. Sem JavaScript, o formulário continua a funcionar — o servidor só mantém o que pertence ao perfil escolhido.

    Nenhuma lista de addons é escrita à mão: os perfis são construídos a partir das declarações presets de cada addon. É a diferença para a tentativa de junho de 2026, abandonada porque uma instalação aligeirada acabava num erro do servidor (500): módulos do núcleo consultavam as tabelas de módulos opcionais sem verificar que existiam. Essas verificações existem agora e são controladas em cada execução da CI.

  • Cada módulo, widget e tema incluído declara o seu papel: no seu __info(), diz se pertence ao núcleo, de que perfis de instalação faz parte, e de que módulos precisa. A pertença ao núcleo era até agora um efeito secundário da presença no pacote — foi assim que emojis, files e webhooks lá foram parar sem que nenhuma decisão fosse tomada.

  • Três novas salvaguardas de integração contínua:

    Verificação O que recusa
    check-addon-declarations.php um addon que não declara nada, uma dependência inexistente, um addon do núcleo que depende de um opcional, um addon não distribuível publicado no catálogo, uma declaração em desacordo com seed.sql
    check-addon-coupling.php um acoplamento fatal (tabela, classe) nem declarado nem anotado; um ciclo duro. Lido no código com o tokenizador do PHP, não com expressões regulares — portanto sem falsos positivos nos comentários
    check-install-profiles.php um perfil que não arranca. Instala mesmo numa base de dados descartável, serve o site e falha ao menor 5xx — também nas rotas dos módulos ausentes, que têm de devolver um 404 limpo
  • Encontrar um membro a partir da barra de pesquisa. A pesquisa do site só encontrava conteúdo — fórum, notícias, páginas. Procurar alguém obrigava a abrir o diretório de membros e percorrê-lo, embora seja uma das coisas que mais se procuram num site de comunidade. Os membros aparecem agora na pesquisa global e nas sugestões instantâneas, por nome de utilizador, nome próprio ou apelido.

    Nada de novo é exposto pelo caminho: estes três campos já são mostrados no perfil público de cada membro, e a pesquisa aplica exatamente o mesmo filtro que o diretório — uma conta eliminada não aparece.

  • Gerir uma série de eventos de uma só vez. Criar um evento recorrente já gerava todas as suas ocorrências com um clique — voltar a elas obrigava depois a abri-las uma a uma.

    Agora, uma ocorrência de uma série tem um botão «Eliminar toda a série», cuja confirmação indica quantas ocorrências vão desaparecer, e o formulário de edição oferece «Aplicar a todas as ocorrências da série». O título, o tipo, as descrições, o local, a imagem e o estado de publicação são copiados para cada uma; as datas nunca — são elas que distinguem uma sessão da seguinte.

  • Desfazer uma atualização e restaurar uma cópia de segurança. O CMS já fazia uma cópia de segurança completa — ficheiros e base de dados — mesmo antes de cada atualização do núcleo. Não a sabia voltar a usar: a rede de segurança estava lá, mas ninguém sabia cair nela.

    Agora, se a colocação dos ficheiros ou uma migração falhar, o site é automaticamente reposto no estado em que estava; a mensagem diz ao mesmo tempo o que falhou e se o regresso atrás resultou. Cada cópia de segurança da lista tem também um botão Restaurar, para os casos em que o estrago não vem de uma atualização — um módulo de terceiros, uma ação de que nos arrependemos. A confirmação indica o que se vai perder.

    O que a restauração não toca, de propósito: a configuração do site (repor credenciais da base de dados desatualizadas cortaria o site da sua própria base), os registos (são a memória do incidente que se está a reparar) e a cache (esvaziada para ser reconstruída, em vez de reposta no estado de outra versão).

    Pelo caminho, a cópia de segurança inclui agora vendor/, que o pacote de atualização traz e que ela não incluía: sem ele, um regresso atrás teria posto o código antigo por cima das novas dependências.

  • Responder a um comentário. O botão «Responder», desativado no código original, funciona agora: a resposta é mostrada indentada por baixo do comentário a que responde. Só se pode responder a um comentário de primeiro nível do mesmo conteúdo que não tenha sido eliminado (um nível de respostas); o servidor verifica-o.

  • Para os criadores de temas: zonas chamadas pelo nome (ideia tirada do HiddenCMS). Uma vista chama agora uma zona pelo seu nome — $this->output->region('content') — em vez de pelo seu número — zone(2). O tema declara a correspondência entre nomes e zonas no seu __info() (regions). A antiga chamada zone() continua a funcionar, e um tema sem esta declaração fica inalterado. Os cinco temas públicos (Nebula, Forge, Granite, Blockcraft, Extend) usam os nomes.

  • Instalar pela linha de comandos (install/cli.php, ideia tirada do HiddenCMS): uma alternativa ao assistente web, prática para instalar um servidor de forma reprodutível ou automatizada. As suas opções cobrem a base de dados (--db-*, --create-db), a conta de administrador (--admin-*), o nome e o endereço do site (--site-name, --site-url), a língua (--lang), os dados de demonstração (--demo) e a execução (--force, --yes, --dry-run, --no-lock). Sem opções, faz as perguntas uma a uma e esconde a palavra-passe enquanto é escrita; --admin-pass-env lê a palavra-passe de uma variável de ambiente para que não apareça na lista de processos. Usa o mesmo código que o assistente web e instala todos os addons incluídos, como o perfil Completo.

  • Um lançador para toda a bateria: php tools/check-all.php. As verificações não tinham um ponto de entrada comum — a CI chama-as uma a uma, e localmente cada um escrevia o seu próprio ciclo à mão, nunca o mesmo. O lançador descobre as verificações presentes (uma verificação nova junta-se sem que ninguém lhe toque), corre primeiro composer audit, limita a duração de cada verificação, e diz no fim o que não correu: os testes no navegador (--navigateur) e as verificações com um alvo explícito, entre elas check-restauration, que danifica o site de propósito.

  • Cada addon mostra o seu aspeto (2026-09-22). A página «Temas & addons» da administração e o marketplace mostram uma miniatura: uma verdadeira captura do módulo, widget, tema ou língua tal como corre na demonstração. Os 61 addons do marketplace têm uma, em 960×600 para os módulos e os widgets. Para lá chegar, foram instalados na demonstração seis módulos e dois widgets com conteúdo de exemplo — um glossário, citações, receitas, um mapa de locais e uma programação de rádio web —, e os widgets que não mostram nada sem definições foram capturados com definições de exemplo. O que não tem nada para mostrar mantém o seu ícone, como os conectores Discord, GitHub e Google, cujo ícone é o seu logótipo. A demonstração tem também finalmente a identidade da sua comunidade — nome, tipo, data de criação e descrição —, que tinha ficado vazia.

  • Dez addons têm finalmente uma descrição (2026-09-22): as seis línguas e os quatro addons de início de sessão externo (o de base e os seus conectores Discord, GitHub e Google). É mostrada na língua do site.

  • Campos de perfil definidos pelo administrador (2026-09-20). O perfil de um membro só tinha campos fixos. Administração → Utilizadores → Campos do perfil permite acrescentar os seus — nome no jogo, plataforma, posição… —, entre oito tipos de campo. Os membros preenchem-nos no painel «Informações adicionais» do seu perfil. Um campo é privado por predefinição; tornado público, é mostrado na página do membro. Os valores estão incluídos na exportação dos dados pessoais do membro e são eliminados com a sua conta.

  • O tipo de letra do site escolhe-se na administração (2026-09-20). Administração → Definições → Preferências gerais → Tipo de letra do site oferece doze tipos de letra, que substituem o de cada tema. Por predefinição, «Tipo de letra do tema» mantém o tipo de letra próprio de cada tema e não chama nenhum serviço externo; os doze tipos de letra oferecidos são servidos pelo Google Fonts.

  • O histórico de inícios de sessão já não é guardado para sempre (2026-09-20). Regista o endereço IP, o navegador e a data de cada início de sessão, e nada o apagava. É agora purgado para lá de 395 dias (treze meses), uma duração definida em Administração → Definições → Preferências gerais; 0 desliga a purga.

  • Lembretes dos eventos seguidos do calendário (2026-09-20). Um membro que segue um evento do calendário recebe um lembrete antes do seu início, como os participantes de um evento do módulo Eventos. O prazo define-se na configuração do calendário («Lembrete antes de um evento seguido», 24 horas por predefinição, 0 para desligar).

  • O pacote de atualização diz o que protege e o que retira (2026-09-20). Tem um ficheiro nf-manifest.json: as pastas do site em que uma atualização nunca escreve (config/, install/, upload/, logs/, backups/, cache/), e os ficheiros que a versão retira. Até agora a atualização deduzia sozinha o que apagar; um pacote sem este ficheiro continua a ser aceite.

Alterado

  • Toda a interface fala Bootstrap 5 (2026-09-23). Restavam cerca de 470 usos de classes do Bootstrap 3 e 4, mantidos a funcionar por uma folha de estilo de compatibilidade: campos de formulário, distintivos de cor, botões de fechar, botões em toda a largura, blocos «avatar e texto», grupos de entrada, caixas de verificação, grelhas de formulário. Toda a marcação foi migrada para os seus equivalentes do Bootstrap 5; o que é próprio do produto tem agora um nome próprio do produto. Uma verificação recusa qualquer nome antigo que volte, mesmo redefinido. O que se vê:

    • as listas pendentes recuperam a sua seta — uma centena, na administração e no site, pareciam campos de texto;
    • os distintivos de cor (estados, grupos, cargos, sanções) são legíveis em todos os temas, em claro como em escuro: o seu texto chumbava na verificação de contraste;
    • os grupos «Moderador» e «Moderador sénior» são mostrados: o seu nome estava escrito a branco sobre fundo branco;
    • os botões de fechar das janelas têm uma zona de clique suficiente nos telemóveis.
  • O JavaScript é revisto por um linter (2026-09-22). Setenta e um ficheiros do projeto escritos ao longo dos anos, sem que nada os verificasse para lá da sua sintaxe e da ausência de jQuery. O ESLint vê o que a sintaxe não diz: uma variável global criada por esquecer um var, um eval disfarçado, código depois de um return, um innerHTML alimentado por um valor calculado. Nenhum pacote npm é implementado: é uma ferramenta de desenvolvimento, tal como a análise estática do PHP.

    As regras são escolhidas por um único critério — já ter mordido aqui. É a família de «$ is not defined», que tinha posto fora de serviço a ordenação das tabelas em toda a administração durante três meses. A desordem existente (usos de innerHTML a sanear) é congelada tal como está em vez de reescrita de uma vez: o seu número já não pode subir.

  • A linha de base do PHPStan regenera-se com um comando, e a classe Config do núcleo está anotada (2026-09-21). Três erros novos levaram a reabrir phpstan-baseline.neon: as entradas acrescentadas à mão estavam escritas de forma diferente das do próprio PHPStan, e perto de trezentos blocos já não correspondiam a nada — toda uma família «Function NeoFrag not found», morta desde que o ficheiro de arranque declara a função. A configuração vive em phpstan-base.neon, phpstan.neon só lhe acrescenta a linha de base, e composer stan:baseline regenera-a por inteiro. Config anota agora a língua atual, a lista das línguas e as definições do núcleo que os módulos leem: estes acessos são analisados em vez de ficarem congelados.

  • As ferramentas de tools/ refeitas sobre uma biblioteca comum (2026-09-21). Umas sessenta ferramentas, escritas cada uma à sua maneira, copiavam a mesma canalização: arrancar um servidor PHP, abrir uma sessão de administrador, lançar o Chrome, ler config/db.php. Uma lição aprendida numa não chegava às outras. tools/lib/ tem agora esta base — ligação, sessão, servidor, navegador, percurso do repositório, SQL, opções, veredictos —, e cada ferramenta reduz-se à sua própria lógica. Restam cinquenta e duas, sem perda de funções: check-js-syntax e check-js-jquery formam check-js-sources; check-docs-counts e check-docs-liens formam check-docs; check-lang-args junta-se a check-langs; seed-wiki-docs e dump-wiki formam wiki-docs; smoke-test passa a check-smoke, como qualquer verificação; addons-manifest e table-map, que são dados, vivem na biblioteca. Cada ferramenta tem agora a sua própria porta reservada (várias partilhavam uma), três códigos de saída que distinguem «nada a assinalar», «recusado» e «não conseguiu julgar», e um cabeçalho a partir do qual se gera o catálogo de tools/README.md. bs5-codemod, a ferramenta da migração do Bootstrap 4 para o 5 de junho, foi retirada: check-classes-bs4 cobre tudo o que ela verificava, incluindo os pontos de quebra dos utilitários direcionais.

  • declare(strict_types=1) em todo o perímetro útil (2026-09-21): 1365 ficheiros contra 78 na véspera. O trabalho avançava em pequenos lotes desde junho; está concluído. Os 209 ficheiros restantes são os modelos views/**.tpl.php, onde a declaração seria sintaticamente válida e não protegeria nada.

    A conversão foi feita por ordem de risco decrescente — o número de chamadas a funções nativas por ficheiro —, com o conjunto de testes corrido entre cada lote.

    Uma consequência de fundo, própria deste produto: o PHP em modo estrito recusa __toString() para as funções internas. Ora, lang() devolve um objeto de tradução diferido, resolvido no momento da apresentação, quando a língua é finalmente conhecida, e as datas também são objetos. A barra da administração, a página de cada notícia e vários ecrãs falhavam, portanto, com um erro fatal — módulo fora de combate, página truncada, sem uma palavra. A conversão faz-se agora no ponto de escape (htmlspecialchars), ou seja, onde o valor tem de se tornar uma cadeia por definição: perto de 500 sítios em 86 ficheiros.

    A vaga exigiu também onze conversões explícitas, três delas em caminhos percorridos em cada página — a ordem de apresentação das línguas e dos grupos, lida no início de cada sessão, e o cálculo do token que protege cada formulário contra os pedidos falsificados (CSRF): sem elas, um site com duas línguas ativas teria devolvido um erro 500 em todas as suas páginas.

  • O registo diz agora ONDE, não só o quê (2026-09-21). Quando um módulo lança uma exceção, a sua apresentação é abandonada e a página mostrada truncada — em silêncio. A linha do registo dava a mensagem sem nunca nomear um ficheiro. Nomeia agora o primeiro sítio do código próprio do produto na pilha de chamadas. Encontrar a origem dos erros acima passou de uma investigação a uma simples leitura.

  • O compilador SCSS passa para a 2.1 (2026-09-20). No PHP 8.5, cada compilação de estilos escrevia dez avisos de obsolescência no registo; já não resta nenhum. A 2.x minimiza um pouco mais (.25rem em vez de 0.25rem, #ccc em vez de #CCCCCC), o que muda três folhas de estilo — as dos módulos addons e palmarés e a da página de manutenção. A equivalência não foi deduzida do texto: os dois conjuntos de CSS foram dados ao motor do Chrome, que vê neles exatamente as mesmas regras, propriedades e valores calculados.

  • A documentação foi relida por inteiro face ao código (2026-09-17). Os guias de instalação, de conceitos e de desenvolvimento (criar um módulo, um widget, um tema, o framework) datavam de junho e descreviam o CMS de antes: uma instalação sem escolha de perfil, um tema que carregava o jQuery, grelhas do Bootstrap 4. Dizem agora o que o produto faz — perfis de instalação, declarações dos addons, regiões com nome, front end sem jQuery sob uma política de segurança estrita, definições de widget com valores de recurso, vocabulário de cores partilhado. O README, o guia de contribuição, a política de segurança e a referência técnica estão alinhados da mesma forma.

  • O que um addon permite lê-se na sua declaração, já não em listas de nomes escritas no código. Três delas decidiam a sorte dos addons, e as três estavam erradas: a lista dos widgets protegia sete nomes que não são widgets; a dos temas protegia um tema default inexistente deixando nebula, o único tema público do núcleo, eliminável assim que estivesse inativo; a dos módulos duplicava, em desacordo, o que __info() já dizia. Verificado addon a addon face à lógica antiga: nenhuma mudança no que pode ser desativado, nenhuma mudança de estado ativo, e 39 addons passam a não poder ser eliminados — que é o objetivo da correção.

  • A Reciclagem já não conhece os outros módulos. Tinha escrita no código a lista das tabelas, chaves primárias e métodos de restauro de news, articles, gallery, comments e forum: não podia, portanto, pertencer ao núcleo sem arrastar consigo quatro módulos opcionais — comments pertence ele próprio ao núcleo. Cada módulo declara agora os seus tipos restauráveis; o núcleo recolhe-os. A mesma inversão para os descritores de conteúdo (reações, subscrições, revisões).

  • A lista dos addons do núcleo e opcionais já não é mantida à mão. tools/lib/addons-manifest.php, uma tabela escrita à mão e congelada em junho, é agora deduzida das declarações. As duas já tinham divergido: emojis estava listado como núcleo quando se declara à la carte — podia portanto ser desmarcado na instalação mas faltava no catálogo, e era por isso impossível de reinstalar. Catálogo: 52 → 53 addons nesse dia (61 à saída da 1.2.0).

  • O instalador, refeito visualmente: paginação em duas colunas, tokens de estilo tirados do nebula (azul-marinho e verde-azulado, destaque #2dd4bf), degradê retirado de trás do texto, logótipo posto num distintivo.

Corrigido

  • A cópia de segurança da Monitorização volta a funcionar (2026-09-23). Desde 21 de setembro, parava na primeiríssima linha da base de dados: o botão «Iniciar backup», e a atualização do núcleo, que começa por uma cópia de segurança, falhavam em todos os sites. Encontrado ao testar a atualização antes de a publicar.

  • Mudar de língua numa notícia traduzida já não leva a uma página não encontrada (2026-09-23). O seletor de língua mantém o endereço, e com ele o título na língua anterior: a versão traduzida recusava-o. Redireciona agora para o seu próprio endereço.

  • Uma página traduzida é mostrada na língua certa (2026-09-23). As páginas públicas eram servidas na versão que a base de dados devolvia primeiro, fosse qual fosse a língua do visitante.

  • O tema escolhido por um visitante já não se estende a outro site do mesmo domínio (2026-09-23). A escolha era memorizada para todo o domínio: um visitante que passava um site para o Forge via também no Forge outro site instalado no mesmo domínio. A escolha é agora memorizada para cada site separadamente, e uma nova definição, Preferências gerais → Escolha do tema, permite desligá-la: o menu desaparece e o tema predefinido aplica-se a todos.

  • A demonstração volta a repor-se (2026-09-23). Um erro no seu conjunto de dados fazia falhar a reposição de quarto em quarto de hora desde a véspera: o que os visitantes lá mudavam ficava. Uma verificação recusa agora este defeito antes de qualquer coisa ir para o ar, e uma reposição falhada é escrita no registo em vez de passar despercebida.

  • A conta de emergência da demonstração já não aparece em lado nenhum (2026-09-23): nem na lista de membros, nem na pesquisa, nem entre os membros online, nem na administração; a sua página responde «não encontrado».

  • O site num telemóvel (2026-09-23), a partir de capturas tiradas num telemóvel:

    • O menu está sempre ao alcance. No tema Nebula, desaparecia abaixo dos 860 píxeis de largura sem nenhum botão para o reabrir: agora abre-o um botão «hambúrguer». Nos outros temas, um menu demasiado longo para uma linha recolhe-se atrás de um botão «Menu», em vez de mudar de linha até encher o ecrã; um menu curto continua aberto.
    • Os blocos empilhados já não se tocam: a área de membros estava colada ao bloco de cima.
    • O texto já não se cola aos avatares dos membros (comentários, conversas, autor de uma notícia, candidaturas, perfil).
    • Os pontos do diaporama são verdadeiros botões, centrados por baixo da imagem, e continuam claros nos temas escuros, como as setas e a legenda: o Bootstrap tornava-os pretos.
    • A pesquisa do tema Extend mantém o seu botão ao lado do campo.
    • As fotos de um álbum preenchem o seu cartão.
    • O cabeçalho dos comentários mostra o título antes do contador, que antes o precedia.
    • As datas abreviadas são escritas na língua do site («30 août 2026», «Sonntag»), e já não em inglês; a linha do autor de uma notícia recupera um tamanho de texto normal.
  • A página de uma foto da galeria existe (2026-09-23). O widget «Imagem aleatória», o diaporama da galeria e a ligação de um comentário escrito sobre uma foto levavam todos a uma página não encontrada: nunca tinha sido declarada. Mostra a foto, a sua descrição, o caminho de volta ao álbum e os comentários. Uma foto segue também as regras do seu álbum: já não há acesso pelo seu endereço quando o álbum está na reciclagem ou ainda não foi publicado.

  • Os últimos restos do Bootstrap 3 e 4 (2026-09-23), que os seus nomes de classe não denunciavam: a estrutura do diaporama, as cruzes de fechar que mostravam um «×» por cima do ícone, dois acordeões (FAQ, ligações de navegação) ainda construídos à maneira do Bootstrap 4 (o da FAQ abria-se, mas sem o aspeto nem a seta do componente), campos que se envolviam num grupo vazio, a seta das dicas que ficava branca por baixo de uma dica escura, e duas regras do widget dos parceiros. check-classes-bs4 lê agora também a ESTRUTURA dos componentes e os estilos escritos nas vistas.

  • Páginas de erro que não o eram (2026-09-23). Na moderação, e na gestão dos cargos, dos modelos de e-mail, dos membros e do diaporama, um endereço que apontava para um elemento retirado devia responder «página não encontrada»: chamava uma função que não existe, escrevia um aviso no registo, e a página da moderação aparecia vazia. Encontrado ao ensinar à análise estática as funções «mágicas» do framework — o que tirou 455 ocorrências da sua lista de exceções.

  • O botão dos e-mails enviados aos membros é legível (2026-09-23): a validação da conta, a palavra-passe perdida e os outros modelos tinham um botão branco sobre turquesa claro (contraste de 2,3:1). A correção aplica-se aos modelos incluídos e aos já instalados, exceto os que um administrador personalizou.

  • Últimos retoques de apresentação (2026-09-23): as ligações da wiki na tonalidade legível do tema; os botões de «sucesso» nos temas escuros; o estado de uma candidatura, cuja caixa não tinha fundo (classes de um antigo tema de administração); as redes sociais nos cartões de membro; os títulos truncados na administração; um visitante que segue a ligação para participar num evento recebe «Acesso não autorizado» em vez de uma página não encontrada.

  • O texto é legível em todo o lado, em modo claro como em modo escuro (2026-09-23). As ligações e os botões da administração, os alertas, as datas e os cabeçalhos de tabela dos temas, as categorias das notícias, a página do marketplace nos temas claros, o botão «Aceitar tudo» do banner de cookies, os distintivos de reputação e de tipo de evento: todos atingem agora o contraste mínimo recomendado (4,5:1). Em modo escuro, a administração tem as suas próprias cores de estado, e o painel «Saúde do site» e a zona de envio de imagens da galeria seguem o tema.

  • A administração num telemóvel (2026-09-23). A barra superior passa para duas linhas — o trilho de navegação completo, e depois os botões — em vez de truncar o título da página; os alvos pequenos (ícone de início, contadores) são suficientemente grandes para um dedo; o cabeçalho das categorias do fórum já não desliza para baixo dos seus botões.

  • O fórum num telemóvel (2026-09-23): num tópico, o autor passa para cima da mensagem em vez de lhe deixar só 200 px de largura, e os botões de uma mensagem já não tapam a sua data.

  • Os plurais traduzidos (2026-09-23). 47 cadeias tinham perdido a sua forma plural na tradução: um site em inglês mostrava «3 topic», «5 image», «2 year». O contador das categorias do fórum, escrito em francês em todas as línguas, está agora traduzido.

  • A documentação do site está atualizada (2026-09-23). As dez páginas da wiki incluídas com o produto e as da demonstração estavam uma semana atrasadas em relação aos guias; «Criar um widget» ainda ensinava uma classe do Bootstrap 4. Uma verificação compara-as agora com os guias.

  • O formulário de resposta do fórum cabe num telemóvel (2026-09-23): a lista dos tipos de anexo permitidos, escrita sem espaços, formava uma só palavra demasiado larga para o ecrã.

  • Todo o site passado a pente fino, em cada tema, cada modo e cada largura (2026-09-23). Uma verificação automática mostra agora cada página da administração no seu tema e cada página pública em cada tema público, em claro e em escuro, com sessão iniciada como administrador e como visitante, em oito larguras de 360 a 2560 px, com e sem conteúdo. Esta primeira passagem corrigiu:

    • ícones partidos nas listas de categorias da galeria, dos jogos, das equipas e das notícias, quando uma categoria não tinha ícone;
    • o país dos perfis da demonstração, escrito por extenso: o perfil não mostrava nenhum país e procurava uma bandeira que não se encontrava;
    • os assuntos dos modelos de e-mail, que mostravam {{site_name}} tal como estava na lista;
    • tabelas demasiado largas para um telemóvel (Gestor de bugs, transferências, histórico da wiki, moderação, sessões, participantes de um evento, palmarés): deslocam-se agora dentro da sua moldura em vez de alargar toda a página;
    • as listas do fórum num telemóvel: quatro colunas dividiam 360 px e a última mensagem era cortada; cada entrada empilha-se agora — ícone e título, depois estatísticas e última mensagem;
    • a barra do tema Nebula num telemóvel, que transbordava do ecrã;
    • três ficheiros pedidos por páginas sem existirem, e duas linhas escritas no registo a cada verificação de atualizações enquanto nenhuma versão estiver publicada.
  • Os botões «Editar» e «Eliminar» já não estão desalinhados (2026-09-22). Nas listas da administração em duas colunas — categorias das notícias, categorias da galeria… — o segundo botão passava para a linha seguinte, desviado por baixo do primeiro. Ficam agora lado a lado.

  • O cartão «Armazenamento» da monitorização é mostrado corretamente (2026-09-22). O indicador era desenhado como um círculo completo em vez do semicírculo previsto, com um número em bruto no centro, e o valor e a percentagem, colocados em cima, sobrepunham-se ao traço; ficam agora no côncavo do indicador. O título «Informações do servidor» da mesma página passa para duas linhas quando a coluna é estreita, em vez de ser cortado. No grupo «Envio de e-mail», a linha «Transporte de email» mostrava [object Object] em vez do método usado.

  • Um widget colocado sem definições é mostrado com os seus valores predefinidos (2026-09-22). Quando um tema coloca um widget na instalação, ou uma disposição antiga o restaura, chega sem definições: escrevia então avisos no registo em cada página mostrada, e o menu de navegação simplesmente desaparecia. Recebe agora os valores que o seu formulário teria guardado por predefinição. Os widgets já configurados não mudam.

  • A página dos eventos volta a ser mostrada (2026-09-22). Mostrava uma página de erro «não encontrado» assim que tinha eventos para distribuir por várias páginas — sob um título perfeitamente normal, o que tornava difícil dar por isso. A definição do número de eventos por página era guardada como texto, e o código, tornado mais estrito na véspera, recusava-a. Todas as listas paginadas aceitam agora esta definição nas suas duas formas.

  • Os votos das sondagens são registados (2026-09-22). Quem votava lia «Obrigado pelo teu voto!», e o voto nunca era contado: nenhuma opção era reconhecida como pertencendo à sondagem. Um voto que não visa nenhuma opção da sondagem é agora recusado com uma mensagem que o diz, em vez de ser bem recebido.

  • O widget «Fórum» mostra finalmente tópicos e mensagens (2026-09-22). Os seus dois tipos, «Tópicos recentes» e «Publicações recentes», não selecionavam nenhuma categoria do fórum, e ficavam por isso vazios em todos os sites, houvesse as mensagens que houvesse.

  • Outras três funções caíam na mesma armadilha que as sondagens (2026-09-22), encontradas pela verificação escrita para este defeito:

    • abrir uma candidatura com campos personalizados fazia falhar a página, do lado do candidato como na administração;
    • uma notificação que leva a um evento do calendário falhava ao construir a sua ligação;
    • a profundidade máxima das respostas do fórum nunca era aplicada: o cálculo parava no primeiro nível.
  • Voltar à página 1 de uma lista já não leva a uma página não encontrada (2026-09-22). Nas listas da administração cujo número de elementos por página se pode ajustar, o botão «1» construía um endereço que o site não reconhecia.

  • O ecrã de edição de um campo de perfil personalizado abre-se (2026-09-22). O ecrã falhava de cada vez que era aberto: não dava etiqueta ao seu botão de guardar.

  • Dois botões «Voltar» levavam a uma página não encontrada (2026-09-22): da página de uma imagem para o seu álbum; de um modo de jogo para o seu jogo.

  • «Candidatar-se» já não aparece onde a candidatura seria recusada (2026-09-22): numa oferta fechada ou completa, e para quem não tem o direito de se candidatar. Da mesma forma, um administrador que lê uma conversa reservada à equipa pode agora convidar para ela e denunciar nela uma mensagem, em vez de ser recusado depois de ver o botão.

  • Os submenus do widget de navegação abrem-se (2026-09-22). Uma ligação que agrupa outras ligações não abria nada ao clicar: ainda tinha o atributo da versão antiga do Bootstrap, que o seu próprio script já não procurava.

  • As restantes dicas de ajuda dos formulários aparecem ao passar o rato (2026-09-22). A correção da véspera só cobria uma parte dos formulários: o ícone (i) ao lado dos campos dos outros ecrãs da administração, e as dicas das etiquetas, continuavam a não mostrar nada — o mesmo defeito de atributo, nas duas bibliotecas que os constroem.

  • As etiquetas de menu acentuadas são traduzidas (2026-09-22). Uma ligação de menu guardada a partir da administração — «Actualités», «Équipes» — é guardada codificada, e a sua tradução já não se encontrava: ficava em francês nas outras cinco línguas, com um aviso no registo em cada página mostrada.

  • Os arquivos do marketplace são reprodutíveis (2026-09-22). Tinham os mapas de fonte .map, que o compilador de estilos regenera em cada instalação e que o repositório ignora: dois arquivos do mesmo addon, construídos em duas máquinas, diferiam mesmo sem o código ter mudado. Os arquivos já não têm estes ficheiros.

  • O widget «Palmarés» pode finalmente ser instalado enviando um arquivo (2026-09-22). Era o único dos 61 addons distribuíveis que não declarava a sua dependência do núcleo; o instalador, que a exige para reconhecer um addon, saltava-o SEM UMA PALAVRA — nem mensagem, nem rasto.

  • A página de manutenção já não está em branco (2026-09-22). Os dois campos «Título» e «Conteúdo» vêm VAZIOS, por isso a página não mostrava NADA além do nome do site — embora a pré-visualização da administração prometesse um título e um texto. Um título e uma mensagem predefinidos, traduzidos nas seis línguas, preenchem o vazio; assim que os campos são preenchidos, são eles os mostrados.

  • Os botões de contorno recuperam a sua margem (2026-09-22). Os temas só redefiniam a variante «primary» do botão de contorno, e a sua própria regra apagava a margem das outras: as outras seis variantes usadas pelo produto — 90 usos no código — pareciam simples ligações. O mais visível era «Abrir o sítio», no banner de manutenção, que só tinha margem ao passar o rato.

  • O código técnico já não é cor-de-rosa na administração (2026-09-22). O tema só definia o tipo de letra dos excertos <code>, que mantinham por isso o cor-de-rosa do Bootstrap — uma cor estranha a todas as paletas do produto. Muito visível na lista dos cargos.

  • O botão «Fechar» das janelas fecha finalmente a janela (2026-09-22). Em TODAS as janelas do produto, o botão «Fechar» (ou «Cancelar») em baixo não fazia nada: era preciso a cruz no canto superior direito. A causa: o Bootstrap 5 mudou o nome do atributo que desencadeia o fecho, e o núcleo ainda punha o nome antigo; um navegador ignora um atributo desconhecido em silêncio. O botão tornou-se também um verdadeiro botão — era apresentado como um <span>, e portanto inacessível pelo teclado. Duas salvaguardas impedem que volte: a verificação do código recusa o nome antigo, e uma passagem num navegador, lançada à mão, CLICA no botão.

  • O tema Nebula já não mostra o seu menu duas vezes (2026-09-22). Cada instalação nova mostrava duas vezes o nome do site e duas vezes o menu: o tema desenha a sua própria barra, e a instalação colocava TAMBÉM um título e um menu logo por baixo. O menu vive agora na barra superior, onde só aparece uma vez — e é configurável a partir da administração, o que antes não acontecia: as ligações da barra estavam escritas no código, por isso faltava «Contacto» e um módulo desativado mantinha a sua ligação. Os sites já instalados são corrigidos por uma migração, que só toca no cabeçalho se tiver ficado como foi incluído.

  • Mudar de língua já não vai parar a uma página de código (2026-09-22). O seletor de língua do rodapé — o de cinco temas, entre eles o predefinido — mandava o visitante para uma página que mostrava {"redirect":"/en/…"} como texto em bruto, em vez de o levar à página traduzida. Era preciso voltar atrás para sair.

    A causa: este seletor é um verdadeiro formulário, que nada intercetava, e visava um endereço técnico que responde sempre em JSON. O servidor distingue agora uma chamada da janela «Escolher o meu idioma», que espera JSON, de um envio de formulário comum, que espera ser levado à página. Encontrado ao seguir o gesto num navegador real, o que nenhuma verificação tinha feito até então.

  • O conteúdo escrito numa só língua já não manda as outras línguas para uma página de erro (2026-09-21). Uma notícia escrita em francês continuava a oferecer as outras cinco línguas no seu seletor, e as cinco respondiam 404: medido na demonstração, 60 endereços mortos em 72. O gesto mais natural de um visitante estrangeiro ia parar a um erro. A versão que existe é agora servida, com um aviso que o diz na língua do visitante e uma ligação para o original. Isto aplica-se às notícias, aos artigos e aos álbuns (e às suas categorias), bem como às equipas.

    Duas precauções inseparáveis, sem as quais o remédio custaria mais do que a doença: a página só anuncia agora aos motores de pesquisa as línguas que existem mesmo, e designa o original como endereço canónico — senão seriam indexados seis endereços para um só texto. Na administração, nenhum recurso: uma versão vazia tem de aparecer vazia, é o que se vem lá preencher. tools/check-langues-contenu.php faz cumprir as três propriedades, na integração contínua.

  • A integração contínua volta a estar verde (2026-09-21); no ramo principal, estava vermelha desde 10 de junho. Quase todas as causas estavam nas ferramentas de teste e na configuração da CI, não no produto. A exceção: com o servidor integrado do PHP 8.3, o site podia calcular mal o seu endereço base e redirecionar folhas de estilo e scripts; agora só o deduz de um SCRIPT_NAME terminado em index.php. Um conjunto de testes que não consegue correr falha agora em vez de se saltar em silêncio, e a maioria dos trabalhos da CI tem um limite de tempo.

  • O logótipo do instalador não aparecia numa instalação nova (2026-09-21): o caminho era relativo à pasta install/, que o servidor não serve nesse endereço. A imagem está agora incorporada na página.

  • Componentes que já não se abriam desde a passagem ao Bootstrap 5 (2026-09-21). O Bootstrap 5 pôs o prefixo bs- em todos os seus atributos de dados. Um atributo que fique com o nome antigo não provoca nenhum erro: o componente simplesmente não faz nada. Estes estavam mortos em silêncio:

    O que já não funcionava Onde
    O acordeão da FAQ não se abria modules/faq
    A lista de participantes de um evento não se abria modules/events
    Os balões de ajuda de uma parte dos formulários estavam vazios núcleo — neofrag/libraries/form.php
    O balão do perfil do fórum, o de eliminar uma ligação de navegação modules/forum, widgets/navigation
    A colocação das dicas no Editor ao vivo, o intervalo do carrossel modules/live_editor, widgets/slider
  • Paginações partidas, também silenciosas (2026-09-21). O Bootstrap 5 mudou o nome dos seus utilitários direcionais; uma classe com o nome mudado já não está definida em lado nenhum, e o elemento mantém a sua paginação predefinida sem que nada o assinale.

    • Os rodapés dos painéis e das janelas modais não se alinhavam à direita. O núcleo construía a classe por concatenação ('float-'.$align), por isso nenhuma pesquisa de float-right a podia encontrar. A única ponte de compatibilidade do produto só cobria as tabelas do tema da administração: nada para os temas públicos. A mesma causa para o alinhamento das células das tabelas, nas duas bibliotecas.
    • Nenhum campo de formulário recusado era marcado, em nenhum tema. As duas bibliotecas punham um nome herdado — has-error (Bootstrap 3) e has-danger (uma versão preliminar do Bootstrap 4) — que nenhuma folha de estilo servida define. A mensagem aparecia, mas nada indicava o campo em causa. São substituídos por um marcador próprio, definido uma só vez.
    • O rodapé tinha <div class="float-right">: «Desenvolvido por NeoFrag Reborn» descia para uma nova linha, à esquerda. O valor vem de longe — uma migração da Alpha 0.2.2 tinha-o mudado de pull-right para float-right no tempo do Bootstrap 4, e o passo seguinte nunca foi dado. Uma migração (2026_09_20_bootstrap5_float) corrige os sites existentes; a semente traz agora float-end.
    • E as últimas classes mortas nas vistas: a barra de depuração num telemóvel, a margem das listas de eventos, as etiquetas do editor de menus, as duas barras do voto do recrutamento — que saíam da mesma cor, deixando o gráfico de distinguir as opiniões favoráveis das desfavoráveis.
  • O corpo de um artigo podia ser apagado na apresentação (2026-09-21). A construção do índice substituía o texto pelo resultado de um tratamento que pode desistir perante um artigo longo: a página respondia então normalmente, com um artigo vazio, e nada nos registos.

  • Um widget colocado no topo ou no fundo da página desaparecia. O tema Nebula oferecia os lugares «Cabeçalho» e «Rodapé» no editor de disposições, mas não os mostrava. O widget era mesmo guardado, e nada aparecia — sem mensagem. Os outros quatro temas públicos não eram afetados.

  • O widget de navegação oferecia dois módulos internos (live_editor e pages) que devia esconder. O mesmo defeito fazia as estatísticas da administração perder o seu nome de módulo, sem efeito visível enquanto dois módulos não usarem o mesmo nome de estatística.

  • O registo de depuração crescia sem limite quando estava ligado. Tem agora um teto: para lá de 64 MB, recomeça mantendo a geração anterior.

  • Num site em inglês, «No» ficava em francês («Non»).

  • Cinco páginas da administração não ofereciam nenhum caminho de volta (2026-09-20): a ficha de um membro, o registo de auditoria, a adição de um grupo, a lista de sessões e os ficheiros da monitorização. O trilho de navegação só torna clicável o nome do módulo se o módulo declarar ter uma página inicial de administração; user e monitoring declaravam o contrário embora a tenham. Uma vez nessas páginas, era preciso passar pelo menu lateral ou pelo botão de voltar do navegador.

  • Os motores de pesquisa recebiam JSON em vez do mapa do site. Pedido na raiz, sem prefixo de língua — a única forma como um robô o pede —, /sitemap.xml respondia {"redirect":"/fr/sitemap.xml"} com o código de estado 200, e robots.txt e humans.txt faziam o mesmo. O redirecionamento que acrescenta o prefixo de língua respondia em JSON sempre que o endereço terminava em .txt, .xml ou .json. Como estes ficheiros não têm versão por língua, já não passam por este redirecionamento: são servidos diretamente, com o seu verdadeiro tipo de conteúdo.

  • /favicon.ico respondia 404. Os navegadores pedem este endereço seja o que for que a página declare; leva agora ao favicon configurado nas definições, ou ao do CMS.

  • Ligar a autenticação de dois fatores falhava. Ao guardar os códigos de recuperação, um erro interrompia a página: a conta acabava marcada «protegida» sem um único código de emergência. Encontrado por um teste escrito ao reforçar a tipagem desta biblioteca; corrigido, e o teste fica.

  • Um limite de «uma só tentativa» nunca bloqueava. O limiar só era verificado a partir da segunda tentativa. Sem efeito nos limiares incluídos, mas o limite de denúncias da moderação, que se pode baixar até 1, nunca bloqueava então. O limiar aplica-se agora desde a primeira tentativa.

  • Alguns textos ficavam em francês nas outras línguas, e o registo continuava a encher-se. Três causas, todas corrigidas: o título de uma página da wiki, de um tipo de evento ou de uma campanha de doações passava pela tradução como se fosse texto da interface (não tem tradução: é conteúdo); um texto já traduzido voltava a passar pela tradução — «Espace membre» tornava-se «Member area», e depois «Member area» era procurado como chave e assinalado em falta em cada apresentação; e trinta cadeias da interface (o campo «Nome de utilizador ou endereço de e-mail» do formulário de início de sessão, títulos de painel na administração dos jogos e do recrutamento, as redes sociais do perfil…) não tinham tradução em nenhuma língua, porque a verificação que controla as seis línguas só olhava para as chamadas de tradução explícitas, não para os títulos de campos e cabeçalhos traduzidos mais à frente. A verificação vê-os agora; as trinta cadeias estão traduzidas em inglês, alemão, espanhol, italiano e português.

  • O Google Analytics espera agora pelo teu consentimento. Se houver um ID do Analytics configurado, o script da Google só é carregado agora depois de um clique em «Aceitar tudo» no banner de cookies, nunca antes. Além disso, a política de segurança do site bloqueava este script em todos os casos: o Analytics não funcionava, e nada o dizia. Funciona agora, e só com o consentimento do visitante.

  • Três funções da administração tinham deixado de responder desde junho. A ordenação das tabelas clicando num cabeçalho de coluna, a reordenação por arrastamento das categorias, fóruns e subfóruns, e os botões Aberto/Fechado das páginas Manutenção e Inscrições: os seus scripts ainda pressupunham a presença do jQuery, embora tenha sido retirado do CMS em junho de 2026, e paravam de repente ao carregar a página — sem mensagem, os botões ficavam simplesmente inertes. Os três foram reescritos sem jQuery, estão cobertos por testes no navegador, e uma verificação automática recusa agora qualquer script que volte a chamar o jQuery.

  • Um endereço mal formado provocava um erro do servidor. Um pedido como /fr/a:80 ou /:80, dos que os robôs enviam, fazia falhar o cálculo da extensão do endereço e devolvia um erro 500 ao visitante. O site responde agora com um 404 comum.

  • O formulário de contacto escrevia «De:» com o endereço do visitante. Enviar uma mensagem do teu servidor em nome de visiteur@example.org é exatamente o que as proteções contra a falsificação dos fornecedores de e-mail (SPF, DMARC) recusam: a mensagem acabava no spam ou era recusada. O remetente é agora o endereço de contacto do site, e o endereço do visitante é posto em «Responder a», o que na prática vem dar ao mesmo. A mesma correção para as respostas a uma candidatura, que podiam sair com o endereço pessoal do administrador.

  • O instalador podia guardar um endereço de contacto inválido. Quando o site era instalado acedendo a ele pelo seu endereço IP, o endereço de contacto passava a noreply@<IP>, que os fornecedores de e-mail recusam — e já não saía nenhum e-mail, sem nenhuma mensagem de erro visível. O endereço só é agora deduzido de um verdadeiro nome de domínio.

  • Aparecia um banner vazio nas páginas em que uma zona da disposição está vazia. No tema Extend, todas as páginas exceto a inicial mostravam uma larga faixa colorida que não continha nada, assim como uma secção vazia por cima do conteúdo.

    A causa não era o tema: uma zona declarada mas sem widget devolvia espaços em vez de nada, por isso os temas desenhavam a sua moldura à volta do nada. Corrigido de uma vez para todos os temas. Se construíres um tema, podes escrever if ($zone = $this->output->region('banner')) (ou zone(n)): a condição diz agora a verdade.

  • O tema Extend mostrava duas vezes a sua menção «Desenvolvido por NeoFrag Reborn». A sua disposição incluída punha no rodapé um bloco que repetia o que o tema já escreve ele próprio. Os sites já instalados são corrigidos automaticamente na atualização; os novos nunca a terão.

  • Procurar uma palavra comum devolvia uma página de erro. Uma pesquisa como «le» ou «de» mostrava os seus resultados no ecrã, mas o servidor respondia 404 — que é o que veem os motores de pesquisa, as ferramentas de monitorização e os navegadores, e que fazia parecer desaparecida uma página perfeitamente válida.

    O destaque das palavras encontradas pressupunha que a palavra procurada aparecia forçosamente no texto mostrado. É duplamente falso: a pesquisa examina vários campos e só mostra um — um tópico do fórum intitulado «Salut tout le monde !» corresponde a «le» pelo seu título, não pela mensagem mostrada por baixo — e a base de dados compara sem ter em conta os acentos, enquanto o código os tinha em conta: «éléphant» aparecia na pesquisa «ele», sem que nenhuma palavra fosse destacada.

    Os dois casos estão tratados: o destaque reconhece agora as variantes acentuadas de uma letra, como faz a base de dados, e quando a palavra não está mesmo no texto mostrado, o excerto começa simplesmente pelo seu início.

  • As atualizações automáticas do núcleo não podiam funcionar — cinco defeitos, cada um suficiente por si só: o endereço para verificar as novas versões não estava definido em lado nenhum, por isso o botão nunca aparecia; um interruptor global, a definir na configuração, bloqueava a operação; a transferência apontava para as versões do NeoFrag original, que teriam substituído o NeoFrag Reborn; o pacote guardava os seus ficheiros numa subpasta, por isso uma atualização não teria substituído nada, sem o menor erro; e o arquivo era extraído através de uma interface PHP obsoleta desde o PHP 8.0.

    O interruptor é substituído por quatro garantias: a origem das versões tem de estar numa lista branca de endereços (a mesma que para o marketplace); o ficheiro de versão só dá um nome de ficheiro, nunca um endereço; a impressão SHA-256 do pacote é verificada antes de tocar num único ficheiro; cada ficheiro do arquivo é controlado (nenhum caminho que saia do site, nenhuma ligação simbólica). As pastas config/ e install/ nunca são reescritas se já existirem.

  • O catálogo do marketplace estava inacessível a partir de qualquer site. O servidor que o distribui respondia {"redirect":"/fr/…"} com o código de estado 200 em vez do ficheiro estático — um corpo perfeitamente válido como JSON, e perfeitamente errado, portanto uma falha silenciosa que fazia todos os sites recorrer ao seu catálogo local. A causa era a configuração desse servidor, entretanto corrigida: nada a fazer nos sites. No código, a atualização do núcleo valida agora a forma dos seus manifestos, já não só se se leem como JSON.

  • O botão «Eliminar» de um tema, em «Temas & addons», só protegia o tema da administração, pelo seu nome escrito no código. Segue agora a declaração do tema, e protege portanto também o Nebula.

  • Acoplamentos do núcleo para o opcional. Sete módulos consultavam as tabelas de módulos opcionais: cinco do núcleo (admin, moderation, settings, statistics, user), mais games e teams. Duas consultas estavam sem proteção: em teams, a verificação de existência de recruits estava colocada depois da consulta que devia proteger, e em games, eliminar um jogo consultava a tabela das equipas sem verificar que existe. As outras estavam protegidas mas mudas: têm agora uma anotação verificada pela CI. O único ciclo duro do pacote (games ↔ teams) está quebrado.

  • Editor ao vivo: as alterações aparecem sem recarregar a página. Eliminar um widget deixava-o no ecrã e acrescentar uma linha não a mostrava até a página ser recarregada, embora o servidor tivesse guardado a alteração. O script esperava outro formato de resposta do que o que o servidor envia; o defeito vinha da retirada do jQuery.

  • Editor ao vivo: arrastar e largar widgets volta a funcionar. Com o modo Colunas ligado, um widget acrescentado ficava preso no fundo da sua coluna e não podia ser movido para cima do conteúdo da página. As linhas e as colunas não eram afetadas.

  • Editor ao vivo: os widgets sem definições voltam a poder ser acrescentados. Dez widgets que não têm ecrã de definições (breadcrumb, copyright, downloads, forum, module, news, newsletter, slider, surveys, teams) não podiam ser acrescentados: a adição falhava com um erro 404 e nenhuma mensagem útil.

  • Um erro do servidor já não é mostrado como conteúdo. Quando uma ação feita sem recarregar a página recebia um erro do servidor (uma página 404, por exemplo), alguns ecrãs inseriam essa página de erro na interface. O erro é agora tratado como uma falha.

  • Editor ao vivo: o formulário de definições corresponde sempre ao widget escolhido. Ao mudar depressa de widget ou de tipo, a resposta mais lenta podia mostrar o formulário de outro widget. O pedido ultrapassado é agora anulado, e o formulário já não é recarregado (nem o que se está a escrever perdido) quando a seleção não mudou.

  • A porta da base de dados é agora respeitada. O CMS ligava-se sempre pela porta 3306, fosse qual fosse a porta introduzida no assistente de instalação: não podia ser instalado nem funcionar num servidor MySQL ou MariaDB à escuta noutro lado. A porta é agora guardada em config/db.php (só se for diferente de 3306) e usada em cada ligação.

  • Um tema ativado já não está vazio. Ativar o Forge, o Granite, o Blockcraft ou o Extend mudava o tema sem aplicar a sua disposição predefinida, que só se aplicava pelo botão «Reinstalar predefinição»: o site não mostrava nenhum widget. A ativação aplica agora a disposição predefinida do tema se ainda não tiver nenhuma, sem nunca substituir uma disposição personalizada.

  • Mudar o tema predefinido aplica-se agora também aos visitantes que tinham escolhido um. O seletor de tema do rodapé memorizava a escolha de um visitante durante um ano, e essa escolha prevalecia sobre o tema predefinido: quando o administrador mudava de tema, os visitantes, e o administrador também, ficavam no antigo, sem saída a partir de um tema sem seletor. Uma escolha feita antes da última mudança de tema predefinido é agora esquecida; uma feita depois continua a ser respeitada.

  • O navegador já não guarda cópias desatualizadas das páginas. Na falta de instruções, podia voltar a mostrar uma versão antiga de uma página: uma mudança de tema, por exemplo, só aparecia depois de um recarregamento forçado (Ctrl+F5). As páginas e respostas do site proíbem agora esta cache (Cache-Control: no-store); as imagens, os estilos e os scripts, servidos diretamente pelo servidor web, não são afetados.

Segurança

  • Um valor guardado já não pode injetar etiquetas num formulário (2026-09-23). O formulário de edição punha o valor de um campo na página escapando as aspas como o faria uma cadeia PHP — o que não tem nenhum efeito em HTML. Um valor que não tivesse passado pelo próprio formulário (importação, dados de demonstração, outro módulo) podia portanto sair do seu campo e acrescentar código ao ecrã de administração: uma citação cuja fonte era "><img src=x> demonstrou-o. Os campos de texto, as áreas de texto, as listas, as caixas de verificação e os botões de opção codificam agora o seu valor; a apresentação de um valor introduzido normalmente não muda. As notificações («Citação modificada», etc.) são também passadas ao script da página numa forma que já não o pode partir.

  • A política de segurança declara agora uma regra para os media (media-src). Não tinha nenhuma e recorria à regra geral (default-src 'self'). Permite agora os media do próprio site e os media incorporados na página ('self' data:); o endereço da emissão de uma rádio web é acrescentado só se houver uma emissão configurada: um site sem rádio web não permite nenhuma origem externa adicional.

  • Onze avisos de segurança fechados nas dependências (2026-09-20): league/commonmark passa da 2.8.2 para a 2.10.1 (dez avisos, oito deles graves) e phpseclib da 3.0.52 para a 3.0.57 (um aviso de gravidade média).

    Nove dos dez avisos do commonmark são negações de serviço através de Markdown preparado — análise em tempo quadrático, títulos com âncoras em colisão, notas de rodapé duplicadas, blocos de atributos adjacentes, saída XML profundamente aninhada — e o décimo é uma vulnerabilidade XSS: o filtro dos atributos on* podia ser contornado com uma quebra de página U+000C. A biblioteca apresenta o Markdown da wiki, dos artigos e da FAQ, escrito pelos membros. Vários destes avisos visam extensões que o produto não ativa (notas de rodapé, atributos, âncoras de títulos, saída XML); a atualização fecha-os todos.

    A apresentação não muda, e não é só uma impressão: doze casos representativos — títulos, tabela, lista de tarefas, bloco de código, HTML injetado, ligação javascript:, citação, texto riscado, ligação automática, listas aninhadas, imagem, entidades e nota de rodapé, aninhamento profundo —, apresentados pelas duas versões com a configuração real do produto, dão o mesmo HTML byte a byte (1568 bytes, a mesma impressão).

    Nota: o Composer recusa agora instalar a 2.8.2, precisamente por causa destes dez avisos. Foi preciso desligar a política numa pasta descartável para fazer a comparação.

Leia também

0
Comentários

Gerir os meus cookies

O site só instala os cookies necessários ao seu funcionamento: não exigem o seu consentimento. Os outros serviços pertencem a outras empresas; só são carregados se os aceitar. A sua escolha é guardada durante seis meses, e pode alterá-la a qualquer momento.

Necessários ao site Sempre ativos

  • __Host-session Mantém a sua sessão iniciada e protege os formulários contra envios fraudulentos. Até fechar o navegador; um ano com «Lembrar-me»
  • nf_consent Guarda as escolhas que faz nesta janela. 6 meses
  • nf_fuseau Mostra as datas e as horas no seu fuso horário. 1 ano
  • Armazenamento do navegador Guarda a sua escolha entre o modo dia e o modo noite, e a apresentação escolhida para a lista de artigos. Até que o limpe

Vídeos

Os vídeos integrados nas páginas: o leitor vem da plataforma, que recebe o seu endereço IP e pode instalar os seus cookies.

Música

As faixas e listas de reprodução integradas nas páginas: o leitor vem da plataforma, que recebe o seu endereço IP e pode instalar os seus cookies.