WordPress. Theme Customize API. Часть 9
17.04.2019
Теги: API • CMS • Web-разработка • WordPress • Настройка
Разработчики WordPress рекомендуют не доверять пользовательским данным и для каждой настройки задавать функции обратного вызова, чтобы проверить и «дезинфицировать» полученные данные. Эти функции указываются в параметрах validate_callback
и sanitize_callback
метода add_setting()
.
Давайте создадим настройку «Дата начала публикаций», которая позволяет задать год начала публикаций в блоге, чтобы правильно выводить copyright:
<footer> <div class="container"> <div id="copyright"> © 2015 — 2019 Все права защищены </div> </div> </footer>
И зададим для этой настройки функции проверки и «дезинфекции» введенных данных. Чтобы не создавать новую секцию настроек, разместим ее в уже существующей секции «Настройки главной страницы»:
<?php add_action( 'customize_register', function($customizer) { // $customizer — объект класса WP_Customize_Manager // Добавляем настройку «Дата начала публикаций» $customizer->add_setting( 'setting_copyright_start', // идентифкатор настройки [ // значение по умолчанию 'default' => date('Y'), // настройка только для темы 'type' => 'theme_mod', // как обновлять окно предпросмотра (refresh или postMessage) 'transport' => 'refresh', // функция очистки данных 'sanitize_callback' => 'absint', // функция проверки данных 'validate_callback' => function($validity, $value) { $value = intval($value); if (empty($value) || !is_numeric($value)) { $validity->add('required', 'Поле обязательно для заполнения'); } elseif ($value < 1900) { $validity->add('year_too_small', 'Значение слишком маленькое' ); } elseif ($value > date('Y')) { $validity->add('year_too_big', 'Значение слишком большое'); } return $validity; } ] ); $customizer->add_control( 'control_copyright_start', // идентификатор элемента управления [ 'label' => 'Дата начала публикаций', // label элемента формы 'section' => 'static_front_page', // идентификатор секции 'settings' => 'setting_copyright_start', // идентификатор настройки 'priority' => 100, // порядок сортировки ] ); );
<footer> <div class="container"> <div id="copyright"> © <?php $start = get_theme_mod('setting_copyright_start', date('Y')); ?> <?php if ($start != date('Y')): ?> <?= $start; ?> — <?php endif; ?> <?= date('Y'); ?> Все права защищены </div> </div> </footer> <?php wp_footer(); ?> </body> </html>
И вот что получилось в итоге:
Хорошо, теперь изменим параметр transport
на postMessage
. В этом случае возможны два варианта. Если мы задаем выборочное обновление (selective refresh) для нашей настройки — сообщения об ошибках будут переданы на сторону клиента и показаны пользователю без нашего участия. В противном случае, мы должны сами написать js-код, который будет выводить в окне просмотра значение настройки. И сами написать js-код, который будет показывать сообщения об ошибках.
Итак, первый вариант — используем selective refresh:
add_action( 'customize_register', function($customizer) { // $customizer — объект класса WP_Customize_Manager // Добавляем настройку «Дата начала публикаций» $customizer->add_setting( 'setting_copyright_start', // идентифкатор настройки [ // значение по умолчанию 'default' => date('Y'), // значение по умолчанию 'type' => 'theme_mod', // настройка только для темы // как обновлять окно предпросмотра (refresh или postMessage) 'transport' => 'postMessage', // функция очистки данных 'sanitize_callback' => 'absint', // функция проверки данных 'validate_callback' => function($validity, $value) { $value = intval($value); if (empty($value) || !is_numeric($value)) { $validity->add('required', 'Поле обязательно для заполнения'); } elseif ($value < 1900) { $validity->add('year_too_small', 'Значение слишком маленькое' ); } elseif ($value > date('Y')) { $validity->add('year_too_big', 'Значение слишком большое'); } return $validity; } ] ); $customizer->add_control( 'control_copyright_start', // идентификатор элемента управления [ 'label' => 'Дата начала публикаций', // label элемента формы 'section' => 'static_front_page', // идентификатор секции 'settings' => 'setting_copyright_start', // идентификатор настройки 'priority' => 100, // порядок сортировки ] ); // используем selective refresh для обновления окна просмотра $customizer->selective_refresh->add_partial( 'setting_copyright_start', // идентификатор настройки [ // CSS-селектор контейнера, который будет обновляться 'selector' => '#copyright > span', // функция генерирует контент для контейнера #copyright > span 'render_callback' => function() { $start = get_theme_mod('setting_copyright_start', date('Y')); if ($start != date('Y')) { echo $start, ' —'; } } ] ); } );
<footer> <div class="container"> <div id="copyright"> © <?php $start = get_theme_mod('setting_copyright_start', date('Y')); ?> <?php if ($start != date('Y')): ?> <span><?= $start; ?> —</span> <?php endif; ?> <?= date('Y'); ?> Все права защищены </div> </div> </footer> <?php wp_footer(); ?> </body> </html>
Второй вариант — не используем selective refresh. Нам нужно подключить js-файл, который будет обеспечивать обновление окна просмотра. И еще один js-файл — для проверки данных и вывода сообщений об ошибках. Первый файл мы уже создали ранее, это customize.js
в директории customize
. А вот второй надо создать и подключить.
Здесь надо понимать, что первый файл выполняется в контексте окна просмотра, а второй — контексте панели настройщика. Соответственно, подключение первого вешаем на событие customize_preview_init
, а второй — на событие customize_controls_enqueue_scripts
.
add_action( 'customize_register', function($customizer) { // $customizer — объект класса WP_Customize_Manager // Добавляем настройку «Дата начала публикаций» $customizer->add_setting( 'setting_copyright_start', // идентифкатор настройки [ // значение по умолчанию 'default' => date('Y'), // значение по умолчанию 'type' => 'theme_mod', // настройка только для темы // как обновлять окно предпросмотра (refresh или postMessage) 'transport' => 'postMessage', // функция очистки данных 'sanitize_callback' => 'absint', // функция проверки данных 'validate_callback' => function($validity, $value) { $value = intval($value); if (empty($value) || !is_numeric($value)) { $validity->add('required', 'Поле обязательно для заполнения'); } elseif ($value < 1900) { $validity->add('year_too_small', 'Значение слишком маленькое'); } elseif ($value > date('Y')) { $validity->add('year_too_big', 'Значение слишком большое'); } return $validity; } ] ); $customizer->add_control( 'control_copyright_start', // идентификатор элемента управления [ 'label' => 'Дата начала публикаций', // label элемента формы 'section' => 'static_front_page', // идентификатор секции 'settings' => 'setting_copyright_start', // идентификатор настройки 'priority' => 100, // порядок сортировки ] ); } ); /* * Подключаем 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 ); } ); /* * Подключаем JS-файл скрипта, который обеспечивает проверку введенных * пользователем данных и показывает сообщения об ошибках */ add_action( 'customize_controls_enqueue_scripts', function() { wp_enqueue_script( 'theme-settings-validate', // будет зарегистрирован под этим именем get_template_directory_uri() . '/customizer/validator.js', array('customize-controls'), // должен быть подключен после этих скриптов null, // версии нет, поэтому null true // подключаем перед закрывающим тегом body ); } );
Теперь создаем файл validator.js
в директории customize
и добавляем в него js-код проверки данных:
wp.customize('setting_copyright_start', function (setting) { setting.validate = function (value) { var code, notification; var year = parseInt(value, 10); code = 'required'; if (isNaN(year)) { notification = new wp.customize.Notification( code, {message: 'Поле обязательно для заполнения'} ); setting.notifications.add(code, notification); } else { setting.notifications.remove(code); } // если это не число, дальше проверять нет смысла if (isNaN(year)) { return value; } code = 'year_too_small'; if (year < 1900) { notification = new wp.customize.Notification( code, {message: 'Значение слишком маленькое'} ); setting.notifications.add(code, notification); } else { setting.notifications.remove(code); } code = 'year_too_big'; if (year > new Date().getFullYear()) { notification = new wp.customize.Notification( code, {message: 'Значение слишком большое'} ); setting.notifications.add(code, notification); } else { setting.notifications.remove(code); } return value; }; });
Добавляем в файл customize.js
js-код обновления окна просмотра:
(function(api, $) { api('setting_copyright_start', function(setting) { // обновляем окно просмотра setting.bind(function(value) { if (new Date().getFullYear() != value) { $('#copyright > span').text(value + ' —'); } else { $('#copyright > span').text(''); } }); }); })(wp.customize, jQuery);
Шаблон footer.php
, где выводится наша настройка:
<footer> <div class="container"> <div id="copyright"> © <?php $start = get_theme_mod('setting_copyright_start', date('Y')); ?> <?php if ($start != date('Y')): ?> <span><?= $start; ?> —</span> <?php endif; ?> <?= date('Y'); ?> Все права защищены </div> </div> </footer> <?php wp_footer(); ?> </body> </html>
Дополнительно
- The WordPress Customizer – A Developers Guide (Part 1)
- The WordPress Customizer – A Developers Guide (Part 2)
- Using the WordPress Theme Customizer Media Controls
- WordPress customizer sanitization examples
- WordPress. API настроек (опций). Часть 4 из 4
- WordPress. API настроек (опций). Часть 3 из 4
- WordPress. API настроек (опций). Часть 2 из 4
- WordPress. API настроек (опций). Часть 1 из 4
- WordPress. Theme Customize API. Часть 12
- WordPress. Theme Customize API. Часть 11
- WordPress. Theme Customize API. Часть 8
Поиск: API • CMS • Web-разработка • WordPress • Настройка • Элемент управления • Секция • Control • Section • Setting • Theme Customize • Sanitize • Validate