Работа с фильтрами сотрудника
Как мы уже обсудили, фильтр представляет собой сложную систему из полей, пресетов и выбранных значений, что на практике намного сложнее и неповоротливее чем нам бы хотелось. Если мы зайдем с технической стороны, то фильтр состоит из пресетов и все это складывается в так называемую конфигурацию. Конфигурация индивидуальна.
Конфигурация
Как любая индивидуальная настройка конфигурация фильтра хранится в таблице b_user_option
со следующими параметрами:
-
CATEGORY = main.ui.filter
(категория всегда фиксирована) -
NAME = <filterId>
(<filterId>
- идентификатор фильтра) -
VALUE = <data>
(<data>
- строка, сериализованная php-методомserialize
для хранения конфигурации).
Из чего состоит конфигурация и что собственно сериализуется?
Структура состоящая из полей:
-
filters
(array) - ассоциативный набор пресетов, -
filter
(string) - идентификатор текущего выбранного фильтра, -
default
(string) - идентификатор пресета назначенного по-умолчанию, -
default_presets
(array) - ассоциативный набор пресетов по-умолчанию (доступных в системе), -
deleted_presets
(array) - ассоциативный набор<presetId> => true
в котором содержатся перечни исключенных пресетов (из перечня стандартных тех что были удалены). -
use_pin_preset
(bool) - один из флагов отвечающий за закрепление фильтра.
Пример десериализованной конфигурации:
[
'use_pin_preset' => true,
'deleted_presets' => [],
'default_presets' => [],
'default' => 'filter_1678877570797',
'filter' => 'filter_1678877570797',
'filters' => [
'filter_in_work' => [
'name' => 'Лиды в работе',
'fields' => [
'TITLE' => '',
'STATUS_SEMANTIC_ID' => [
0 => 'P',
]
],
'filter_rows' => 'TITLE,STATUS_SEMANTIC_ID',
'for_all' => false,
'sort' => '0',
],
'filter_1678877570797' => [
'name' => 'asd',
'fields' => [
'TITLE' => '',
'OPPORTUNITY_from' => '',
'OPPORTUNITY_to' => '',
'OPPORTUNITY_numsel' => 'exact',
'DATE_CREATE_datesel' => 'NONE',
'DATE_CREATE_from' => '',
'DATE_CREATE_to' => '',
'DATE_CREATE_days' => '',
'DATE_CREATE_month' => '',
'DATE_CREATE_quarter' => '',
'DATE_CREATE_year' => '',
],
'filter_rows' => 'TITLE,OPPORTUNITY,DATE_CREATE',
'sort' => '5',
'for_all' => false,
],
'tmp_filter' => [
'name' => 'Лиды в работе',
'fields' => [
'TITLE' => '',
'OPPORTUNITY_from' => '',
'OPPORTUNITY_to' => '',
'OPPORTUNITY_numsel' => 'exact',
'DATE_CREATE_datesel' => 'NONE',
'DATE_CREATE_from' => '',
'DATE_CREATE_to' => '',
'DATE_CREATE_days' => '',
'DATE_CREATE_month' => '',
'DATE_CREATE_quarter' => '',
'DATE_CREATE_year' => '',
'STATUS_SEMANTIC_ID' => '',
],
'filter_rows' => 'TITLE,ASSIGNED_BY_ID,OPPORTUNITY,DATE_CREATE,STATUS_SEMANTIC_ID',
],
'default_filter' => [
'name' => 'Фильтр',
'for_all' => false,
'sort' => '4',
'fields' => [],
'filter_rows' => 'TITLE,ASSIGNED_BY_ID,OPPORTUNITY,DATE_CREATE,STATUS_SEMANTIC_ID',
]
]
]
Немного отвлечемся и разберем конфигурацию одного пресета.
В исходной структуре мы видим 4 пресета: filter_in_work
, filter_1678877570797
, tmp_filter
, default_filter
.
Пресеты default_filter
и tmp_filter
являются системными (один отвечает за фильтр по-умолчанию, а второй за временный, т.е. примененный фильтр).
Пресет filter_in_work
является изначально заложенным (предустановленными) пресетом.
Пресет filter_1678877570797
- это индивидуальный пресет, созданный пользователем.
Рассмотрим структура пресета filter_1678877570797
:
'filter_1678877570797' => [
'name' => 'asd',
'fields' => [
'TITLE' => '',
'OPPORTUNITY_from' => '',
'OPPORTUNITY_to' => '',
'OPPORTUNITY_numsel' => 'exact',
'DATE_CREATE_datesel' => 'NONE',
'DATE_CREATE_from' => '',
'DATE_CREATE_to' => '',
'DATE_CREATE_days' => '',
'DATE_CREATE_month' => '',
'DATE_CREATE_quarter' => '',
'DATE_CREATE_year' => '',
],
'filter_rows' => 'TITLE,OPPORTUNITY,DATE_CREATE',
'sort' => '5',
'for_all' => false,
],
Он состоит из следующих ключей:
-
name
(string) - отображаемое название пресета -
fields
(array) - набор полей -
filter_rows
(string) - перечисление через запятую полей который отображаются в фильтре -
sort
(int|string) - порядковый номер пресета для вывода -
for_all
(bool) - признак того что пресет добавлен не только для указанного сотрудника
Обращаю внимание на набор
fields
- это не просто набор полей фильтра, а набор подготовленных полей для вывода.
API
Вся работа с внешним отображением ограничивается классом Bitrix\Main\UI\Filter\Options
, но при работе с ним нужно помнить что он использует глобальную переменную $USER
и зависит от авторизации текущего пользователя, так что поработать с другими будет достаточно сложно.
Мы создаем экземпляр класса передавая ему начальные параметры:
-
$filterId
(string) - идентификатор текущего фильтра -
$filterPresets
(array) - набор предустановленных фильтров -
$commonPresetsId
(null|string) - код ключа для хранения пресетов
Пример получения объекта Options
:
use \Bitrix\Main\UI\Filter\Options;
$filterId = "MY_FILTER_ID";
$filterPresets = [
'filter_in_work' => [
'name' => 'Лиды в работе',
'fields' => [
'TITLE' => '',
'STATUS_SEMANTIC_ID' => [
0 => 'P',
]
],
'filter_rows' => 'TITLE,STATUS_SEMANTIC_ID',
'for_all' => false,
'sort' => '0',
],
];
$uiFilter = new Options(
$filterId,
$filterPresets
);
Полезные функции
Получив объект фильтра мы можем выполнять различные действия:
- Закрепить произвольный пресет:
$uiFilter->pinPreset($presetId = "default_filter");
- Получить список полей которые используются в текущем фильтр:
$usedFields = $uiFilter->getUsedFields();
- Получить идентификатор/код фильтра по-умолчанию или текущего выбранного
$defaultFilterId = $uiFilter->getDefaultFilterId();
$currentFilterId = $uiFilter->getCurrentFilterId();
Получение фильтра
Продемонстрированный в этой главе фильтр используется исключительно для демонстрационных целей или устаревших систем. Настоятельно рекомендуется использовать механизм описанный в разделе Свой фильтр.
Поскольку фильтр в своем отображении использует и значения указанные в фильтрации в ui-объекте так же есть методы, которые позволяют преобразовать фильтр из запроса в orm-подобный фильтр. Именно для таких целей и существуют два полезных метода - getFilter
(для получения фильтра указанных полей) и getFilterLogic
(преобразование результата getFilter
в логические значения подготовленные для использования в DataManager
).
Предположим что у нас имеется набор полей фильтра (подробнее в главе “Поля фильтра” из статьи Обзор) и мы хотим из запроса (REQUEST) получить подготовленный набор.
Давайте посмотрим на результаты работы кода:
use Bitrix\Main\UI\Filter\FieldAdapter;
use Bitrix\Main\UI\Filter\DateType;
use Bitrix\Main\UI\Filter\Options;
$sourceFields = [
[
`id` => 'STAGE',
`name` => "List field example",
'type' => FieldAdapter::LIST,
'required' => false,
'items' => [
"NEW" => "Новый",
"FINISH" => "Согласован",
],
],
[
`id` => 'DATE',
`name` => "Date fields example",
'type' => FieldAdapter::DATE,
'time' => false,
'valueType' => [
DateType::MONTH,
]
]
];
$filterId = "MY_FILTER_ID";
$uiFilter = new Options($filterId);
$rawFilter = $uiFilter->getFilter($sourceFields);
/*
$rawFilter = [
'DATE_datesel' => 'MONTH',
'DATE_month' => '3',
'DATE_quarter' => 1,
'DATE_year' => '2023',
'DATE_from' => '01.03.2023 00:00:00',
'DATE_to' => '31.03.2023 23:59:59',
'STAGE' => [
0 => "FINISH",
],
'STAGE_label' => [
0 => 'Согласован',
],
'PRESET_ID' => 'tmp_filter',
'FILTER_ID' => 'tmp_filter',
'FILTER_APPLIED' => true,
'FIND' => '',
];
*/
$logicFilter = $uiFilter->getFilterLogic($sourceFields);
/*
$logicFilter = [
">=DATE" => "01.03.2023 00:00:00",
"<=DATE" => "31.03.2023 23:59:59",
"STAGE" => [
0 => "FINISH"
]
];
*/