Blog
GuiaWordPressRefined Admin Dashboard

Como impedir que os avisos tomem conta do painel do WordPress

Raphaël, Robot sensible 5 min de leitura
Como impedir que os avisos tomem conta do painel do WordPress

Você abre o painel para corrigir um erro de digitação. Antes que você chegue à página, quatro mensagens passam na frente: um plugin de backup quer que você renove a licença, um plugin de formulários adoraria cinco estrelas, um plugin de SEO tem uma dica e um plugin de cache limpou o cache e achou que você devia saber. Depois de rolar a tela até passar por todas, o erro de digitação já pode esperar.

Os avisos são o jeito que o WordPress e os plugins encontraram para falar com você, e alguns têm mesmo algo a dizer: um backup que falhou, um plugin pausado depois de um erro fatal, uma licença que vence na sexta. O resto é marketing com a mesma borda colorida, no mesmo lugar, no topo de cada tela.

Por que os avisos se acumulam

O WordPress dispara um hook chamado admin_notices perto do topo de cada página do painel. Qualquer plugin pode exibir ali o que bem entender, e o WordPress usa o mesmo hook para as próprias mensagens, como o banner de atualização do core ou o alerta sobre plugins pausados pelo modo de recuperação. O WordPress não impõe limite nem ordem de importância.

O xizinho ajuda menos do que parece. Num aviso dispensável, o WordPress acrescenta um botão de fechar, e esse botão tira o aviso da página que está na sua frente. Lembrar do seu clique é trabalho do plugin. Muitos fazem isso. Os outros cumprimentam você de novo na tela seguinte, como se nada tivesse acontecido.

Duas soluções rápidas, ambas pouco sutis

A primeira é uma linha de CSS que esconde todos os .notice. A segunda é remove_all_actions( 'admin_notices' ), que simplesmente impede o WordPress de exibi-los.

As duas limpam o topo da tela. Também escondem o alerta sobre o backup que falhou ontem à noite, e você só descobre isso no dia em que precisa desse backup.

Mostre os avisos só para os administradores

Nos sites que você entrega, cabe um meio-termo justo: os administradores continuam vendo todos os avisos, e os demais não veem nenhum. Quem edita o site não tem o que fazer com um lembrete de licença e, de qualquer forma, não poderia agir sobre ele.

Salve este arquivo como wp-content/mu-plugins/quiet-admin-notices.php. O WordPress carrega os plugins must-use sozinho, e ninguém consegue desativá-los pela tela de Plugins, o que cai bem para uma regra da casa como esta.

<?php
/**
 * Plugin Name: Quiet admin notices
 * Description: Only administrators see admin notices.
 */
add_action( 'in_admin_header', function () {
	if ( current_user_can( 'manage_options' ) ) {
		return;
	}
	remove_all_actions( 'admin_notices' );
	remove_all_actions( 'all_admin_notices' );
	remove_all_actions( 'user_admin_notices' );
	remove_all_actions( 'network_admin_notices' );
}, PHP_INT_MAX );

A função roda em in_admin_header, logo antes de o WordPress exibir os avisos e depois de todos os plugins terem acrescentado os seus. Os quatro hooks cobrem o painel normal, o painel do usuário e o painel da rede de um multisite. Um plugin que injeta o aviso via JavaScript ainda passa, porque nunca chegou perto do hook.

Remova um aviso que você conhece pelo nome

Às vezes é um aviso só que precisa sumir. Comece descobrindo quem o exibe. Este snippet grava no seu log de erros cada função ligada a admin_notices (wp-content/debug.log, com WP_DEBUG e WP_DEBUG_LOG ativados):

add_action( 'admin_notices', function () {
	global $wp_filter;
	foreach ( $wp_filter['admin_notices']->callbacks as $priority => $callbacks ) {
		foreach ( $callbacks as $callback ) {
			$f = $callback['function'];
			if ( is_array( $f ) ) {
				$class = is_object( $f[0] ) ? get_class( $f[0] ) : $f[0];
				$name  = $class . '::' . $f[1];
			} elseif ( is_string( $f ) ) {
				$name = $f;
			} else {
				$name = 'a closure';
			}
			error_log( "admin_notices, priority $priority: $name" );
		}
	}
}, PHP_INT_MIN );

Depois remova o aviso pelo nome, com a mesma prioridade com que ele foi adicionado. Errou a prioridade, e o remove_action() não faz nada, sem dar um pio.

add_action( 'in_admin_header', function () {
	// A plain function, added with the default priority of 10.
	remove_action( 'admin_notices', 'myplugin_renewal_notice' );
	// A static method, added with priority 20.
	remove_action( 'admin_notices', array( 'My_Plugin_Admin', 'review_request' ), 20 );
}, PHP_INT_MAX );

Você vai esbarrar em alguns limites. Um aviso adicionado pelo método de um objeto só pode ser removido com esse mesmo objeto, e os plugins raramente compartilham os seus. Um aviso adicionado por uma função anônima não pode ser removido de jeito nenhum. E quando o plugin renomeia a função numa atualização, o aviso volta e a sua lista precisa de mais uma linha.

Em vez disso, reúna os avisos

O problema dos avisos é o lugar onde eles ficam: no topo de cada tela, todos de uma vez, tenha você um minuto livre ou não. Coloque-os atrás de um contador. Você vê que tem algo esperando, abre a lista quando for melhor para você, e a página que você veio buscar volta para o topo. O retorno sobre algo que você acabou de fazer é outro caso: você clicou em Salvar, então «Configurações salvas» deve continuar aparecendo na hora.

A central de avisos do Refined Admin Dashboard

O Refined Admin Dashboard, nosso plugin gratuito que redesenha o painel inteiro do WordPress, trata os avisos desse jeito, sem nenhuma configuração para procurar. Nenhum aviso é maltratado durante o processo.

  • Os avisos do WordPress e dos seus plugins vão para um contador de Notificações no canto superior direito da página, inclusive os que um plugin acrescenta depois via JavaScript.
  • O plugin move cada aviso, sem nunca copiar nem apagar nenhum. Cada aviso mantém o próprio botão de fechar, então um plugin que lembra do seu clique continua lembrando.
  • Descartar tudo aperta por você o botão de fechar de cada aviso. Um aviso sem botão de fechar fica na lista até que o plugin dele o retire.
  • O retorno sobre o que você acabou de fazer, como «Configurações salvas» ou um erro de formulário, também aparece numa mensagem curta que some sozinha.
  • Os avisos feitos para ficar dentro de um formulário continuam lá.

Um recado para quem desenvolve plugins

Se você desenvolve plugins, exiba seus avisos com wp_admin_notice() (WordPress 6.4 ou mais recente) em vez de marcação escrita à mão. Dê a cada um o tipo real (error, warning, success ou info), torne-o dispensável e lembre quando alguém o dispensar. Mantenha-o nas suas próprias telas, a menos que o site inteiro precise saber. E, por favor, deixe o banner de promoção fora da lista de posts. Seus usuários abriram aquela tela para escrever um post.

Perguntas frequentes

Como esconder os avisos do painel do WordPress sem plugin?
Crie um plugin must-use que chame remove_all_actions() em admin_notices a partir do hook in_admin_header. Limite isso às funções que não podem fazer nada com os avisos, para que os administradores continuem vendo um backup que falhou ou um plugin pausado. O código está neste artigo.
É seguro esconder todos os avisos do painel?
Não totalmente. Erros e marketing passam pelo mesmo hook, então você esconde um backup que falhou ou uma licença prestes a vencer junto com os banners de promoção. Esconda os avisos para as funções que não podem fazer nada com eles, ou reúna todos num só lugar.
Por que os avisos do painel voltam depois de fechados?
O botão de fechar que o WordPress acrescenta tira o aviso da página em que você está, e só. Quem precisa lembrar do seu clique é o plugin que exibiu o aviso, e alguns não lembram.
Como mostrar os avisos do painel só para os administradores?
Ligue ao hook in_admin_header uma função que retorna logo de cara para os usuários com a capacidade manage_options e, para os demais, chama remove_all_actions() em admin_notices, all_admin_notices, user_admin_notices e network_admin_notices. O snippet completo está neste artigo.
O Refined Admin Dashboard apaga os avisos do painel?
Não. Ele move cada aviso para um contador de Notificações que você abre quando quiser, e cada aviso mantém o próprio botão de fechar.