Работа с окружением

Любые действия бизнес-процесса для выполнения своих функций должны работать со своим окружением - иметь доступ к чтению параметров, чтению/записи переменных, уметь работать с константами и глобальными значениями. Задача этой главы показать как взаимодействовать с ними. В главе PHP код мы обсуждали, что использование механизма авто-подстановки значений с точки зрения кода является очень плохим, хоть и работающим подходом и чем можно его заменить.

Использование парсера

Самый простой способ взаимодействия на чтение с выражением является использование встроенного парсера. Суть данного способа заключается в том, что разбить техническое выражение на части, а затем конкатенировать его при передаче в парсер. Звучит достаточно сложно, но на деле все просто. Представьте себе что у нас есть БП на сущности компания и нам нужно получить его значение, а значит нам достаточно использовать выражение:

$companyTitle = $this->ParseValue('{'.'=Document:TITLE}');

Для получения названия компании. То же самое можно проделать и с любыми другими выражениями, которые вы можете подставить через редактор бизнес процесса.

Метод является нестатическим (т.е. он вызывается только в контексте действия бизнес процесса) и имеет следующую сигнатуру:

\CBPActivity::parseValue($value, $convertToType = null): mixed

Параметры метода:

  • $value (string) - выражение для парсинга
  • $convertToType (null|string) - код типа, в случае если необходима конвертация.

Очень важно чтобы при использовании указанного кода вы не использовали значения, которые могут быть истолкованы как маркеры и попасть под автозамену, а это значит что код ниже является ошибочным:

$companyTitle = $this->ParseValue('{=Document:TITLE}');

Дополнительные возможности парсера:

  1. В нем используется механизм вычисления, а значит вы можете использовать функции бизнес процессов, калькулятор выражений и приведение типов
  2. В одном парсере можно использовать несколько выражений

Геттер

Помимо парсера в CBPActivity существует так же универсальный геттер который помогает извлекать значение и мета-информацию по определенному полю.

Сигнатура метода: \CBPActivity::getRuntimeProperty($object, $field, CBPActivity $ownerActivity): array

Параметры:

  • $object (string) - код объекта. Например: Template, Document, Variable и т.п. В качестве значения можно так же использовать константы класса из \Bitrix\Bizproc\Workflow\Template\SourceType
  • $field (string) - название поля
  • $ownerActivity (CBPActivity) - исходное действие.

Метод возвращает массив из двух элементов: Описания свойства (array) и Реального значения (mixed)

Рассмотрим выполнение этого метода как для примера из парсера: мы будем запускать бизнес процесс на сущности компания.

use \Bitrix\Bizproc\Workflow\Template\SourceType;

list($property, $companyTitle) = $this->getRuntimeProperty(
	SourceType::DocumentField,
	'TITLE',
	$this
);

Если вы установите логгирование изменений, то в наших переменных будут:

$property = [
	"Name"       => "Название компании",
	"Type"       => "string",
	"Filterable" => true,
	"Editable"   => true,
	"Required"   => true,
	"BaseType"   => "string",
];

$companyTitle = "Веб-сервис";

В классе SourceType помимо указанного DocumentField так же доступны:

  • SourceType::DocumentField
  • SourceType::Parameter
  • SourceType::Variable
  • SourceType::Constant
  • SourceType::GlobalConstant
  • SourceType::GlobalVariable
  • SourceType::System
  • SourceType::Activity
  • SourceType::CalcFunction

Параметры

Параметры бизнес-процесса - это значения, которые указываются при запуске бизнес-процесса. Таким образом они остаются постоянными в ходе его работы.

Пример кода как можно обратиться к параметру Parameter1:

$rootActivity = $this->getRootActivity();

$ourValue = $rootActivity->Parameter1;

Переменные

В отличие от параметров переменные могут изменяться в ходе всего бизнес-процесса, поэтому у действия (CBPActivity) есть методы как на чтение getVariable, так и на запись setVariable.

Сигнатуры нестатических методов:

/**
 * @param string $name - Variable name
 * @return mixed|null If value not exist - null. If multiple values - array
 */
\CBPActivity::getVariable($name): mixed|null

/**
 * @param string $name - Variable name
 * @param mixed $value - Variable value
 * @return void
 */
\CBPActivity::setVariable($name, $value): void

Например, мы хотим записать переменную ApprovedByUsers с типом “Привязка к сотрудникам” (множественная) и сразу же ее прочитать:

$this->setVariable(
	'ApprovedByUsers',
	[
		'user_1',
		'user_2',
	]
);

$users = $this->getVariable('ApprovedByUsers');

Константы

Константы это неизменяемые значения для запущенного бизнес-процесса. Их поведение похоже на параметры, однако задать их можно только в дизайнере бизнес процесса при редактировании шаблона. Метода на изменение констант не существует.

Для получения константы существует нестатический метод:

/**
 * @param string $name - Contant name
 * @return mixed|null If value not exist - null. If multiple values - array
 */
\CBPActivity::getConstant($name): mixed|null

Предположим, что у нас есть константа hr_user, которую мы задали в шаблоне бизнес процесса. Тогда ее получение будет выглядеть следующим образом:

$ourHrUser = $this->getConstant('hr_user');

Сущность

Очень часто для получения сущности используются один из двух способов: либо прямое получение данных (подстановка, парсинг, геттер), либо получение ID текущей сущности и дополнительные запросы в базу данных. В случае с парсингом и геттером это является допустимым, однако в остальных случаях это не самый эффективный способ. Мы уже знаем что бизнес процесс запускается по шаблону на определенной сущности, а значит к полям этой сущности у нас есть довольно простой доступ - работа через сервис документов.

Пример работы:


/**
 * @var CBPDocumentService
 */
$documentService = $this->workflow->getService('DocumentService');

/**
 * @var Bitrix\Bizproc\Document\ValueCollection
 */
$document = $documentService->getDocument( $this->getDocumentId() );

// Example: $document['TITLE'];

Преимущество работы с использованием данного способа:

  1. DocumentService имеет локальное кеширование. Повторный вызов метода не вызовет запрос на получение данных, а значит все активити которые будут работать с данным сервисом не будут иметь накладных расходов в виде запросов в базу данных. Он так же является Lazy-load, а значит простой вызов кода не сделает запросов в базу данных.
  2. Универсален. Не важно с какой сущностью вы работаете - сервис получит необходимые данные, а удобство работы с ArrayAccess позволит быстро к нему обратиться
  3. Выполняется без проверки прав. Вы больше не забудете прописать CHECK_PERMISSION => N в своем коде.

Глобальные хранилища

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

Абстрактно это можно представить следующим образом:

use \Bitrix\Bizproc\Workflow\Type\GlobalsManager;
use \Bitrix\Bizproc\Workflow\Type\GlobalVar;
use \Bitrix\Bizproc\Workflow\Type\GlobalConst;

class GlobalVar extends GlobalsManager {}
class GlobalConst extends GlobalsManager {}

Поскольку все методы находятся в родительском классе GlobalsManager, то мы будем рассматривать именного его работу, а не конкретную реализацию. Поскольку глобальное хранилище зависимо от сущности (в crm свои глобальные константы, а в rpa другие) для работы с ними необходимо использовать массив описания типа документа ($documentType)

Пример типа документа для CRM сущности Компания: ['crm', 'CCrmDocumentCompany', 'COMPANY']

Пример получения списка глобальных переменных:

use \Bitrix\Bizproc\Workflow\Type\GlobalVar;

$documentType = ['crm', 'CCrmDocumentCompany', 'COMPANY'];

$allEntities = GlobalVar::getAll($documentType);

// Пример содержимого

$allEntities = [
	"Variable1684762282405" => [
		"Name"        => "Test",
		"Description" => "",
		"Type"        => "string",
		"Required"    => false,
		"Multiple"    => false,
		"Options"   => "",
		"Default"   => "",
		"CreatedBy" => 1,
		"CreatedDate" => new Bitrix\Main\Type\DateTime(),
		"Visibility" => "GLOBAL", 
		"ModifiedBy" => 1,
		"ModifiedDate" => new Bitrix\Main\Type\DateTime(),
	]
];

Примечание: Visibility может принимать значения: GLOBAL, <module>, <module>_<entity>. Переменные отображаемые только в CRM компаниях могут иметь значения GLOBAL, CRM и CRM_COMPANY.

С обновлением значения свойства намного сложнее - для того чтобы обновить значение, необходимо обновлять описание всего свойства. Поэтому изменение будет выглядеть как набор команд: получение описания, изменение описания и сохранение значения.

Для сохранения используется команда:

use \Bitrix\Bizproc\Workflow\Type\GlobalsManager;
public static function upsert($id, $property, int $userId = null): bool

Параметры:

  • $id (string) - код свойства
  • $property (array) - ассоциативный массив описывающий свойство
  • $userId (null|int) - идентификатор пользователя создающего/изменяющего свойство

Пример изменения глобальной переменной:

use \Bitrix\Bizproc\Workflow\Type\GlobalVar;

$variableId = 'Variable1684762282405';

$property = GlobalVar::getById($variableId);

if ( is_null($property) )
{
	throw new \Exception("Property not exist: ".$variableId);
}

$property['Default'] = "new value";
GlobalVar::upsert($variableId, $property);

Для удаления глобальной переменной используется статический метод delete:

use \Bitrix\Bizproc\Workflow\Type\GlobalVar;

$variableId = 'Variable1684762282405';

GlobalVar::delete($variableId); //return true if success or false otherwise

Дополнительные значения

В рамках действия (CBPActivity) существует так же набор методов для получения полезной информации:

/**
 * Return document identifier
 * e.g. ['crm', 'CCrmDocumentCompany', 'COMPANY_123']
 * @var array 
 */
$documentId = $this->getDocumentId();

/**
 * Return document type identifier
 * e.g. ['crm', 'CCrmDocumentCompany', 'COMPANY']
 * @var array 
 */
$documentType = $this->getDocumentType();

/**
 * Return workflow template identifier
 * @var string
 */
$wfTemplateId = $this->getWorkflowTemplateId();

/**
 * Template user id (who start process)
 * @var int
 */
$templateUserId = $this->getTemplateUserId();

/**
 * Return root bizproc activity
 * @var \CBPActivity
 */
$rootActivity = $this->getRootActivity();

Полезные ссылки

  1. PHP код