Ajouter des liens d'archive de type publication à votre menu

Une demande courante, en particulier pour ceux qui ont créé des types de publication personnalisés tels que «Actualités» ou «Événements», consiste à ajouter un lien vers la page d'archive de leur type de publication dans leur menu de navigation. Actuellement, toutefois, cela ne peut être fait qu'en entrant manuellement l'URL de l'archive de type publication. En plus d’être assez inélégante, cette solution présente quelques inconvénients: elle n’apparaît pas toujours comme «actuelle», si vous modifiez la structure de votre lien permanent, le lien peut être rompu, l’ajout manuel des URL est fastidieux et le lien n’apparaît pas comme « courant 'quand sur un message de ce type.

Dans ce tutoriel, je vais vous montrer comment créer un plugin qui crée une méta-boîte sur votre page Apparence -> Menu, qui vous permet d’ajouter des liens d’archive de type publication. Ces liens ne souffrent pas des inconvénients mentionnés ci-dessus.


Étape 1 Créer un plugin

Ce plugin s’appellera "Mes liens d’archive de type publication" et créera à cet effet d’abord un dossier appelé ma-post-type-archive-links sous votre / wp-content / plugins / dossier, et à l'intérieur qui créent un fichier mon-post-type-archive-links.php. Ce fichier est le fichier plugin principal. Nous allons le placer dans une classe - c'est simplement pour ne pas avoir à nous soucier du conflit de noms de fonctions entre WordPress ou d'autres plugins: nous devons simplement nous assurer que notre nom de classe est unique. Ajouter ce qui suit à mon-post-type-archive-links.php

  Page de menu pour ajouter des liens d'archive de type post Auteur: Stephen Harris URI de l'auteur: http://profiles.wordpress.org/users/stephenh1988/ * / class My_Post_Type_Archive_Link // Tout ira ici My_Post_Type_Archive_Link :: load (); ?>

Tout dans ce tutoriel sera assis à l'intérieur de cette classe.


Étape 2 Charger le plugin

Lorsque le fichier de plugin est chargé, il lance la méthode de classe charge(). Cette méthode sera responsable de l’ajout d’actions et de filtres sur divers hooks WordPress. Nous allons passer en revue chacune d’elles dans les étapes suivantes, mais cela fournit également un résumé utile. Ajoutez la méthode suivante à notre classe:

 fonction publique load () // Fonction de crochet pour ajouter le metabox à la page de menu add_action ('admin_init', array (__ CLASS __, 'add_meta_box')); // Javascript pour la méta-boîte add_action ('admin_enqueue_scripts', array (__ CLASS __, 'metabox_script')); // Ajax callback pour créer un élément de menu et l'ajouter au menu add_action ('wp_ajax_my-add-post-type-archive-links-links', array (__CLASS__, 'ajax_add_post_type')); // Attribue à l'item approprié le paramètre add_filter ('wp_setup_nav_menu_item', array (__ CLASS __, 'setup_archive_item')); // Crée un lien d'archive de type post 'current' add_filter ('wp_nav_menu_objects', array (__ CLASS __, 'Maybe_make_current')); 

Résumons ce que chacune de ces parties fait:

  1. Ajouter une meta-box - Assez explicite. La fonction accrochée sera responsable de l'ajout de notre boîte méta.
  2. JavaScript en file d'attente - Nous utilisons le admin_enqueue_scripts hook pour mettre en file d'attente notre fichier JavaScript. Notre JavaScript, lorsque vous cliquez sur 'Ajouter au menu', déclenchera une demande AJAX.
  3. Rappel AJAX - Cette fonction est responsable du traitement de la demande AJAX ci-dessus. Il va créer les éléments de menu et les ajouter au menu.
  4. Élément de menu mis en place - Cela garantit que lorsque le lien d'archive apparaît sur votre menu, il pointe correctement sur l'archive du type de publication..
  5. Peut-être faire courant - Chaque fois qu’un menu apparaît et que ses éléments sont passés à travers un filtre, nous veillerons à ce que la classeélément de menu actuel'est ajouté au lien de type de message approprié.

Étape 3 Ajout du Metabox

Nous définissons d’abord notre add_meta_box méthode, qui appelle simplement la fonction WordPress add_meta_box (). Les détails de cette fonction ont déjà été abordés à maintes reprises, mais en cas de doute, vous pouvez en prendre connaissance dans les pages du Codex..

 fonction publique add_meta_box () add_meta_box ('post-type-archives', __ ('Types de publication', ',' Types de publication ',' my-post-type-archive-links '), array (__ CLASS __,' metabox '),' nav-menus ' , 'side', 'low'); 

Ensuite, nous définissons la fonction de rappel de la méta-boîte chargée d’afficher les éléments internes de la métaboxe:

 fonction publique metabox () global $ nav_menu_selected_id; // Récupère les types de publication $ post_types = get_post_types (array ('public' => true, '_ builtin' => false), 'objet');?>>  

valeur = ""name =" add-post-type-menu-item "/>

Cette méthode obtient simplement tous les types de publication personnalisés publics avec get_post_types () et les parcourt ensuite pour créer une liste de cases à cocher. Chaque case à cocher a le nom du type de publication comme valeur. Dans l'étape suivante, nous ajoutons du code javascript qui sera déclenché lorsqu'un utilisateur clique sur le bouton "Ajouter au menu"..


Étape 4 Le JavaScript

Nous souhaitons uniquement mettre en file d'attente notre code JavaScript sur la page d'administration Apparence -> Menu. Nous avons utilisé le admin_enqueue_scripts crochet qui ne se déclenche que sur les pages d'administration et transmet le crochet de la page en tant qu'argument. Le crochet de la page Apparence -> Menu est nav-menus.php. Après avoir mis notre script en file d'attente, nous utilisons wp_localize_script pour rendre le nonce disponible dans notre JavaScript. Nous l'incluons dans la demande AJAX pour nous aider à vérifier que l'action était intentionnelle..

 fonction publique metabox_script ($ hook) if ('nav-menus.php'! = $ hook) return; // Dans Apparence> Page de menu, script de mise en file d'attente: wp_enqueue_script ('my-post-type-archive-links_metabox', plugins_url ('/ metabox.js', __FILE__), array ('jquery')); // Ajout de la variable nonce wp_localize_script ('my-post-type-archive-links_metabox', 'MyPostTypeArchiveLinks', array ('nonce' => wp_create_nonce ('mon-add-post-type-archive-type-archives-liens')); 

Dans l'étape précédente, le bouton 'Ajouter au menu' a reçu l'identifiant soumettre-post-type-archives. Nous utilisons maintenant jQuery pour cibler ce bouton et, lorsque vous cliquez dessus, envoyez une demande AJAX pour créer l'élément de menu et l'ajouter au menu. Ce qui suit est la seule partie de ce didacticiel qui n’appartient pas à notre classe. Il devrait aller dans un fichier appelé metabox.js, dans notre dossier de plug-ins.

 jQuery (document) .ready (function ($) $ ('# submit-post-type-archives'). click (function (event) event.preventDefault (); / * Cocher les cases * / var postTypes = [ ]; $ ('# # post-type-archive-checklist li: coché'). each (function () postTypes.push ($ (this) .val ());); / * Envoyer des types de publication cochés avec notre action, et nonce * / $ .post (ajaxurl, action: "mon-add-post-type-archive-liens", posttypearchive_nonce: MyPostTypeArchiveLinks.nonce, post_types: postTypes, / * AJAX renvoie html pour l'ajouter au menu * / fonction (réponse) $ ('# menu-à-modifier'). append (response););));

Notez l'URL à laquelle nous envoyons la demande: ajaxurl. Nous ne l'avons défini nulle part. C'est une variable globale définie par WordPress côté admin seulement qui pointe vers la page utilisée par WordPress pour gérer les requêtes AJAX. Lorsque le bouton de soumission est cliqué, les noms des types de publication cochés, une action unique et des nonce sont tous envoyés à cette URL. Lorsque WordPress reçoit la demande, il déclenche la wp_ajax_my-add-post-type-archive-links crochet. Le nonce est une mesure de sécurité visant à vérifier que l'action était destinée.


Étape 5: le rappel AJAX

Nous définissons maintenant la fonction de rappel AJAX ajax_add_post_type.

 fonction publique ajax_add_post_type () if (! current_user_can ('edit_theme_options')) die ('- 1'); check_ajax_referer ('mon-add-post-type-archive-liens', 'posttypearchive_nonce'); require_once ABSPATH. 'wp-admin / includes / nav-menu.php'; if (empty ($ _ POST ['post_types']))) exit; // Créer des éléments de menu et stocker des identifiants dans un tableau $ item_ids = array (); foreach ((array) $ _POST ['post_types'] en tant que $ post_type) $ post_type_obj = get_post_type_object ($ post_type); if (! $ post_type_obj) continue; $ menu_item_data = array ('menu-item-title' => esc_attr ($ post_type_obj-> labels-> name), 'menu-item-type' => 'post_type_archive', 'menu-item-object' => esc_attr ( $ post_type), 'menu-item-url' => get_post_type_archive_link ($ post_type)); // Collecte les identifiants des objets. $ item_ids [] = wp_update_nav_menu_item (0, 0, $ menu_item_data);  // S'il y avait une erreur die ici if (is_wp_error ($ item_ids)) die ('- 1'); // Configurez les éléments de menu poureach ((array) $ item_ids comme $ id_item_menu) $ menu_obj = get_post ($ id_item_menu); if (! empty ($ menu_obj-> ID)) $ menu_obj = wp_setup_nav_menu_item ($ menu_obj); $ menu_obj-> label = $ menu_obj-> titre; // ne montre pas "(en attente)" dans les éléments ajoutés par ajax $ menu_items [] = $ menu_obj;  // Ceci obtient le code HTML qui le renvoie au menu si (! Empty ($ menu_items)) $ args = array ('after' => ", 'before' =>", 'link_after' => ", 'link_before' => ", 'walker' => new Walker_Nav_Menu_Edit); echo walk_nav_menu_tree ($ menu_items, 0, (objet) $ args);  // Enfin, n'oubliez pas de quitter exit; 

Passons en revue ce rappel un peu à la fois. Nous vérifions d’abord les autorisations de l’utilisateur, vérifions le nonce et chargeons le nav-menu.php page (nous avons besoin de certaines fonctions).

 if (! current_user_can ('edit_theme_options')) die ('- 1'); check_ajax_referer ('mon-add-post-type-archive-liens', 'posttypearchive_nonce'); require_once ABSPATH. 'wp-admin / includes / nav-menu.php'; if (empty ($ _ POST ['post_types']))) exit;

Nous créons ensuite un élément de menu pour chaque type de publication sélectionné. Nous vérifions d’abord le type de message que nous avons reçu en vérifiant la valeur renvoyée par get_post_type_object (). Nous pouvons obtenir le lien d'archive avec la fonction get_post_type_archive_link ()

Les éléments de menu sont en fait des messages de type message 'nav_menu_item'avec méta de poste intégré, y compris les champs relatifs à'url','type' et 'objet'. Les objets 'type'est normalement'Douane','Type de poste' ou 'taxonomie'- mais nous lui attribuerons la valeur'post_type_archive'. Les objets 'objet'La méta valeur est normalement utilisée uniquement pour les éléments de'Type de poste' ou 'taxonomie'type et fait référence au type de message ou à la taxonomie auquel le lien fait référence. Nous allons l'utiliser pour stocker le type de publication du lien d'archive.

 // Créer des éléments de menu et stocker des identifiants dans un tableau $ item_ids = array (); foreach ((array) $ _POST ['post_types'] en tant que $ post_type) $ post_type_obj = get_post_type_object ($ post_type); if (! $ post_type_obj) continue; $ menu_item_data = array ('menu-item-title' => esc_attr ($ post_type_obj-> labels-> name), 'menu-item-type' => 'post_type_archive', 'menu-item-object' => esc_attr ( $ post_type), 'menu-item-url' => get_post_type_archive_link ($ post_type)); // Collecte les identifiants des objets. $ item_ids [] = wp_update_nav_menu_item (0, 0, $ menu_item_data);  // S'il y avait une erreur die ici if (is_wp_error ($ item_ids)) die ('- 1');

Ensuite, nous générons simplement le code HTML qui sera ajouté au menu. Nous utilisons le $ item_ids array pour obtenir un tableau d’éléments de menu et le transmettre à une classe de WordPress Walker pour qu’il fasse le travail difficile.

 // Configurez les éléments de menu poureach ((array) $ item_ids comme $ id_item_menu) $ menu_obj = get_post ($ id_item_menu); if (! empty ($ menu_obj-> ID)) $ menu_obj = wp_setup_nav_menu_item ($ menu_obj); $ menu_obj-> label = $ menu_obj-> titre; // ne montre pas "(en attente)" dans les éléments ajoutés par ajax $ menu_items [] = $ menu_obj;  // Ceci obtient le code HTML qui le renvoie au menu si (! Empty ($ menu_items)) $ args = array ('after' => ", 'before' =>", 'link_after' => ", 'link_before' => ", 'walker' => new Walker_Nav_Menu_Edit); echo walk_nav_menu_tree ($ menu_items, 0, (objet) $ args);  // Enfin, n'oubliez pas de quitter exit;

Étape 6 L'élément de menu

Malheureusement, à cause d'un bug avec WordPress, si le type de votre élément n'est pas 'taxonomie','Douane' ou 'Type de poste'l'URL est supprimé. Pour contrer cela, quand un 'post_type_archive'lien est utilisé dans un menu, nous rajoutons manuellement l'URL. Cela garantit également que le lien d'archive est «à jour» (au cas où votre structure de lien permanent a été modifiée).

 fonction publique setup_archive_item ($ menu_item) if ($ menu_item-> type! = 'post_type_archive') return $ menu_item; $ post_type = $ menu_item-> object; $ menu_item-> url = get_post_type_archive_link ($ post_type); return $ menu_item; 

Étape 7: Rendre le lien actuel

Enfin, nous devons rendre l'élément «actuel» lorsque nous sommes sur la page appropriée. Je souhaite que le lien archive de type publication soit mis en surbrillance comme courant si nous sommes sur cette page d’archive ou si nous visionnons une publication de ce type. Pour ce faire je vérifie:

  • is_post_type_archive ()
  • is_singular ()

Pour que l’article soit à jour, il suffit d’ajouter élément de menu actuel aux classes de l'article qui sont stockées dans $ item-> classes. Nous devons ensuite parcourir ses parents dans le menu et ajouter les classes current_item_parent et current_item_ancestor. Regardons chaque bit individuellement:

Nous parcourons chacun des éléments du menu:

 fonction publique may_make_current ($ items) foreach ($ items en tant que $ item) // C'est ici que nous vérifions l'élément return $ items; 

Si l'article n'est pas de 'post_type_archive'ou si c'est le cas, mais nous ne voulons pas qu'il soit' actuel ', nous passons simplement à l'élément suivant. Rappelez-vous que pour nos liens d’archive, le type de publication est stocké en tant qu’objet de l’élément. Donc à l'intérieur du pour chaque boucle:

 if ('post_type_archive'!! = $ item-> type) continue; $ post_type = $ item-> object; if (! is_post_type_archive ($ post_type) &&! is_singular ($ post_type)) continue;

Si nous voulons l'actualiser, nous lui donnons la classe appropriée, puis nous prenons ses parents dans le menu. Le parent d'un élément de menu est stocké en tant que méta post avec clé méta _menu_item_menu_item_parent.

 // Rendre l'article courant $ item-> current = true; $ item-> classes [] = 'élément de menu actuel'; // Récupère les ancêtres de l'élément de menu: $ _anc_id = (int) $ item-> db_id; $ actif_ancestor_item_ids = array (); while (($ _anc_id = get_post_meta ($ _anc_id, '_menu_item_menu_item_parent', true)) &&! in_array ($ _anc_id, $ active_ancestor_item_ids)) $ active_ancestor_item_it [_ = $ _anc_id; 

Nous parcourons ensuite les éléments de menu et donnons les classes appropriées aux parents et aux ancêtres de l'élément 'actuel'.

 // Parcourt les éléments et donne aux ancêtres et aux parents la classe appropriée pour chaque objet ($ items en tant que $ key => $ parent_item) $ classes = (array) $ parent_item-> classes; // Si l'élément de menu est le parent si ($ parent_item-> db_id == $ item-> menu_item_parent) $ classes [] = 'current-menu-parent'; $ items [$ key] -> current_item_parent = true;  // Si l'élément de menu est un ancêtre if (in_array (intval ($ parent_item-> db_id), $ actif_ancestor_item_ids)) $ classes [] = 'current-menu-ancestor'; $ items [$ key] -> current_item_ancestor = true;  $ items [$ key] -> classes = array_unique ($ classes); 

Assembler cette fonction:

 fonction publique may_make_current ($ items) foreach ($ items en tant que $ item) if ('post_type_archive'! = $ item-> type) continue; $ post_type = $ item-> object; if (! is_post_type_archive ($ post_type) &&! is_singular ($ post_type)) continue; // Rendre l'article courant $ item-> current = true; $ item-> classes [] = 'élément de menu actuel'; // Récupère les ancêtres de l'élément de menu: $ _anc_id = (int) $ item-> db_id; $ actif_ancestor_item_ids = array (); while (($ _anc_id = get_post_meta ($ _anc_id, '_menu_item_menu_item_parent', true)) &&! in_array ($ _anc_id, $ active_ancestor_item_ids)) $ active_ancestor_item_it [_ = $ _anc_id;  // Parcourez les ancêtres et donnez-leur la classe 'ancêtre' ou 'parent' pour chaque ($ items en tant que $ key => $ parent_item) $ classes = (tableau) $ parent_item-> classes; // Si l'élément de menu est le parent si ($ parent_item-> db_id == $ item-> menu_item_parent) $ classes [] = 'current-menu-parent'; $ items [$ key] -> current_item_parent = true;  // Si l'élément de menu est un ancêtre if (in_array (intval ($ parent_item-> db_id), $ actif_ancestor_item_ids)) $ classes [] = 'current-menu-ancestor'; $ items [$ key] -> current_item_ancestor = true;  $ items [$ key] -> classes = array_unique ($ classes);  return $ items; 

Il ne reste plus qu’à accéder à la page d’administration de votre plugin et à l’activer..


Conclusion

Il y a toujours moyen de s'améliorer. Par exemple, avec un peu de jQuery, vous pouvez ajouter un lien "Tout sélectionner" sous les cases à cocher ou afficher un symbole "de chargement" pendant le traitement d'AJAX. Maintenant, ce plugin n'est pas la solution la plus simple - mais il fonctionne bien et évite les pièges de simplement ajouter un lien personnalisé. Le plugin ci-dessus dans son intégralité peut être trouvé sur mon GitHub. Si vous avez des commentaires ou des suggestions, n'hésitez pas à laisser un commentaire ou à me contacter via Twitter.