Приветствую, коллеги!
Хочу представить вам плагин Joomla Shortcoder, который я разработал, чтобы упростить работу с шорткодами в Joomla.
И, так как в Joomla шорткоды широко не применяются, на всякий случай проясню что это такое.
Шорткод (англ. shortcode — короткий код) — это удобный способ добавить в текст статьи динамический контент или сложные HTML-элементы, не захламляя редактор громоздким кодом. Вместо того чтобы вставлять, скажем, полноценный <iframe> с кучей параметров, вы используете короткий и понятный тег.
Классический пример — вставка видео из YouTube в WordPress. Традиционный код выглядит примерно так:
<iframe
src="https://www.youtube.com/embed/kBddBRQ-xic"
width="560"
height="315"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
title="YouTube video player"
referrerpolicy="strict-origin-when-cross-origin"
frameborder="0"
allowfullscreen>
</iframe>
С шорткодом всё это превращается в одну строку:
[youtube https://www.youtube.com/watch?v=dQw4w9WgXcQ width="560" height="315"]
В Joomla тоже есть несколько встроенных шорткодов, например:
- {loadmoduleid 123}: загружает модуль по ID;
- {loadposition sidebar}: выводит модули из заданной позиции;
- {field 5}: вставляет значение произвольного поля материала.
Однако WordPress, в отличие от Joomla, позволяет легко добавлять собственные шорткоды при помощи функции add_shortcode(), которую можно прописать в functions.php текущей темы или в MU-плагине.
Типичный вариант выглядит так:
add_shortcode('current_year', fn () => date('Y'));
После этого в любом посте будет работать конструкция [current_year], заменяясь на текущий год.
В Joomla для создания собственного шорткода вам придётся:
- Создать полноценный плагин группы content с XML-файлом манифеста.
- Установить его и активировать (можно через php cli/joomla extension:discovery).
- Подписаться на событие onContentPrepare.
- Написать регулярное выражение для поиска вашего тега.
- Обработать текст статьи при помощи preg_replace_callback().
- И, возможно, что-то ещё…
Это не самый простой путь, особенно если вам нужно всего лишь вывести текущую дату.
Среди расширений есть, например, JShortcodes с drag-and-drop интерфейсом или Easy Shortcodes на базе INI-файлов. Первый, на мой взгляд, перегружен сотнями виджетов и платный, второй — использует ini-файлы там, где естественнее писать на PHP.
Мне больше всего нравится Snippets от Regular Labs, но в нём также нет поддержки PHP.
Shortcoder использует другой подход. Никакого сложного визуального интерфейса: все шорткоды описываются прямо в PHP-файлах или задаются как вызываемые объекты (обычно это функции). Плагин автоматически подхватывает файлы из папки /shortcodes и превращает их имена в одноимённые теги.
Вот как можно просто создать шорткод для текущего года.
Для этого мы создаём файл shortcodes/current_year.php с содержимым:
<?php \defined('_JEXEC') or die;
// Весь вывод файла попадает в {current_year}
echo date('Y');
Теперь в любой статье можно написать {current_year} — и увидеть актуальный год.
Вообще говоря, такой шорткод лучше реализовать в виде замыкания. Для этого используется специальный файл shortcodes.php в директории shortcodes:
<?php // shortcodes/shortcodes.php
\defined('_JEXEC') or die;
// Файл должен возвращать массив с шорткодами
return [
// {current_year}
'current_year' => fn () => date('Y'),
// {hello "John Doe"}
'hello' => fn (array $attributes) =>
sprintf('Hello, %s!', $attributes[0] ?? 'World'),
];
А вот пример более сложного шорткода {details} для вставки спойлера. Здесь используется именованный атрибут summary и специальная переменная $content для получения содержимого внутри тега:
<?php // shortcodes/details.php
\defined('_JEXEC') or die;
$summary = $attributes['summary'] ?? 'Click to see more';
?>
<details>
<summary><?php echo htmlspecialchars($summary); ?></summary>
<div>
<?php echo $content; ?>
</div>
</details>
Использование в редакторе:
{details summary="Важная информация"}
Здесь скрытый текст, который увидит пользователь после клика.
{/details}
Надеюсь, я смог передать основную идею плагина.
Установка
Системные требования:
- Joomla 4 и выше.
- PHP 7.4 и выше.
Установка стандартная — скачиваете zip-файл с последней версией с GitHub Releases и устанавливаете через панель администратора: «Система» → «Установка» → «Расширения».
Можно использовать CLI:
php cli/joomla.php extension:install https://github.com/PopArtDesign/joomla-shortcoder/a.../tags/v1.0.0.zip
После установки активируйте плагин «Content - Shortcoder» в менеджере плагинов.
Затем создайте директорию shortcodes в корне вашего сайта (там же, где лежат файлы Joomla). Любой php-файл из этой папки автоматически становится одноимённым шорткодом. Загружать и править файлы можно любым удобным способом — через FTP, файловый менеджер хостинга или даже прямо из админки, если используется компонент для редактирования файлов.
mkdir shortcodes && touch shortcodes/shortcodes.php
Синтаксис шорткодов
Шорткоды добавляются в текст при помощи тегов, заключённых в фигурные скобки: {foo}, {bar}, {baz} и т.д. В качестве имени тега может использоваться любая строка, содержащая буквы латинского алфавита, цифры, символы тире и нижнего подчёркивания.
Шорткоды бывают двух типов:
- самозакрывающиеся: {hello "John Doe"}
- с закрывающим тегом: {repeat 10}Repeat Me{/repeat}
Последние используются для захвата внутреннего содержимого, которое будет доступно в переменной $content:
<?php // shortcodes/shortcodes.php
\defined('_JEXEC') or die;
return [
// {repeat 5}Hello, World!{/repeat}
'repeat' => fn (array $attributes, string $content) =>
str_repeat($content, (int) ($attributes[0] ?? 1))
];
Атрибуты
Дополнительные параметры передаются в шорткоды через атрибуты, которые указываются после имени тега.
Атрибуты также бывают двух типов:
- позиционные — перечисляются через пробел и доступны по индексу в массиве: $attributes[0], $attributes[1] и т.д.
Пример: {hello John Doe}:
- $attributes[0] = 'John'
- $attributes[1] = 'Doe'
- именованные — записываются в формате ключ="значение". Внутри обработчика шорткода они доступны по имени ключа: $attributes['key'].
Пример: {hello first="John" last="Doe"}:
- $attributes['first'] = 'John'
- $attributes['last'] = 'Doe'
Все атрибуты передаются в обработчик в виде единого массива $attributes.
Также существует специальный атрибут _ (нижнее подчёркивание), который содержит только позиционные атрибуты в виде индексированного массива:
<?php // shortcodes/shortcodes.php
\defined('_JEXEC') or die;
return [
// {sum 1 2 3 4}
'sum' => fn (array $attributes) => array_sum($attributes['_']),
];
Значения атрибутов можно заключать в “двойные” или ‘одинарные’ кавычки. Если значение не содержит пробелов и специальных символов, кавычки можно опустить.
- {button url="https://example.com" label="Click me"}
- {button url=https://example.com label=Click} — валидно, но нужно помнить: значения без кавычек обрезаются первым же пробелом.
Переменная $item
В специальную переменную $item передаётся текущий объект публикации: статья, категория или другой элемент, который обрабатывается плагином. Это позволяет шорткоду взаимодействовать с контекстом, например, получать значения пользовательских полей (custom fields).
Вот пример шорткода, который выводит значение произвольного поля по его имени, а не по ID (в отличие от встроенного {field}):
<?php // shortcodes/shortcodes.php
\defined('_JEXEC') or die;
return [
// Пример: {jcfield price raw="false"}
'jcfield' => function (array $attributes, string $content = '', $item = null) {
$name = $attributes['name'] ?? $attributes[0] ?? '';
// Вообще говоря, свойство $item->jcfields может отсутствовать,
// и лучше делать загрузку с помощью FieldsHelper
if (!$name || !$item || empty($item->jcfields ?? null)) {
return '';
}
// Выводить "сырое" значение?
$raw = ($attributes['raw'] ?? 'true') === 'true';
foreach ($item->jcfields as $field) {
if ($field->name === $name) {
return $raw ? $field->rawvalue : $field->value;
}
}
return '';
},
];
Вложенность
Шорткоды могут вкладываться друг в друга, но есть одно ограничение: не поддерживаются вложенные одноимённые теги.
✅ Работает:
{outer}
{inner}Текст{/inner}
{/outer}
❌ Не работает:
{details}
{details}Вложенный спойлер{/details}
{/details}
Это связано с ограничениями парсера, использующего регулярные выражения. Если кратко, регулярные выражения (конечные автоматы) «не умеют считать» и могут найти либо самый первый закрывающий тег, либо самый последний (жадный вариант). Если выбрать первый вариант — теряется поддержка вложенности, если второй — поддержка соседних тегов. Первый вариант мне показался более предпочтительным.
GitHub Gist
Напоследок давайте сделаем ещё один пример шорткода {gist} для вставки содержимого GitHub Gist:
<?php // shortcodes/gist.php
\defined('_JEXEC') or die;
// Получение URL для вставки
if (!$url = $attributes[0] ?? '') {
// URL не был передан: {gist}, можно ничего не выводить
return;
}
if (strpos($url, 'https://gist.github.com') !== 0) {
// Был указан некорректный адрес: {gist https://gitflic.ru}
return;
}
$scriptUrl = rtrim($url, '/') . '.js';
// Имя файла: {gist url file="somefile.php"}
if ($file = $attributes['file'] ?? '') {
$scriptUrl .= '?file=' . urlencode($file);
}
?>
<script src="<?php echo htmlspecialchars($scriptUrl); ?>"></script>
Использование:
{gist https://gist.github.com/voronkovich/d35cdcdf6eb09e986ab9b16f91a5b2e8}
{gist https://gist.github.com/voronkovich/d35cdcdf6eb09e986ab9b16f91a5b2e8 file=somefile.php}
Более подробную документацию по работе с плагином вы можете прочитать в репозитории проекта.
Благодарю за внимание!-Источник