6use Bitrix\Bizproc\WorkflowTemplateTable;
47 public function __construct(array $documentType, $documentStatus =
null)
49 $this->
template = array(
51 'MODULE_ID' => $documentType[0],
52 'ENTITY' => $documentType[1],
53 'DOCUMENT_TYPE' => $documentType[2],
54 'DOCUMENT_STATUS' => $documentStatus,
55 'AUTO_EXECUTE' => $this->autoExecuteType,
64 $row = WorkflowTemplateTable::getList([
66 '=MODULE_ID' => $documentType[0],
67 '=ENTITY' => $documentType[1],
68 '=DOCUMENT_TYPE' => $documentType[2],
69 '=DOCUMENT_STATUS' => $documentStatus,
75 $this->
template = $row;
76 $this->autoExecuteType = (int) $this->
template[
'AUTO_EXECUTE'];
84 $instance->template = $tpl->collectValues();
85 $instance->autoExecuteType = (int) $instance->template[
'AUTO_EXECUTE'];
92 $isSameRobot =
function ($lhsRobot, $rhsRobot) {
93 return strcmp($lhsRobot->getName(), $rhsRobot->getName());
96 $remainingRobots = array_udiff($this->
getRobots(), $robots, $isSameRobot);
98 return $this->
save($remainingRobots, $userId);
103 return isset($this->
template[
'DOCUMENT_STATUS']) ? $this->
template[
'DOCUMENT_STATUS'] :
null;
108 $this->
template[
'DOCUMENT_STATUS'] = (string) $status;
114 $this->
template[
'NAME'] = $name;
135 return isset($this->
template[
'ID']) ? (int)$this->
template[
'ID'] : 0;
140 return $this->
template[
'PARAMETERS'] ?? [];
145 if (isset($robot[
'Properties']) && is_array($robot[
'Properties']))
147 $robot[
'Properties'] = Automation\Helper::convertProperties($robot[
'Properties'], $this->
getDocumentType());
150 unset($robot[
'Delay'], $robot[
'Condition']);
153 $copy->setRobots([$robot]);
155 return \CBPActivity::callStaticMethod(
157 "GetPropertiesDialog",
160 $robot[
'Name'] ??
null,
161 $copy->template[
'TEMPLATE'],
165 'bizproc_automation_robot_dialog',
174 $saveResult =
new Result();
177 if (isset($robot[
'Properties']) && is_array($robot[
'Properties']))
179 $robot[
'Properties'] = Automation\Helper::unConvertProperties($robot[
'Properties'], $documentType);
182 $request = Automation\Helper::unConvertProperties($request, $documentType);
185 $copy->setRobots([$robot]);
186 $raw = $copy->template[
'TEMPLATE'];
188 $robotErrors = $v = $p = array();
189 $result = \CBPActivity::callStaticMethod(
191 "GetPropertiesDialogValues",
194 $robot[
'Name'] ??
null,
205 $templateActivity = \CBPWorkflowTemplateLoader::findActivityByName($raw, $robot[
'Name'] ??
null);
207 $robotTitle = $robot[
'Properties'][
'Title'] ??
null;
208 $robot[
'Properties'] = $templateActivity[
'Properties'];
209 $robot[
'Properties'][
'Title'] = $robotTitle;
211 $saveResult->setData(array(
'robot' => $robot));
215 foreach ($robotErrors as $i => $error)
217 $errorMessage = $error[
'message'] ??
null;
218 $errorCode = $error[
'code'] ??
null;
219 $errorParameter = $error[
'parameter'] ??
null;
220 $saveResult->addError(
new Error($errorMessage, $errorCode, [
'parameter' => $errorParameter]));
227 public function save(array
$robots, $userId, array $additional = [])
229 $userId = (int)$userId;
231 $templateId = !empty($this->
template[
'ID']) ? $this->
template[
'ID'] : 0;
233 if (isset($additional[
'PARAMETERS']) && is_array($additional[
'PARAMETERS']))
235 $this->
template[
'PARAMETERS'] = $additional[
'PARAMETERS'];
237 if (isset($additional[
'CONSTANTS']) && is_array($additional[
'CONSTANTS']))
239 $this->
template[
'CONSTANTS'] = $additional[
'CONSTANTS'];
244 $templateResult = $this->updateTemplateRobots(
$robots, $userId);
252 if ($templateResult->isSuccess())
254 $resultData = $templateResult->getData();
255 if (isset($resultData[
'ID']))
257 $this->
template[
'ID'] = $resultData[
'ID'];
262 $result->addErrors($templateResult->getErrors());
270 $this->robots = array();
272 foreach ($robots as $robot)
274 if (is_array($robot))
275 $robot =
new Robot($robot);
277 if (!($robot instanceof
Robot))
282 $this->robots[] = $robot;
297 'ID' => $this->
getId(),
299 'DOCUMENT_STATUS' => $this->
template[
'DOCUMENT_STATUS'],
300 'PARAMETERS' => $this->
template[
'PARAMETERS'],
301 'CONSTANTS' => $this->
template[
'CONSTANTS'],
302 'VARIABLES' => $this->
template[
'VARIABLES'] ?? [],
306 $result[
'ROBOTS'] = array();
310 $result[
'ROBOTS'][] = $robot->toArray();
318 $key = implode(
'@', $documentType);
319 if (!isset(static::$availableActivities[$key]))
321 static::$availableActivities[$key] = \CBPRuntime::getRuntime()
322 ->searchActivitiesByType(
'robot_activity', $documentType);
324 return static::$availableActivities[$key];
329 $key = implode(
'@', $documentType);
330 if (!isset(static::$availableActivityClasses[$key]))
332 static::$availableActivityClasses[$key] = array();
333 $activities = static::getAvailableRobots($documentType);
334 foreach ($activities as $activity)
336 static::$availableActivityClasses[$key][] = $activity[
'CLASS'];
339 return static::$availableActivityClasses[$key];
344 $userId = (int)$userId;
348 $raw[
'DOCUMENT_TYPE'] = $documentType;
350 $raw[
'USER_ID'] = $userId;
351 $raw[
'MODIFIER_USER'] = new \CBPWorkflowTemplateUser($userId);
356 $raw[
'ID'] = \CBPWorkflowTemplateLoader::add($raw, $userId === 1);
357 $result->setData(array(
'ID' => $raw[
'ID']));
359 $raw[
'MODULE_ID'] = $documentType[0];
360 $raw[
'ENTITY'] = $documentType[1];
361 $raw[
'DOCUMENT_TYPE'] = $documentType[2];
362 $raw[
'PARAMETERS'] = [];
363 $raw[
'CONSTANTS'] = [];
364 $this->
template = $raw;
368 $result->addError(
new Error($e->getMessage()));
377 '#STATUS#' => $this->
template[
'DOCUMENT_STATUS']
380 if ($this->autoExecuteType === \CBPDocumentEventType::Script)
388 private function updateTemplateRobots(array
$robots,
int $userId):
Result
390 $templateId = $this->
template[
'ID'];
393 $errors = $this->validateUpdatedRobots(
$robots,
new \CBPWorkflowTemplateUser($userId));
394 if (!$errors->isEmpty())
396 $result->addErrors($errors->getValues());
403 'TEMPLATE' => $this->
template[
'TEMPLATE'],
404 'PARAMETERS' => $this->
template[
'PARAMETERS'],
406 'CONSTANTS' => $this->
template[
'CONSTANTS'],
407 'USER_ID' => $userId,
408 'MODIFIER_USER' => new \CBPWorkflowTemplateUser($userId),
411 if (isset($this->
template[
'NAME']))
413 $updateFields[
'NAME'] = $this->
template[
'NAME'];
418 \CBPWorkflowTemplateLoader::update($templateId, $updateFields,
false,
false);
420 catch (\Exception $e)
422 $result->addError(
new Error($e->getMessage()));
428 private function validateUpdatedRobots(array
$robots, \CBPWorkflowTemplateUser $user): ErrorCollection
430 $errors =
new ErrorCollection();
431 $loader = \CBPWorkflowTemplateLoader::GetLoader();
434 $isSameRobot =
function ($lhsRobot, $rhsRobot) {
435 return $lhsRobot->getName() === $rhsRobot->getName();
441 if (is_array($robot))
443 $robot =
new Robot($robot);
445 if (!($robot instanceof Robot))
447 $errors->setError(
new Error(
'Robots array is incorrect'));
449 if (!$errors->isEmpty())
454 $indexOfFoundRobot = -1;
455 foreach ($originalRobots as $index => $originalRobot)
457 if ($isSameRobot($robot, $originalRobot))
459 $indexOfFoundRobot = $index;
464 if ($indexOfFoundRobot < 0 || !$this->areRobotsEqual($robot, $originalRobots[$indexOfFoundRobot]))
466 $sequence = $this->convertRobotToSequenceActivity($robot);
467 foreach ($loader->ValidateTemplate($sequence, $user) as $rawError)
469 $errors->setError(
new Error(trim($rawError[
'message'])));
471 unset($originalRobots[$indexOfFoundRobot]);
478 private function areRobotsEqual(Robot $lhsRobot, Robot $rhsRobot): bool
480 $lhsCondition = $lhsRobot->getCondition() ??
new ConditionGroup();
481 $rhsCondition = $rhsRobot->getCondition() ??
new ConditionGroup();
483 $lhsDelay = $lhsRobot->getDelayInterval();
484 $rhsDelay = $rhsRobot->getDelayInterval();
485 if (!isset($lhsDelay) || $lhsDelay->isNow())
487 $lhsDelay =
new DelayInterval();
489 if (!isset($rhsDelay) || $rhsDelay->isNow())
491 $rhsDelay =
new DelayInterval();
495 $lhsCondition->toArray()[
'items'] === $rhsCondition->toArray()[
'items']
496 && $lhsDelay->toArray() === $rhsDelay->toArray()
497 && $lhsRobot->getBizprocActivity() === $rhsRobot->getBizprocActivity()
507 'TEMPLATE' => $raw[
'TEMPLATE'],
508 'PARAMETERS' => $raw[
'PARAMETERS'],
510 'CONSTANTS' => $raw[
'CONSTANTS'],
511 'USER_ID' => $userId,
512 'MODIFIER_USER' => new \CBPWorkflowTemplateUser($userId),
515 if (isset($raw[
'NAME']))
517 $updateFields[
'NAME'] = $raw[
'NAME'];
522 \CBPWorkflowTemplateLoader::update($id, $updateFields);
526 $result->addError(
new Error($e->getMessage()));
534 $this->robots = array();
537 if (!is_array($raw) || !isset($raw[
'TEMPLATE']))
548 if (empty($raw[
'TEMPLATE'][0][
'Children']) || !is_array($raw[
'TEMPLATE'][0][
'Children']))
551 if (count($raw[
'TEMPLATE'][0][
'Children']) > 1)
557 $parallelActivity = $raw[
'TEMPLATE'][0][
'Children'][0];
558 if (!$parallelActivity || $parallelActivity[
'Type'] !== static::$parallelActivityType)
564 foreach ($parallelActivity[
'Children'] as $sequence)
566 $delay = $condition =
null;
568 foreach ($sequence[
'Children'] as $activity)
571 $activity[
'Type'] === static::$delayActivityType
572 || $activity[
'Type'] === static::$robotDelayActivityType)
578 if ($activity[
'Type'] === static::$conditionActivityType)
581 if ($condition ===
false)
584 $this->robots = array();
589 if (!$this->
isRobot($activity))
592 $this->robots = array();
596 $robotActivity =
new Robot($activity);
600 $robotActivity->setDelayInterval($delayInterval);
601 $robotActivity->setDelayName($delay[
'Name']);
605 if ($condition !==
null)
607 $robotActivity->setCondition($condition);
613 $robotActivity->setExecuteAfterPrevious();
617 $this->robots[] = $robotActivity;
621 $this->isConverted =
true;
629 'ID' => $this->
getId(),
630 'MODULE_ID' => $documentType[0],
631 'ENTITY' => $documentType[1],
632 'DOCUMENT_TYPE' => $documentType[2],
633 'DOCUMENT_STATUS' => $this->
template[
'DOCUMENT_STATUS'],
637 'Type' =>
'SequentialWorkflowActivity',
638 'Name' =>
'Template',
639 'Properties' => [
'Title' =>
'Bizproc Automation template'],
642 'PARAMETERS' => $this->
template[
'PARAMETERS'],
643 'CONSTANTS' => $this->
template[
'CONSTANTS'],
644 'SYSTEM_CODE' =>
'bitrix_bizproc_automation',
649 $parallelActivity = $this->createParallelActivity();
650 $sequence = $this->createSequenceActivity();
652 foreach ($this->robots as $i => $robot)
654 if ($i !== 0 && !$robot->isExecuteAfterPrevious())
656 $parallelActivity[
'Children'][] = $sequence;
657 $sequence = $this->convertRobotToSequenceActivity($robot);
661 $sequence[
'Children'] = array_merge(
662 $sequence[
'Children'],
663 $this->convertRobotToSequenceActivity($robot)[
'Children']
668 $parallelActivity[
'Children'][] = $sequence;
670 if (count($parallelActivity[
'Children']) < 2)
672 $parallelActivity[
'Children'][] = $this->createSequenceActivity();
675 $this->
template[
'TEMPLATE'][0][
'Children'][] = $parallelActivity;
677 $this->robots =
null;
678 $this->isConverted =
false;
681 private function convertRobotToSequenceActivity(
Robot $robot): array
683 $sequence = $this->createSequenceActivity();
686 if ($delayInterval && !$delayInterval->isNow())
695 $sequence[
'Children'][] = $this->createDelayActivity(
696 $delayInterval->toActivityProperties($this->getDocumentType()),
704 if ($condition && $condition->getItems())
706 $activity = $condition->createBizprocActivity($activity, $this->
getDocumentType(), $this);
709 $sequence[
'Children'][] = $activity;
716 if (!in_array($activity[
'Type'], static::getAvailableRobotClasses($this->
getDocumentType())))
719 if (!empty($activity[
'Children']))
729 if ($this->robots ===
null)
744 if ($name === $robot->getName())
754 return array_uintersect($this->
getRobots(), $names,
function ($lhs, $rhs) {
755 $lhsName = is_string($lhs) ? $lhs : $lhs->getName();
756 $rhsName = is_string($rhs) ? $rhs : $rhs->getName();
758 return strcmp($lhsName, $rhsName);
767 return $this->
template[
'TEMPLATE'];
772 return $this->
template[
'MODIFIED'] ??
null;
789 return [$this->
template[
'MODULE_ID'], $this->
template[
'ENTITY'], $this->
template[
'DOCUMENT_TYPE']];
797 return $this->
template[
'PARAMETERS'][$field] ??
null;
799 return $this->
template[
'VARIABLES'][$field] ??
null;
801 return $this->
template[
'CONSTANTS'][$field] ??
null;
803 return Bizproc\Workflow\Type\GlobalConst::getVisibleById($field, $this->
getDocumentType());
805 return Bizproc\Workflow\Type\GlobalVar::getVisibleById($field, $this->
getDocumentType());
810 $documentService = \CBPRuntime::GetRuntime(
true)->getDocumentService();
811 $fields = $documentService->GetDocumentFields($this->
getDocumentType());
814 return $fields[$field] ??
null;
816 if ($this->isConverted)
818 return $this->findRobotProperty($object, $field);
822 return $this->findActivityProperty($object, $field);
827 private function findRobotProperty($object, $field): ?array
833 private function findActivityProperty($object, $field): ?array
835 $activity = self::findTemplateActivity($this->
template[
'TEMPLATE'], $object);
841 $props = \CBPRuntime::GetRuntime(
true)->getActivityReturnProperties($activity[
'Type']);
842 return $props[$field] ??
null;
845 private static function findTemplateActivity(array
$template, $id)
849 if ($activity[
'Name'] === $id)
853 if (is_array($activity[
'Children']))
855 $found = self::findTemplateActivity($activity[
'Children'], $id);
865 private function createSequenceActivity()
868 'Type' => static::$sequenceActivityType,
871 'Title' =>
'Automation sequence',
877 private function createParallelActivity()
880 'Type' => static::$parallelActivityType,
882 'Properties' => array(
889 private function createDelayActivity(array $delayProperties, $delayName)
891 if (!isset($delayProperties[
'Title']))
893 $delayProperties[
'Title'] =
Loc::getMessage(
'BIZPROC_AUTOMATION_ROBOT_DELAY_ACTIVITY');
897 'Type' => static::$robotDelayActivityType,
898 'Name' => $delayName,
899 'Properties' => $delayProperties,
static convertBizprocActivity(array &$activity, array $documentType, Template $template)
static createFromActivityProperties(array $properties)
getReturnProperty(string $name)
static $availableActivityClasses
static $delayActivityType
static $sequenceActivityType
setExecuteType($autoExecuteType)
addBizprocTemplate($userId)
deleteRobots(array $robots, int $userId)
updateBizprocTemplate($id, $userId)
setDocumentStatus($status)
static $parallelActivityType
static getAvailableRobotClasses(array $documentType)
static $conditionActivityType
getProperty($object, $field)
static getAvailableRobots(array $documentType)
__construct(array $documentType, $documentStatus=null)
static $robotDelayActivityType
getRobotsByNames(array $names)
static $availableActivities
getRobotByName(string $name)
getRobotSettingsDialog(array $robot, $request=null)
save(array $robots, $userId, array $additional=[])
static createByTpl(Tpl $tpl)
getExecuteType($autoExecuteType)
saveRobotSettings(array $robot, array $request)
static loadMessages($file)
static getMessage($code, $replace=null, $language=null)