Создание шорткодов в WordPress

Шорткод — это тег вида ‘[shortcode]’, помещённый в текст поста и преобразуемый в определённый контент при его отображении. Шорткоды помогают легко конструировать весьма сложные фрагменты страниц. Простейший пример — галерея WordPress: встреченный в тексте поста тег будет заменён кодом галереи изображений.

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

Создание шорткодов в WordPress

[shortcode параметр1=»значение1″ параметр2=»значение2″ …]

А также параметры без значений, носящие флаговый характер:

[shortcode параметр1 параметр2]

Наконец, в теги шорткода можно заключить текст:

[shortcode параметры]ТЕКСТ[/shortcode]

В этом случае появляется закрывающий тег [/shortcode].

Создание шорткода

Регистрация нового шорткода выполняется функцией add_shortcode:

add_shortcode(‘mySC’, ‘myShortCode_fn’);

Первый аргумент — имя тега, второй — функция, которая этот тег обработает. Имя зависит от регистра. Поэтому теги ‘[mySC]’ и ‘[mysc]’ различны.

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

function myShortCode_fn ($attr, $text = null) {
return $text ? ‘<h1>’.$text.'</h1>’ : »;
}

С такой функцией фрагмент ‘[mySC]Header[/mySC]’ будет преобразован в строку ‘<h1>Header</h1>’.

Если задан только головной тег, аргумент $text будет нулевым.

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

То есть при обработке шорткода ‘[mySC x y=»v» z]’ мы будем иметь значение $attr[‘y’] == ‘v’, $attr[0] == ‘x’ и $attr[1] == ‘z’.

Работа с параметрами

Использование параметров в виде $attr[‘pname’] не очень удобно. Было бы проще выполнить extract($attr) и использовать непосредственно $pname, но тогда необходим жёсткий контроль за содержимым массива. Без контроля пользователи получат возможность определять переменные внутри нашей функции.

Необходимую обработку массива осуществляет функция shortcode_atts:

$attr = shortcode_atts($defaults, $attr);

Она формирует массив из массива $defaults, заменяя его значения соответствующими значениями массива $attr, если в нём таковые имеются. Все ключи $attr, отсутствующие в $defaults, будут проигнорированы. Поэтому вызов можно выполнить иначе:

extract(shortcode_atts($defaults, $attr));

После этого все параметры $attr[‘pname’] будут доступны в виде переменных $pname.

Неудобство может возникнуть при работе с флаговыми атрибутами. Вводить шорткод в виде ‘[short a b]’ гораздо удобнее, чем ‘[short a=»true» b=»true»]’.

Выражения ‘[short a b]’ и ‘[short b a]’ равнозначны. Поэтому умолчания для числовых ключей смысла не имеют и чтобы shortcode_atts их не удалил, флаги следует как-то совместить с параметрами.

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

$defaults = array(‘a’ => false, ‘b’ => false, … );

$def_keys = array_keys($defaults);
for ($i = 0; isset($attr[$i]); $i++)
if (in_array($attr[$i], $def_keys))
$attr[$attr[$i]] = true;
extract(shortcode_atts($defaults, $attr));

В этом случае записи ‘[short a]’, ‘[short a=»1″]’ и ‘[short a=»true»]’ полностью идентичны. Умолчания для всех флагов должны быть ложными.

Ручная обработка

Для задействования шорткодов напрямую мы можем использовать функцию do_shortcode:

<?php echo do_shortcode($text); ?>

Такой код выдаст текст, предварительно обработав в нём все теги.

Практика

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

Расположим его в wp-content/plugins/short_debug.php. Вот его текст:

<?php
/*
* Plugin Name: short_debug
*/

add_shortcode(‘sdbg’, ‘shortdebug_shortcode’);

function shortdebug_shortcode ($attr, $text = null) {
$rv = ‘<hr><h3>DBG Shortcode</h3>’;
$rv .= ‘<p>$attr:<ul>’;
if ($attr)
foreach ((array)$attr as $k => $v)
$rv .= ‘<li>[‘.esc_html($k).’] =&gt; &laquo;’.esc_html($v).’&raquo;</li>’;
else
$rv .= ‘<code>[empty]</code>’;
$rv .= ‘</ul>$text: ‘.($text == null ? ‘<code>[null]</code>’ : ‘<b>’.esc_html($text).'</b>’).'</p><hr>’;

return $rv;
}

?>
Активируем плагин, создаём новую запись, пишем тестовую строку:

[sdbg arg_without_any_value arg_with_a_value=»value» arg=»val» arg=»VAL» another_standalone_arg]Некоторый текст[/sdbg]
Сохраняем или публикуем и переходим на просмотр поста. Результат выглядит так:

DBG Shortcode

$attr:

[0] => «arg_without_any_value»
[arg_with_a_value] => «value»
[arg] => «VAL»
[1] => «another_standalone_arg»

$text: Некоторый текст
Заметьте: первое значение arg=»val» затёрто вторым значением «VAL» — смысл имеет только последнее указание атрибута.

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

Заключение

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

Всегда необходимо здравое планирование: запоминаться шорткоды должны быстро, читаться легко, необходимых параметров требовать поменьше. Желательно, чтобы умолчания были приемлемы в большинстве случаев.

И никогда не следует забывать о безопасности. В нашем простейшем случае это был контроль атрибутов и выводимого текста.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *