web-dev-qa-db-fra.com

Comment changer l'en-tête de thème pour prendre en charge plusieurs menus de navigation?

Je vais essayer d'être bref ....

J'ai un thème qui ne prend en charge qu'un seul menu de navigation. À ce stade, j'aimerais ajouter 2 ou 3 menus supplémentaires. J'ai enregistré avec succès mes menus dans functions.php avec register_nav_menus et je peux permuter manuellement le code header.php entre mes différents menus.

Mon problème ... Étant donné que mon thème utilise un seul en-tête (header.php), je ne peux pas attribuer mes pages ni publier le menu de navigation de mon choix sans modifier tous les menus de navigation des autres pages.

Quelqu'un peut-il m'aider à ce sujet? Merci d'avance. Greg

1
user27251

Tout d'abord, certaines choses que vous devez savoir sur les menus de navigation:

  1. Les menus sont simplement des termes dans une taxonomie appelée nav_menu.
  2. Les éléments de menu sont un type de message spécial

En bref: les menus sont comme presque tous les autres contenus de WordPress, ils ont juste une interface utilisateur personnalisée.

Cela étant fait, la tâche est assez simple: placez une méta-boîte personnalisée sur votre écran d'édition, qui indique les options permettant de choisir les menus de navigation. Au début, réglez le menu de navigation sur ce que vous avez défini dans la zone d'administration. La seule chose à considérer est la valeur de theme_location pour l'appel de votre thème à wp_nav_menu. Où voulez-vous changer le menu?

Cet exemple utilisera Twenty Twelve, qui utilise l'emplacement du thème primary.

Un appel à tout emballer dans:

<?php
class PerPostNavMenu
{
    const NONCE = 'wpse85243_nav_nonce';
    const FIELD = '_wpse85243_per_post_menu';
    const LOC   = 'primary'; // the location for twenty twelve

    private static $ins = null;

    public static function instance()
    {
        if (is_null(self::$ins)) {
            self::$ins = new self;
        }

        return self::$ins;
    }

    public static function init()
    {
        add_action('plugins_loaded', array(self::instance(), '_setup'));
    }

    public function _setup()
    {
        // we'll add actions/filters here later
    }
}

Ajoutons maintenant notre meta box. Comme cela est couvert en détail dans de nombreux endroits, je vais donner l'explication des notes de falaise: accrocher dans add_meta_boxes, appeler add_meta_box . Dans la fonction de rappel de la boîte à méta, éditez un nonce et votre (vos) champ (s).

Pour enregistrer les valeurs, connectez-vous à save_post, vérifiez que nous sommes exactement où nous voulons être (pas de sauvegarde automatique, nonce valide) et que l’utilisateur actuel peut éditer la publication, enregistrer (ou supprimer) la valeur avec (update|delete)_post_meta.

<?php
class PerPostNavMenu
{
    const NONCE = 'wpse85243_nav_nonce';
    const FIELD = '_wpse85243_per_post_menu';
    const LOC   = 'primary'; // the location for twenty twelve

    // snip snip

    public function _setup()
    {
        add_action('add_meta_boxes', array($this, 'addBox'));
        add_action('save_post', array($this, 'save'), 10, 2);
    }

    public function addBox($post_type)
    {
        if (!post_type_exists($post_type)) {
            return;
        }

        add_meta_box(
            'wpse85243_nav_menu',
            __('Nav Menu', 'wpse'),
            array($this, 'boxCallback'),
            $post_type,
            'side',
            'low'
        );
    }

    public function boxCallback($post)
    {
        $menu = get_post_meta($post->ID, static::FIELD, true);

        wp_nonce_field(static::NONCE . $post->ID, static::NONCE, false);

        printf(
            '<label for="%s">%s</label>',
            esc_attr(static::FIELD),
            esc_html__('Nav Menu', 'wpse')
        );

        echo '<br />';

        printf('<select name="%1$s" id="%1$s">', esc_attr(static::FIELD));

        foreach ($this->getNavMenus() as $id => $name) {
            printf(
                '<option value="%s" %s>%s</option>',
                esc_attr($id),
                selected($menu, $id, false),
                esc_html($name)
            );
        }

        echo '</select>';
    }

    public function save($post_id, $post)
    {
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }

        if (
            !isset($_POST[static::NONCE]) ||
            !wp_verify_nonce($_POST[static::NONCE], static::NONCE . $post_id)
        ) {
            return;
        }

        $type = get_post_type_object($post->post_type);
        if (!current_user_can($type->cap->edit_post, $post_id)) {
            return;
        }

        $menu = isset($_POST[static::FIELD]) ? $_POST[static::FIELD] : false;

        if ($menu && '-' !== $menu) {
            update_post_meta($post_id, static::FIELD, absint($menu));
        } else {
            delete_post_meta($post_id, static::FIELD);
        }
    }

    private function getNavMenus()
    {
        $terms = get_terms('nav_menu');

        $menus = array('-' => __('Default', 'wpse'));
        if ($terms && !is_wp_error($terms)) {
            foreach($terms as $t) {
                $menus[$t->term_id] = $t->name;
            }
        }

        return apply_filters('per_post_nav_menus_list', $menus);
    }
}

Notez la méthode d'assistance pour récupérer les menus de navigation. Pas grand chose, juste un assistant pratique qui analyse le résultat à travers un filtre.

Enfin, il nous suffit de changer le menu. Pour ce faire, connectez-vous à wp_nav_menu_args et, si vous êtes sur une page singulière et que vous avez l'emplacement du thème correct, modifiez le menu selon le cas. Certains filtres supplémentaires sont inclus pour rendre cela un peu plus extensible.

<?php
class PerPostNavMenu
{
    const NONCE = 'wpse85243_nav_nonce';
    const FIELD = '_wpse85243_per_post_menu';
    const LOC   = 'primary'; // the location for twenty twelve

    // snip snip

    public function _setup()
    {
        add_action('add_meta_boxes', array($this, 'addBox'));
        add_action('save_post', array($this, 'save'), 10, 2);
        add_filter('wp_nav_menu_args', array($this, 'switchMenu'));
    }

    // snip snip

    public function switchMenu($args)
    {
        // we can only deal with singular pages
        if (!is_singular()) {
            return;
        }

        $switch = apply_filters(
            'per_post_nav_menus_switch',
            isset($args['theme_location']) && static::LOC === $args['theme_location'],
            $args
        );

        // if we're allowed to switch, the the `menu` argument to
        // the correct menu ID.
        if ($switch) {
            $menu = get_post_meta(get_queried_object_id(), static::FIELD, true);

            if ('-' !== $menu) {
                $args['menu'] = absint($menu);
            }
        }

        return $args;
    }

    // snip snip
}

Tout ce qui précède est un plugin .

1
chrisguitarguy