Как изменить заголовок темы для поддержки нескольких навигационных меню?


Я постараюсь быть кратким....

У меня есть тема, которая поддерживает только одно навигационное меню. На этом этапе я хотел бы добавить еще 2 или 3 меню. Я успешно зарегистрировал свои меню в functions.php с помощью register_nav_menus и я могу переключать header.php код вручную между моими различными меню.

Моя проблема... Поскольку моя тема использует один заголовок (header.php ) Я не могу назначить своим страницам или публикациям нужное мне навигационное меню, не изменив все остальные меню навигации по страницам.

Может ли кто-нибудь помочь мне в этом? Заранее спасибо. Грег

Author: user27251, 2013-02-09

1 answers

Во-первых, некоторые вещи, которые вы должны знать о навигационных меню:

  1. Меню - это просто термины в таксономии, называемой nav_menu.
  2. Пункты меню - это особый тип записи

Короче говоря: меню похожи почти на любой другой контент в WordPress, у них просто есть пользовательский интерфейс.

С учетом этого задача довольно проста: поместите пользовательское мета-поле на экран редактирования, в котором отображаются параметры выбора навигационных меню. На передней панели переключите навигатор выберите в меню все, что вы установили в административной области. Единственное, о чем стоит беспокоиться, - это значение theme_location для вызова вашей темы wp_nav_menu. Где вы хотите отключить меню?

В этом примере будет использоваться Twenty Twelve, в котором используется расположение темы primary.

Призыв завершить все в:

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

Теперь давайте добавим наш мета-блок. Поскольку это подробно описано во многих местах, я дам объяснение в примечаниях к утесу: подключитесь к add_meta_boxes, позвоните add_meta_box. В функции обратного вызова мета-поля выведите значение nonce и ваши поля.

Чтобы сохранить значения, подключитесь к save_post, убедитесь, что мы находимся там, где хотим быть (нет автоматического сохранения, не проверяется), и что текущий пользователь может редактировать сообщение, сохранять (или удалять) значение с помощью (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);
    }
}

Обратите внимание на вспомогательный метод получения навигационных меню. Не так много, просто удобный помощник, который пропускает результат через фильтр.

Наконец, нам просто нужно отключить меню. Чтобы сделать это, подключитесь к wp_nav_menu_args и, если мы находимся на отдельной странице и у нас правильное расположение темы, соответствующим образом переключите меню. Некоторые дополнительные фильтры включены, чтобы сделать это немного более расширяемым.

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

Все вышеперечисленное в качестве плагина.

 1
Author: chrisguitarguy, 2013-02-10 05:52:09