Contenu principal
• •

Lister ses pages dans le menu admin de WordPress

Pour ceux qui modifient souvent leurs pages (ou custom posts) et qui aimeraient y avoir accès plus rapidement, voici une astuce pour les lister directement dans le menu d’administration de WordPress. Ce bout de code vous permettra d’insérer les liens vers l’édition de chacune de vos pages dans le menu, ou un sous-menu.

Méthode générale et options

D’abord nous créons une fonction sf_admin_menu() que nous allons « hooker » à admin_menu() de WordPress. Ensuite, nous créons des options pour personnaliser l’affichage de nos liens selon nos besoins :

  • $in_sub : si $in_sub = true, les liens s’afficheront dans le sous-menu de « Pages », sinon sous forme de menu de 1er niveau,
  • $gal_pages_item : utile seulement pour l’affichage « Menu de 1er niveau », si $gal_pages_item = true, on affiche l’item général « Pages », sinon il est supprimé du menu,
  • $pages_in_trash : utile seulement pour l’affichage « Menu de 1er niveau », si $pages_in_trash = true, on affiche un lien vers les pages situées dans la corbeille.

Comme d’habitude, tout ce qui suit va aller dans le fichier functions.php de votre thème.

12345678

function sf_admin_menu() {
	$in_sub = true;
	$gal_pages_item = false;
	$pages_in_trash = true;
	$templ_url = get_bloginfo('template_directory');
	global $wpdb, $menu, $submenu;
}
add_action('admin_menu', 'sf_admin_menu');

Par la même occasion nous créons la variable $templ_url pour enregistrer le chemin vers le dossier de notre thème, elle nous servira pour les images de menu/sous-menu. Nous aurons également besoin des variables globales $wpdb, $menu et $submenu de WordPress.

Requête

Pour créer nos entrées de menu/sous-menu nous aurons besoin pour chaque page d’aller chercher dans la base de données son identifiant unique, son titre et son statut. Le statut d’une page peut être « publish » (publiée), « draft » (brouillon), « pending » (en attente de relecture) ou « trash » (à la corbeille). Pour les posts et les custom posts types déclarés avec 'capability_type' => 'page', il y a aussi le statut « static » (mis en avant).
Nous allons donc demander les posts dont le « post_type » est égal à « page » et dont le « post_status » est différent de « trash » (car on ne peut pas éditer une page qui est à la corbeille, donc inutile de mettre un lien vers chaque article de la corbeille).

7

	$pages_for_menu = $wpdb->get_results( "SELECT ID, post_title, post_status FROM $wpdb->posts WHERE post_type='page' AND post_status!='trash' ORDER BY post_title" );

Cette requête nous servira pour les deux modes d’affichage : menu de 1er niveau ou sous-menu.

Version « sous-menu »

Listing des pages dans un sous-menu de l'adminNous vérifions notre réglage $in_sub pour savoir si l’on souhaite un affichage en sous-menu, et si le résultat de notre requête n’est pas vide, nous utilisons la fonction add_submenu_page() de WordPress bouclée avec foreach :

010203040506070809101112131415161718

function sf_admin_menu() {
	$in_sub = true;
	$gal_pages_item = false;
	$pages_in_trash = true;
	$templ_url = get_bloginfo('template_directory');
	global $wpdb, $menu, $submenu;
	$pages_for_menu = $wpdb->get_results( "SELECT ID, post_title, post_status FROM $wpdb->posts WHERE post_type='page' AND post_status!='trash' ORDER BY post_title" );
	if ($in_sub) {
		if ($pages_for_menu){
			foreach($pages_for_menu as $pagemenu){
				add_submenu_page('edit.php?post_type=page', '', '<img title="'.$pagemenu->post_status.'" alt="['.$pagemenu->post_status.'] " src="'.$templ_url.'/images/admin/'.$pagemenu->post_status.'.png"/> '.$pagemenu->post_title, 'edit_pages', 'post.php?post='.$pagemenu->ID.'&action=edit');
			}
		}
	} else {
		// Affichage "Menu de 1er niveau"
	}
}
add_action('admin_menu', 'sf_admin_menu');

Petite explication pour add_submenu_page() :

  • 'edit.php?post_type=page' : il s’agit de l’item parent. Ici, l’item de menu « Pages »,
  • '' : le deuxième paramètre est vide, c’est le titre de la page vers laquelle mène le lien. Inutilisable dans notre cas, WordPress ne nous permettra pas de changer celui par défaut,
  • '<img title="'.$pagemenu->post_status.'" alt="['.$pagemenu->post_status.'] " src="' . $templ_url . '/images/admin/' . $pagemenu->post_status . '.png"/> ' . $pagemenu->post_title : titre du lien. Ici, j’insère une image avant le titre, elle nous servira à différencier les pages publiées de celles en attente de relecture ou des brouillons. Le résultat sera sous la forme : '<img title="publish" alt="[publish] " src="http://www.mon-site.com/wp_content/themes/mon_theme/images/admin/publish.png"/> Titre de page'. Tout ce dont vous aurez besoin ce sont 3 images 16px x 16px placées dans un sous-dossier ‘images/admin/’ de votre thème et les appeler publish.png, draft.png et pending.png.
  • 'edit_pages' : capability pour accéder à la page d’édition,
  • 'post.php?post='.$pagemenu->ID.'&action=edit' : le lien vers la page d’édition de votre page.

Version « menu »

Listing des pages dans le menu adminPour mettre nos pages au même niveau « Articles », « Médias », « Liens », etc., la première chose que nous devons voir c’est que nous n’aurons pas assez de place pour les insérer directement en dessous de l’item « Pages ». En effet, comme je l’avais indiqué lors de mon précédent article Personnaliser son administration WordPress au paragraphe « Ajouter ou supprimer des liens dans le menu d’administration », l’onglet « Pages » est à la position 20 dans la variable $menu, s’en suivent les « Commentaires » à la position 25, de quoi rentrer seulement 4 pages entre.
Cependant, le prochain onglet est un séparateur à la position 59, ça nous laisse assez de place pour tout mettre. Donc, nous allons créer un autre « bloc de menu » sous l’item « Commentaires » et supprimer l’item « Pages » d’origine.

1314151617181920212223242526

	//... Notre code précédent...
	} else {
		if ($pages_for_menu){
			$menu[29] = $menu[59];							// Séparateur
			if($gal_pages_item) {
				$menu[30] = $menu[20];						// On duplique l'item "Pages" pour l'insérer en position 30
				$menu[30][4] = 'menu-top menu-top-first menu-icon-page';	// Pour avoir l'arrondi de "1er item" sur le nouvel item "Pages"
			}
			unset($menu[20]);							// On supprime l'item original "Pages"
			$menu[25][4] = 'menu-top menu-top-last menu-icon-comments';		// Pour avoir l'arrondi de "dernier item" sur "Commentaires"
			// ...
		}
		// ...
	}

Nous allons insérer nos page à partir de la position 30. Nous commençons par créer un séparateur à la position 29, en copiant celui existant à la position 59.
Ensuite, avec $gal_pages_item, on teste si on veut avoir l’onglet général « Pages » à la position 30. Si oui, on le crée en copiant celui déjà existant à la position 20, puis on lui ajoute la classe « menu-top-first » pour qu’il ait les coins supérieurs arrondis.
Étape suivante, nous supprimons l’onglet « Pages » d’origine (à la position 20) avec unset($menu[20]), puis nous ajoutons la classe « menu-top-last » à l’onglet situé à la position 25 (c’est l’onglet « Commentaires », juste au-dessus du séparateur que nous venons de rajouter) pour qu’il ait les coins inférieurs arrondis.

Maintenant il nous faut une nouvelle boucle foreach() pour ajouter nos pages. Le système est presque identique à la version « sous-menu » sauf qu’il nous faut indiquer à chaque fois la position du nouveau lien dans le menu. Nous commençons à 31.

1314151617181920212223242526272829303132

	//... Notre code précédent...
	} else {
		if ($pages_for_menu){
			$menu[29] = $menu[59];							// Séparateur
			if($gal_pages_item) {
				$menu[30] = $menu[20];						// On duplique l'item "Pages" pour l'insérer en position 30
				$menu[30][4] = 'menu-top menu-top-first menu-icon-page';	// Pour avoir l'arrondi de "1er item" sur le nouvel item "Pages"
			}
			unset($menu[20]);							// On supprime l'item original "Pages"
			$menu[25][4] = 'menu-top menu-top-last menu-icon-comments';		// Pour avoir l'arrondi de "dernier item" sur "Commentaires"
			$i = 31;
			foreach($pages_for_menu as $pagemenu){
				add_menu_page( '', $pagemenu->post_title, 'edit_pages', 'post.php?post='.$pagemenu->ID.'&action=edit', '', $templ_url.'/images/admin/'.$pagemenu->post_status.'.png', $i );
				if($i == 31 && !$gal_pages_item)
					$menu[$i][4] = 'menu-top menu-top-first';		// Pour avoir l'arrondi de "1er item" sur cette première page
				$i++;
			}
		}
		// ...
	}

Petite explication pour add_menu_page() :

  • '' : le titre de la page vers laquelle mène le lien. Inutilisable cette fois encore,
  • $pagemenu->post_title : titre du lien,
  • 'edit_pages' : capability pour accéder à la page d’édition,
  • 'post.php?post='.$pagemenu->ID.'&action=edit' : le lien vers la page d’édition de votre page,
  • '' : fonction servant à afficher le contenu de la page vers laquelle le lien pointe. Inutile dans notre cas.
  • $templ_url.'/images/admin/'.$pagemenu->post_status.'.png' : url de l’image de l’item. C’est la même chose que pour la version « sous-menu »,
  • $i : la position de l’item dans le menu.

A la ligne suivante, on demande si $i est égal à 31, c’est à dire si nous nous sommes sur notre premier lien, et si $gal_pages_item est à false (on ne crée pas de nouvel item « Pages ») alors nous devons arrondir les coins supérieurs de ce lien puisqu’il s’agira effectivement du 1er lien de notre « bloc ».
On incrémente enfin notre compteur $i.

Dernière chose, il peut être utile d’avoir un lien vers la page listant les pages situées dans la corbeille, surtout si nous avons décidé de ne pas afficher le lien « Pages ». En plus, le lien affichera le nombre de pages dans la corbeille. C’est donc là que nous testons notre réglage $pages_in_trash.

303132333435363738

		// ...
		if ($pages_in_trash) {
			$trashed_pages = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_type='page' AND post_status='trash'");
			if($trashed_pages)
				add_menu_page( '', 'Corbeille ('.$trashed_pages.')', 'edit_pages', 'edit.php?post_status=trash&post_type=page', '', $templ_url.'/images/admin/trash.png', $i );
		}
	}
}
add_action('admin_menu', 'sf_admin_menu');

Avec $trashed_pages, nous stockons directement le nombre de pages dans la corbeille.
Hé oui, vous avez bien vu, il vous faudra une image appelée trash.png avec les autres.

Conclusion

0102030405060708091011121314151617181920212223242526272829303132333435363738

function sf_admin_menu() {
	$in_sub = true;
	$gal_pages_item = false;
	$pages_in_trash = true;
	$templ_url = get_bloginfo('template_directory');
	global $wpdb, $menu, $submenu;
	$pages_for_menu = $wpdb->get_results( "SELECT ID, post_title, post_status FROM $wpdb->posts WHERE post_type='page' AND post_status!='trash' ORDER BY post_title" );
	if ($in_sub) {
		if ($pages_for_menu){
			foreach($pages_for_menu as $pagemenu){
				add_submenu_page('edit.php?post_type=page', '', '<img title="'.$pagemenu->post_status.'" alt="'.$pagemenu->post_status.'" src="'.$templ_url.'/images/admin/'.$pagemenu->post_status.'.png"/> '.$pagemenu->post_title, 'edit_pages', 'post.php?post='.$pagemenu->ID.'&action=edit');
			}
		}
	} else {
		if ($pages_for_menu){
			$menu[29] = $menu[59];							// Séparateur
			if($gal_pages_item) {
				$menu[30] = $menu[20];						// On duplique l'item "Pages" pour l'insérer en position 30
				$menu[30][4] = 'menu-top menu-top-first menu-icon-page';	// Pour avoir l'arrondi de "1er item" sur le nouvel item "Pages"
			}
			unset($menu[20]);							// On supprime l'item original "Pages"
			$menu[25][4] = 'menu-top menu-top-last menu-icon-comments';		// Pour avoir l'arrondi de "dernier item" sur "Commentaires"
			$i = 31;
			foreach($pages_for_menu as $pagemenu){
				add_menu_page( '', $pagemenu->post_title, 'edit_pages', 'post.php?post='.$pagemenu->ID.'&action=edit', '', $templ_url.'/images/admin/'.$pagemenu->post_status.'.png', $i );
				if($i == 31 && !$gal_pages_item)
					$menu[$i][4] = 'menu-top menu-top-first';		// Pour avoir l'arrondi de "1er item" sur cette première page
				$i++;
			}
		}
		if ($pages_in_trash) {
			$trashed_pages = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_type='page' AND post_status='trash'");
			if($trashed_pages)
				add_menu_page( '', 'Corbeille ('.$trashed_pages.')', 'edit_pages', 'edit.php?post_status=trash&post_type=page', '', $templ_url.'/images/admin/trash.png', $i );
		}
	}
}
add_action('admin_menu', 'sf_admin_menu');
  • $in_sub = true : les liens s’afficheront dans le sous-menu de « Pages », sinon sous forme de menu de 1er niveau,
  • $gal_pages_item = true : on affiche l’item général « Pages », sinon il est supprimé du menu (affichage « Menu de 1er niveau »),
  • $pages_in_trash = true : on affiche un lien vers les pages situées dans la corbeille (affichage « Menu de 1er niveau »).

Quatre images (16px x 16px, format .png) dans le sous-dossier images/admin/ de votre thème : publish.png, draft.png, pending.png et trash.png (allez, je suis sympa, je vous file les miennes dans l’archive à télécharger :) ).
Si vous utilisez relativement peu de pages, ces quelques lignes vous seront peut-être utiles :)

See ya!