Os menus de navegação personalizados são um recurso incrível do WordPress que permite aos usuários administrativos adicionar qualquer lista de links em qualquer lugar no site. Eles podem ser links para recursos internos, como posts, páginas e arquivos, assim como links para recursos externos, como suas páginas de perfis sociais. O WordPress reserva uma página de administração específica para menus de navegação personalizados. Nesta página o usuário administrador pode criar menus, organizar itens e definir propriedades que afetam a forma como eles aparecem no front-end.

Tela de Menus de Aparência do WordPress

Tela de Menus de Aparência do WordPress

Dito isto, as principais questões por detrás deste posto são: “Podemos ampliar as funcionalidades embutidas do Menus Screen?”
Claro que podemos. Por isso vou mergulhar profundamente no tema, e vou dissecar seções e objetos que permitem adicionar e gerir menus e os seus itens. Mas não vai ser apenas uma descrição do ecrã. Vou mostrar como adicionar itens personalizados ao menu de acordeão colocado na barra lateral esquerda.

Estas caixas personalizadas irão mostrar listas adicionais de links para escolher quando construir menus de navegação personalizados. Mais especificamente, vou mostrar como adicionar uma caixa contendo links para os arquivos dos autores do site.
Vamos começar a mergulhar na construção de um menu personalizado do WordPress.

A Tela dos Menus de Aparência

A página de edição de Menus permite aos utilizadores criar e gerir menus personalizados graças a uma interface intuitiva. O botão Opções de Tela no canto superior direito revela a primeira seção da página que contém dois grupos de caixas de seleção. O grupo Caixas permite ao usuário esconder e mostrar meta-caixas de menu na barra lateral esquerda, enquanto o grupo Mostrar propriedades avançadas do menu esconde e mostra propriedades como alvos de links, descrições e classes CSS para itens de lista.

Separador Opções de Tela

Separador Opções de Tela

Uma vez criado o primeiro menu, o Menus Screen tem um aspecto um pouco diferente da sua aparência padrão. Novas seções aparecem na guia Editar Menus.

 As meta-caixas de itens do menu incorporado mostram listas de links que apontam para o conteúdo do site

As meta-caixas de itens do menu incorporado mostram listas de links que apontam para o conteúdo do site

Meta Caixas e Módulos

A barra lateral esquerda do Menus Screen contém um menu de acordeões cujos elementos são chamados de meta-caixas de itens de menu. Estes blocos fornecem uma série de campos de formulário e controles que permitem ao usuário pesquisar o conteúdo do site e adicionar links para os menus de navegação.
Por padrão, o WordPress fornece as seguintes meta-caixas de itens de menu:

Quando o usuário adiciona um link a um menu, um novo módulo de item é anexado à seção Estrutura de Menu da tela. O WordPress fornece quatro tipologias de módulos de itens de menu:

Módulos de itens de menu comparados

Módulos de itens de menu comparados

Vamos ampliar a estrutura interna da tela de menus de aparência com meta-caixas personalizadas que permitiriam ao usuário administrador selecionar partes de conteúdo não disponíveis por padrão, como os arquivos de autor.
Infelizmente, o Core Navigation Menu API não está documentado e para atingir nosso objetivo foi necessário dissecar linha por linha dois arquivos principais: /wp-admin/includes/nav-menu.php para as meta-caixas de menu, e /wp-includes/nav-menu.php para os módulos de item de menu.
Vamos começar a codificar.

Criar uma Meta-Box do Item do Menu Personalizado do WordPress

Crie um novo plugin e adicione o seguinte código ao arquivo principal:

/**
 * Add menu meta box
 *
 * @param object $object The meta box object
 * @link https://developer.wordpress.org/reference/functions/add_meta_box/
 */
function custom_add_menu_meta_box( $object ) {
	add_meta_box( 'custom-menu-metabox', __( 'Authors' ), 'custom_menu_meta_box', 'nav-menus', 'side', 'default' );
	return $object;
}
add_filter( 'nav_menu_meta_box_object', 'custom_add_menu_meta_box', 10, 1);

A função add_meta_box do WordPress registra meta-caixas nas páginas administrativas. Mantém os seguintes argumentos:

Argumento Tipo Descrição
$id string (obrigatório) a meta-identificação da caixa
$callback callable (obrigatório) a função que ecoa o conteúdo da meta-caixa
$screen string|array|WP_Screen (opcional) a tela na qual mostrar a meta-caixa
$context string (opcional) o contexto dentro da tela onde a meta-caixa é exibida em alta voz (os valores possíveis são 'normal', 'side', 'advanced', padrão para 'advanced')
$priority string (optional) valores possíveis 'high', 'low', 'default'
$callback_args array (opcional) uma série de argumentos a serem passados para a ligação de retorno

Talvez você esperasse que a função add_meta_box estivesse ligada a uma ação como add_meta_boxes, que é acionada nas páginas de pós-processamento. Infelizmente, não temos uma ação em nav-menus.php a que possamos ligar a função, por isso somos forçados a usar o filtro nav_menu_meta_box_object. Este gancho determina se uma meta-caixa de item de menu será adicionada para um tipo de objeto. Quando o filtro é executado, add_meta_box registra a meta-caixa personalizada.
Agora podemos definir a função de callback que irá produzir o conteúdo HTML para a meta-caixa.

/**
 * Displays a metabox for an author menu item.
 *
 * @global int|string $nav_menu_selected_id (id, name or slug) of the currently-selected menu
 */
function custom_menu_meta_box(){
	global $nav_menu_selected_id;
	$walker = new Walker_Nav_Menu_Checklist();
	...
}

A variável global mantém a memória do ID do menu atual, enquanto $walker armazena uma nova instância do objeto Walker_Nav_Menu_Checklist, que constrói a lista HTML de itens de menu.
Depois, temos de definir o valor da variável $current_tab que irá determinar a aba ativa na meta-caixa. Para manter as coisas fáceis, vou fornecer apenas dois separadores:

$current_tab = 'all';
if ( isset( $_REQUEST['authorarchive-tab'] ) && 'admins' == $_REQUEST['authorarchive-tab'] ) {
	$current_tab = 'admins';
}elseif ( isset( $_REQUEST['authorarchive-tab'] ) && 'all' == $_REQUEST['authorarchive-tab'] ) {
	$current_tab = 'all';
}

A seguir, vamos obter todos os usuários com privilégios de escrita, adicionando um número de propriedades ao objeto $authors.

$authors = get_users( array( 'orderby' => 'nicename', 'order' => 'ASC', 'who' => 'authors' ) );
$admins = array();

/* set values to required item properties */
foreach ( $authors as &$author ) {
	$author->classes = array();
	$author->type = 'custom';
	$author->object_id = $author->nickname;
	$author->title = $author->nickname . ' - ' . implode(', ', $author->roles);
	$author->object = 'custom';
	$author->url = get_author_posts_url( $author->ID ); 
	$author->attr_title = $author->displayname;
	if( $author->has_cap( 'edit_users' ) ){
		$admins[] = $author;
	}
}
$removed_args = array( 'action', 'customlink-tab', 'edit-menu-item', 'menu-item', 'page-tab', '_wpnonce' );
?>

get_users retorna um array de objetos $user selecionados pelos parâmetros especificados. O who param força o WordPress a consultar o banco de dados apenas para usuários com privilégios de escrita.
O array $admins irá armazenar um array de autores, enquanto a última variável, $removed_args, irá armazenar uma lista de variáveis de consulta a serem removidas.
Quando terminarmos com os dados, podemos imprimir a margem da meta-caixa. Primeiro vamos construir etiquetas e links:

<div id="authorarchive" class="categorydiv">
	<ul id="authorarchive-tabs" class="authorarchive-tabs add-menu-item-tabs">
		<li <?php echo ( 'all' == $current_tab ? ' class="tabs"' : '' ); ?>>
			<a class="nav-tab-link" data-type="tabs-panel-authorarchive-all" href="<?php if ( $nav_menu_selected_id ) echo esc_url( add_query_arg( 'authorarchive-tab', 'all', remove_query_arg( $removed_args ) ) ); ?>#tabs-panel-authorarchive-all">
				<?php _e( 'View All' ); ?>
			</a>
		</li><!-- /.tabs -->

		<li <?php echo ( 'admins' == $current_tab ? ' class="tabs"' : '' ); ?>>
			<a class="nav-tab-link" data-type="tabs-panel-authorarchive-admins" href="<?php if ( $nav_menu_selected_id ) echo esc_url( add_query_arg( 'authorarchive-tab', 'admins', remove_query_arg( $removed_args ) ) ); ?>#tabs-panel-authorarchive-admins">
				<?php _e( 'Admins' ); ?>
			</a>
		</li><!-- /.tabs -->
	</ul>

Temos de ter cuidado e atribuir os nomes de classe, IDs e atributos de dados corretos aos elementos da meta-caixa. Em caso de erro, o menu do acordeão não funciona corretamente.
Usamos as funções add_query_arg e remove_query_arg para definir valores específicos de tabulação para a variável de consulta authorarchive-tab e remover variáveis de consulta desnecessárias.
A imagem abaixo mostra as etiquetas das abas resultantes.

Lutando com tempo de inatividade e problemas no WordPress? Kinsta é a solução de hospedagem projetada para economizar seu tempo! Confira nossos recursos
abas do menu personalizado wordpress para autores

abas do menu personalizado wordpress para autores

A seguir, vamos construir o conteúdo HTML das abas (novamente, preste atenção aos nomes das classes e IDs):

<div id="tabs-panel-authorarchive-all" class="tabs-panel tabs-panel-view-all <?php echo ( 'all' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>">
	<ul id="authorarchive-checklist-all" class="categorychecklist form-no-clear">
	<?php
		echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $authors), 0, (object) array( 'walker' => $walker) );
	?>
	</ul>
</div><!-- /.tabs-panel -->

<div id="tabs-panel-authorarchive-admins" class="tabs-panel tabs-panel-view-admins <?php echo ( 'admins' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>">
	<ul id="authorarchive-checklist-admins" class="categorychecklist form-no-clear">
	<?php
		echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $admins), 0, (object) array( 'walker' => $walker) );
	?>
	</ul>
</div><!-- /.tabs-panel -->

Cada separador contém uma lista de caixas de verificação. Esta lista é impressa pela função walk_nav_menu_tree, que mantém os três argumentos seguintes:

Argumento Tipo Descrição
$items array (obrigatório) Um conjunto de itens de menu
$depth int (obrigatório) Quantos níveis da hierarquia devem ser incluídos
$r object (obrigatório) Instância de uma classe Walker_Nav_Nav_Menu_Checklist personalizada

$items armazena a variedade de usuários administrativos. A função array_map aplica a função wp_setup_nav_menu_item a $admins, adicionando propriedades de item de menu aos elementos do array.
A imagem seguinte mostra a lista de verificação resultante dos autores.

A primeira aba na caixa de seleção mostrará a lista completa de autores com capacidade de escrita

A primeira aba na caixa de seleção mostrará a lista completa de autores com capacidade de escrita

Agora podemos adicionar o botão submeter e um spinner.

<p class="button-controls wp-clearfix">
	<span class="list-controls">
		<a href="<?php echo esc_url( add_query_arg( array( 'authorarchive-tab' => 'all', 'selectall' => 1, ), remove_query_arg( $removed_args ) )); ?>#authorarchive" class="select-all"><?php _e('Select All'); ?></a>
	</span>
	<span class="add-to-menu">
		<input type="submit"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e('Add to Menu'); ?>" name="add-authorarchive-menu-item" id="submit-authorarchive" />
		<span class="spinner"></span>
	</span>
</p>

</div><!-- /.categorydiv -->
<?php
}

O link no primeiro elemento span permite selecionar todas as caixas de seleção da lista atual, graças ao argumento de consulta selectall. O segundo span contém um botão submeter que será desativado pela função wp_nav_menu_disabled_check se nenhum item for verificado.
Finalmente, o elemento span.spinner adiciona um ícone spinner.
A Meta Box dos Autores está completa, e podemos apreciar o resultado do nosso árduo trabalho na seguinte imagem.

A meta-caixa final permitirá ao usuário administrador adicionar links para os arquivos dos autores

A meta-caixa final permitirá ao usuário administrador adicionar links para os arquivos dos autores

Resumo

O WordPress Core Navigation Menu API é um conjunto de funções principais que criam seções e objetos na Tela de Menus de Aparência. Infelizmente, esta API não está documentada no Codex, e a única forma de aprender como alterar as funcionalidades da Tela de Menus é uma dissecação profunda do arquivo /wp-admin/includes/nav-menu.php.
O mesmo problema com os módulos de itens de menu. Como eles estão estruturados? Quantas tipologias estão disponíveis? Podemos criar novas tipologias? Não há respostas a estas perguntas no Codex. No momento da escrita, a única maneira de entender melhor os módulos do item é analisar /wp-admin/includes/nav-menu.php core file, e a função wp_setup_nav_menu_item (linha 730 no WordPress 4.5).
Por estas razões, este post pode ser considerado uma primeira abordagem a este tópico, e espero que vocês leitores deixem suas sugestões e idéias para discussão nos comentários abaixo.

O código completo do nosso exemplo de plugin de menu personalizado do WordPress está disponível em um resumo público.


Se você gostou deste artigo, então você vai adorar a plataforma de hospedagem WordPress da Kinsta. Turbine seu site e obtenha suporte 24/7 de nossa experiente equipe de WordPress. Nossa infraestrutura baseada no Google Cloud se concentra em escalabilidade automática, desempenho e segurança. Deixe-nos mostrar-lhe a diferença Kinsta! Confira nossos planos