WordPress. Theme Customize API. Часть 12

24.04.2019

Теги: APICMSWeb-разработкаWordPressНастройка

В WordPress доступны два элемента управления, которые позволяют выбрать значение из множества допустимых — это select (выпадающий список) и radio (группа переключателей). Но нет элемента управления, который позволил бы выбрать несколько значений. Давайте исправим это упущение и создадим такой элемент управления.

Для этого создаем в директории customize файл My_Multiple_Checkbox_Control.php и добавляем в него код:

<?php
class My_Multiple_Checkbox_Control extends WP_Customize_Control {

    public $type = 'checkbox-multiple';

    public function enqueue() {
        wp_enqueue_script(
            'theme-customize-control', // будет зарегистрирован под этим именем
            get_template_directory_uri() . '/customize/customize-control.js',
            ['jquery', 'customize-controls'], // должен быть подключен после этих скриптов
            null, // версии нет, поэтому null
            true // подключаем перед закрывающим тегом body
        );
    }

    protected function render_content() {
        if (empty($this->choices)) return;

        $input_id = '_customize-input-' . $this->id;
        $description_id = '_customize-description-' . $this->id;
        ?>

        <?php if (!empty($this->label)): ?>
            <label for="<?php echo esc_attr($input_id); ?>"
                   class="customize-control-title">
                <?= esc_html($this->label); ?>
            </label>
        <?php endif; ?>
        <?php if (!empty($this->description)) : ?>
            <span id="<?php echo esc_attr($description_id); ?>"
                  class="description customize-control-description">
                <?= $this->description; ?>
            </span>
        <?php endif; ?>

        <?php
        $values = !is_array($this->value()) ? explode(',', $this->value()) : $this->value();
        ?>
        <ul>
            <?php foreach ($this->choices as $value => $label) : ?>
                <li>
                    <label>
                        <input type="checkbox"
                               value="<?= esc_attr($value); ?>"
                               <?php checked(in_array($value, $values)); ?> />
                        <?= esc_html($label); ?>
                    </label>
                </li>
            <?php endforeach; ?>
        </ul>

        <input type="hidden" <?php $this->link(); ?>
               value="<?= esc_attr(implode(',', $values)); ?>" />
        <?php
    }
}

Это позволит создать несколько checkbox-ов, а отмеченные значения будем записывать в hidden элемент через запятую. И это будет делать js-код, который мы подключаем к странице в методе enqueue(). Как нетрудно догадаться, этот код будет выполняться контексте панели настройщика.

Создадим в директории customize файл customize-control.js и добавим в него код:

jQuery(document).ready(function($) {
    $('.customize-control-checkbox-multiple input[type="checkbox"]').on(
        'change',
        function() {
            var values = $(this).parents('.customize-control' )
                                .find('input[type="checkbox"]:checked')
                                .map(function() {
                                    return this.value;
                                })
                                .get()
                                .join(',');

            $(this).parents('.customize-control')
                   .find('input[type="hidden"]' )
                   .val(values)
                   .trigger('change');
        }
    );
});

Теперь все готово к тестированию. Удалим весь код из файла customize.php в директории customize и добавим новый. Тем самым создадим настройку favorite_colors, которая позволит выбрать несколько цветов из предлагаемых вариантов:

<?php
add_action(
    'customize_register',
    function($customizer) { // $customizer — объект класса WP_Customize_Manager

        require_once __DIR__ . '/My_Multiple_Checkbox_Control.php';

        /*
         * Добавляем настройку «Выберите любимые цвета»
         */
        $customizer->add_setting(
            'setting_favorite_colors', // идентификатор настройки
            [
                // значение по умолчанию
                'default'   => ['red', 'blue'],
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно предпросмотра
                'transport' => 'refresh',
            ]
        );
        $customizer->add_control(
            new My_Multiple_Checkbox_Control(
                $customizer,
                'control_favorite_colors', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'    => 'Выберите любимые цвета',
                    // идентификатор секции
                    'section'  => 'static_front_page',
                    // идентификатор настройки
                    'settings' => 'setting_favorite_colors',
                    'choices'  => [
                        'red'    => 'Красный',
                        'green'  => 'Зеленый',
                        'blue'   => 'Синий',
                        'yellow' => 'Желтый'
                    ],
                    // порядок сортировки
                    'priority' => 120,
                ]
            )
        );
    }
);

И вот что получилось в итоге:

Хорошо, теперь вернемся к фильтрации последних записей на главной странице. Если раньше можно было выбрать только одну категорию или метку, то теперь можно будет выбрать несколько:

<?php
add_action(
    'customize_register',
    function($customizer) { // $customizer — объект класса WP_Customize_Manager

        require_once __DIR__ . '/My_Multiple_Checkbox_Control.php';

        /*
         * Добавляем настройку «Фильтровать последние записи»
         */
        $customizer->add_setting(
            'setting_filter_last_posts', // идентификатор настройки
            [
                // значение по умолчанию
                'default'           => 0,
                // настройка только для темы
                'type'              => 'theme_mod',
                // как обновлять окно предпросмотра
                'transport'         => 'refresh',
                // функция очистки данных
                'sanitize_callback' => 'absint',
            ]
        );
        $customizer->add_control(
            'control_filter_last_posts', // идентификатор элемента управления
            [
                // label элемента формы
                'label'    => 'Фильтровать записи',
                // идентификатор секции
                'section'  => 'static_front_page',
                // идентификатор настройки
                'settings' => 'setting_filter_last_posts',
                // порядок сортировки
                'priority' => 100,
                // тип элемента формы
                'type'     => 'radio',
                // значения radio-кнопок
                'choices'  => [
                    0 => 'Не фильтровать',
                    1 => 'Только записи выбранных категорий',
                    2 => 'Только записи с выбранными тегами',
                ],
            ]
        );

        /*
         * Добавляем настройку «Записи выбранных категорий»
         */
        $customizer->add_setting(
            'setting_filter_ctgs_front', // идентификатор настройки
            [
                // значение по умолчанию
                'default'   => [],
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно предпросмотра
                'transport' => 'refresh',
            ]
        );
        // получаем список категорий
        $choices = [];
        $categories = get_categories();
        foreach ($categories as $category) {
            $choices[$category->term_id] = $category->name;
        }
        $customizer->add_control(
            new My_Multiple_Checkbox_Control(
                $customizer,
                'control_filter_ctgs_front', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'    => 'Записи выбранных категорий',
                    // идентификатор секции
                    'section'  => 'static_front_page',
                    // идентификатор настройки
                    'settings' => 'setting_filter_ctgs_front',
                    // когда показывать этот элемент управления
                    'active_callback' => function ($control) {
                        $value = $control->manager->get_setting('setting_filter_last_posts')->value();
                        if (1 == $value) {
                            return true;
                        }
                        return false;
                    },
                    'choices'  => $choices,
                    // порядок сортировки
                    'priority' => 120,
                ]
            )
        );

        /*
         * Добавляем настройку «Записи с выбранным тегом»
         */
        $customizer->add_setting(
            'setting_filter_tags_front', // идентификатор настройки
            [
                // значение по умолчанию
                'default'   => [],
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно предпросмотра
                'transport' => 'refresh',
            ]
        );
        // получаем список меток
        $choices = [];
        $tags = get_tags();
        foreach ($tags as $tag) {
            $choices[$tag->term_id] = $tag->name;
        }
        $customizer->add_control(
            new My_Multiple_Checkbox_Control(
                $customizer,
                'control_filter_tags_front', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'    => 'Записи с выбранным тегом',
                    // идентификатор секции
                    'section'  => 'static_front_page',
                    // идентификатор настройки
                    'settings' => 'setting_filter_tags_front',
                    // когда показывать этот элемент управления
                    'active_callback' => function ($control) {
                        $value = $control->manager->get_setting('setting_filter_last_posts')->value();
                        if (2 == $value) {
                            return true;
                        }
                        return false;
                    },
                    'choices'  => $choices,
                    // порядок сортировки
                    'priority' => 120,
                ]
            )
        );
    }
);

Теперь добавим фильтрацию последних записей блога. Для этого удаляем старый код фильтрации из functions.php и добавляем новый:

/*
 * На странице последних записей показываем только посты выбранных
 * категорий или посты с выбранными тегами.
 */
if (get_theme_mod('setting_filter_last_posts', 0)) {
    add_action(
        'pre_get_posts',
        function ($query) {
            if ($query->is_main_query() && $query->is_home) {
                $filter = get_theme_mod('setting_filter_last_posts', 0);
                if (1 == $filter) {
                    $cats = get_theme_mod('setting_filter_ctgs_front', '');
                    if (!empty($cats)) {
                        $query->set('category__in', explode(',', $cats));
                    }
                } elseif (2 == $filter) {
                    $tags = get_theme_mod('setting_filter_tags_front', '');
                    if (!empty($tags)) {
                        $query->set('tag__in', explode(',', $tags));
                    }
                }
            }
        }
    );
}

И вот что получилось в итоге:

Поиск: API • CMS • Web-разработка • WordPress • Настройка • Элемент управления • Секция • Control • Section • Setting • Theme Customize • Multiple Checkbox

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.