Encapsuler la navigation BP dans un wp_nav_menu (reloaded!)

Publié le

par

Crédits Photo Menu on the streets of Canterbury by Mskadu, on Flickr

Dernièrement, je suis tombé sur ce billet intéressant de WP First Aid. Il y est question de wp_nav_menu et de se raccrocher à un filter (wp_nav_menu_items) afin d’ajouter des items à un menu existant. Rappelez-vous j’avais proposé une première méthode pour intégrer la navigation BuddyPress à un wp_nav_menu en février dernier. Or via l’utilisation de ce fameux filter c’est encore plus simple !!

Rappel: activation du support des wp_nav_menu

Pour activer le support des menus dans votre thème, il suffit de commencer par écrire quelques lignes de code dans le script functions.php

<?php

function register_my_menu() {
  register_nav_menu( array(
    'primary' => 'Menu 1',
    'secondary' => 'Menu 2',
  ) );
}
add_action( 'init', 'register_my_menu' );

Depuis l’administration WordPress, il est désormais possible de paramétrer les menus (primary et secondary).

Application du filter

Juste pour le fun, on va légèrement corser l’histoire en décidant de n’afficher la navigation BuddyPress qu’à partir du moment où l’utilisateur est loggé. Dans votre functions.php, ajoutez ces quelques lignes de code :

function imath_bp_nav_menu_items($items, $args) {
   //on ne veut ajouter la navigation que sur le premier menu
   if ( $args->theme_location == "primary" ){
     $buddypress_menu = '<li class="menu-item">
<a href="'.get_bloginfo('url') .'/'. BP_ACTIVITY_SLUG.'">Communauté</a>     <ul class="sub-menu">
       <li class="menu-item"><a href="'.get_bloginfo('url') .'/'. BP_ACTIVITY_SLUG.'">'.__( 'Activity', 'buddypress' ).'</a></li>
       <li class="menu-item"><a href="'.get_bloginfo('url') .'/'. BP_MEMBERS_SLUG.'">'.__( 'Members', 'buddypress' ).'</a></li>
       <li class="menu-item"><a href="'.get_bloginfo('url') .'/'. BP_GROUPS_SLUG.'">'.__( 'Groups', 'buddypress' ).'</a></li>
       <li class="menu-item"><a href="'.get_bloginfo('url') .'/'. BP_FORUMS_SLUG.'">'.__( 'Forums', 'buddypress' ).'</a></li>
     </ul>
     </li>';
     // vous pouvez si vous le souhaitez sur le même modèle ajouter les blogs du réseaux...
     // si l'utilisateur est loggé, on affiche les items BuddyPress
   if ( is_user_logged_in() ) {
     $items = $items . $buddypress_menu ;
   }

   return $items;
   } else {
     return $items;
   }
}
add_filter( 'wp_nav_menu_items', 'imath_bp_nav_menu_items', 9, 2 );

Et voilà, le tour est joué 😉

Bonus

Si vous voulez être certain que les visiteurs non loggés ne puissent pas atteindre la zone BuddyPress…

function imath_is_user_loggedout_die( $located_template ){
   if ( is_user_logged_in() ){
     return $located_template;
   }

   // sinon la page n'existe pas !!!
   return locate_template( array( '404.php' ) );
}
add_filter('bp_load_template', 'imath_is_user_loggedout_die', 1, 1);

A+

9 réponses à “Encapsuler la navigation BP dans un wp_nav_menu (reloaded!)”

  1. Avatar de Mecanographik

    Merci pour cet article que j’ai appliqué sans souci à mon site Buddypress de test (v 1.5.1).
    Juste une petite chose, il faut modifier à la ligne 5 du script de ta première fonction « Communauté » par « Communauté » pour éviter un problème d’encodage … je chipote ! On pourrai également améliorer la sémantique avec les css pour rendre actif l’onglet « Communauté » lorsque l’utilisateur a cliqué sur un des items enfants…

    J’ai combiné ce filtre avec les slugs francisés, définis dans mon fichier : plugins/bp-custom.php en indiquant par exemple « define( ‘BP_MEMBERS_SLUG’, ‘membres’ ); »
    J’ai également retiré mon « Admin bar » en indiquant :
    « define(‘BP_DISABLE_ADMIN_BAR’, true); »
    En tout cas, c’est le genre de petits « tricks » à connaître pour optimiser l’expérience utilisateur avec Buddypress !

  2. Avatar de imath

    Salut Mecanographik, merci pour ton commentaire et son apport 🙂

  3. Avatar de Mecanographik

    Dois-je ajouter que ce plugin (compatible BP 1.5.1) fait également le job, mais il demande de modifier directement le fichier header.php du thème Buddypress par défaut bp-default :

    http://wordpress.org/extend/plugins/buddypress-profile-menu/

    Donc étant donné que tu utilises le fichier function.php, ta méthode est davantage pérenne 😉

    Je cogite pour ma part sur la refonte du menu de réglage de la page de profil utilisateur, pour le placer (comme Widget?) dans la sidebar par exemple… Ou en utilisant le même principe que pour ton menu « Communauté » (sous forme de menu déroulant) et s’intitulerait « Mon profil ». Ce menu fonctionnerait avec comme principe :
    1 lien -> 1 page
    Par exemple :
    Settings (lien placé dans la sidebar) -> Page « Settings »

    Cela éviterait le système de « Tabs » actuel sur plusieurs lignes. A mon avis, actuellement, un nouvel utilisateur inscrit ne comprend pas grand chose à la gestion de son compte Buddypress ! le problème principal qui se pose est : Comment subdiviser Activity – Groups – Forums – Settings en plusieurs pages ?

    1. Avatar de imath

      Salut @Mecanographik,

      J’ai retiré comme demandé, tes 2 derniers commentaires 🙂 A l’occase, je regarderai le code..
      Autrement pour ton projet de menu profil. Pour la partie déroulante c’est du css et du js.
      Je pense qu’il y a un moyen assez simple de le faire. Il s’agit de s’accocher au hook ‘bp_after_sidebar_me’ pour automatiquement le mettre sous l’avatar de l’utilisateur de la sidebar. L’avantage est que si pas loggé pas de hook et donc pas de menu 😉
      Voici ce que j’ai testé et qui semble fonctionner :

      function imath_user_menu(){
        global $bp;
        ?>
        <br style="clear:both"/>
        <div id="user-menu" class="widget widget_nav_menu">
          <ul>
            <li class="<?php if(BP_XPROFILE_SLUG == $bp->current_component && 'edit' != $bp->current_action && 'change-avatar' != $bp->current_action) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_XPROFILE_SLUG;?>">Mon Profil</a></li>
            <li class="<?php if(BP_XPROFILE_SLUG == $bp->current_component && 'edit' == $bp->current_action ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_XPROFILE_SLUG;?>/edit/">Editer Mon Profil</a></li>
            <li class="<?php if(BP_XPROFILE_SLUG == $bp->current_component && 'change-avatar' == $bp->current_action) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_XPROFILE_SLUG;?>/change-avatar/">Editer Mon Avatar</a></li>
            <li class="<?php if(BP_SETTINGS_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_SETTINGS_SLUG;?>">Mes réglages</a></li>
            <li class="<?php if(BP_ACTIVITY_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_ACTIVITY_SLUG;?>">Mon activité</a></li>
            <li class="<?php if(BP_BLOGS_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_BLOGS_SLUG;?>">Mes Blogs</a></li>
            <li class="<?php if(BP_GROUPS_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_GROUPS_SLUG;?>">Mes Groupes</a></li>
            <li class="<?php if(BP_FRIENDS_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_FRIENDS_SLUG;?>">Mes amis</a></li>
            <li class="<?php if(BP_MESSAGES_SLUG == $bp->current_component ) echo 'current-menu-item';?>"><a href="<?php echo $bp->loggedin_user->domain . BP_MESSAGES_SLUG;?>">Mes messages</a></li>
          </ul>
        </div>
        <br style="clear:both"/>
        <?php
      }

      add_action('bp_after_sidebar_me', 'imath_user_menu');

      Voici ce que ça peut donner :
      lien vers illustration

  4. Avatar de Mecanographik

    ok, merci pour le test ! c’est tout à fait ça dans l’idée,
    c’est clair que je n’aurai pas pensé à bp_after_sidebar_me. Finalement je me suis attaqué à la fonction bp_get_displayed_user_nav()
    Je l’ai copiée, ajouté à function.php de mon thème enfant et l’ai utilisé dans members/single/settings/general.php
    Mais ta technique permet de ne pas à devoir redéployer le menu déroulant dès qu’on veut changer de tab dans le profil…

    voici le résultat :
    http://i1081.photobucket.com/albums/j360/mecanographik/snap/profile-tabs.png

    Je ne suis pas parvenu à faire un hook sur la fonction bp_get_displayed_user_nav() pour ne pas à devoir recopier les fichiers du thème par défaut, dans lesquels elel est présente… Ma modification force à n’afficher que le Tab « courant » (current component)

    1. Avatar de imath

      Intéressant !!
      En fait si tu veux ajouter un item à la navigation, tu peux utiliser
      add_action('bp_member_options_nav', 'tafonction');

      Mais dans ton cas et vu la fonction en question (bp_get_displayed_user_nav), tu pourras t’apercevoir qu’elle permet de filtrer ce qu’elle retourne (apply_filters(‘bp_get_displayed_user_nav_[cssid]’,…)). Donc tu peux éventuellement également utiliser un autre moyen en bouclant sur le tableau de la global $bp->bp_nav pour être sûr de ne pas manquer un menu (cas des plugins qui ajoutent des menus par exemple…). Voici ce que ça pourrait donner :

      add_action('template_redirect', 'imath_user_nav_filters', 1);

      function imath_user_nav_filters(){
        global $bp;
        foreach((array)$bp->bp_nav as $nav){
          add_filter('bp_get_displayed_user_nav_'.$nav['slug'], 'imath_hide_or_show_user_nav', 9, 2);
        }  
      }

      function imath_hide_or_show_user_nav($li, $user_nav_item){
        global $bp;
        if($bp->current_component == $user_nav_item['slug']){
          return $li;
        }
        else return false;
      }

      Bonne nuit 😉

  5. Avatar de Mecanographik

    J’ai implémenté ta dernière proposition dans functions.php, mais sans succès ! Merci pour le coup de pouce car tu m’as permis de trouver une solution allant dans ton sens, et plus simple encore grâce à la fonction bp_core_remove_nav_item, la voici :

    http://chopapp.com/#bvueknrg

    Merci pour ton aide en tout cas, il me reste un petit problème que tu as évoqué précédemment, le slug « évènements » n’est pas identifié donc appraît dans le menu du profil(cas des plugins qui ajoutent des menus). La solution serait peut-être de déclarer ce slug dans bp-custom.php, je regarde cela de plus près…
    Voici le résultat actuel :
    http://i1081.photobucket.com/albums/j360/mecanographik/profile-tabs-v2.png

  6. Avatar de Mecanographik

    Je suis finalement parvenu à mes fins en reprenant mon dernier exemple et en réutilisant ta fonction imath_hide_or_show_user_nav
    Le défaut de ma fonction est que je dois gérer un cas d’exception pour l’item nommé « Evènements » qui a comme slug « events »… mais ça marche 😉
    Voici le code complet sur CHO :

    http://chopapp.com/#913z34bd

    1. Avatar de imath

      Hello @Mecanographik,

      Merci pour le code joint à ton commentaire 🙂 Content que tu es réussi à trouver la solution.

      A+