Блог

Theme Customizer: Настройка темы WordPress

перевод 22 июня 2013 Рубрики: Программирование. Метки: theme customizer и wordpress.

В данном руководстве подробно рассказывается о возможностях настройки темы в Вордпрессе с помощью одноименного инструмента — WordPress Theme Customizer.

Специальная страница настройки темы появилась в Вордпрессе 3.4. На этой странице администратор сайта может изменять различные параметры темы и здесь же наблюдать то, как она меняется, не затрагивая работу «живого» сайта. В качестве подопытной темы мы будем использовать тему Responsive 1.9.3.2 Эмиля Узелака.

Добавляем страницу настроек в админку Вордпресса

Для начала мы откроем файл functions.php и добавим в него следующий код. Конкретное место данного кода не так уж и важно — на ваше усмотрение. Главное, чтобы вы смогли его потом легко найти.

/**
 * Добавляет страницу настройки темы в админку Вордпресса
 */
add_action('admin_menu', function(){
    add_theme_page('Настроить', 'Настроить', 'edit_theme_options', 'customize.php');
});

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

В замыкании, которое мы только что добавили в качестве функции обратного вызова для хука admin_menu, содержится вызов всего одной функции add_theme_page(), которая добавляет дополнительные страницы в админку Вордпресса. Эта функция принимает пять аргументов, четыре из которых — обязательные.

Функция: add_theme_page($page_title, $menu_title, $capability, $menu_slug, $function)
$page_title string Заголовок страницы. На странице настройки темы не выводится
$menu_title string Текст нового элемента меню во вкладке «Внешний вид»
$capability string Права, которыми должен обладать пользователь, чтобы попасть на страницу настройки
$menu_slug string Уникальный адрес страницы настройки

Учтите, что если вы создаете свободную тему, а не просто для себя, стоит обратить внимание на перевод $page_title и $menu_title. Почитайте документацию об интернационализации в Вордпрессе.

Теперь вернёмся на главную страницу админки. Здесь, в подменю «Внешний вид», мы увидим элемент меню с текстом «Настроить». Это как раз то, что нам нужно. Заметьте, что на странице настройки темы уже имеются четыре блока параметров, именуемые секциями. Они расположены на серой панели слева. Секции «Название и описание сайта» и «Статическая главная страница» Вордпресс добавил автоматически. А секции «Цвета» и «Фоновое изображение» появились там потому, что наша тема поддерживает возможность настройки фонового изображения сайта. Далее мы научимся добавлять собственные секции с параметрами темы.

Добавляем новую секцию с параметрами

Чтобы создать свою собственную секцию с параметрами темы, поместите данный код в файл functions.php сразу за тем кодом, который написали ранее.

/**
 * Добавляет секции, параметры и элементы управления (контролы) на страницу настройки темы
 */
add_action('customize_register', function($customizer){
    $customizer->add_section(
        'example_section_one',
        array(
            'title' => 'Мои настройки',
            'description' => 'Секция-пример',
            'priority' => 35,
        )
    );
});

Вуаля, секция добавлена. Сейчас вы не увидите ее на экране, поскольку она не содержит ни одного параметра. Такова логика Вордпресса.

Что мы сейчас сделали? Мы использовали хук customize_register, в коллбек-фунцию которого передается объект класса WP_Customize_Manager, позволяющий манипулировать секциями, параметрами и контролами. Мы начали с добавления секции с помощью метода add_section(). Этот метод принимает два аргумента.

Метод: add_section($id, $args)
$id string Уникальный идентификатор секции
$args array Массив дополнительных параметров, передаваемых в метод

Массив $args позволяет определить некоторые свойства секции, которую мы создаём.

Массив: $args
title string Заголовок секции
description string Необязательный. Описание секции. Отображается как подсказка при наведении на заголовок
priority integer Необязательный. Очередность, определяющая порядок вывода секций на экран. Значение по умолчанию: 10
capability string Необязательный. Право пользователя, которого будет достаточно, чтобы отобразить данную секцию на экране
theme_supports string Необязательный. Указывает на то, что текущая тема должна поддерживать описанную в параметре функцию (такую, как настраиваемое фоновые изображение страницы)

Добавляем новую настройку

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

Регистрируем параметр

Параметры регистрируются с помощью метода add_setting(). Поместите этот код сразу после кода, который вызывает add_section() и создает секцию.

$customizer->add_setting(
    'copyright_textbox',
    array('default' => 'Моя компания')
);

Метод add_setting() принимает два аргумента, точно так же, как и add_section(): уникальный идентификатор параметра и массив дополнительных свойств.

Метод: add_setting($id, $args)
$id string Уникальный идентификатор параметра
$args array Массив дополнительных свойств, передаваемых в метод

Давайте посмотрим, какие свойства мы можем задать в массиве $args.

Массив: $args
default string Значение для параметра по умолчанию, если никакое другое не было задано. По умолчанию: пустая строка
type string Определяет каким образом параметр будет сохраняться в базу данных. По умолчанию: theme_mod
capability string Право пользователя, которого будет достаточно, чтобы отобразить данный параметр на экране. По умолчанию: edit_theme_opitons
theme_supports string Указывает на то, что текущая тема должна поддерживать описанную в свойстве функцию. По умолчанию: пустая строка
transport string Определяет, каким образом новые значения параметров будут передаваться в предпросмотр. По умолчанию: refresh
sanitize_callback string Имя коллбек-функции, которая будет фильтровать входные данные перед сохранением в базу данных. По умолчанию: пустая строка.
sanitize_js_callback string Имя коллбек-функции, которая будет фильтравать данные, получаемые из базы данных, при передаче их на страницу настройки темы. По умолчанию: пустая строка

Наверняка вы заметите, что создавая новый параметр, из всех возможных свойств мы воспользовались только одним — default. Все свойства параметра имеют значения по умолчанию, так что нам совершенно не обязательно добавлять их в вызов метода add_setting(). Есть несколько свойств параметра, на которые стоит обратить внимание.

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

Второе — sanitize_js_callback, метод, который вызывается для фильтрации данных, получаемых из базы данных и выводящихся на экран. Например, можно было бы подставлять «#» к полученному шеснадцатеричному значению цвета в случае, если оно хранится без решетки.

Третье свойствоtransport. Оно определяет два способа обновления «живого» предпросмотра на странице настройки темы, когда мы меняем значение нашего параметра. В первом случае, когда свойство transport имеет значение refresh, перезагружается весь фрейм предпросмотра при каждом изменении нашего параметра. С другой стороны, значение postMessage позволяет использовать AJAX для обновления конкретного параметра без полной перезагрузки фрейма. В случае использования postMessage вам необходимо самостоятельно писать скрипт, который будет работать с данными полученными через AJAX и отправлять из на экран. Покамест мы не стали рассматривать этот способ, но к нему мы еще вернёмся.

Добавляем контрол

Контролы — это элементы интерфейса, используемые для изменения значений параметров. Любой параметр должен иметь соответствующий контрол, чтобы отобразиться на странице настройки темы. Контролы добавляются с помощью метода add_control(), который всё так же принимает два аргумента. Здесь идентификатор контрола должен совпадать с идентификатором параметра, которому он принадлежит. Поместите этот код вслед за тем, который создает наш параметр.

$customizer->add_control(
    'copyright_textbox',
    array(
        'label' => 'Текст копирайта',
        'section' => 'example_section_one',
        'type' => 'text',
    )
);

Вот теперь, наконец-то, мы сможем увидеть нашую новую секцию и параметр в ней на странице настройки темы.

Страница настройки темы с новой секцией и параметром
Страница настройки темы с новой секцией и параметром

Метод add_control, как вы уже могли догадаться, принимает два аргумента — идентификатор и массив свойств контрола.

Метод: add_control($id, $args)
$id string Идентификатор контрола, который должен совпадать с идентификатором параметра
$args array Массив дополнительных свойств, передаваемых в метод

Далее список свойств, которые можно передать в массиве $args.

Массив: $args
label string Текст контрола, который в HTML-разметке будет помещен в тег <label></label>
description string Необязательный. Описание секции. Отображается как подсказка при наведении на заголовок
section string Идентификатор секции, в которую необходимо поместить данный параметр (и его контрол)
type string Необязательный. Тип контрола, который будет использоваться. По умолчанию: text (текстовое поле)
choices array Если параметр использует переключатели или флажки, choices определяет список значений на выбор
priority integer Необязательный. Очередность, определяет порядок в котором параметры будут выведены в своей секции. По умолчанию: 10

Большинство свойств контрола вполне понятны без дополнительных разъяснений. Как видите, в нашем примере мы использовали только первые три свойства. Остальные свойства, такие как choices, мы рассмотрим немного позже в нашем руководстве.

Получаем значения параметров из темы

Вот теперь, наконец-то, мы можем использовать созданный нами параметр в нашей теме. Если помните, мы создавали его для того, чтобы вывести информацию о копирайте в подвале нашего сайта. Сейчас копирайт выводится в файле footer.php с помощью следующего кода (в строке 116):

<?php bloginfo('name'); ?>

А мы просто возьмём и заменим вызов этой функции вызовом следующей:

<?php echo get_theme_mod('copyright_textbox', 'Текст копирайта еще не придумали'); ?>
Текст копирайта после сделанных изменений
Текст копирайта после сделанных изменений

Функция get_theme_mod() принимает два аргумента.

Функция: get_theme_mod($name, $default)
$name string Идентификатор параметра, значение которого необходимо получить
$default string Необязательный. Значение по умолчанию, если параметр еще не был задан

Другие типы контролов

Мы уже создали параметр с текстовым полем и добавили его в нашу тему. Но это только самое начало, поскольку Вордпресс предлагает еще несколько стандартных контролов.

Флажок <input type="checkbox">

Мы создадим параметр, который позволит скрывать и снова показывать информацию о копирайте.
Скопируйте этот код и вставьте в то место, где мы создавали текстовое поле.

$customizer->add_setting('hide_copyright');

Обратите внимание, что в данном случае (в отличие от текстового поля) мы не используем массив свойств нашего параметра, потому что для него нам не нужно значение по умолчанию.

Следующим нашим действием будет добавление кода, который создаст для нового параметра свой контрол.

$customizer->add_control(
    'hide_copyright',
    array(
        'type' => 'checkbox',
        'label' => 'Скрыть текст копирайта',
        'section' => 'example_section_one',
    )
);
Секция «Мои настройки» после добавления в неё флажка
Секция «Мои настройки» после добавления в неё флажка

В нашем случае единственное отличие данного контрола (с программной точки зрения) от текстового поля, которое мы создали ранее, — свойство type. По содержанию этого свойства Вордпресс определит, что мы хотим использовать флажок вместо текстового поля в качестве контрола.

Теперь давайте используем созданный параметр в нашей теме и сделаем так, что когда флажок установлен, копирайт в подвале будет скрываться. Для этого нам надо добавить проверку параметра hide_copyright. Параметр флажка имеет значение 1, если флажок установлен, иначе — пустую строку.

<?php
if(get_theme_mod('hide_copyright') == '')
    echo get_theme_mod('copyright_textbox', 'Текст копирайта еще не придумали');
?>

Группа переключателей <input type="radio">

Чтобы продемонстрировать использование переключателей, мы создадим новый параметр, предлагающий положение логотипа: слева, по центру, справа. Как обычно, начнем с создания параметра и контрола для него, добавив вот этот блок кода туда, где мы создавали контрол hide_copyright.

$customizer->add_setting(
    'logo_placement',
    array('default' => 'left')
);
 
$customizer->add_control(
    'logo_placement',
    array(
        'type' => 'radio',
        'label' => 'Положение логотипа',
        'section' => 'example_section_one',
        'choices' => array(
            'left' => 'Слева',
            'right' => 'Справа',
            'center' => 'По центру',
        ),
    )
);

Единственное значимое отличие (с программной точки зрения) у контрола типа «переключатель» от всех предыдущих контролов — в свойстве choices. Оно представляет из себя массив возможных значений параметра. На экране отображается в виде нескольких переключателей. Ключ элемента — это имя переключателя (которое хранится в базе данных как значение параметра), а значение — текст, который будет помещен в тег <label></label>.

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

add_action('wp_head', function(){
    $placement = get_theme_mod('logo_placement');
    if (!empty($placement)): ?>
<style>
    <?php
        switch($placement){
            case 'right':
                $styles = '#header #logo{ float:right; }';
            break;

            case 'center':
                $styles = '#header{ text-align:center; }
                           #header #logo{ float:none; margin-left:auto; margin-right:auto; }';
                break;
        }
        echo $styles; ?>
</style>
<?php endif;
});

Заметьте, что если позиция логотипа — left, то никакого кода CSS вообще не создается, потому что тема изначально выводит логотип слева.

Положение логотипа после изменения параметра <code>logo_placement</code>
Положение логотипа после изменения параметра logo_placement

Списки <select>

Создание списка происходит точно так же, как и группы переключателей, за исключением того, что свойство контрола type примет значение select. Чтобы продемонстрировать работу списков, мы создадим такой список, который позволит нам заменить стандартный «Powered by» текст в подвале сайта на что-нибудь другое. Добавьте вот этот код прямо за тем кодом, где мы создавали группу переключателей.

$customizer->add_setting(
    'powered_by',
    array('default' => 'Вордпресса')
);
 
$customizer->add_control(
    'powered_by',
    array(
        'type' => 'select',
        'label' => 'При поддержке',
        'section' => 'example_section_one',
        'choices' => array(
            'Вордпресса' => 'Вордпресса',
            'хомячков' => 'хомячков',
            'реактивного топлива' => 'реактивного топлива',
            'атомной энергии' => 'атомной энергии',
        ),
    )
);

Ничего сложного! Теперь у нас есть список и мы можем использовать его в нашей теме. Для этого мы уберём стандартный «Powered by» текст в footer.php (строки 123-126):

<a href="<?php echo esc_url(__('http://themeid.com/responsive-theme/','responsive')); ?>" title="<?php esc_attr_e('Responsive Theme', 'responsive'); ?>">
        <?php printf('Responsive Theme'); ?></a>
<?php esc_attr_e('powered by', 'responsive'); ?> <a href="<?php echo esc_url(__('http://wordpress.org/','responsive')); ?>" title="<?php esc_attr_e('WordPress', 'responsive'); ?>">
        <?php printf('WordPress'); ?></a>

Вместо этого мы поместим туда всего одну строку:

При поддержке <?php echo get_theme_mod('powered_by', 'Вордпресса'); ?>

Если параметр powered_by не был установлен, в подвале будет написано «При поддержке Вордпресса», иначе слово «Вордпресса» будет заменено на один из элементов нашего списка.

Текст в подвале после изменения параметра <code>powered_by</code>
Текст в подвале после изменения параметра powered_by

Фильтрация данных

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

Фильтрация данных из текстового поля

Давайте снова покодим. Функция фильтрации данных «привязывается» к создаваемому параметру через его свойство sanitize_callback. Помните, как мы добавляли текстовое поле, которое позволяет изменять текст копирайта в подвале сайта? Сейчас мы просто добавим свойство sanitize_callback в массив:

$customizer->add_setting(
    'copyright_textbox',
    array(
        'default' => 'Моя компания',
        'sanitize_callback' => 'example_sanitize_text'
    )
);

Теперь всякий раз при сохранении значения параметра copyright_textbox будет вызываться функция example_sanitize_text, в которую передается сохраняемое значение в качестве аргумента. Нам необходимо обеспечить «чистоту» этого значения, нам нужна простая строка текста. Будем считать, что в использовании HTML ничего страшного нет, однако запретим использование скриптов и удостоверимся, что все теги HTML, если таковые присутствуют, используются корректно и не ломают вёрстку. Исходя из всего этого, код нашей фильтрующей функции может быть таким:

function example_sanitize_text($input) {
    return wp_kses_post(force_balance_tags($input));
}

Функция force_balance_tags() исправляет все незакрытые теги HTML, а wp_kses_post() оставляет только «безопасные» теги, которые разрешены в стандартном посте Вордпресса. Эти функции встроены в Вордпресс и задокументированы в Кодексе Вордпресса.

Фильтрация флажка

Только что мы увидели, как создать фитрующую коллбек-функцию, так что заново мы это разбирать не будем, а сразу перейдем к фильтрующей коллбек-функции для флажка.

Настройщик темы (WordPress Theme Customizer) использует значение «1» для установленного флажка и пустое значение для неустановленного. То есть наша фильтрующая функция должна возвращать ничего кроме одного из этих двух значений. Примерно так:

function example_sanitize_checkbox($input) {
    if ($input == 1) {
        return 1;
    } else {
        return '';
    }
}

Если входные данные содержат единицу (что означает установленный флажок), то и функция возвращает единицу. Чтобы ни было там иначе, функция вернёт пустую строку, что предотвратит попадание всякого мусора в базу данных.

Фильтрация переключателей и списков

Фильтрация параметров с возможностью выбора одного из нескольких значений, таких, как переключатели и списки, чуть сложнее, поскольку в каждом таком параметре список допустимых значений разный. Например, чтобы отфильтровать данные о положении логотипа (тот параметр, который мы создавали ранее), нам необходимо принимать на вход только три значения: left, right и center. В то время как параметр с текстом «При поддержке…» может содержать одно из этих значений: Вордпресса, хомячков, реактивного топлива или атомной энергии. Поэтому нам придётся создавать отдельные коллбек-функции для подобных параметров.

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

function example_sanitize_logo_placement($input) {
    $valid = array(
        'left' => 'Слева',
        'right' => 'Справа',
        'center' => 'По центру',
    );
 
    if (array_key_exists($input, $valid)) {
        return $input;
    } else {
        return '';
    }
}

Вот, собственно и всё. Дублируем допустимые значения в фильтрующую функцию и в зависимости от того, какое значение параметра получаем на входе, возвращаем либо это значение, либо пустую строку. Это позволит, как и в предыдущем примере, не допустить попадание в базу данных любого неправильного значения.

Фильтрующая функция для списка выглядит абсолютно точно так же, за исключением того, что допустимые значения в массиве будут соответствующими значениям параметра «При поддержке…».

function example_sanitize_powered_by($input) {
    $valid = array(
        'Вордпресса' => 'Вордпресса',
        'хомячков' => 'хомячков',
        'реактивного топлива' => 'реактивного топлива',
        'атомной энергии' => 'атомной энергии',
    );
 
    if (array_key_exists($input, $valid)) {
        return $input;
    } else {
        return '';
    }
}

Примерно таким способом фильтруются все стандартные контролы, предлагаемые Вордпрессом.

Специальные типы контролов

В дополнение к «обычным» типам контролов, рассмотренных нами ранее, Вордпресс предлагает некоторые специальные типы.

Выпадающий список страниц

Создать выпадающий список страниц очень просто. Мы можем взять код, который использовали для создания флажка и просто поменять идентификатор параметра, фильтрующий метод и тип контрола.

$customizer->add_setting(
    'page-setting',
    array('sanitize_callback' => 'example_sanitize_integer')
);
 
$customizer->add_control(
    'page-setting',
    array(
        'type' => 'dropdown-pages',
        'label' => 'Выберите страницу:',
        'section' => 'example_section_one',
    )
);
Отображение выпадающего списка страниц
Отображение выпадающего списка страниц

Просто? Обратите внимание на то, что свойство type имеет значение dropdown-pages, что сообщает Вордпрессу создать выпадающий список, содержащий страницы. В качестве значения параметра в базе данных хранится числовой идентификатор страницы. Поэтому в фильтрующей функции нам необходимо отсеивать все не целочисленные значения. Вот пример такой фильтрующей функции:

function example_sanitize_integer($input) {
    if(is_numeric($input)) {
        return intval($input);
    }
}

Палитра

А здесь уже интереснее. Способ добавления параметра не изменился, а вот добавление контрола, в сравнении с другими, несколько отличается. Начнём с параметра.

$customizer->add_setting(
    'color-setting',
    array(
        'default' => '#000000',
        'sanitize_callback' => 'sanitize_hex_color',
    )
);

Похоже на всё, что было раньше? Единственное отличие — фильтрующая функция, которую бы будем использовать. В Вордпрессе имеется встренная функция фильтрации шеснадцатеричных кодов цветов, как раз таких, которые будет передавать нам палитра. В качестве значения по умолчанию для параметра мы выбрали черный цвет.

А теперь давайте посмотрим на код, с помощью которого создаётся контрол палитры.

$customizer->add_control(
    new WP_Customize_Color_Control(
        $customizer,
        'color-setting',
        array(
            'label' => 'Настройка цвета',
            'section' => 'example_section_one',
            'settings' => 'color-setting',
        )
    )
);

Контрол палитры встраивался в Вордпресс с использованием ООП в PHP, так что формат вызова метода add_control() отличается от предыдущих. Обратите внимание на строку new WP_Customize_Color_Control, здесь мы создаем объект класса WP_Customize_Color_Control.

Конструктор класса WP_Customize_Color_Control принимает три агрумента. Первый, $wp_customize, всегда одинаковый, является объектом класса WP_Customize_Manager. Второй аргумент — идентификатор параметра, для которого мы создаем контрол. Третий аргумент — массив свойств контрола, которые перечислены в следующей таблице:

Массив: $args
label string Имя параметра
section string Секция, к которой относится данный контрол
settings string Идентификатор параметра, который визуализирует данный контрол
Так выглядит контрол палитры после нажатия на кнопку «Текущий цвет»
Так выглядит контрол палитры после нажатия на кнопку «Текущий цвет»

Контрол загрузчика файлов

Контрол загрузчика файлов реализован в классе WP_Customize_Upload_Control. В Вордпрессе список типов файлов, которые могут быть загружены на сайт, ограничен изначально, так что мы не будем рассматривать фильтрующую функцию для этого контрола.

$customizer->add_setting('file-upload');
$customizer->add_control(
    new WP_Customize_Upload_Control(
        $customizer,
        'file-upload',
        array(
            'label' => 'Загрузка файла',
            'section' => 'example_section_one',
            'settings' => 'file-upload'
        )
    )
);

Как видите, отличие от предыдущего примера, по большому счету, только в имени класса контрола.

Контрол загрузчика изображения

Класс загрузки изображения расширяет базовый класс загрузки файлов. Сейчас мы просто поменяем в имени класса Upload на Image и установим новый идентификатор параметра.

$wp_customize->add_setting('img-upload');
$wp_customize->add_control(
    new WP_Customize_Image_Control(
        $wp_customize,
        'img-upload',
        array(
            'label' => 'Загрузка изображения',
            'section' => 'example_section_one',
            'settings' => 'img-upload'
        )
    )
);

Ровно так же, как и с загрузкой «простого» файла, Вордпресс ограничивает количество типов файлов, которые могут попасть к вам на сайт.

Создание собственных контролов

Теперь, когда мы узнали, какие контролы есть в Вордпрессе, почему бы нам не создать свой собственный? Отто написал замечательную статью о создании собственных контролов, так что данный раздел руководства будет основан на его статье.

Вы, возможно, заметили, что текстовое поле <textarea> отсутствует в списке встроенных контролов в Вордпрессе. Так что созданием этого контрола мы сейчас и займемся.

Чтобы создать свой контрол, нам необходимо создать класс, наследующий WP_Customize_Control и переопределить в нём метод render_content(), который выводит контрол на страницу настройки темы.

Вместо того, чтобы писать наш класс прямо внутри хука customize_register, мы поместим его в отдельный файл textarea-control.php. А этот файл, чтобы он не путался среди шаблонов нашей темы, поместим в папку customize-controls. Этой папки, конечно, нет еще, так что создадим её в директории нашей темы.

А теперь поместите вот этот код в только что созданный файл textarea-control.php:

<?php

require_once ABSPATH.WPINC.'/class-wp-customize-control.php';

/**
 * Позволяет использовать контрол textarea на странице настройки темы
 */
class Customize_Textarea_Control extends WP_Customize_Control {
    public $type = 'textarea';
 
    public function render_content() {
        ?>
            <label>
                <span class="customize-control-title"><?php echo esc_html($this->label); ?></span>
                <textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea($this->value()); ?></textarea>
            </label>
        <?php
    }
}

Обратите внимание на то, каким образом метод render_content() выводит наш контрол и его название. Если вы загляните в код метода render_content() стандартных контролов, то увидите, что их вывод ничем существенно не отличается от нашего контрола. Это позволяет добиться однообразия интерфейса на странице настройки темы.

Итак, мы создали свой собственный контрол, теперь нам необходимо создать параметр и «прицепить» к нему наш контрол.

Перво-наперво нам небоходимо подключить файл с нашим новым контролом в коллбек-функции хука customize-register. Сделать это можно прямо в первой строчке кода коллбек-функции примерно так:

add_action('customize-regiser', function($customizer){
    require_once get_template_directory().'/customize-controls/textarea-control.php';

    ... //а далее весь тот код, который мы писали с вами ранее
}

Теперь, когда класс нашего контрола будет подгружен, создадим настройку и прицепим к ней наш контрол:

$customizer->add_setting('textarea');
$customizer->add_control(
    new Customize_Textarea_Control(
        $customizer,
        'textarea',
        array(
            'label' => 'Текстовое поле',
            'section' => 'example_section_one',
            'type' => 'textarea'
        )
    )
);

Как видите, всё, что изменилось с тех пор, как мы создавали контрол палитры, — это:

  1. Идентификатор параметра. Мы назвали его textarea
  2. Название класса, объект которого мы создаем. Теперь это Customize_Textarea_Control
  3. Подпись (или название контрола) изменилось на «Текстовое поле»

Вот вы и научились создавать собственные контролы для страницы настройки темы!

Добавление параметров в существующие секции

Может получиться так, что однажды вы захотите добавить некий параметр в уже существующую секцию. Например, поскольку тема Responsive поддерживает возможность Вордпресса изменять свойства фона для страницы, секция параметров «Colors» создаётся автоматически и параметр «Background Color» помещается внутрь этой секции. Так давайте добавим еще один параметр в секцию «Colors» и назовём его «Font Color» (или «Цвет текста»). Для начала нам необходимо узнать идентификатор секции, чтобы мы смогли «присоединить» к ней наш новый параметр. Секции, которые добавляются Вордпрессом автоматически, определены в методе register_controls() класса WP_Customize_Manager, который располагается в файле wp-includes/class-wp-customize-manager.php. Заглянув в этот метод, мы узнаем, что идентификатор секции «Colors» — colors.

Поскольку контрол палитры мы уже создавали, мы можем просто скопировать тот код и сделать несколько изменений.

$customizer->add_setting(
    'font-color',
    array(
        'default' => '#444444',
        'sanitize_callback' => 'sanitize_hex_color',
    )
);
 
$customizer->add_control(
    new WP_Customize_Color_Control(
        $wp_customize,
        'font-color',
        array(
            'label' => 'Цвет текста',
            'section' => 'colors',
            'settings' => 'font-color'
        )
    )
);

А вот, что нам следует изменить:

  1. Измените идентификатор параметра со старого color-setting на новый — font-color
  2. Измените цвет по умолчанию в свойстве default
  3. Измените текст контрола в свойстве label
  4. И, наконец, установите свойству section значение colors, чтобы наш параметр и контрол к нему попали в секцию «Colors».

Использование AJAX для обновления фрейма предпросмотра

Сейчас на странице настройки темы при обновлении любого из созданных нами параметров фрейм, в котором отображается сайт и происходят изменения, перезагружается полностью. Каждый раз, при любом изменении параметра. Вы наверняка замечали «мигание» или подтормаживание правой части страницы при этом. Такое поведение, т.е. полную перезагрузку фрейма, можно изменить, если использовать изменение параметра «налету», с помощью AJAX. В таком случае отпадёт необходимость в перезагрузке фрейма для того, чтобы изменения отобразились на экране.

Чтобы разобраться, как это делается и работает, мы создадим новый параметр, который позволит изменять цвет фона у области избранного содержимого на главной странице. Сначала, как обычно, мы добавим параметр и контрол для него. Примерно так:

$customizer->add_setting(
    'featured-background',
    array(
        'default' => '#ffffff',
        'sanitize_callback' => 'sanitize_hex_color',
        'transport' => 'postMessage',
    )
);
 
$customizer->add_control(
    new WP_Customize_Color_Control(
        $customizer,
        'featured-background',
        array(
            'label' => 'Цвет фона Избранного',
            'section' => 'colors',
            'settings' => 'featured-background'
        )
    )
);

Обратите внимание на появление свойства transport у параметра featured-background и на его значение. Значение postMessage свойства transport означает, что обновление значения данного параметра (как запись в базу данных, так и вывод на экран) будет производиться с помощью AJAX. Поэтому теперь нам необходимо написать коллбек-функцию, которая будет обрабатывать AJAX-запрос. Мы задействуем её через хук wp_footer, а поместим в коллбек-функцию для хука customize_register (тот хук, где создавались все наши параметры и контролы). Выглядеть это будет примерно вот так:

... //весь предыдущий код в хуке customizer_register

if ($customizer->is_preview() && !is_admin()) {
    add_action('wp_footer', function(){
    }, 21);
}

Сама коллбек-функция пока что пуста, однако объясню, что здесь происходит. Наш хук добавится только в том случае, если пользователь обладает достаточными административными правами и если в данный момент используется страница настройки темы. Последний аргумент — это приоритет или очередность выполнения данной коллбек-функции ко всем остальным в хуке wp_footer. Рекомендуется выставлять число не менее 20, чтобы «всё работало».

Собственно коллбек-функция сейчас у нас пустая, так что давайте поместим в неё немного кода на JavaScript, который будет обрабатывать обновление параметра через AJAX.

... //весь предыдущий код в хуке customizer_register

if ($customizer->is_preview() && !is_admin()) {
    add_action('wp_footer', function(){
    ?>
    <script type="text/javascript">
        (function($) {
            wp.customize('featured-background',function(value) {
                value.bind(function(to) {
                    $('#featured').css('background-color', to);
                });
            });
        })(jQuery)
    </script>
    <?php
    }, 21);
}

Весь этот код просто добавляет небольшой фрагмент кода на JavaScript в подвал нашей темы (при том только тогда, когда задействована страница настройки нашей темы). Эта коллбек-функция может стать отправной точкой в обработке практических любых данных поступающих через AJAX. Код, что мы только что написали, совершает два простых действия. Во-первых, здесь мы получаем значение параметра всякий раз, когда он изменяется (в нашем случае это значение параметра featured-background). Во-вторых, наш код предпринимает что-нибудь относительно этого значения. У нас происходит изменения цвета фона элемента #featured с помощью jQuery.

Использование AJAX с уже существующими параметрами

Например, мы хотим изменить свойство transport у встроенного свойства. Давайте изменим этого свойство у стандартного параметра «Название сайта» так, чтобы его новое значение обновлялось без перезагрузки фрейма через AJAX. Для этого нам необходимо сделать следующее:

$customizer->get_setting('blogname')->transport = 'postMessage';

Вот так просто. Всё благодаря тому, что свойства параметра объявлены как public, и мы можем их изменять. Однако чтобы всё это заработало, нам необходимо, как и в предыдущем случае, немножко кода на JavaScript. Следующий код мы можем добавить в ту же коллбек-функцию, которую создавали недавно для хука wp_footer. Этот код будет обновлять текст ссылки каждый раз, когда значение параметра будет изменяться.

wp.customize('blogname',function(value){
    value.bind(function(to) {
        $('.site-name a').html(to);
    });
});

Учтите, что тема «Responsive», которую мы использовали в этом руководстве, не показывает заголовок с именем сайта, если в шапке присутствует изображение. Так что, если начали эксперименты с заголовком, удостоверьтесь, что изображение в шапке отключено.

Конец.