Для решения некоторых задач порой не хватает стандартного набора пользовательских полей поставляемых из «коробки» 1С Битрикс Управление сайтом. Однако вы можете создать свой собственный тип пользовательского поля, определить его внешний вид и даже подключить какие-нибудь сторонние jQuery плагины. В данной статье мы рассмотрим несколько таких полей:

  • Привязка к пользователю
  • Выбор цвета

Первый можно использовать для фиксации автора изменения записи в HL блоке, второй для изменения внешнего вида элемента на странице. И так приступим.

Находим подходящий стандартный тип поля

Естественно мы не будем писать всё с нуля и изобретать велосипеды, а подберём подходящий под наши задачи существующий класс реализующий нужный тип поля. Все классы пользовательских полей хранятся в главном модуле в папке /bitrix/modules/main/classes/general/ файлы классов имеют префикс usertype, здесь вы найдёте следующий набор классов:

  • usertypebool.php
  • usertypedate.php
  • usertypedbl.php
  • usertypeelement.php
  • usertypeenum.php
  • usertypefile.php
  • usertypeint.php
  • usertypesection.php
  • usertypestr.php
  • usertypestrfmt.php
  • usertypetime.php
  • usertypeurl.php
Как мы будем хранить значения? Очевидно что для пользователя это будет USER_ID, а для цвета строка, я предпочитаю hex формат  формат цвета. Следовательно нам потребуется скопировать и кастомизировать классы  usertypeenum (список) и usertypestr (строка).



В принципе USER_ID можно реализовать на основе usertypeint, но давайте дадим администратору возможность удобного выбора пользователя, к тому же возможно нам потребуется сделать это поле множественным.

Подготовка  init.php и пространства имён

Давайте для начала подготовим место где будем хранить все наши пользовательские классы, константы и обработчики событий. Я предпочитаю использовать папку local с вот такой структурой:

Структура папки local

первый делом рассмотрим init.php


<?php

//Константы
require dirname(__FILE__) . '/constants.php';

//Автозагрузка классов
require dirname(__FILE__) . '/autoload.php';

//Обработка событий
require dirname(__FILE__) . '/event_handler.php';


/**
 * обёртка для print_r() и var_dump()
 * @param $val - значение
 * @param string $name - заголовок
 * @param bool $mode - использовать var_dump() или print_r()
 * @param bool $die - использовать die() после вывода
 */
function print_p($val, $name = 'Содержимое переменной', $mode = false, $die = false){
    global $USER;
    if($USER->IsAdmin()){
        echo '<pre>'.(!empty($name) ? $name.': ' : ''); if($mode) { var_dump($val); } else { print_r($val); } echo '</pre>';
        if($die) die;
    }
}


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

Рассмотрим остальные файлы.

Файл constants.php


<?php

//Папка с пользовательскими классами
define('APP_CLASS_FOLDER', '/local/php_interface/lib/');
//Папка с медиа-файлами
define('APP_MEDIA_FOLDER', '/local/media/');


В константах я определил пару путей для удобства дальнейшего обращения к лежащим в них файлам.

Файл autoload.php


<?php

use Bitrix\Main\Loader;

//Автозагрузка наших классов
Loader::registerAutoLoadClasses(null, [
    'lib\UserType\CUserTypeUserId' => APP_CLASS_FOLDER . 'UserType/CUserTypeUserId.php',
    'lib\UserType\CUserTypeColor' => APP_CLASS_FOLDER . 'UserType/CUserTypeColor.php'
]);

А здесь вызовем загрузчик классов битрикс и добавим в него массив с нашими будущими классами (ссылка на документацию).

Файл event_handler.php


<?php

use Bitrix\Main;
$eventManager = Main\EventManager::getInstance();

//Вешаем обработчик на событие создания списка пользовательских свойств OnUserTypeBuildList
$eventManager->addEventHandler('main', 'OnUserTypeBuildList', ['lib\UserType\CUserTypeUserId', 'GetUserTypeDescription']);
$eventManager->addEventHandler('main', 'OnUserTypeBuildList', ['lib\UserType\CUserTypeColor', 'GetUserTypeDescription']);


Чтобы наши кастомные свойства были доступны в списке выбора типа пользовательского поля, нам необходимо перехватить событие создания этого списка и дополнить его своими типами свойств, вызвав зарезервированный метод GetUserTypeDEscription.

Создаём класс для определения своего пользовательского свойства

Как вы уже поняли и листинга файла с константами, наши классы будут лежать в директории /local/php_interface/lib/. Я предпочитаю разделять собственные классы на группы по директориям, например классы для работы с инфоблоками храню в папке Iblock, работы с каталогом в Catalog, для пользовательских свойств предлагаю создать папку UserType.

И так в директории /local/php_interface/lib/UserType/ создадим 2 файла CUserTypeUserId.php и CUserTypeColor.php. Начнём со свойства «Привязка к пользователю».  Определим пространство имён, подключим доп.классы ядра.


<?

namespace lib\usertype;

use \Bitrix\Main,
    \Bitrix\Main\Localization\Loc,
    \Bitrix\Main\UserField;

class CUserTypeUserId
{

    /**
     * Метод возвращает массив описания собственного типа свойств
     * @return array
     */
    public function GetUserTypeDescription()
    {
        return array(
            "PROPERTY_TYPE" => 'N' // S - строка, N - число и т.д.
            "USER_TYPE" => 'userid', //Уникальный идентификатор типа свойств
            "CLASS_NAME" => __CLASS__,
            "DESCRIPTION" => 'Привязка к пользователю',
            "BASE_TYPE" => \CUserTypeManager::BASE_TYPE_INT,
        );
    }

    /**
     * Обязательный метод для определения типа поля таблицы в БД при создании свойства
     * @param $arUserField
     * @return string
     */
    function GetDBColumnType($arUserField)
    {
        global $DB;
        switch(strtolower($DB->type))
        {
            case "mysql":
                return "int(18)";
            case "oracle":
                return "number(18)";
            case "mssql":
                return "int";
        }
        return "int";
    }

}




  В принципе, этого достаточно чтобы наш новый тип свойств появился в этом списке:

Свойства привязка к пользователю

Однако, пока что оно бесполезно. Давайте добавим недостающие методы:
  • GetList() — Получаем список значений
  • GetEditFormHTML() — Получить HTML формы для редактирования свойства
  • GetEditFormHTMLMulty() — Получить HTML формы для редактирования МНОЖЕСТВЕННОГО свойства
  • GetAdminListViewHTML() — Получаем HTML для списка элементов в админке
  • getEmptyCaption() — Получаем текст для пустого значения свойства
  • GetAdminListEditHTML() — Получить HTML для редактирования свойства в списке админ-панели
  • GetAdminListEditHTMLMulty() — Получить HTML для редактирования МНОЖЕСТВЕННОГО свойства в списке админ-панели
  • GetFilterHTML() — Получаем HTML блок для фильтрации списка элементов по этому свойству

Я не стану размещать здесь все методы, хочу отметить лишь GetList(), т.к. в стандартных классах он обычно возвращает объект CDBResult, а мне больше нравится подготовить данные для отображения заранее, поэтому в нём я получаю массив значений для отрисовки его в методах GetEditFormHTML() и подобных:


    /**
     * Получаем список значений
     * @param $arUserField
     * @return array|bool|\CDBResult
     */
    public function GetList($arUserField)
    {
        $rsEnum = [];
        //GROUPS_ID - Администраторы, контент редакторы
        $dbResultList = \CUser::GetList(($by='id'), ($order='asc'), ['GROUPS_ID'=>[1, 5]]);
        while ($arResult = $dbResultList->Fetch()){
            $rsEnum[] = [
                'ID' => $arResult['ID'],
                //Формат отображения значений
                'VALUE' => $arResult['NAME'] . ' ' . $arResult['LAST_NAME'] . ' (' . $arResult['EMAIL'] . ')'
            ];
        }

        return $rsEnum;
    }


Оба класса целиком вы найдёте в конце статьи. Подключив полноценный класс мы получаем вот такое свойство:

Выбор значения собственного свойства

За вывод этого списка отвечает метод GetEditFormHTML(). В настройках свойства так же можно включить множественный вариант его работы, который выглядит так:

Множественный вариант свойства
В данном случае работает метод GetEditFormHTMLMulty(). Если у класса корректно определены метод
  • GetAdminListViewHTML()
  • GetAdminListEditHTML()
  • GetAdminListEditHTMLMulty()

Значение свойств будут так же корректно отображаться и редактироваться в списке элементов:

Множественное свойство в списке и фильтре

На скриншоте виден так же блок фильтрации, он определяется методом GetFilterHTML() . Чтобы вывести собственное свойство в фильтр его можно добавить в настройках формы фильтра так:

Фильтр списка



Это свойство можно применять для того, чтобы связать запись HL блока с пользователем создавшим её или внёсшим в неё изменения, ставить ответственного за обработку записи (например если хранить в HL блоке какие-то не стандартные заявки от посетителей) и многое другое.

Пользовательское свойство «Цвет»

Давайте разберёмся с более экзотическим классов «Цвет». Иногда нужно дать возможность контент-менеджеру определять цветовую схему элемента (новости, статьи или какой-то части её оформления), обычно для этого создаётся простое свойство типа «строка» куда записывается цвет скопированный из Photoship или ColorPicker, однако это требует больше действий от контентщика. Давайте реализуем такой функционал прямо внутри элемента.

За основу возьмём стандартный класс типа пользовательского поля «Строка» и определим для него необычный внешний вид (метод GetEditFormHTML()) . Нам так же потребуется какой-нибудь jQuery плагин для выбора цвета, я остановил свой выбор на jQuery ColorPicker он обладает нужным функционалом имеет необходимые события и довольно прост в настройке.

И так, для начала скачаем этот плагин и загрузим всё в /local/media/ как помните выше я определил константу APP_MEDIA_FOLDER.

Создаём класс для свойства «Цвет»

Как и для первого класса нам нужно определить метод GetUserTypeDescription который будет вызван в момент построения списка доступных пользовательских свойств.


<?php

namespace lib\usertype;

use \Bitrix\Main,
    \Bitrix\Main\Localization\Loc,
    \Bitrix\Main\UserField,
    Bitrix\Main\Page\Asset;


class CUserTypeColor
{
    const USER_TYPE_ID = 'color';

    /**
     * Обработчик события OnUserTypeBuildList.
     *
     * <p>Эта функция регистрируется в качестве обработчика события OnUserTypeBuildList.
     * Возвращает массив описывающий тип пользовательских свойств.</p>
     * <p>Элементы массива:</p>
     * <ul>
     * <li>USER_TYPE_ID - уникальный идентификатор
     * <li>CLASS_NAME - имя класса методы которого формируют поведение типа
     * <li>DESCRIPTION - описание для показа в интерфейсе (выпадающий список и т.п.)
     * <li>BASE_TYPE - базовый тип на котором будут основаны операции фильтра (int, double, string, date, datetime)
     * </ul>
     * @return array
     * @static
     */
    function GetUserTypeDescription()
    {
        return array(
            "USER_TYPE_ID" => static::USER_TYPE_ID,
            "CLASS_NAME" => __CLASS__,
            "DESCRIPTION" => 'Выбор цвета',
            "BASE_TYPE" => \CUserTypeManager::BASE_TYPE_STRING,
        );
    }


Самый примечательный метод здесь это GetEditHTML()


  /**
     * Эта функция вызывается при выводе формы редактирования значения свойства.
     *
     * <p>Возвращает html для встраивания в ячейку таблицы.
     * в форму редактирования сущности (на вкладке "Доп. свойства")</p>
     * <p>Элементы $arHtmlControl приведены к html безопасному виду.</p>
     * @param array $arUserField Массив описывающий поле.
     * @param array $arHtmlControl Массив управления из формы. Содержит элементы NAME и VALUE.
     * @return string HTML для вывода.
     * @static
     */
    function GetEditFormHTML($arUserField, $arHtmlControl)
    {

        if(!$arUserField['VALUE']){
            $arHtmlControl['VALUE'] = htmlspecialcharsbx($arUserField["SETTINGS"]["DEFAULT_VALUE"]);
        } else {
            $arHtmlControl['VALUE'] = $arUserField['VALUE'];
        }

        //CSS файлвы не захотели подключаться через Asset::getInstance()->addCss() поэтому подтягиваем
        // их через HTML загружаемый на странице редактирования свойства
        $return = '	<link rel="stylesheet" href="' . APP_MEDIA_FOLDER .'css/colorpicker.css?v='. md5(date("h:i:s")) .'" type="text/css" />
        <link rel="stylesheet" media="screen" type="text/css" href="' . APP_MEDIA_FOLDER .'css/layout.css?v='. md5(date("h:i:s")) .'" />';

        \CJSCore::Init(['jquery2']);

        Asset::getInstance()->addJs(APP_MEDIA_FOLDER . 'js/colorpicker.js');
        Asset::getInstance()->addJs(APP_MEDIA_FOLDER . 'js/CUserTypeColor.js');

        $return = $return . '<div id="colorpickerHolder"></div><input id="colorpickerHolderInput" type="text" name="' . $arHtmlControl['NAME'] . '" value="'. $arHtmlControl['VALUE'] .'">';

        return $return;
    }


В нём я подключаю css и js файлы плагина и пользовательский CUserTypeColor.js в котором осуществляется запуск плагина и указаны его настройки. Здесь блок colorpickerHolder предназначен для отрисовки формы выбора цвета а в поле  colorpickerHolderInput записывается значение света, когда пользователь меняет параметры в форме или выбирает цвет на палитре при помощи мышки.  Т.к. это демонстрационный пример, методы типа GetAdminListViewHTML() унаследованы у пользовательского типа «Строка» и просто выводят значение цвета в виде HEX-кода.

В результате подключения такого класса и создания пользовательского свойства типа «Цвет» получаем вот такой вот функционал:

Собственное свойство выбор цвета

Его можно использовать для подсветки важных элементов в списке или другого визуального оформления страницы. Как и обещал все материалы из статьи прикреплю в виде архива.

Желаю удачи!


Спсиок файлов к статье (исходники)
Полезная статья?
(Голосов: 22, Рейтинг: 3.91)
Вам также могут понравиться
Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как правильно подключать стили и скрипты к шаблону 1С Битрикс.

Генерация оглавления статьи

Генерация оглавления статьи

В статье рассмотрен пример функции для генерации оглавления статьи блога или новости

Переменные доступные в компоненте 1С Битрикс

Переменные доступные в компоненте 1С Битрикс

В статье разобран список доступных в компоненте 1С Битрикс переменных, позволяющих получить доступ к различным параметрам и методам компонента.


Комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
19.03.2024 | Денис

Только это не работает для добавления пользовательского типа поля в карточку CRM->Сделки, во всплывашке добавленное пользовательское поле не отображается.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Александр Андреев

Описанный в статье функционал не относится к "1С Битрикс CRM" или "Битрикс 24", реализация этих свойств делалась для 1С Битрикс Управление сайтом, это немного разные продукты. Думаю вам следует поискать то, как реализованы свойства доступные в CRM->Сделки и сделать по аналогии с теми классам.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Денис

А где этот функционал смотреть, в каком инфоблоке? Я нашёл только где посмотреть добавленный тип поля, где можно посмотреть всё остальное?

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Александр Андреев

Это тип пользовательских полей, не свойств инфоблока. Список пользовательских полей находится в админке, Настройки -> Настройки продукта -> Пользовательские поля. Вот здесь когда вы создаёте новое поле, вы выбираете его тип (строка, число и т.п.) и тут в списке типов будет ваш собственный тип поля (если всё сделано верно). Если вам необходимо создать пользовательское свойство какаого-то хитрого типа в инфоблоке, чтобы потом оно было доступно элементам этого инфоблока, то вам в другую статью https://it-svalka.ru/blog/bitrix/polzovatelskiy-tip-svoystv-infobloka-v-1s-bitriks/ ))

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Андрей

Все получилось. спасибо автору!

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Егор

толку нет, ошибка идет.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Александр Андреев

Опишите детальнее что за ошибка.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Евгений

Тоже столкнулся с ошибкой. При попытке добавления пользовательского поля с новым типом данных ошибка "Ошибка сохранения поля". Возможно, в последних версиях битрикса что-то изменилось.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Ольга

Та же ошибка. Наблюдается, даже если закомментировать все методы,кроме описания поля(GetUserTypeDescription). Однако, если поле сделать множественным - оно сохраняется. P.S.Удивительно, но я тоже именно сегодня(19.03.2022) натолкнулась на статью и попробовала применить на проекте =)

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Александр Андреев

Евгений спасибо! Постараюсь на неделе разобраться и обновить статью

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Алекскандр

после всего сделанного у меня в карточке сделки при создании поля "выбор цвета" пишет ошибку Cannot find 'color' template with page ''. Не могу понять какой шаблон ни не находит.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
19.03.2024 | Александр Андреев

Вообще эта ошибка говорит о том что битрикс не может найти (или получить доступ) к шаблону компонента color . Он указывается в вызове компонента на странице. Т.е. ошибка скорее всего не связана с внедрением класса из статьи. Если не получится разобраться, напишите в группе vk, постараюсь помочь.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
10.02.2021 | Екатерина Владимировна

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

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть