Documentation

Start

Introduction


In general, element data for main CRM entities is performed using an array.

This approach has several drawbacks:

  • Various entities have different field names, but the same content. Their names must always be memorized.
  • No autocomplete in IDE.
  • No type checking and etc.

To unify the approach and resolve all the above listed deficiencies new API has introduced an abstract class Bitrix\Crm\Item.

This class contains Bitrix\Main\ORM\Objectify\EntityObject and imitates its behaviour.

Each entity type has its own implementation of this class containing specifics of this type.

Class reproduces the interface \ArrayAccess, when querying the object as an array, calling methods get and set.

Codes for "general" fields of this class are based on the corresponding field codes for SPA element table.


Because the class itself doesn't query the database directly, its fully dependant on the status of internal EntityObject.

Meaning, when object have some empty data (not passed in select), the class won't have access to such data.

Names methods

Class has a set of names methods (similar to EntityObject) for handling status and value of fields.

For example, method getStageId returns string ID for element stage. Even if the field is named not as STAGE_ID, but STATUS_ID, method will still operate.

In similar fashion, method setStageId writes new value into the stage field, independently from its code in element table.

The method isChangedStageId operates in the same manner. The rest of cases, available in EntityObject are not implemented.

Handling of named methods is implemented via the "magic" method __call.

Below is full set of methods, available for handling "Title" field (TITLE):

  • getTitle(): ?string - returns current value;
  • setTItle(string $title): Item - write new value;
  • isChangedTitle(): bool - returns true, when field value was updated.

In similar fashion you can query methods for other fields. Field code must be converted into UpperCamelCase notation.


Example:

  • getCreatedTime(): ?DateTime
  • getUpdatedTime(): ?DateTime
  • getMovedTime(): ?DateTime
  • getCreatedBy(): ?int
  • getUpdatedBy(): ?int
  • getMovedBy(): ?int
  • getAssignedById(): ?int
  • getOpened(): bool
  • getBegindate(): ?DateTime
  • getClosedate(): ?DateTime
  • getCompanyId(): ?int
  • getContactId(): ?int
  • getStageId(): ?string
  • getCategoryId(): ?int
  • getOpportunity(): ?float
  • getIsManualOpportunity(): bool
  • getTaxValue(): float
  • getCurrencyId(): ?string
  • getOpportunityAccount(): ?float
  • getTaxValueAccount(): ?float
  • getAccountCurrencyId(): ?string
  • getMycompanyId(): ?int
  • getProductRows(): ?ProductRowCollection
  • getClosed(): bool
  • getSourceId(): ?string
  • getSourceDescription(): ?string
  • getWebformId(): ?int

Similarly, you can handle UTM-tag fields. Although, values for these fields are not stored directly in table with elements, they can be accessed in the same manner from this class.


  • getUtmSource(): ?string
  • getUtmMedium(): ?string
  • getUtmCampaign(): ?string
  • getUtmContent(): ?string
  • getUtmTerm(): ?string

General methods

Method Description Available from version
public function __construct(int $entityTypeId, EntityObject 
$entityObject, array $fieldsMap = [], array $disabledFieldNames = [])

  • $entityTypeId - CRM entity type ID;
  • $entityObject - orm-object with data;
  • $fieldsMap - key map, where key - "general" field code (see. public class constants FIELD_NAME_), and value - field code from element's table;
  • $disabledFieldNames - field codes, unavailable in specific methods.
Its not recommended to use the constructor directly. Use the corresponding factory methods for getting objects.
public function hasField(string $fieldName): bool
Returns true, when element has the field with $fieldName.
Here and later $fieldName can be both "general", and specific for entity.

For example, hasField('STAGE_ID') and hasField('STATUS_ID') for "Lead" entity element both return true.
public function getDefaultValue(string $fieldName)
Returns default value for the field $fieldName.
public function get(string $fieldName)
Returns current field value for $fieldName.
public function set(string $fieldName, $value): self
Writes new current $value for the field $fieldName.
public function reset(string $fieldName): self
Resets $fieldName to initial status.
public function unset(string $fieldName): self
Writes empty value to the field $fieldName.
public function remindActual(string $fieldName)
Returns initial field value $fieldName.
public function isChanged(string $fieldName): bool
Returns true, when field $fieldName was updated (current value is different from initial).
public function getData(int $valuesType = Values::ALL): array
Returns array with field values, where keys are "general" field codes, and values - field values, selected by mask $valuesType.
$valuesType can receive values, described in the class \Bitrix\Main\ORM\Objectify\Values:
\Bitrix\Main\ORM\Objectify\Values::ACTUAL - returns only initial field values
\Bitrix\Main\ORM\Objectify\Values::CURRENT - returns only current field values
\Bitrix\Main\ORM\Objectify\Values::ALL - returns all field values.
public function getCompatibleData
(int $valuesType = Values::ALL): array

$valuesType accepts the same values with the same content as in the method getData
Returns array with field values in the same format as processed in the "legacy" API.
Here, field codes are passed in codes specific for individual type.
Field values are converted to strings/numericals/arrays.
public function getCompatibleData
(int $valuesType = Values::ALL): array

$valuesType accepts the same values with the same content as in the method getData
Returns array with field values in the same format as processed in the "legacy" API.
Here, field codes are passed in codes specific for individual type.
Field values are converted to strings/numericals/arrays.
public function setFromCompatibleData(array $data): self
Method writes new field values from the $data array. Array data must have format of "legacy" API.
Array keys must be field codes, specific for the individual type.
If the element is new and the value of a field is not passed, this field value is written into this element by default (see the method getDefaultValue).
public function isNew(): bool
Returns true when element is not yet saved in the database.
public function getId(): int
Returns element ID.
public function getEntityTypeId(): int
Returns CRM entity type ID.
public function getTitlePlaceholder(): ?string
Returns default header to be displayed in the creation form.
public function save(bool $isCheckUserFields = true): Result
Saves current element status in the database. Returns object Bitrix\Main\Result.
Flag $isCheckUserFields indicates a performed check for custom fields when saving.
This method executes only saving to the database. No additional actions are executed inside it (except of event handlers, subscribed to table).
All additional actions are performed via operations.
public function delete(): Result
Deletes element from database, returns Bitrix\Main\Result.
Flag $isCheckUserFields indicates a performed check for custom fields when saving.
Method directly performs deletion.
All additional actions are performed via operations.
public function jsonSerialize(): array
Returns element data in prepared format for the frontend or REST (see. Service\Converter).
public function getEntityFieldNameIfExists
(string $commonFieldName): ?string
Returns field code by its "general" name specific for the type.
public function isCategoriesSupported(): bool
Returns true, when element type supports handling of pipelines.
public function isStagesEnabled(): bool
Returns true, when element type must have stages displayed in the interface.
public function getCategoryIdForPermissions(): int
Returns pipeline ID when verifying access permissions. When pipeline is not supported, returns 0.

Handling collections

All methods that update status of associated collections doesn't write updates to the database. They only change object status (similar to the behaviour of methods get/ set).

For the belowlisted methods to operate correctly, corresponding data must be selected from the database: fields Item::FIELD_NAME_CONTACTS or Item::FIELD_NAME_CONTACT_BINDINGS for handling contacts, field Item::FIELD_NAME_OBSERVERS and field Item::FIELD_NAME_PRODUCTS for product items.

You can achieve this by passing necessary fields to select of the method Factory::getItems.

When a single retrieved element is required, use the method Factory::getItem. Returns the object for which all associated entries are received from the database.

To save all updates, call the method save.

Method Description Available from version
public function getPrimaryContact(): ?Contact
Returns ORM object with "main" contact, if at least one is available.
public function getContacts(): array
Returns array with ORM objects of associated contacts.
public function bindContacts(array $contactBindings): void
Writes a binding with contacts $contactBindings of element.
$contactBindings data must have format that passed by the method \Bitrix\Crm\Binding\EntityBinding::prepareEntityBindings().
public function unbindContacts(array $contactBindings): void
Deletes binding with element contacts $contactBindings.
$contactBindings data must have format, passed by the method \Bitrix\Crm\Binding\EntityBinding::prepareEntityBindings().
public function getContactBindings(): array
Returns data on current binding contacts.
Result will have format, passed by the method \Bitrix\Crm\Binding\EntityBinding::prepareEntityBindings().
public function getObservers(): array
Returns array with user IDs that are observers for an element.
public function setObservers($observerIds): Item
Writes user $observerIds into the observer data.
All the required actions for saving access attributes and chat creating will be performed during operation in class Bitrix\Crm\Field\Observers.
public function addToProductRows(ProductRow $product): Result
Method adds ORM object for $product position to current collection of product positions.
public function removeFromProductRows(ProductRow $product): void
Method deletes ORM object for $product position from current collection of product positions.
public function setProductRowsFromArrays(array $productArrays): Result
Method re-writes product collection data from the array $productArrays.
Each element from array $productArrays - is a data array for product position.
public function setProductRows($products): Result
Method re-writes product collection data from $products parameter. $products can be an array of ProductRow ORM objects, or a ProductRowCollection.

Custom fields, File fields.

Class doesn't differentiate which fields are handled: table fields or users. Only condition for these fields is to be available in EntityObject.

There are some specifics when handling "File" type fields.

File fields handling particulars

From the database standpoint, "File" field type is just a number. However, in the legacy API, file must have been passed as an array with the uploaded file description (see. \CFile::MakeFileArray())

For this to work, passing such data to the method setFromCompatibleData immediately saved to the table b_file, and its ID is written to the field EntityObject.

Uploading is performed via the file loading service, clearing files that weren't saved.

Example


Creating an element


use Bitrix\Crm\Service;
use Bitrix\Crm\Item;

$factory = Service\Container::getInstance()->getFactory(\CCrmOwnerType::Quote);

$newFile = [
    'name' => 'document.docx',
    'size' => 145961,
    'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'description' => '', 
    'tmp_name' => '/tmp/d1gadg',
];

$fields = [
    'UF_CRM_FIELD' => 'some value',
    'UF_CRM_FILE' => $newFile,
];
$item = $factory->createItem([
    Item::FIELD_NAME_STAGE_ID => 'D128_3:CLIENT' ,
]);
$item->setFromCompatibleData($fields);

// here we can get new file identifier. But if item not saved, this file will be deleted.
$newFileId = $item->get('UF_CRM_FILE');

$result = $item->save();

Updating an element


use Bitrix\Crm\Service;
use Bitrix\Crm\Item;

$factory = Service\Container::getInstance()->getFactory(\CCrmOwnerType::Quote);

$item = $factory->getItem(1);
if ($item)
{
    $item->setStageId('SENT');
    $result = $item->save();
}

Deleting an element


use Bitrix\Crm\Service;
use Bitrix\Crm\Item;

$factory = Service\Container::getInstance()->getFactory(\CCrmOwnerType::Quote);

$item = $factory->getItem(1);
if ($item)
{
    $result = $item->delete();
}

Updating contacts


For example, you have a commercial quote with id = 1, associated with two contacts with id = 2 and id = 3. We want for it to be bound to contacts 3 and 4.


use Bitrix\Crm\Binding\EntityBinding;
use Bitrix\Crm\Item;
use Bitrix\Crm\Service;


$factory = Service\Container::getInstance()->getFactory(\CCrmOwnerType::Quote);

$item = $factory->getItem(1);
if ($item)
{
    // add new contact with id = 4
    $item->bindContacts(EntityBinding::prepareEntityBindings(\CCrmOwnerType::Contact, [4]));
    // remove contact with id = 2
    $item->unbindContacts(EntityBinding::prepareEntityBindings(\CCrmOwnerType::Contact, [2]));
}

Advantages and disadvantages


Working with this class has several advantages:

  • Easy to determine if field value was updated (using the method isChanged).
  • Transparent access to field values, corresponding to their meaning, independent from their code in table.
  • Type checking and autocomplete.
  • Option to handle abstracts.

There are some disadvantages when handling this class, associated with behaviour specifics of EntityObject:

  • Field values are converted to corresponding type. Due to this, number fields with unfilled values pass 0. There is no option to define if this field has 0 or field is not filled.
  • When directly handling the object there is no option to determine if field value was passed from the frontend or not. Method isChanged speaks only if the value was updated.

These deficiencies are known and pending to be resolved with newly added methods.

© «Bitrix24», 2001-2022
Up