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
7
6 199
+26
Поблагодарить автора Отправить деньги

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

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 не применимо?
            К свойствам товара нет.
              Артур Шевченко
              21 мая 2022, 15:17
              0
              К свойствам понятно почему не применимо, они в другой таблице, но почему когда я работаю с товарами как с обычными ресурсами, т.е.
              $resource = $modx->getObject('modResource', 66);
              $resource->set('customfield', 'abcd');
              $resource->save();
              customfield остаётся пустым?
              И у товаров добавленные через этот компонент поля не отображаются на вкладке Документ. Это можно как-то исправить или надо создавать аналогичные поля но уже в таблице ms2_products?
                Aleksandr Huz
                22 мая 2022, 21:18
                0
                Для минишопа нет поддержки. Не отображается, потому что там другой js
            Андрей
            02 февраля 2022, 23:22
            2
            +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
              Это просто бомба! А тем более бесплатно, вообще огонь! Спасибо.
                R2m0x94 (Vasily)
                04 июня 2022, 23:34
                0
                Как добавить выпадающий список и какой phptype, dbtype должен быть для выпадающего списка, чтобы в профиле пользователя он был, такой как пол или страна?

                Попробовал добавить тип modx-combo в профиль пользователя, но не могу понять какой тип указывать, так как он trigger, то phptype вроде бы должен быть twintrigger, пробовал json, так он объект в объекте показывает, нет выпадашки, точнее как добавить Ext, в сам компонент. В какой файл?
                  R2m0x94 (Vasily)
                  05 июня 2022, 02:17
                  0
                  Сам спросил, сам ответил: dbtype:varchar, phptype:string, что там такого, а в Ext.form.ComboBox пишешь store: new Ext.data.ArrayStore
                    alex
                    01 августа 2022, 21:14
                    +1
                    Подскажи пожалуйста, куда именно добавить в js список значений?
                      R2m0x94 (Vasily)
                      01 августа 2022, 21:21
                      0
                      Ну я в плагин добавил на событие OnUserFormPrerender и всё хорошо.
                        alex
                        01 августа 2022, 22:03
                        0
                        Покажи код, пожалуйста )
                  Сергей Карпович
                  19 октября 2022, 11:35
                  0
                  Ребята, подскажите как задать свои значения для поля combo-boolean в профиле?
                  Мне нужно что бы там был выбор из 3-х значений: нет, оплачено, волонтер.

                  Создал поле combo-boolean, а там только да/нет
                    Алексей Смирнов
                    20 октября 2022, 15:35
                    0
                    попробуйте combo-box или listbox. Возможно что-то сработает, но не уверен — не пробовал.
                  Константин Ильин
                  10 ноября 2022, 17:17
                  0
                  Подскажите пожалуйста как добавить поле в этот блок disk.yandex.ru/i/JO2k8V_j5WY9TQ

                  В выборе блока, только две колонки ресурса
                  disk.yandex.ru/i/FHSxVIv6LIil3Q

                  В пхп нашел куда добавить выбор поля
                  disk.yandex.ru/i/j00S9ujOIs3v0Q

                  Но в js к сожалению не пойму
                  disk.yandex.ru/i/r4yH_MMEsU0FxA
                    Сергей
                    28 сентября 2023, 12:48
                    0
                    Спасибо, плагин отлично работает. Единственное, сильно не хватает возможности создать поле типа Файл.
                      Сергей Карпович
                      19 октября 2023, 08:54
                      0
                      Тоже интересует вопрос, как созданные поля перемещать по форме ресурса…
                      И также вопрос как отключать созданные поля для отдельных шаблонов?
                        Смайл
                        07 января 2024, 00:04
                        0
                        не могу понять как вывисти в шаблон поля?
                        Как [[+pice_1]] не отображается почему?
                          snowdog178
                          18 апреля 2024, 21:54
                          0
                          Не отображаются добавленные поля в редактировании пользователя.
                          Добавил одно поле в «общую информацию», для другого создал вкладку, в ней ещё вкладку и в ней уже поле.
                          Созданные вкладки отображаются, а вот поля — нет.
                          Что я делаю не так?
                          В датабазе добавленные поля есть, я им даже напрямую задал значения у одного пользователя, всё равно не отображаются.
                            Кровельный
                            07 мая 2024, 11:38
                            0
                            MODX Revolution 2.8.3-pl
                            Ace 1.9.4-pl
                            При выборе ACE ошибка:
                            Uncaught TypeError: Cannot read properties of null (reading 'match')
                                at a.$detectNewLine (ace.min.js?v=2.9.3-pl:1:120718)
                                at a.insert (ace.min.js?v=2.9.3-pl:1:122464)
                                at a.setValue (ace.min.js?v=2.9.3-pl:1:120356)
                                at p.setValue (ace.min.js?v=2.9.3-pl:1:153026)
                                at S.setValue (modx.texteditor.js?v=2.9.3-pl:185:38)
                                at constructor.setValues (ext-all.js:21:603600)
                                at miniShop2.panel.UpdateCategory.setup (modx.panel.resource.js?v=2.9.3-pl:57:28)
                                at h.Event.fire (ext-all.js:21:3699)
                                at miniShop2.panel.UpdateCategory.fireEvent (ext-all.js:21:687)
                                at MODx.FormPanel [as constructor] (modx.panel.js:62:14)
                            Как выбрать текстовый редактор?
                              Lori
                              13 мая 2024, 12:48
                              0
                              Установил компонент. PHP 7.4, Modx 2.8.4. Созданные кастомные поля юзера не отображаются, в логе ошибка:
                              No foreign key definition for parentClass: efFieldAbs using relation alias: Tab
                                Сергей Карпович
                                24 июня 2024, 09:51
                                0
                                После обновления компонента на последнюю версию — пропали ранее созданные поля.
                                Кто знает как вернуть?
                                  Дмитрий
                                  03 сентября 2024, 15:07
                                  0
                                  начиная со 2й версии на modx 2.8.7 компонент валит админку в 500…

                                  2024/09/03 14:28:11 [error] 1762146#1762146: *32171 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined method ExtraFields::getTableFields() in /var/www/site_user/data/www/site.ru/core/cache/includes/elements/modplugin/53.include.cache.php:44
                                  Stack trace:
                                  #0 /var/www/site_user/data/www/site.ru/core/model/modx/modscript.class.php(76): include()
                                  #1 /var/www/site_user/data/www/site.ru/core/model/modx/modx.class.php(1674): modScript->process(NULL)
                                  #2 /var/www/site_user/data/www/site.ru/core/model/modx/modx.class.php(570): modX->invokeEvent('OnMODXInit', Array)
                                  #3 /var/www/site_user/data/www/site.ru/manager/index.php(53): modX->initialize('mgr')
                                  #4 {main}
                                    thrown in /var/www/site_user/data/www/site.ru/core/cache/includes/elements/modplugin/53.include.cache.php on line 44" while reading response header from upstream, client: 10.10.10.10, server: site.ru, request: "GET /manager/?a=workspaces HTTP/2.0", upstream: "fastcgi://unix:/var/run/site.ru.sock:", host: "site.ru", referrer: "https://site.ru/manager/?"

                                  53-й плагин — это плагин ExtraFields
                                    Aleksandr Huz
                                    03 сентября 2024, 17:51
                                    0
                                    Уже исправлено. Спасибо @Михаил
                                      Дмитрий
                                      06 сентября 2024, 12:27
                                      0
                                      Спасибо, Александр. В целом, удаление 1-й версии перед установкой 2-й помогает, но теряются все заполненные поля соответственно.
                                    Сергей Карпович
                                    09 октября 2024, 17:17
                                    0
                                    Всем привет. Снес старую версию компонента ExtraFields, установил новую.
                                    Пытаюсь создать поле: получаю ошибку: «Ошибка при сохранении поля.»

                                    И в логах:
                                    Error 42S22 executing statement:
                                    INSERT INTO `modx_ef_fields` (`class_name`, `field_name`, `field_type`, `field_null`, `field_index`, `field_default`, `menuindex`, `active`) VALUES ('modUserProfile', 'agreed', 'xcheckbox', 0, 0, '0', 0, 1)
                                    Array
                                    (
                                        [0] => 42S22
                                        [1] => 1054
                                        [2] => Unknown column 'field_index' in 'field list'
                                    )
                                      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                                      38