ExtraFields. Дополнительные поля для ресурса (modResource) и пользователя (modUserProfile).

Привет, друзья!
Представляю компонент, который предназначен для добавления новых полей в ресурсе и профиле пользователя. Работает в MODx 2 / 3.

Ресурс (modResource)



При создании поля добавляется соответствующая колонка в таблице site_content (modResource).
При обновлении можно изменить все, кроме название самого поля в таблице.
При удалении удаляется колонка в таблице.

Настройка поля



  • Имя поля — название колонки в таблице.
  • Название поля — заголовок поля, которое отображается над полем.
  • Расположение — место где будет вставлено поле. Главная вкладка ресурса имеет 2 колонки: левая (modx-resource-main-left) и правая (modx-resource-main-right). Вы можете разместить поле в любую колонку или в свою вкладку.
  • Индекс — позиция поля по отношению к другим полям. Если 0, то поле будет отображаться в самом вверху, выше всех других полей в этой колонке или вкладке.
  • Тип поля — тип отображаемого поля. Это может быть текстовое или числовое поле, может быть чекбокс и т.д. Смотрите в разделе **Поля**.
  • Обязательное поле — не дает ресурсу сохраниться, если поле будет не заполнено.
  • Включено — показывать поле в ресурсе или нет.

Вкладки ресурса



Для создание дополнительных вкладок нужно перейти в панель администрирования (кнопка справа вверху).

Настройка вкладки



  • Название — название вкладки
  • Позиция — позиция вкладки по отношению к другим вкладкам. 0 — будет отображено в самом начале, а 99 — в самом конце.
  • Включено — показывать вкладку в ресурсе или нет.

Профиль пользователя (modUserProfile)



При создании поля добавляется соответствующая колонка в таблице user_attributes (modUserProfile).

Настройка поля



  • Имя поля — название колонки в таблице.
  • Название поля — заголовок поля, которое отображается над полем.
  • Расположение — место где будет добавлено поле на главной вкладке профиля пользователя.
  • Индекс — позиция поля по отношению к другим полям. Если 0, то поле будет отображаться в самом вверху, выше всех других полей в этой колонке или вкладке.
  • Тип поля — тип отображаемого поля. Это может быть текстовое или числовое поле, может быть чекбокс и т.д. Смотрите в разделе **Поля**.
  • Обязательное поле — не дает пользователю сохраниться, если поле будет не заполнено.
  • Включено — показывать поле в профиле или нет.

Поля



Таблица возможных типов полей. Для редактирование нужно перейти в панель администрирования.
Доступные поля:
Также вы можете добавлять свои поля.

Настройка поля



  • Название — xtype поле
  • dbtype — тип поля в базе данных
  • precision — размер поля
  • phptype — тип переменной в php
  • null — может ли поле иметь значение null или нет.
  • default — значение по умолчанию

Совместимость


Компонент совместим с MODx 3 благодаря алиасам. В комментарии файла пишут, что в будущем, в версии 3.3 или 3.4, данный файл не будет автоматически подключаться. Я уверен, что это будущее не наступит в ближайшее пол года, поэтому можно спокойно делать компоненты совместимые с обоими версиями. Но, это чисто мое мнение, авторы сами решают как делать свои компоненты.

Проблемы


А вот с какими проблемами столкнулся я.

1. Карта классов
Все помнят статью Васи Наумкина Расширение любых таблиц MODX

Вот код для MODx 2:
<?php
switch ($modx->event->name) {
	case 'OnMODXInit':
		$modx->loadClass('modResource');
		$modx->map['modResource']['fields']['manager_id'] = 0;
		$modx->map['modResource']['fieldMeta']['manager_id'] = array(
			'dbtype' => 'int',
			'precision' => 10,
			'attributes' => 'unsigned',
			'phptype' => 'integer',
			'null' => true,
			'default' => 0,
		);
		break;
}

Но в MODx 3 такое не работает, из-за того, что $modx->map — это уже не массив, а объект, который реализован через интерфейс ArrayAccess. Спасибо @Сергей Шлоков
Вот сам класс — github.com/modxcms/xpdo/blob/3.x/src/xPDO/xPDOMap.php
Он позволяет работать с объектом как с одномерным массивом, поэтому решение для MODx 3 такое:

<?php

use MODX\Revolution\modResource;

switch ($modx->event->name) {
	case 'OnMODXInit':
                // Сохраняем карту класса в переменную
		$map = $modx->map[modResource:class];
                
                // Теперь работаем с данной переменной
		$map['fields']['manager_id'] = 0;
		$map['fieldMeta']['manager_id'] = array(
			'dbtype' => 'int',
			'precision' => 10,
			'attributes' => 'unsigned',
			'phptype' => 'integer',
			'null' => true,
			'default' => 0,
		);
                
                // Обновляем нашу карту класса.
                $modx->map[modResource:class] = $map;
		break;
}

2. getService
Решил это, думал, что уже все, но нет! @Павел Бигель написал в телеграмм чате, что метод getService будет удален в версии 3.1, а это уже не за горами. Поэтому пришлось переделывать, подключать автозагрузку класса и заменить

вот это
$extrafields = $modx->getService('extrafields', 'ExtraFields', MODX_CORE_PATH . 'components/extrafields/model/');
на это:
if ($modx->services instanceof Psr\Http\Client\ClientInterface) {
    $extrafields = $modx->services->get('extrafields');
} else {
    $extrafields = $modx->getService('extrafields', 'ExtraFields', MODX_CORE_PATH . 'components/extrafields/model/');
}
Таким образом, для MODx 3 мы используем контейнер зависимости, а во 2 версии метод getService.

3. Текстовый редактор.
Следующая проблема была с текстовым редактором, дело в том, что если добавить данное поле (richtext) в ресурс то при сохранении ресурса будет ошибка связана с экранированием символов, хотя все поля будут сохранены.
Начинаем изучать код процессора update для ресурса и видим, что проблема в этом:
$returnArray = $this->object->get(array_diff(array_keys($this->object->_fields), array('content','ta','introtext','description','link_attributes','pagetitle','longtitle','menutitle', 'properties', 'resource_groups')));
foreach ($returnArray as $k => $v) {
  if (strpos($k,'tv') === 0) {
        unset($returnArray[$k]);
    }
}

...
return $this->success('',$returnArray);

То есть все стандартные поля и TV вырезаются, поэтому TV c типом richtext работает без ошибок. Этот метод вызывается после сохранения объекта, значит нужно чтобы эти поля не участвовали в формирование массива $returnArray.
Первое что в голову пришло, это очистить новые поля с типом richtext после сохранения ресурса:
if ($modx->event->name == 'OnDocFormSave') {
    $resource->set('customfield', '');
}

И да, это сработало! Но, если указать парный тег в простом поле, то снова получим ошибку((
Тогда, посмотрев внимательно, нашел решение:
if ($modx->event->name == 'OnDocFormSave') {
    unset($resource->_fields['customfield']);
}

Вот и все, проблема решена. Если у кого-то есть другое решение, то пишите в комментарии.

Buy me a coffee


Компонент можно скачать бесплатно с официального репозитория или модстора.
Если компонент был вам полезен, то вы можете угостить меня чашечкой кофе.
Aleksandr Huz
01 февраля 2022, 18:52
modx.pro
5
1 882
+26
Поблагодарить автора Отправить деньги

Комментарии: 16

Sinaite
01 февраля 2022, 19:15
0
Добрый! Подскажите, а в чем преимущество создания дополнительных полей ресурса через данный плагин перед стандартными TV?
    Роман
    01 февраля 2022, 19:22
    +1
    Как минимум в скорости выборки.
      Павел Бигель
      01 февраля 2022, 19:32
      0
      TV к modUserProfile как представляешь себе?)
        Sinaite
        01 февраля 2022, 19:44
        0
        С юзерами понятно, я конкретно про ресурс спрашивал.
        Aleksandr Huz
        01 февраля 2022, 19:55
        +1
        Добрый!
        1. Нет лишних запросов в БД.
        2. Фильтровать по родному полю быстрее чем по TV.
        3. Удобство при создании/обновлении ресурса через API.
          Stepan
          01 февраля 2022, 20:59
          0
          ну в фильтрации может и поможет, но как быть указанием данных, т.е. тут не хватает списков, а это оч печально.
            Aleksandr Huz
            01 февраля 2022, 21:25
            +2
            Не, все сразу. Будет еще улучшение компонента.
        Руслан Алеев
        01 февраля 2022, 20:13
        0
        Здравствуйте, спасибо за компонент!
        А можете скрин добавить, как заполненные поля и вкладки в админке выглядят? Не в ресурсе/профиле, а именно сам список добавленных полей.
          Aleksandr Huz
          01 февраля 2022, 20:15
          +1
          Добрый!

            Руслан Алеев
            01 февраля 2022, 21:01
            +1
            Огонь, пасиб!
            В будущих версиях стоит в сетку еще и «Вкладку» отображать, чтоб проще фильтровать.
          Сергей
          02 февраля 2022, 22:00
          0
          Данный компонент делает поля для всех шаблонов? Т.е. разделять по шаблонам нельзя?
          К товарам в MS не применимо?
            Aleksandr Huz
            02 февраля 2022, 22:11
            0
            Данный компонент делает поля для всех шаблонов? Т.е. разделять по шаблонам нельзя?
            Это будет в след. версии.

            К товарам в MS не применимо?
            К свойствам товара нет.
              Артур
              4 часа назад
              0
              К свойствам понятно почему не применимо, они в другой таблице, но почему когда я работаю с товарами как с обычными ресурсами, т.е.
              $resource = $modx->getObject('modResource', 66);
              $resource->set('customfield', 'abcd');
              $resource->save();
              customfield остаётся пустым?
              И у товаров добавленные через этот компонент поля не отображаются на вкладке Документ. Это можно как-то исправить или надо создавать аналогичные поля но уже в таблице ms2_products?
              Андрей
              02 февраля 2022, 23:22
              1
              +4
              К товарам в MS не применимо?
              Для расширения полей минишопа и так есть 2 компонента — msFieldsManager и msAddField
                Rootiys
                13 мая 2022, 00:04
                0
                Данный компонент делает поля для всех шаблонов? Т.е. разделять по шаблонам нельзя?
                Можно поля разделить по вкладкам. В настройках форм добавить области, которые скрыть нужно для конкретного шаблона. Ну и скрываем их соответственно.

                В настройках форм id области указываем modx-resource-extrafields-[id вкладки созданной в настройках ExtraFields]. Например modx-resource-extrafields-2
                Илья Уткин
                08 февраля 2022, 22:24
                +3
                Это просто бомба! А тем более бесплатно, вообще огонь! Спасибо.
                  Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                  16