Los menús de navegación personalizados son una asombrosa característica de WordPress que permite a los usuarios administradores añadir cualquier lista de enlaces en cualquier lugar del sitio. Pueden ser enlaces a recursos internos, como publicaciones, páginas y archivos, así como enlaces a recursos externos, como sus páginas de perfiles sociales. WordPress reserva una página de administración específica para los menús de navegación personalizados. En esta página el usuario administrador puede crear menús, organizar elementos y establecer propiedades que afectan a la forma en que aparecen en el front-end.

Pantalla de menús de apariencia de WordPress

Visualización de menús de inicio de sesión de WordPress

Dicho esto, las principales preguntas detrás de este post son: «¿Podemos ampliar las funciones incorporadas de la visualización de menús?»
Por supuesto que podemos. Así que me sumergiré profundamente en el tema, y analizaré secciones y objetos que permitan añadir y gestionar menús y sus elementos. Pero no será sólo una descripción de la visualización. Le mostraré cómo añadir elementos personalizados al menú del estilo acordeón situado en la barra lateral izquierda.

Estos Boxes personalizados mostrarán listas adicionales de enlaces para elegir cuando se construya menús de navegación personalizados. Más específicamente, les mostraré cómo añadir un box que contiene enlaces a los archivos de los autores del sitio. Empecemos a sumergirnos en la construcción de un menú personalizado de WordPress.

Visualización de menús de inicio de sesión

La página de edición de menús permite a los usuarios crear y gestionar menús personalizados gracias a una interfaz intuitiva. El botón de Opciones de Visualización en la esquina superior derecha revela la primera sección de la página que contiene dos grupos de casillas de verificación. El grupo Boxes permite al usuario ocultar y mostrar las meta boxes del menú en la barra lateral izquierda, mientras que el grupo Mostrar propiedades avanzadas del menú oculta y muestra propiedades como objetivos de enlaces, descripciones y clases CSS para los elementos de la lista.

Pestaña de opciones de la pantalla

Pestaña de opciones de la visualización

Una vez que se ha creado el primer menú, la visualización de menús se ve un poco diferente de su apariencia por defecto. Aparecen nuevas secciones en la pestaña Edit Menús.

 El menú incorporado muestra listas de enlaces que apuntan al contenido del sitio...

El menú incorporado muestra listas de enlaces que apuntan al contenido del sitio…

Meta Boxes y Módulos

La barra lateral izquierda de la visualización de menús contiene un menú en estilo acordeón cuyos elementos se denominan meta boxes de elementos de menú. Estos bloques proporcionan una serie de campos de formulario y controles que permiten al usuario buscar el contenido del sitio y añadir enlaces a los menús de navegación.
De forma predeterminada, WordPress proporciona los siguientes meta boxes de elementos de menú:

Cuando el usuario añade un enlace a un menú, se añade un nuevo módulo de elementos a la sección Menu Structure de la visualización. WordPress proporciona cuatro tipologías de módulos de elementos de menú:

Comparación de los módulos de los elementos del menú

Comparación de los módulos de los elementos del menú

Vamos a ampliar la estructura incorporada de la visualización de menús de apariencia con meta-boxes personalizados que permitan al usuario administrador seleccionar piezas de contenido no disponibles por defecto, como los archivos de autor. Desafortunadamente, el Core Navigation Menu API no está documentado y para lograr nuestro objetivo fue necesario diseccionar línea por línea dos archivos centrales: /wp-admin/includes/nav-menu.php para los meta boxes del menú, y /wp-includes/nav-menu.php para los módulos de los elementos del menú.
Empecemos a codificar.

Crear un Meta Box de elementos de menú personalizados de WordPress

Cree un nuevo plugin y añada el siguiente código al archivo 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);

La función add_meta_box de WordPress registra meta boxes en las páginas de administración. Mantiene los siguientes argumentos:

Argumento Escriba Descripción
$id string (requerido) la ID de meta box
$callback callable (requerido) la función que hace eco del contenido del meta box
$screen string|array|WP_Screen (opcional) la visualización en la que se muestra el meta box
$context string (opcional) el contexto dentro de la visualización donde se despliega el meta box (los valores posibles son 'normal', 'side', 'advanced', por defecto 'advanced')
$priority string (opcional) posibles valores 'high', 'low', 'default'
$callback_args array (opcional) una serie de argumentos para ser pasados a la llamada de retorno

Tal vez habría esperado que la función add_meta_box se enganchara a una acción como add_meta_boxes, que se activa en las páginas de edición de post. Desafortunadamente, no tenemos una acción en nav-menus.php a la que podamos enganchar la función, por lo que estamos obligados a usar el filtro nav_menu_meta_box_object. Este gancho determina si se agregará un meta box de elementos de menú para un tipo de objeto. Cuando el filtro se ejecuta, add_meta_box registra el meta box personalizado.
Ahora podemos definir la función de devolución de llamada que producirá el contenido HTML para el meta box.

/**
 * 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();
	...
}

La variable global mantiene la memoria del ID del menú actual, mientras que $walker almacena una nueva instancia del objeto Walker_Nav_Menu_Checklist, que construye la lista HTML de elementos del menú.
Entonces, tenemos que establecer el valor de la variable $current_tab que determinará la pestaña activa en el meta-boxes. Para facilitar las cosas, le daré sólo dos fichas:

$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 continuación, obtendremos todos los usuarios con privilegios de escritura, agregando un número de propiedades al 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 devuelve un array de objetos $user seleccionados por los parámetros especificados. El who param obliga a WordPress a consultar la base de datos sólo para usuarios con privilegios de escritura.
La matriz $admins almacenará una matriz de autores, mientras que la última variable, $removed_args, almacenará una lista de vars de consulta a ser eliminados.
Cuando terminemos con los datos, podemos imprimir la marca del meta box. Primero construiremos etiquetas de pestañas y enlaces:

<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>

Tenemos que ser cuidadosos y asignar los nombres de clase, identificaciones y atributos de datos correctos a los elementos del meta box. En caso de error, el menú del estilo acordeón no funcionará correctamente.
Utilizamos las funciones add_query_arg y remove_query_arg para establecer los valores específicos de las pestañas para la varilla de consulta authorarchive-tab y eliminar las variables de consulta innecesarias.
La imagen de abajo muestra las etiquetas de las pestañas resultantes.

¿Luchando con el tiempo de inactividad y los problemas de WordPress? Kinsta es la solución de alojamiento diseñada para ahorrarle tiempo! Vea nuestras características
wordpress personalizado de las pestañas del menú para los autores

wordpress personalizado de las pestañas del menú para los autores

A continuación, construiremos el contenido HTML de las pestañas (de nuevo, preste atención a los nombres de clase y a los ID):

<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 ficha contiene una lista de casillas de verificación. Esta lista se imprime con la función walk_nav_menu_tree, que mantiene los siguientes tres argumentos:

Argumento Escriba Descripción
$items array (requerido) Una serie de elementos del menú
$depth int (requerido) ¿Cuántos niveles de la jerarquía deben incluirse
$r object (requerido) Instancia de una clase personalizada de Walker_Nav_Menu_Checklist

$items almacena el conjunto de usuarios de administración. La función array_map aplica la función wp_setup_nav_menu_item a $admins, agregando las propiedades de los elementos del menú a los elementos de la matriz.
La siguiente imagen muestra la lista de control resultante de los autores.

La primera pestaña de la casilla mostrará la lista completa de autores con capacidad de escritura

La primera pestaña de la casilla mostrará la lista completa de autores con capacidad de escritura

Ahora podemos añadir el botón de envío y un girador.

<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
}

El enlace del primer elemento span permite seleccionar todas las casillas de verificación de la lista actual, gracias al argumento de consulta selectall. El segundo intervalo contiene un botón de envío que será desactivado por la función wp_nav_menu_disabled_check si no se marca ningún elemento.
Finalmente, el elemento span.spinner añade un icono de giro.
El Meta Box de los Autores está completa, y podemos apreciar el resultado de nuestro duro trabajo en la siguiente imagen.

La meta casilla final permitirá al usuario administrador añadir enlaces a los archivos de los autores

La meta box final permitirá al usuario administrador añadir enlaces a los archivos de los autores

Resumen

La API del menú de navegación principal de WordPress es un conjunto de funciones principales que crean secciones y objetos en la visualización de menús de apariencia. Desafortunadamente, esta API no está documentada en el Codex, y la única forma de aprender a cambiar las funcionalidades de la visualización de menús es una disección en profundidad del archivo /wp-admin/includes/nav-menu.php.
El mismo problema con los módulos del menú. ¿Cómo están estructurados? ¿Cuántas tipologías están disponibles? ¿Podemos crear nuevas tipologías? No hay respuestas a estas preguntas en el Codex. En el momento de escribir este artículo, la única forma de entender mejor los módulos de elementos es analizar el archivo central /wp-admin/includes/nav-menu.php, y la función wp_setup_nav_menu_item (línea 730 en WordPress 4.5).
Por estas razones, esta publicación puede considerarse como un primer acercamiento a este tema, y espero que ustedes, los lectores, dejen sus sugerencias e ideas para el debate en los comentarios que figuran a continuación.

El código completo de nuestro ejemplo de plugin de menú personalizado de WordPress está disponible en una lista pública.


Si le ha gustado este artículo, entonces le encantará la plataforma de Kinsta WordPress hosting. Acelere su sitio y reciba soporte 24/7 de nuestro equipo de WordPress veterano. Nuestra infraestructura potenciada por Google Cloud se centra en escalamiento automático, rendimiento y seguridad. ¡Déjenos mostrarle la diferencia con Kinsta! Conozca nuestros planes