Создание своего провайдера
Описание
Провайдер должен наследовать класс \Bitrix\DocumentGenerator\DataProvider.
При желании можно наследовать существующий провайдер, переопределить нужные методы, добавить его в список и он будет фигурировать там наравне с предустановленными.
У класса \Bitrix\DocumentGenerator\DataProvider
есть несколько вспомогательных наследников:
\Bitrix\DocumentGenerator\DataProvider\EntityDataProvider
- для работы с таблетами ORM;\Bitrix\DocumentGenerator\DataProvider\HashDataProvider
- для работы с простыми провайдерами в виде хеша;\Bitrix\DocumentGenerator\DataProvider\ArrayDataProvider
- предоставляет доступ к множественным значениям одного поля.
Цепочка провайдеров
У каждого провайдера может быть указан родительский провайдер. Если провайдер был инициализирован автоматически из описания поля, то у него будет указан родительский провайдер. Или его можно указать вручную через \Bitrix\DocumentGenerator\DataProvider::setParentProvider($dataProvider);
.
Проверки
Проверка прав доступа
Проверка прав осуществляется методом \Bitrix\DocumentGenerator\DataProvider::hasAccess($userId);
.
Проверка доступа вызывается в \Bitrix\DocumentGenerator\Document::hasAccess()
каждый раз при работе с документом. Это не абстрактный метод. Если метод не определен, но у текущего провайдера есть родитель - этот метод будет вызван у родительского провайдера. Если родителя нет - вернет false
.
Проверка успешной загрузки данных провайдера
Модуль documentgenerator
спроектирован таким образом, что экземпляры провайдеров могут иметь два состояния:
- До загрузки данных. В этом состоянии провайдер отдает список своих полей "обезличенно".
- После загрузки данных. В этом состоянии провайдер может отдать "актуальный" список своих полей и их значения.
В исходном классе нет метода для получения данных (но есть в наследнике \Bitrix\DocumentGenerator\DataProvider\EntityDataProvider
).
Программист должен сам решить, как и когда эти данные должны загружаться (из соображений производительности). В некоторых случаях данные должны загружаться прямо в конструкторе, в некоторых - перед получением списка полей и т.д.
Для хранения данных есть атрибут $data. Исходный метод определения загруженности провайдера:
/** * @return bool */ public function isLoaded() { return $this->data !== null; }
Этот метод вызывается в методе проверки прав и при получении значения. Если на момент обращения к этим методам провайдер не будет загружен - проверка прав вернет false
, а значение не будет получено.
Поля провайдера
Основной метод любого провайдера - getFields
. В целях улучшения производительности рекомендуется сделать так, чтобы основной код метода исполнялся только один раз, т.к. метод провайдера getFields()
вызывается несколько раз в процессе формирования документа.
public function getFields() { if($this->fields === null) { parent::getFields(); $this->fields['MY_FIELD'] = ['TITLE' => 'My Field Title',]; } return $this->fields; }
Он должен возвращать массив, где ключ - название поля (лучше использовать английские буквы в верхнем регистре + подчеркивание), а значение - его описание. Описание поля может содержать следующие ключи (все они не обязательны, можно оставить пустой массив):
- TITLE - заголовок поля (если его нет - выводится название)
- TYPE - тип поля. Может принимать значения:
- IMAGE - поле является путем к файлу-картинке
- STAMP - аналогично IMAGE, но это поле является подписью или печатью
- DATE - будет сформирован объект класса
\Bitrix\DocumentGenerator\Value\DateTime
- TEXT - обычное поле, но на странице изменения документа вместо input будет textarea
- NAME - будет сформирован объект класса
\Bitrix\DocumentGenerator\Value\Name
- PHONE - будет сформирован объект класса
\Bitrix\DocumentGenerator\Value\PhoneNumber
- также сюда можно в явном виде передать полное имя класса-наследника
\Bitrix\DocumentGenerator\Value
- FORMAT - формат по умолчанию для наследников
\Bitrix\DocumentGenerator\Value
- VALUE - описание способа получения значения. Само значение по умолчанию берётся из
$data
. В качестве значения может выступать: - собственно, само значение поля в виде числа или строки
- строка, содержащая название другого поля - в этом случае будет сделана попытка получить значение этого поля из другого поля с соответствующим названием. (пример - поле COMPANY_NAME из
\Bitrix\Crm\Integration\DocumentGenerator\DataProvider\Lead
) - callable-конструкция. В этом случае для получения значения будет вызван этот метод/функция
- Closure (анонимная функция). Аналогично предыдущему пункту будет вызвана при получении значения. Но если вы пишете значения полей в атрибуты объекта, то придётся отказаться от этого варианта, лучше сделать соответствующий метод и указать его имя в явном виде
- массив значений. В этом случае в шаблон попадёт объект
\Bitrix\DocumentGenerator\Value\Multiple
- PROVIDER - если значение поля должно быть другим провайдером, то здесь надо указать полное имя соответствующего класса.
- OPTIONS - массив $options, который будет передан в конструктор провайдера.
- VALUES - массив значений, которые будут переданые в созданный по этому описанию провайдер и переопределят его значения.
- COPY - указатель на описание другого поля. Если вы хотите иметь несколько полей с одинаковым содержимым, но разным названием, то можно сделать это с помощью этого ключа. Например, у вас есть основное поле, это провайдер с множеством опций. Вы хотите, чтобы доступ к этому полю мог быть получен через разные названия полей. В этом случае создаются новые поля, где указываются только TITLE, VALUE и OPTIONS[COPY], равные названию основного поля.
Итоговое значение
За получение значений полей отвечает метод \Bitrix\DocumentGenerator\DataProvider::getValue()
.
Если по каким-то причинам не устраивает получение значения поля из его описания, то можно переопределить этот метод. Например, так:
public function getValue($name) { if($name == 'myComplexFieldValue') { return 'complexValue'; } return parent::getValue($name); }
Но класс спроектирован таким образом, что метод получения значения можно указать в описании поля, поэтому переопределять этот метод не рекомендуется.
Исходная реализация сначала ищет значение поля в $this->data
и если его нет - пытается его получить из описания поля.
Само вычисление значения выполняет \Bitrix\DocumentGenerator\DataProviderManager::getDataProviderValue()
.
Порядок получения значения следующий:
- Считывается описание поля из
\Bitrix\DocumentGenerator\DataProvider::getFields()
. Если такого поля нет - вернетсяfalse
. - Если в $options провайдера есть ключ VALUES и в нём есть значение этого поля, то значение берется оттуда.
- Если в VALUE описании поля строка - значение берется как
getValue()
текущего провайдера с этой строкой - Если в VALUE - callable-конструкция, то она вызывается для получения значения. На вход этого метода/функции всегда идёт название поля
- Если в описании поля есть PROVIDER, то создается новый экземпляр этого класса, на вход ему передается вычисленное значеие, а в $options - передаются OPTIONS из описания поля
После получения значения над ним вызывается \Bitrix\DocumentGenerator\DataProviderManager::prepareValue()
.
Этот метод преобразует полученное значение к соответствующему типу из описания поля. Если вычисленное значение уже экземпляр \Bitrix\DocumentGenerator\Value
, то он возвращается как есть.
Множественное значение
Возможна ситуация, когда в значении одного поля может быть несколько вариантов. Особенно это актуально для полей-провайдеров. Например, поле "моя компания" в провайдерах CRM. Моих компаний может быть несколько, и пользователь должен иметь возможность быстро сменить используемую компанию в документе.
Результат вычисления значения (обычно это результат выполнения callable-конструкции в описании поля) должен иметь вид простого массива, где каждое значение - это массив вида:
array( 'VALUE' => $value, // само значение 'TITLE' => $title, // заголовок, который будет выводиться в форме изменения документа для этого пункта 'SELECTED' => $selected, // true - если должно использоваться это значение по умолчанию );
Если SELECTED у всех false
, то при формировании документа будет выбран первый вариант из списка.
Значения в виде массивов
Некоторые поля могут иметь несколько значений одновременно. Значения таких полей вставляются внутрь таблиц/повторяющихся блоков. Например, товары, налоги, контакты сделки.
В этом случае описание поля должно быть сформировано следующим образом:
$this->fields['LIST'] = [ 'PROVIDER' => \Bitrix\DocumentGenerator\DataProvider\ArrayDataProvider::class, 'TITLE' => 'My List', 'OPTIONS' => [ 'ITEM_PROVIDER' => 'MyItemDataProvider::class', // полное имя класса-провайдера отдельного элемента 'ITEM_NAME' => 'ITEM', // название поля, по которому будет идти обращение к элементу 'ITEM_TITLE' => 'My Item', // заголовок элемента ], 'VALUE' => [$this, 'loadItems'], ];
Метод loadItems
должен вернуть простой массив сформированных провайдеров.
Иван Новоселов
|
||||
Судя по коду провайдер должен наследоваться ещё от Nameable
\bitrix\modules\documentgenerator\lib\registry.php getFromEvent вызывает checkClassName
| ||||
Игорь Шевчик
|
||
| ||
Пользовательские комментарии
Мы будем рады, если разработчики добавят свои комментарии по практическому использованию методов системы.Для этого нужно всего лишь авторизоваться на сайте
Но помните, что Пользовательские комментарии, несмотря на модерацию, не являются официальной документацией. Ответственность за их использование несет сам пользователь.
Также Пользовательские комментарии не являются местом для обсуждения функционала. По подобным вопросам обращайтесь на форумы.