Creating your own provider
Description
Provider must inherit class \Bitrix\DocumentGenerator\DataProvider.
When desired, existing provider can be inherited, needed methods re-defined, added to the list and be used jointly with predefined methods.
The class \Bitrix\DocumentGenerator\DataProvider
has several auxiliary descendants:
\Bitrix\DocumentGenerator\DataProvider\EntityDataProvider
- for handling ORM data access objects (DAO);\Bitrix\DocumentGenerator\DataProvider\HashDataProvider
- for handling empty providers as hash;\Bitrix\DocumentGenerator\DataProvider\ArrayDataProvider
- provides access to multiple values of single field.
Provider chain
Each provider can have parent provider indicated. When provider was initialized automatically from field description, it will have parent provider indicated. Or it can be specified manually via \Bitrix\DocumentGenerator\DataProvider::setParentProvider($dataProvider);
.
Verification checks
Access permission verification
Access permissions are verified by the method \Bitrix\DocumentGenerator\DataProvider::hasAccess($userId);
.
Verification of access permissions is called in \Bitrix\DocumentGenerator\Document::hasAccess()
each time when handling a document. It is not an abstract method. When method is not defined, but the current provider has a parent - this method will be called from parent provider. When there is no parent - returns false
.
Verification of successful provider data upload
The module documentgenerator
is designed for provider instances to have two states:
- Before data upload. Provider in this state sends list of its fields "anonymously".
- After data upload. Provider in this state can send "actual" list of its fields and their values.
Initial class does not have method for getting data (but do have in the descendant \Bitrix\DocumentGenerator\DataProvider\EntityDataProvider
).
Programmer must decide how and when these data must be uploaded (based on performance considerations). In some cases, the data must be uploaded directly in constructor, and in some - before getting list of fields and etc.
The attribute $data exist for data storage. Original method to determine provider workload:
/** * @return bool */ public function isLoaded() { return $this->data !== null; }
This method is called in the method for access permission verification and when getting a value. When querying these methods, the provider will not be loaded - access permission verification will return false
, and the value will not be retrieved.
Provider fields
Main method of any provider - getFields
. To increase performance, its recommended for the main code to be executed only a single time, because the provider method getFields()
is called several times during document generation.
public function getFields() { if($this->fields === null) { parent::getFields(); $this->fields['MY_FIELD'] = ['TITLE' => 'My Field Title',]; } return $this->fields; }
It must return an array, where key - field name (it's better to use English letters in uppercase + underlining), and the value - its description. Field description can contain the following keys (all of them are optional, the array can be empty):
- TITLE - field title (when nonexistent - shows name)
- TYPE - field type. Can have the following values:
- IMAGE - field is path to image file
- STAMP - similar to IMAGE, but this field is only a signature or stamp
- DATE - generates object class
\Bitrix\DocumentGenerator\Value\DateTime
- TEXT - standard field, but the document update page will have textarea instead of input
- NAME - generates object class
\Bitrix\DocumentGenerator\Value\Name
- PHONE - generates object class
\Bitrix\DocumentGenerator\Value\PhoneNumber
- full name of descendant class
\Bitrix\DocumentGenerator\Value
can be passed directly here - FORMAT - default format for descendants
\Bitrix\DocumentGenerator\Value
- VALUE - description for method of getting the value. By default, the value is sourced from
$data
. The value can be represented by the following: - it can be the field value itself as a number or string
- string, containing the name of other field - in this case, an attempt will be made to get the value of this field from another field with corresponding name. (for example - field COMPANY_NAME from
\Bitrix\Crm\Integration\DocumentGenerator\DataProvider\Lead
) - callable structure. In this case, this method/function is called to get a value
- Closure (anonymous function). Similar to the previous item, it will be called when getting a value. But if you write field values into object attributes, this option won't be suitable, it's better to use corresponding method and to specify its name explicitly
- array of values. In this case, template will receive the object
\Bitrix\DocumentGenerator\Value\Multiple
- PROVIDER - when field value must be another provider, a full name of corresponding class must be specified here.
- OPTIONS - array $options that will be passed to provider constructor.
- VALUES - array of values that will be passed into provider created by this description and which redefines its values.
- COPY - indicator of description of another field. When you want to have several fields with the same content, but under different names, it can be done using this key. For example, you have a main field, it's a provider with multiple options. You want the access to this field to be acquired via different field names. In this case, new fields are created, where only TITLE, VALUE and OPTIONS[COPY] are specified, equal the name of the main field.
Final value
The method \Bitrix\DocumentGenerator\DataProvider::getValue()
is responsible for getting field values .
When for some reasons, getting field value from this field description is not suitable, this method can be redefined. For example:
public function getValue($name) { if($name == 'myComplexFieldValue') { return 'complexValue'; } return parent::getValue($name); }
However, the class is designed in such a way, that the method of getting a value can be specified in the field description, that is why it's not recommended to redefine this method.
Initial realization first starts to search the value of the field $this->data
and if is not able to find it - tries to get it from field description.
The calculation of the value executes \Bitrix\DocumentGenerator\DataProviderManager::getDataProviderValue()
.
Sequence of getting the values is as follows:
- Field description is read from
\Bitrix\DocumentGenerator\DataProvider::getFields()
. When such field is not available - returnsfalse
. - When provider's $options has the key VALUES and it has the value of this field, the value is taken from there.
- When field description's VALUE is a string - the value is taken as
getValue()
of current provider with this string - When VALUE is a callable structure, then its called for getting the value. Field name is always indicated for this method/function
- When field description has PROVIDER, a new instance of this class is created, receiving a calculated value, and OPTIONS from field description are passed to $options.
After a value is received, the \Bitrix\DocumentGenerator\DataProviderManager::prepareValue()
is called for it.
This method converts the received value to a corresponding type from field description. When the calculated value is already an instance \Bitrix\DocumentGenerator\Value
, its returned as is.
Multiple values
A situation is possible, when a single field value can have several options. Especially when its concerns provider fields. For example, the "my company" field in CRM providers. There can be several my companies and the user must have the option to quickly change the company used in the document.
Value calculate results (usually its the result of executed callable structure in field description) must be a simple array, where each value is an array type:
array( 'VALUE' => $value, // the value itself 'TITLE' => $title, // title that will be displayed in the document update form for this item 'SELECTED' => $selected, // true - when this value must be displayed by default );
When SELECTED is false
for all, the first option in the list will be selected when generating the document.
Values as arrays
Some fields may have several values simultaneously. Values of such fields are inserted into tables/repeated blocks. For example, products, taxes, deal contacts.
In this case, field description must be generated as follows:
$this->fields['LIST'] = [ 'PROVIDER' => \Bitrix\DocumentGenerator\DataProvider\ArrayDataProvider::class, 'TITLE' => 'My List', 'OPTIONS' => [ 'ITEM_PROVIDER' => 'MyItemDataProvider::class', // full name of class-provider of separate element 'ITEM_NAME' => 'ITEM', // field name used to query the element 'ITEM_TITLE' => 'My Item', // element title ], 'VALUE' => [$this, 'loadItems'], ];
The method loadItems
must return simple array of generated providers.