RadicalMart 3: настройки компонента
Как расширять настройки RadicalMart
Настройки RadicalMart используют форму Joomla с именем com_radicalmart.config. XML задает поля и структуру данных, а отдельный массив групп отвечает за левую навигацию, секции, вкладки и способ вывода полей в интерфейсе администратора.
Главное правило сохранения
Параметр должен быть описан в форме. При сохранении RadicalMart строит структуру значений по полям формы, берет отправленные данные, подмешивает уже сохраненные значения и только затем применяет значения по умолчанию. Если поля нет в форме, это не полноценная настройка компонента.
Где что находится
Форма настроек
com_radicalmart.config
Основная форма настроек загружается как com_radicalmart.config. Базовый XML компонента лежит на сайте в /administrator/components/com_radicalmart/config.xml.
Хранилище
#__extensions.params
Итоговые параметры записываются в запись расширения com_radicalmart. Читать их можно как обычные параметры компонента Joomla.
Интерфейс
groups / sections / tabs
Левая навигация и содержимое секций собираются из массива групп. XML добавляет поля, а группы решают, где администратор увидит эти поля.
Как сохраняются настройки
| Шаг | Что происходит | Зачем это важно |
|---|---|---|
1. Форма | loadForm + validate | Контроллер берет данные jform, загружает форму com_radicalmart.config и запускает стандартную валидацию Joomla. Перед валидацией удаляется блок permissions. |
2. Нормализация | onContentNormaliseRequestData | До валидации данные проходят через событие Joomla. Его можно использовать для аккуратной подготовки структуры запроса, если обычного XML недостаточно. |
3. Значения по умолчанию | getDefaultSaveData | RadicalMart проходит по полям формы и собирает структуру defaults. Поля типов note, spacer, rules и shortcodes не становятся обычными сохраняемыми параметрами. |
4. Текущие параметры | #__extensions.params | Сохраненный JSON параметров компонента читается из базы. Это нужно, чтобы не потерять значения, которые не были отправлены текущей формой. |
5. Merge | posted → current → default | Для каждого ключа из структуры формы приоритет такой: отправленное значение, уже сохраненное значение, затем default из XML или пустая строка. |
6. Запись | updateObject | Итоговый массив превращается в Registry string и записывается обратно в параметры расширения com_radicalmart. |
Почему поле нужно добавить именно в форму
Если значение просто отправить в запросе, но не описать его в XML формы, RadicalMart не увидит его в структуре defaults. Для надежного сохранения настройка должна существовать как JForm field: с именем, типом, фильтром и default при необходимости.
Как читать значения
Добавленные через форму значения читаются через Joomla\Component\RadicalMart\Administrator\Helper\ParamsHelper. Методы возвращают Joomla\Registry\Registry, поэтому значение получают через get('path.to.value', default). Для поля enabled, вложенного в plugins.example, путь будет plugins.example.enabled.
| Метод | Что возвращает | Когда использовать |
|---|---|---|
ParamsHelper::getComponentParams() | параметры компонента | Основной способ получить глобальные настройки RadicalMart, включая значения из ветки plugins.*, добавленные плагином в форму конфигурации. |
ParamsHelper::getCategoryParams($categoryId) | компонент + категория | По умолчанию объединяет параметры компонента и категории. Передайте третий аргумент false, если нужны только собственные параметры категории. |
ParamsHelper::getProductParams($productId) | компонент + категория + товар | Используйте для логики товара: минимум, максимум и шаг количества, скрытие цен, параметры витрины и собственные поля товара с учетом наследования. |
ParamsHelper::getMenuParams($id, $view) | параметры пункта меню | Нужно, когда логика зависит от конкретного пункта меню RadicalMart. Если пункт не найден, вернется пустой Registry. |
ParamsHelper::getShippingMethodsParams($id) | параметры способа доставки | Берет параметры способа доставки по id и кэширует результат на время запроса. Для обновления кэша есть парный метод setShippingMethodsParams(). |
ParamsHelper::getPaymentMethodsParams($id) | параметры способа оплаты | Берет параметры способа оплаты по id и кэширует результат на время запроса. Для обновления кэша есть парный метод setPaymentMethodsParams(). |
ParamsHelper::merge([$base, $override]) | ручное объединение Registry/array | Полезно, если нужно собрать параметры из нескольких источников. Непустые значения следующих наборов перекрывают предыдущие, массивы заменяются, если в них есть элементы. |
Прочитать настройку плагина
plugins.example.enabled
use Joomla\Component\RadicalMart\Administrator\Helper\ParamsHelper;
$params = ParamsHelper::getComponentParams();
$enabled = (int) $params->get('plugins.example.enabled', 0) === 1;
$params = ParamsHelper::getComponentParams();
$enabled = (int) $params->get('plugins.example.enabled', 0) === 1;
Путь повторяет вложенность XML: fields plugins, затем fields example, затем field enabled.
Параметры товара с наследованием
component + category + product
use Joomla\Component\RadicalMart\Administrator\Helper\ParamsHelper;
$params = ParamsHelper::getProductParams($productId);
$min = (int) $params->get('quantity_min', 1);
$step = (float) $params->get('quantity_step', 0);
$params = ParamsHelper::getProductParams($productId);
$min = (int) $params->get('quantity_min', 1);
$step = (float) $params->get('quantity_step', 0);
Такой вызов учитывает глобальные настройки, параметры категории и собственные параметры товара.
Только собственные параметры
merge = false
$categoryParams = ParamsHelper::getCategoryParams($categoryId, false, false);
$productParams = ParamsHelper::getProductParams($productId, false, false);
$productParams = ParamsHelper::getProductParams($productId, false, false);
Третий аргумент отключает наследование. Это удобно для проверки, задано ли значение прямо у категории или товара.
Ручное объединение
ParamsHelper::merge
$params = ParamsHelper::merge([
ParamsHelper::getComponentParams(),
$customParams,
]);
$value = $params->get('plugins.example.enabled', 0);
ParamsHelper::getComponentParams(),
$customParams,
]);
$value = $params->get('plugins.example.enabled', 0);
Используйте, когда наборы параметров собираются вручную и нужен тот же порядок перекрытия значений.
События расширения
| Событие | Когда использовать | Что получает обработчик |
|---|---|---|
onRadicalMartPrepareConfigForm | основная форма настроек | Получает Form $form и mixed $data. Здесь загружают XML с новыми fieldset и field, меняют атрибуты существующих полей или удаляют лишние поля. |
onRadicalMartPrepareConfigCurrencyForm | подформа валют | Получает Form $currencyForm. Используйте, если нужно добавить поля внутрь строки валюты, которая используется в subform currencies. |
onRadicalMartPrepareConfigGroups | левая навигация настроек | Получает массив $groups по ссылке. Здесь добавляют группы, секции, вкладки, fieldsets, fields, условия доступности и специальные шаблоны вывода. |
onContentNormaliseRequestData | подготовка POST перед validate | Это событие Joomla вызывается с context com_radicalmart.config. Оно полезно только когда нужно преобразовать данные запроса до стандартной валидации формы. |
Структура групп
| Ключ | Где используется | Что означает |
|---|---|---|
group | $groups['example'] | Верхний раздел левой навигации. У группы есть title, key, sections и при необходимости available. |
section | sections[] | Пункт внутри группы. Секция обязана иметь type: fieldsets, fields или tabs. |
tabs | type = tabs | Секция с внутренними вкладками. Каждая вкладка тоже имеет title, key, type и список fieldsets или fields. |
fieldsets | type = fieldsets | Список fieldset name из формы. Можно передавать строки или массивы с name и available. |
fields | permissions.com_radicalmart | Список отдельных полей. Если строка содержит точку, RadicalMart делит ее по последней точке: левая часть становится group, правая - name. |
template | seo, fieldsets, fields | Подшаблон секции или вкладки. Например seo выводит fieldset-ы рядом с таблицей shortcodes. |
layout | Joomla layout path | Альтернатива template. Layout получает displayData с view и подходит для нестандартного интерфейса. |
shortcodes | template = seo | Список секций shortcodes для SEO-шаблона. Если не указан, используется базовый набор. |
Непривязанные fieldset-ы
Если XML добавил fieldset в форму, но он не указан ни в одной группе, RadicalMart добавит его в служебную группу “Другие / Расширения”. Это удобно для быстрого результата, но для публичной интеграции лучше явно добавить свою группу или секцию.
Условия доступности
Пусто
доступно всегда
Если available не задан или пустой, группа, секция, вкладка, fieldset или field выводится без дополнительных условий.
remove
скрыть элемент
Значение remove выключает элемент из интерфейса. Это удобно, когда другой плагин должен убрать секцию из настроек.
shop
только режим магазина
Значение shop показывает элемент только когда режим RadicalMart равен shop.
multilanguage / associations
условия Joomla
Эти значения показывают элемент только при включенной мультиязычности или ассоциациях Joomla.
access
права доступа
Массив access проверяет права по asset и action, например com_radicalmart_bonuses / core.admin.
Строка или массив
оба варианта поддерживаются
Можно передать строку вроде shop или массив условий. Для access нужен массив с asset и actions.
Примеры
XML с настройками
forms/com_radicalmart.config.xml
<form addfieldprefix='Joomla\Component\RadicalMart\Administrator\Field'>
<fieldset name='example_settings' label='PLG_EXAMPLE_CONFIG' full_width='true'>
<fields name='plugins'>
<fields name='example'>
<field name='enabled' type='radio' label='PLG_EXAMPLE_ENABLED' default='0' class='btn-group btn-group-yesno'>
<option value='1'>JYES</option>
<option value='0'>JNO</option>
</field>
</fields>
</fields>
</fieldset>
</form>
<fieldset name='example_settings' label='PLG_EXAMPLE_CONFIG' full_width='true'>
<fields name='plugins'>
<fields name='example'>
<field name='enabled' type='radio' label='PLG_EXAMPLE_ENABLED' default='0' class='btn-group btn-group-yesno'>
<option value='1'>JYES</option>
<option value='0'>JNO</option>
</field>
</fields>
</fields>
</fieldset>
</form>
Загрузить XML
onRadicalMartPrepareConfigForm
public function onRadicalMartPrepareConfigForm(Form $form, mixed $data = []): void
{
$form->loadFile($this->formsPath . '/com_radicalmart.config.xml');
}
{
$form->loadFile($this->formsPath . '/com_radicalmart.config.xml');
}
Добавить группу
onRadicalMartPrepareConfigGroups
public function onRadicalMartPrepareConfigGroups(array &$groups): void
{
$groups['example'] = [
'title' => 'PLG_EXAMPLE_CONFIG',
'key' => 'example',
'sections' => [
'general' => [
'title' => 'COM_RADICALMART_CONFIG_GENERAL',
'key' => 'example-general',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
];
}
{
$groups['example'] = [
'title' => 'PLG_EXAMPLE_CONFIG',
'key' => 'example',
'sections' => [
'general' => [
'title' => 'COM_RADICALMART_CONFIG_GENERAL',
'key' => 'example-general',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
];
}
Секция с вкладками
type = tabs
'advanced' => [
'title' => 'PLG_EXAMPLE_ADVANCED',
'key' => 'example-advanced',
'type' => 'tabs',
'tabs' => [
'main' => [
'title' => 'PLG_EXAMPLE_MAIN',
'key' => 'example-advanced-main',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
]
'title' => 'PLG_EXAMPLE_ADVANCED',
'key' => 'example-advanced',
'type' => 'tabs',
'tabs' => [
'main' => [
'title' => 'PLG_EXAMPLE_MAIN',
'key' => 'example-advanced-main',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
]
Поля валюты
onRadicalMartPrepareConfigCurrencyForm
public function onRadicalMartPrepareConfigCurrencyForm(Form $currencyForm): void
{
$currencyForm->loadFile($this->formsPath . '/com_radicalmart.config.currency.xml');
}
{
$currencyForm->loadFile($this->formsPath . '/com_radicalmart.config.currency.xml');
}
Права доступа
rules + fields
<fields name='permissions'>
<field name='com_example' type='rules' label='JCONFIG_PERMISSIONS_LABEL' filter='unset' component='com_example' section='component' parentclass='stack' hiddenLabel='true' />
</fields>
<field name='com_example' type='rules' label='JCONFIG_PERMISSIONS_LABEL' filter='unset' component='com_example' section='component' parentclass='stack' hiddenLabel='true' />
</fields>
Для вывода такого поля в группе используйте строку permissions.com_example или массив с name/group.
PHP плагина целиком
src/Extension/ExampleConfig.php
<?php
namespace Joomla\Plugin\Radicalmart\ExampleConfig\Extension;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
defined('_JEXEC') or die;
final class ExampleConfig extends CMSPlugin implements SubscriberInterface
{
protected $autoloadLanguage = true;
protected string $formsPath = JPATH_PLUGINS . '/radicalmart/exampleconfig/forms';
public static function getSubscribedEvents(): array
{
return [
'onRadicalMartPrepareConfigForm' => 'onRadicalMartPrepareConfigForm',
'onRadicalMartPrepareConfigCurrencyForm' => 'onRadicalMartPrepareConfigCurrencyForm',
'onRadicalMartPrepareConfigGroups' => 'onRadicalMartPrepareConfigGroups',
];
}
public function onRadicalMartPrepareConfigForm(Form $form, mixed $data = []): void
{
$form->loadFile($this->formsPath . '/com_radicalmart.config.xml');
}
public function onRadicalMartPrepareConfigCurrencyForm(Form $currencyForm): void
{
$file = $this->formsPath . '/com_radicalmart.config.currency.xml';
if (is_file($file)) {
$currencyForm->loadFile($file);
}
}
public function onRadicalMartPrepareConfigGroups(array &$groups): void
{
$groups['example'] = [
'title' => 'PLG_EXAMPLE_CONFIG',
'key' => 'example',
'sections' => [
'general' => [
'title' => 'COM_RADICALMART_CONFIG_GENERAL',
'key' => 'example-general',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
];
}
}
namespace Joomla\Plugin\Radicalmart\ExampleConfig\Extension;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
defined('_JEXEC') or die;
final class ExampleConfig extends CMSPlugin implements SubscriberInterface
{
protected $autoloadLanguage = true;
protected string $formsPath = JPATH_PLUGINS . '/radicalmart/exampleconfig/forms';
public static function getSubscribedEvents(): array
{
return [
'onRadicalMartPrepareConfigForm' => 'onRadicalMartPrepareConfigForm',
'onRadicalMartPrepareConfigCurrencyForm' => 'onRadicalMartPrepareConfigCurrencyForm',
'onRadicalMartPrepareConfigGroups' => 'onRadicalMartPrepareConfigGroups',
];
}
public function onRadicalMartPrepareConfigForm(Form $form, mixed $data = []): void
{
$form->loadFile($this->formsPath . '/com_radicalmart.config.xml');
}
public function onRadicalMartPrepareConfigCurrencyForm(Form $currencyForm): void
{
$file = $this->formsPath . '/com_radicalmart.config.currency.xml';
if (is_file($file)) {
$currencyForm->loadFile($file);
}
}
public function onRadicalMartPrepareConfigGroups(array &$groups): void
{
$groups['example'] = [
'title' => 'PLG_EXAMPLE_CONFIG',
'key' => 'example',
'sections' => [
'general' => [
'title' => 'COM_RADICALMART_CONFIG_GENERAL',
'key' => 'example-general',
'type' => 'fieldsets',
'fieldsets' => ['example_settings'],
],
],
];
}
}
В этом варианте XML формы лежит рядом с плагином в forms/com_radicalmart.config.xml, а группа навигации добавляется тем же классом. Файл валютной подформы сделан необязательным: обработчик есть, но XML загружается только если файл реально создан.
Практические правила
-
Сначала проверьте плагин на локальной или отдельной копии сайта: открытие настроек, поиск, сохранение, повторное открытие и значения по умолчанию.
-
Читайте сохраненные значения через ParamsHelper. Для настройки из ветки plugins.example используйте путь plugins.example.enabled и всегда задавайте значение по умолчанию во втором аргументе get().
-
Для обычных сохраняемых настроек используйте реальные поля формы. Элементы note, spacer, rules и shortcodes не являются обычными параметрами компонента.
-
Если fieldset должен занять всю ширину секции, укажите full_width="true" в XML fieldset.
-
Для отдельных вложенных полей в группах используйте type = fields. Строка с точками делится по последней точке: group слева, name справа.
-
Ключи group, section и tab делайте уникальными. Одинаковые ключи затрудняют навигацию, поиск и расширение другими плагинами.
-
Если нужно только добавить или убрать XML-поля без логики, можно подготовить XML для RadicalMart Forms. Для групп, условий и валютной подформы лучше делать отдельный плагин.
ТЗ для генерации плагина ИИ
Если задачу нужно передать ИИ, дайте ему не только желаемые поля, но и правила RadicalMart: событие для загрузки XML, структуру групп, место хранения значений и ссылки для сверки. Тогда результат будет ближе к рабочему Joomla-плагину, а не к набору разрозненных XML-фрагментов.
| Что указать | Пример | Почему важно |
|---|---|---|
Плагин | group radicalmart, element exampleconfig | Так ИИ правильно соберет manifest, namespace, путь к forms и подписки на события. |
XML | forms/com_radicalmart.config.xml | Файл должен загружаться через onRadicalMartPrepareConfigForm, иначе поля не появятся в форме и не попадут в структуру сохранения. |
Навигация | group / section / type / fieldsets | Для красивого места в настройках нужен onRadicalMartPrepareConfigGroups. Иначе fieldset может оказаться в “Другие / Расширения”. |
Хранение | plugins.example.enabled | Путь значения должен соответствовать XML-структуре fields. Для вложенных параметров явно укажите все levels. |
Источники | доки RadicalMart и Joomla | Ссылки помогают ИИ сверить события, JForm field types, структуру плагина и готовый подход RadicalMart Forms. |
Готовый промпт
Создай Joomla 5 плагин группы radicalmart с element exampleconfig.
Назначение: добавить настройки RadicalMart без правки компонента.
Справка для сверки:
- документация по настройкам RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-add-config
- формы админки RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-admin-forms
- события RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-plugins-events
- пример простого XML-плагина: https://github.com/RadicalMart/RadicalMart-Forms
- Joomla CMS: https://github.com/joomla/joomla-cms
- стандартные поля Joomla Form: https://manual.joomla.org/docs/general-concepts/forms-fields/standard-fields/
Требования:
- подписаться на onRadicalMartPrepareConfigForm и onRadicalMartPrepareConfigGroups;
- если нужны поля валюты, добавить onRadicalMartPrepareConfigCurrencyForm;
- XML настроек хранить в forms/com_radicalmart.config.xml;
- добавить группу example, секцию general и fieldset example_settings;
- значения хранить в plugins.example;
- для чтения сохраненных значений использовать ParamsHelper::getComponentParams()->get('plugins.example.enabled', 0);
- вернуть manifest XML, services/provider.php, src/Extension/ExampleConfig.php, forms/*.xml и language/*.ini;
- не менять файлы RadicalMart и не использовать локальные абсолютные пути.
Назначение: добавить настройки RadicalMart без правки компонента.
Справка для сверки:
- документация по настройкам RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-add-config
- формы админки RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-admin-forms
- события RadicalMart: https://radicalmart.ru/baza-znanij/razrabotchikam/radicalmart-plugins-events
- пример простого XML-плагина: https://github.com/RadicalMart/RadicalMart-Forms
- Joomla CMS: https://github.com/joomla/joomla-cms
- стандартные поля Joomla Form: https://manual.joomla.org/docs/general-concepts/forms-fields/standard-fields/
Требования:
- подписаться на onRadicalMartPrepareConfigForm и onRadicalMartPrepareConfigGroups;
- если нужны поля валюты, добавить onRadicalMartPrepareConfigCurrencyForm;
- XML настроек хранить в forms/com_radicalmart.config.xml;
- добавить группу example, секцию general и fieldset example_settings;
- значения хранить в plugins.example;
- для чтения сохраненных значений использовать ParamsHelper::getComponentParams()->get('plugins.example.enabled', 0);
- вернуть manifest XML, services/provider.php, src/Extension/ExampleConfig.php, forms/*.xml и language/*.ini;
- не менять файлы RadicalMart и не использовать локальные абсолютные пути.