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

12.04.2019

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

Мы уже умеем добавлять секцию, настройку и элемент управления. Но еще не успели познакомиться с панелью. Панель объединяет несколько секций. И таким образом, создает еще один уровень вложенности настроек. При клике по панели происходит переход к списку секций внутри этой панели. При клике по секции мы переходим к настройкам этой секции.

Давайте создадим панель «Настройки шапки и подвала», добавим в нее две секции «Настройки шапки» и «Настройки подвала», в каждой секции разместим по две настройки:

  • Настройки шапки
    • Проигрыватель музыки
    • Фоновое изображение
  • Настройки подвала
    • Текст copyright
    • Фоновое изображение

И начнем с чистого листа. Удалим весь код из файлов customize.php и customize.js. После чего добавляем в customize.php код, отвечающий за создание панели и двух секций:

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

        /*
         * 1. Добавляем панель «Настройки шапки и подвала»
         * 2. Добавляем секцию «Настройки шапки» внутрь панели
         *    2.1. Добавляем настройку «Фоновая музыка»
         *    2.2. Добавляем элемент управления «Фоновая музыка»
         *    2.3. Добавляем настройку «Фоновое изображение»
         *    2.4. Добавляем элемент управления «Фоновое изображение»
         * 3. Добавляем секцию «Настройки подвала» внутрь панели
         *    3.1. Добавляем настройку «Текст copyright»
         *    3.2. Добавляем элемент управления «Текст copyright»
         *    3.3. Добавляем настройку «Фоновое изображение»
         *    3.4. Добавляем элемент управления «Фоновое изображение»
         */

        /*
         * 1. Добавляем панель «Настройки шапки и подвала»
         */
        $customizer->add_panel(
            'panel_header_footer',
            array(
                'title'       => 'Шапка и подвал', // заголовок панели
                'description' => 'Позволяет задать текст, цвет и фон для шапки и подвала',
                'priority'    => 10, // порядок сортировки
            )
        );

        /*
         * Добавляем в панель две секции «Настройки шапки» и «Настройки подвала»
         */

        // 2. Добавляем секцию «Настройки шапки» в панель «Настройки шапки и подвала»
        $customizer->add_section(
            'section_header', // идентификатор секции
            array(
                'title'    => 'Настройки шапки', // заголовок секции
                'panel'    => 'panel_header_footer', // идентифкатор панели
                'priority' => 10, // порядок сортировки
            )
        );

        // 3. Добавляем секцию «Настройки подвала» в панель «Настройки шапки и подвала»
        $customizer->add_section(
            'section_footer', // идентификатор секции
            array(
                'title'    => 'Настройки подвала', // заголовок секции
                'panel'    => 'panel_header_footer', // идентифкатор панели
                'priority' => 20, // порядок сортировки
            )
        );
    }
);

Добавляем настройки и элементы управления для секции «Настройки шапки»:

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

        /*..........*/

        /*
         * Добавляем настройки и элементы управления для секции «Настройки шапки»
         */

        // 2.1. Добавляем настройку «Фоновая музыка»
        $customizer->add_setting(
            'setting_header_background_sound',
            array(
                // значение по умолчанию
                'default'   => '',
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно просмотра
                'transport' => 'postMessage',
            )
        );

        // 2.2. Добавляем элемент управления «Фоновая музыка»
        $customizer->add_control(
            new WP_Customize_Media_Control(
                $customizer,
                'control_header_background_sound', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'       => 'Фоновая музыка',
                    // описание элемента формы
                    'description' => 'Загрузите аудио-файл для проигрывателя',
                    // идентификатор секции
                    'section'     => 'section_header',
                    // идентификатор настройки
                    'settings'    => 'setting_header_background_sound',
                    // только аудио-айлы
                    'mime_type'   => 'audio',
                    // порядок сортировки
                    'priority'    => 10,
                ]
            )
        );

        // 2.3. Добавляем настройку «Фоновое изображение шапки»
        $customizer->add_setting(
            'setting_header_background_image',
            array(
                // значение по умолчанию
                'default'   => '',
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно просмотра
                'transport' => 'postMessage',
            )
        );

        // 2.4. Добавляем элемент управления «Фоновое изображение шапки»
        $customizer->add_control(
            new WP_Customize_Cropped_Image_Control(
                $customizer,
                'control_header_background_image', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'       => 'Фоновое изображение',
                    // описание элемента формы
                    'description' => 'Загрузите фоновое изображение для шапки',
                    // идентификатор секции
                    'section'     => 'section_header',
                    // идентификатор настройки
                    'settings'    => 'setting_header_background_image',
                    // сохраняем заданные пропорции изображения (1200:300)
                    'flex_width'  => false,
                    'flex_height' => false,
                    // значение ширины по умолчанию
                    'width'       => 1200,
                    // значение высоты по умолчанию
                    'height'      => 300,
                    // порядок сортировки
                    'priority'    => 20,
                ]
            )
        );
    }
);

Добавляем настройки и элементы управления для секции «Настройки подвала»:

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

        /*..........*/

        /*
         * Добавляем настройки и элементы управления для секции «Настройки подвала»
         */

        // 3.1. Добавляем настройку «Текст copyright»
        $customizer->add_setting(
            'setting_footer_copyright_text', // идентифкатор настройки
            [
                'default'   => '© Copyright. All rights reserved', // значение по умолчанию
                'type'      => 'theme_mod', // настройка только для темы
                'transport' => 'postMessage', // как обновлять окно просмотра
            ]
        );

        // 3.2. Добавляем элемент управления «Текст copyright»
        $customizer->add_control(
            'control_footer_copyright_text', // идентификатор элемента управления
            [
                'label'       => 'Текст copyright', // label элемента формы
                'description' => 'Добавьте текст copyright, поле поддерживает HTML теги',
                'section'     => 'section_footer', // идентификатор секции
                'settings'    => 'setting_footer_copyright_text', // идентификатор настройки
                'priority'    => 10, // порядок сортировки
                'type'        => 'text', // тип элемента формы
            ]
        );

        // 3.3. Добавляем настройку «Фоновое изображение подвала»
        $customizer->add_setting(
            'setting_footer_background_image',
            array(
                // значение по умолчанию
                'default'   => '',
                // настройка только для темы
                'type'      => 'theme_mod',
                // как обновлять окно просмотра
                'transport' => 'postMessage',
            )
        );

        // 3.4. Добавляем элемент управления «Фоновое изображение подвала»
        $customizer->add_control(
            new WP_Customize_Cropped_Image_Control(
                $customizer,
                'control_footer_background_image', // идентификатор элемента управления
                [
                    // label элемента формы
                    'label'       => 'Фоновое изображение',
                    // описание элемента формы
                    'description' => 'Загрузите фоновое изображение для подвала',
                    // идентификатор секции
                    'section'     => 'section_footer',
                    // идентификатор настройки
                    'settings'    => 'setting_footer_background_image',
                    // сохраняем заданные пропорции изображения (1200:300)
                    'flex_width'  => false,
                    'flex_height' => false,
                    // значение ширины по умолчанию
                    'width'       => 1200,
                    // значение высоты по умолчанию
                    'height'      => 300,
                    // порядок сортировки
                    'priority'    => 20,
                ]
            )
        );
    }
);

Добавляем код, который подключает к странице файл customize.js:

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

/*
 * Подключаем JS-файл скрипта, который обеспечивает предварительный
 * просмотр изменений настроек темы без перезагрузки окна просмотра
 */
add_action(
    'customize_preview_init',
    function() {
        wp_enqueue_script(
            'theme-settings-preview', // будет зарегистрирован под этим именем
            get_template_directory_uri() . '/customize/customize.js',
            array('jquery', 'customize-preview'), // должен быть подключен после этих скриптов
            null, // версии нет, поэтому null
            true // подключаем перед закрывающим тегом body
        );
    }
);

Добавляем в customize.js js-код, отвечающий за обновление окна просмотра с использованием ajax:

(function($) {
    // изменяем аудио-файл для проигрывателя в шапке
    wp.customize('setting_header_background_sound', function(value) {
        value.bind(function(to) {
            if ('' == to) {
                // скрываем элемент audio, если не выбран audio-файл
                $('header audio').attr('src', '').hide();
                return;
            }
            // выполняем ajax-запрос, чтобы по идентификатору файла
            // получить URL и установить src для элемента audio
            var data = {
                action: 'get_attachment_url',
                id: to
            };
            $.post(
                ajax_handler.url,
                data,
                function(response) {
                    if (response != 'none') {
                        $('header audio').attr('src', response).show();
                    } else {
                        $('header audio').attr('src', '').hide();
                    }
                }
            );
        });
    });
    // изменяем фоновое изображение для шапки
    wp.customize('setting_header_background_image', function(value) {
        value.bind(function(to) {
            if ('' == to) {
                $('header').css('background-image', 'none');
                return;
            }
            // выполняем ajax-запрос, чтобы по идентификатору файла
            // получить URL и установить для header background-image
            var data = {
                action: 'get_attachment_url',
                id: to
            };
            $.post(
                ajax_handler.url,
                data,
                function(response) {
                    if (response != 'none') {
                        $('header').css('background-image', 'url(' + response + ')');
                    } else {
                        $('header').css('background-image', 'none');
                    }
                }
            );
        });
    });
    // изменяем текст copyright-а в подвале
    wp.customize('setting_footer_copyright_text', function(value) {
        value.bind(function(to) {
            $('#copyright').html(to);
        });
    });
    // изменяем фоновое изображение для подвала
    wp.customize('setting_footer_background_image', function(value) {
        value.bind(function(to) {
            if ('' == to) {
                $('header').css('background-image', 'none');
                return;
            }
            // выполняем ajax-запрос, чтобы по идентификатору файла
            // получить URL и установить для footer background-image
            var data = {
                action: 'get_attachment_url',
                id: to
            };
            $.post(
                ajax_handler.url,
                data,
                function(response) {
                    if (response != 'none') {
                        $('footer').css('background-image', 'url(' + response + ')');
                    } else {
                        $('footer').css('background-image', 'none');
                    }
                }
            );
        });
    });
})(jQuery);

Здесь для получения URL загруженного файла по его идентификатору, выполняется ajax-запрос. В административной части сайта в js-скриптах доступна глобальная переменная ajaxurl. Но здесь нам нужно самим задать глобальную перменную, которая будет содержать URL для отправки ajax-запросов. Для этого добавляем в customize.php вызов функции wp_localize_script() и создаем анонимную функцию, которую вешаем на хук wp_ajax_get_attachment_url:

add_action(
    'customize_register',
    function($customizer) { // $customizer — объект класса WP_Customize_Manager
        /*..........*/
    }
);

/*
 * Подключаем JS-файл скрипта, который обеспечивает предварительный
 * просмотр изменений настроек темы без перезагрузки окна просмотра
 */
add_action(
    'customize_preview_init',
    function() {
        /*
         * Скрипт обеспечивает предварительный просмотр изменений
         * настроек темы без перезагрузки окна просмотра
         */
        wp_enqueue_script(
            'theme-settings-preview', // будет зарегистрирован под этим именем
            get_template_directory_uri() . '/customize/customize.js',
            array('jquery', 'customize-preview'), // должен быть подключен после этих скриптов
            null, // версии нет, поэтому null
            true // подключаем перед закрывающим тегом body
        );
        /*
         * Определяем глобальную переменную ajax_handler.url, которая
         * нужна, чтобы выполнять ajax-запросы из customize.js
         */
        wp_localize_script(
            'theme-settings-preview',
            'ajax_handler',
            array(
                'url' => admin_url('admin-ajax.php')
            )
        );
    }
);

/*
 * Функция возвращает URL изображения по его идентфикатору
 * в ответ на ajax-запрос из файла customize.js
 */
add_action(
    'wp_ajax_get_attachment_url',
    function() {
        $id = 0;
        if (ctype_digit($_POST['id'])) {
            $id = (int)$_POST['id'];
        }
        echo wp_get_attachment_url($id, 'none');
        wp_die();
    }
);

Вызов функции wp_localize_script() добавит на страницу следующий js-код:

<script type="text/javascript">
var ajax_handler = {"url":"http://www.server.com/wp-admin/admin-ajax.php"};
</script>
Думаю, что есть более простой способ получить URL изображения по его идентификатору, используя объект wp.customize, но пока не разобрался, как это сделать.

Теперь вносим изменения в файлы шаблонов header.php и footer.php:

<body>
<?php
$id = get_theme_mod(
    'setting_header_background_image',
    0
);
$background = '';
if (!empty($id)) {
    $background = wp_get_attachment_url($id);
}
?>
<header<?= !empty($background) ? ' style="background-image: url('.$background.')"' : ''; ?>>
    <div>
        <div class="container">
            <div class="float-left">
                <span id="blogname">
                    <?php bloginfo('name'); ?>
                </span>
                <span id="blogdescription">
                    <?php bloginfo('description'); ?>
                </span>
            </div>
            <div class="float-right">
                <?php
                $sound_id = get_theme_mod('setting_header_background_sound', 0);
                $sound_url = wp_get_attachment_url($sound_id, '');
                ?>
                <?php if (!empty($sound_url)): ?>
                    <audio src="<?= $sound_url; ?>" controls>
                        Ваш браузер не поддерживает audio-элемент.
                    </audio>
                <?php endif; ?>
            </div>
        </div>
    </div>
    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
        <!-- .......... -->
    </nav>
</header>
<?php
$id = get_theme_mod(
    'setting_footer_background_image',
    0
);
$background = '';
if (!empty($id)) {
    $background = wp_get_attachment_url($id);
}
?>
<footer<?= !empty($background) ? ' style="background-image: url('.$background.')"' : ''; ?>>
    <div class="container">
        <div id="copyright">
            <?php
            $copyright = get_theme_mod(
                'setting_footer_copyright_text',
                ''
            );
            echo $copyright;
            ?>
        </div>
    </div>
</footer>

Дополнительно

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

Каталог оборудования
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.