1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
workflowtemplateloader.php
См. документацию.
1<?php
2
12
13define("BP_EI_DIRECTION_EXPORT", 0);
14define("BP_EI_DIRECTION_IMPORT", 1);
15
20{
21 protected $useGZipCompression = false;
22 protected $templateType = null;
23 protected static $workflowConstants = array();
24 const CONSTANTS_CACHE_TAG_PREFIX = 'b_bp_wf_constants_';
25 protected static $typesStates = array();
26
27 private static $instance;
28
29 public const MAX_PARAMETERS_LENGTH = 65535;
30 public const MAX_VARIABLES_LENGTH = 65535;
31 public const MAX_CONSTANTS_LENGTH = 16777215;
32
33 private function __construct()
34 {
35 $this->useGZipCompression = static::useGZipCompression();
36 }
37
38 public function __clone()
39 {
40 trigger_error('Clone in not allowed.', E_USER_ERROR);
41 }
42
48 public static function getLoader()
49 {
50 if (!isset(self::$instance))
51 {
52 $c = __CLASS__;
53 self::$instance = new $c;
54 }
55
56 return self::$instance;
57 }
58
59 public static function getList($arOrder = array("ID" => "DESC"), $arFilter = array(), $arGroupBy = false, $arNavStartParams = false, $arSelectFields = array())
60 {
62 return $loader->GetTemplatesList($arOrder, $arFilter, $arGroupBy, $arNavStartParams, $arSelectFields);
63 }
64
65 public static function checkTemplateActivities(array $template)
66 {
67 foreach ($template as $activity)
68 {
69 if (!CBPActivity::IncludeActivityFile($activity['Type']))
70 return false;
71 if (!empty($activity['Children']))
72 {
73 $childResult = static::checkTemplateActivities($activity['Children']);
74 if (!$childResult)
75 return false;
76 }
77 }
78
79 return true;
80 }
81
82 public function validateTemplate($arActivity, $user)
83 {
85 $arActivity['Type'],
86 'ValidateProperties',
87 [$arActivity['Properties'], $user]
88 );
89
90 $pref = '';
91 if (isset($arActivity['Properties']['Title']))
92 {
93 $pref =
94 Loc::getMessage('BPWTL_ERROR_MESSAGE_PREFIX', ['#TITLE#' => $arActivity['Properties']['Title']])
95 . ' '
96 ;
97 }
98
99 foreach ($errors as $i => $e)
100 {
101 $errors[$i]['message'] = $pref . $e['message'];
102 $errors[$i]['activityName'] = $arActivity['Name'];
103 }
104
105 if (array_key_exists('Children', $arActivity) && count($arActivity['Children']) > 0)
106 {
107 $bFirst = true;
108
109 $childrenErrors = [];
110 foreach ($arActivity['Children'] as $arChildActivity)
111 {
112 if (!isset($arChildActivity['Activated']) || $arChildActivity['Activated'] !== 'N')
113 {
114 $childErrors = CBPActivity::callStaticMethod(
115 $arActivity['Type'],
116 'ValidateChild',
117 [$arChildActivity['Type'], $bFirst]
118 );
119
120 foreach ($childErrors as $i => $e)
121 {
122 $childErrors[$i]['message'] = $pref . $e['message'];
123 $childErrors[$i]['activityName'] = $arActivity['Name'];
124 }
125
126 if ($childErrors)
127 {
128 $childrenErrors[] = $childErrors;
129 }
130
131 $bFirst = false;
132 $validateErrors = $this->validateTemplate($arChildActivity, $user);
133 if ($validateErrors)
134 {
135 $childrenErrors[] = $validateErrors;
136 }
137 }
138 }
139
140 $errors = array_merge($errors, ...$childrenErrors);
141 }
142
143 return $errors;
144 }
145
146 protected function parseFields(&$arFields, $id = 0, $systemImport = false, $validationRequired = true)
147 {
148 $id = intval($id);
149 $updateMode = ($id > 0 ? true : false);
150 $addMode = !$updateMode;
151
152 if ($addMode && !isset($arFields["DOCUMENT_TYPE"]))
153 throw new CBPArgumentNullException("DOCUMENT_TYPE");
154
155 if (isset($arFields["DOCUMENT_TYPE"]))
156 {
157 $arDocumentType = CBPHelper::ParseDocumentId($arFields["DOCUMENT_TYPE"]);
158
159 $arFields["MODULE_ID"] = $arDocumentType[0];
160 $arFields["ENTITY"] = $arDocumentType[1];
161 $arFields["DOCUMENT_TYPE"] = $arDocumentType[2];
162 }
163 else
164 {
165 unset($arFields["MODULE_ID"]);
166 unset($arFields["ENTITY"]);
167 unset($arFields["DOCUMENT_TYPE"]);
168 }
169
170 if (isset($arFields["NAME"]) || $addMode)
171 {
172 $arFields["NAME"] = trim($arFields["NAME"]);
173 if ($arFields["NAME"] == '')
174 throw new CBPArgumentNullException("NAME");
175 }
176
177 if ($addMode && !isset($arFields['TEMPLATE']))
178 {
179 throw new CBPArgumentNullException('TEMPLATE');
180 }
181
182 if (array_key_exists('TEMPLATE', $arFields))
183 {
184 if (!is_array($arFields["TEMPLATE"]))
185 {
186 throw new CBPArgumentTypeException("TEMPLATE", "array");
187 }
188 else
189 {
190 $userTmp = null;
191
192 if (!$systemImport)
193 {
194 if (array_key_exists("MODIFIER_USER", $arFields))
195 {
196 if (is_object($arFields["MODIFIER_USER"]) && is_a($arFields["MODIFIER_USER"], "CBPWorkflowTemplateUser"))
197 $userTmp = $arFields["MODIFIER_USER"];
198 else
199 $userTmp = new CBPWorkflowTemplateUser($arFields["MODIFIER_USER"]);
200 }
201 else
202 {
203 $userTmp = new CBPWorkflowTemplateUser();
204 }
205
206 $errors = array();
207 if ($validationRequired)
208 {
209 foreach ($arFields['TEMPLATE'] as $rawTemplate)
210 {
211 array_push($errors, ...$this->ValidateTemplate($rawTemplate, $userTmp));
212 }
213 }
214
215 if (count($errors) > 0)
216 {
217 $messages = array();
218 foreach ($errors as $v)
219 {
220 $messages[] = trim($v["message"]);
221 }
223 }
224 }
225 }
226 }
227
228 $enumValues = array_column(WorkflowTemplateType::cases(), 'value');
229 if (isset($arFields['TYPE']) && !in_array($arFields['TYPE'], $enumValues, true))
230 {
231 $arFields['TYPE'] = WorkflowTemplateType::Default->value;
232 }
233
234 if (isset($arFields["ACTIVE"]) && $arFields["ACTIVE"] !== 'N')
235 $arFields["ACTIVE"] = 'Y';
236
237 if (isset($arFields["IS_SYSTEM"]) && $arFields["IS_SYSTEM"] !== 'Y')
238 $arFields["IS_SYSTEM"] = 'N';
239
240 if (isset($arFields["IS_MODIFIED"]) && $arFields["IS_MODIFIED"] !== 'N')
241 $arFields["IS_MODIFIED"] = 'Y';
242
243 unset($arFields["MODIFIED"]);
244 }
245
246 public static function add($fields, $systemImport = false)
247 {
249 $loader->getTemplateType($fields);
250 $loader->setShowInTimelineBeforeAdd($fields);
251 $loader->setTemplateType($fields);
252
253 $id = $loader->AddTemplate($fields, $systemImport);
254 $loader->addTemplateSettings($id, $fields);
255
256 return $id;
257 }
258
259 public function addTemplateSettings(int $templateId, array $templateFields): void
260 {
261 if (
262 isset($templateFields['DOCUMENT_TYPE'])
263 && !empty($templateFields['TEMPLATE_SETTINGS'])
264 )
265 {
266 $rows = [];
267 foreach ($templateFields['TEMPLATE_SETTINGS'] as $option => $value)
268 {
269 $rows[] = [
270 'TEMPLATE_ID' => $templateId,
271 'NAME' => $option,
272 'VALUE' => $value,
273 ];
274 }
275
276 WorkflowTemplateSettingsTable::addMultiSettings($rows);
277 }
278 }
279
280 private function deleteTemplateSettings(int $templateId)
281 {
282 WorkflowTemplateSettingsTable::deleteSettingsByFilter(['=TEMPLATE_ID' => $templateId]);
283 }
284
285 public static function update($id, $fields, $systemImport = false, $validationRequired = true)
286 {
288 $loader->getTemplateType($fields, $id);
289 $loader->setShowInTimelineBeforeUpdate($fields);
290 $loader->setTemplateType($fields);
291
292 if (isset($fields['TEMPLATE']) && !$systemImport)
293 {
294 $fields['IS_MODIFIED'] = 'Y';
295 }
296
297 $returnId = $loader->UpdateTemplate($id, $fields, $systemImport, $validationRequired);
298 $loader->updateTemplateSettings($id, $fields);
299 self::cleanTemplateCache($returnId);
300
301 return $returnId;
302 }
303
304 public function setTemplateType(array &$fields, ?string $templateType = null)
305 {
306 $fields['TYPE'] = $this->templateType;
307
308 if (!empty($templateType))
309 {
310 $fields['TYPE'] = $templateType;
311 }
312 }
313
314 private function updateTemplateSettings(int $templateId, array $templateFields)
315 {
316 if (
317 isset($templateFields['DOCUMENT_TYPE'])
318 && !empty($templateFields['TEMPLATE_SETTINGS'])
319 )
320 {
321 $filter = [];
322 $filter['LOGIC'] = 'OR';
323 foreach ($templateFields['TEMPLATE_SETTINGS'] as $option => $value)
324 {
325 $filter[] = ['=NAME' => $option, '=TEMPLATE_ID' => $templateId];
326 }
327
328 $existSettings = [];
329 $result = WorkflowTemplateSettingsTable::getList([
330 'filter' => $filter,
331 'select' => ['ID', 'NAME']
332 ]);
333 while ($row = $result->fetch())
334 {
335 $existSettings[$row['NAME']] = $row['ID'];
336 }
337
338 foreach ($templateFields['TEMPLATE_SETTINGS'] as $option => $value)
339 {
340 if (isset($existSettings[$option]))
341 {
342 WorkflowTemplateSettingsTable::update($existSettings[$option], ['VALUE' => $value]);
343 }
344 else
345 {
346 WorkflowTemplateSettingsTable::add([
347 'TEMPLATE_ID' => $templateId,
348 'NAME' => $option,
349 'VALUE' => $value,
350 ]);
351 }
352 }
353 }
354 }
355
356 public function getTemplateType(array $fields, int $id = 0)
357 {
358 if (
359 empty($fields['DOCUMENT_TYPE'])
360 || empty($fields['TEMPLATE'])
361 || !array_key_exists('AUTO_EXECUTE', $fields)
362 )
363 {
364 if ($id > 0)
365 {
366 $template = self::getList(
367 arFilter: ['ID' => $id],
368 arSelectFields: ['DOCUMENT_TYPE', 'TEMPLATE', 'AUTO_EXECUTE']
369 );
370 if ($row = $template->fetch())
371 {
372 $fields['DOCUMENT_TYPE'] = $row['DOCUMENT_TYPE'];
373 $fields['TEMPLATE'] = $row['TEMPLATE'];
374 $fields['AUTO_EXECUTE'] = $row['AUTO_EXECUTE'];
375 }
376 }
377 else
378 {
379 $this->templateType = WorkflowTemplateType::Default->value; // Not enough data to determine type
380
381 return;
382 }
383 }
384
385 $this->templateType = WorkflowTemplateType::Default->value;
386 if ($this->isRobot((int)$fields['AUTO_EXECUTE']))
387 {
388 $this->templateType = WorkflowTemplateType::Robots->value;
389 if ($this->isExternalModified($fields))
390 {
391 $this->templateType = WorkflowTemplateType::CustomRobots->value;
392 }
393 }
394 }
395
397 {
398 $isCrm = array_key_exists('DOCUMENT_TYPE', $fields) && $fields['DOCUMENT_TYPE'][0] === 'crm';
399
400 $customRobotToRobot =
401 array_key_exists('TYPE', $fields)
402 && $fields['TYPE'] !== WorkflowTemplateType::Robots->value
403 && $this->templateType === WorkflowTemplateType::Robots->value
404 ;
405
406 if ($isCrm && $customRobotToRobot)
407 {
408 $fields['TEMPLATE_SETTINGS']['SHOW_IN_TIMELINE'] = 'N';
409 }
410 }
411
412 private function isRobot(int $autoExecute): bool
413 {
414 return $autoExecute === \CBPDocumentEventType::Automation || $autoExecute === \CBPDocumentEventType::Script;
415 }
416
418 {
419 $isCrm = array_key_exists('DOCUMENT_TYPE', $fields) && $fields['DOCUMENT_TYPE'][0] === 'crm';
420
421 if ($isCrm && empty($fields['TEMPLATE_SETTINGS']['SHOW_IN_TIMELINE']))
422 {
423 $fields['TEMPLATE_SETTINGS']['SHOW_IN_TIMELINE'] = 'N';
424 }
425 }
426
427 private function getSerializedForm($arTemplate)
428 {
429 return WorkflowTemplateTable::toSerializedForm($arTemplate);
430 }
431
432 private function getSerializedSettings($arTemplate)
433 {
434 return WorkflowTemplateTable::encodeJson($arTemplate);
435 }
436
437 public static function delete($id)
438 {
440 $loader->DeleteTemplate($id);
441 $loader->deleteTemplateSettings($id);
442 self::cleanTemplateCache($id);
443
444 \Bitrix\Bizproc\Storage\Factory::getInstance()->onAfterTemplateDelete($id);
445 }
446
447 protected static function cleanTemplateCache($id)
448 {
449 $cache = \Bitrix\Main\Application::getInstance()->getManagedCache();
450 $cache->clean(self::CONSTANTS_CACHE_TAG_PREFIX . $id);
451 unset(self::$workflowConstants[$id]);
452 }
453
454 public function deleteTemplate($id)
455 {
456 $id = (int)$id;
457 if ($id <= 0)
458 {
459 throw new Exception("id");
460 }
461
462 $hasInstance = (bool)WorkflowInstanceTable::getRow([
463 'select' => ['ID'],
464 'filter' => ['=WORKFLOW_TEMPLATE_ID' => $id],
465 'order' => ['DOCUMENT_ID' => 'DESC'],
466 ]);
467
468 if (!$hasInstance)
469 {
470 WorkflowTemplateTable::delete($id);
471
472 $event = new Event(
473 'bizproc',
474 'onAfterWorkflowTemplateDelete',
475 [
476 'ID' => $id,
477 ]
478 );
479 EventManager::getInstance()->send($event);
480
481 WorkflowDurationStatTable::deleteAllByTemplateId($id);
482 Bitrix\Main\Config\Option::delete('bizproc', ['name' => 'tpl_track_on_' . $id]);
483 }
484 else
485 {
486 throw new CBPInvalidOperationException(GetMessage("BPCGWTL_CANT_DELETE"));
487 }
488 }
489
490 public function loadWorkflow($workflowTemplateId)
491 {
492 $workflowTemplateId = intval($workflowTemplateId);
493 if ($workflowTemplateId <= 0)
494 {
495 throw new CBPArgumentOutOfRangeException("workflowTemplateId", $workflowTemplateId);
496 }
497
498 $dbTemplatesList = $this->GetTemplatesList(
499 [],
500 ['ID' => $workflowTemplateId],
501 false,
502 false,
503 ['TEMPLATE', 'VARIABLES', 'PARAMETERS']
504 );
505 $arTemplatesListItem = $dbTemplatesList->Fetch();
506
507 if (!$arTemplatesListItem)
508 {
509 throw new Exception(str_replace('#ID#', $workflowTemplateId, GetMessage('BPCGWTL_INVALID_WF_ID')));
510 }
511
512 $arTemplatesListItem['ID'] = $workflowTemplateId;
513
514 return $this->loadWorkflowFromArray($arTemplatesListItem);
515 }
516
517 public function loadWorkflowFromArray($templatesListItem): array
518 {
519 $wfId = $templatesListItem['ID'];
520 $wfTemplate = $templatesListItem['TEMPLATE'];
521 $wfVariablesTypes = $templatesListItem['VARIABLES'];
522 $wfParametersTypes = $templatesListItem['PARAMETERS'];
523
524 if (!is_array($wfTemplate) || count($wfTemplate) <= 0)
525 {
526 throw new Exception(str_replace('#ID#', $wfId, GetMessage('BPCGWTL_EMPTY_TEMPLATE')));
527 }
528
529 $activityNames = [];
530 $rootActivity = $this->parseWorkflowTemplate($wfTemplate, $activityNames);
531
532 return [$rootActivity, $wfVariablesTypes, $wfParametersTypes];
533 }
534
535 private function parseWorkflowTemplate($arWorkflowTemplate, &$arActivityNames, CBPActivity $parentActivity = null)
536 {
537 if (!is_array($arWorkflowTemplate))
538 {
539 throw new CBPArgumentOutOfRangeException('arWorkflowTemplate');
540 }
541
542 foreach ($arWorkflowTemplate as $activityFormatted)
543 {
544 if (in_array($activityFormatted['Name'], $arActivityNames))
545 {
546 throw new Exception('DuplicateActivityName');
547 }
548
549 $arActivityNames[] = $activityFormatted['Name'];
550 $activity = $this->createActivity($activityFormatted);
551 if ($activity === null)
552 {
553 throw new Exception('Activity is not found.');
554 }
555
556 $activity->initializeFromArray($activityFormatted['Properties']);
557 if ($parentActivity)
558 {
559 $parentActivity->fixUpParentChildRelationship($activity);
560 }
561
562 if (!empty($activityFormatted['Children']))
563 {
564 $this->parseWorkflowTemplate($activityFormatted['Children'], $arActivityNames, $activity);
565 }
566 }
567
568 return $activity;
569 }
570
571 private function createActivity(array $activityFormatted): ?CBPActivity
572 {
573 $code = $activityFormatted['Type'];
574 $name = $activityFormatted['Name'];
575 $activated = !isset($activityFormatted['Activated']) || $activityFormatted['Activated'] === 'Y';
576
578 {
580 if ($instance)
581 {
582 $instance->setActivated($activated);
583 }
584
585 return $instance;
586 }
587 else
588 {
589 throw new Exception('Activity is not found.');
590 }
591 }
592
593 public static function getStatesOfTemplate($arWorkflowTemplate)
594 {
595 if (!is_array($arWorkflowTemplate))
596 throw new CBPArgumentTypeException("arWorkflowTemplate", "array");
597
598 if (!is_array($arWorkflowTemplate[0]))
599 throw new CBPArgumentTypeException("arWorkflowTemplate");
600
601 $arStates = array();
602 foreach ($arWorkflowTemplate[0]["Children"] as $state)
603 $arStates[$state["Name"]] = ($state["Properties"]["Title"] <> '' ? $state["Properties"]["Title"] : $state["Name"]);
604
605 return $arStates;
606 }
607
608 private static function findSetStateActivities($arWorkflowTemplate)
609 {
610 $arResult = array();
611
612 if ($arWorkflowTemplate["Type"] == "SetStateActivity")
613 $arResult[] = $arWorkflowTemplate["Properties"]["TargetStateName"];
614
615 if (is_array($arWorkflowTemplate["Children"]))
616 {
617 foreach ($arWorkflowTemplate["Children"] as $key => $value)
618 $arResult = $arResult + self::FindSetStateActivities($arWorkflowTemplate["Children"][$key]);
619 }
620
621 return $arResult;
622 }
623
624 public static function getTransfersOfState($arWorkflowTemplate, $stateName)
625 {
626 if (!is_array($arWorkflowTemplate))
627 throw new CBPArgumentTypeException("arWorkflowTemplate", "array");
628
629 if (!is_array($arWorkflowTemplate[0]))
630 throw new CBPArgumentTypeException("arWorkflowTemplate");
631
632 $stateName = trim($stateName);
633 if ($stateName == '')
634 throw new CBPArgumentNullException("stateName");
635
636 $arTransfers = array();
637 foreach ($arWorkflowTemplate[0]["Children"] as $state)
638 {
639 if ($stateName == $state["Name"])
640 {
641 foreach ($state["Children"] as $event)
642 $arTransfers[$event["Name"]] = self::FindSetStateActivities($event);
643
644 break;
645 }
646 }
647
648 return $arTransfers;
649 }
650
651 private static function parseDocumentTypeStates($arTemplatesListItem)
652 {
653 $arWorkflowTemplate = $arTemplatesListItem["TEMPLATE"];
654 if (!is_array($arWorkflowTemplate))
655 throw new CBPArgumentTypeException("arTemplatesListItem");
656
657 $result = array(
658 "ID" => "",
659 "TEMPLATE_ID" => $arTemplatesListItem["ID"],
660 "TEMPLATE_NAME" => $arTemplatesListItem["NAME"],
661 "TEMPLATE_DESCRIPTION" => $arTemplatesListItem["DESCRIPTION"],
662 "STATE_NAME" => "",
663 "STATE_TITLE" => "",
664 "TEMPLATE_PARAMETERS" => $arTemplatesListItem["PARAMETERS"],
665 "STATE_PARAMETERS" => array(),
666 "STATE_PERMISSIONS" => array(),
667 "WORKFLOW_STATUS" => -1,
668 );
669
670 $type = "CBP".$arWorkflowTemplate[0]["Type"];
671 $bStateMachine = (
672 $type === CBPStateMachineWorkflowActivity::class
673 || (
674 class_exists($type)
675 && is_subclass_of($type, CBPStateMachineWorkflowActivity::class)
676 )
677 );
678
679 if ($bStateMachine)
680 {
681 //if (strlen($stateName) <= 0)
682 $stateName = $arWorkflowTemplate[0]["Properties"]["InitialStateName"];
683
684 if (is_array($arWorkflowTemplate[0]["Children"]))
685 {
686 foreach ($arWorkflowTemplate[0]["Children"] as $state)
687 {
688 if ($stateName == $state["Name"])
689 {
690 $result["STATE_NAME"] = $stateName;
691 $result["STATE_TITLE"] = $state["Properties"]["Title"];
692 $result["STATE_PARAMETERS"] = array();
693 $result["STATE_PERMISSIONS"] = $state["Properties"]["Permission"];
694
695 if (is_array($state["Children"]))
696 {
697 foreach ($state["Children"] as $event)
698 {
699 if ($event["Type"] == "EventDrivenActivity")
700 {
701 if ($event["Children"][0]["Type"] == "HandleExternalEventActivity")
702 {
703 $result["STATE_PARAMETERS"][] = array(
704 "NAME" => $event["Children"][0]["Name"],
705 "TITLE" => $event["Children"][0]["Properties"]["Title"],
706 "PERMISSION" => $event["Children"][0]["Properties"]["Permission"],
707 );
708 }
709 }
710 }
711 }
712
713 break;
714 }
715 }
716 }
717 }
718 else
719 {
720 $result["STATE_PERMISSIONS"] = $arWorkflowTemplate[0]["Properties"]["Permission"] ?? null;
721 }
722
723 if (is_array($result["STATE_PERMISSIONS"]))
724 {
725 $arKeys = array_keys($result["STATE_PERMISSIONS"]);
726 foreach ($arKeys as $key)
727 {
728 $ar = self::ExtractValuesFromVariables($result["STATE_PERMISSIONS"][$key], $arTemplatesListItem["VARIABLES"], $arTemplatesListItem["CONSTANTS"]);
729 $result["STATE_PERMISSIONS"][$key] = CBPHelper::MakeArrayFlat($ar);
730 }
731 }
732
733 return $result;
734 }
735
736 private static function extractValuesFromVariables($ar, $variables, $constants = array())
737 {
738 if (is_string($ar) && preg_match(CBPActivity::ValuePattern, $ar, $arMatches))
739 $ar = array($arMatches['object'], $arMatches['field']);
740
741 if (is_array($ar))
742 {
743 if (!CBPHelper::IsAssociativeArray($ar))
744 {
745 if (count($ar) == 2 && ($ar[0] == 'Variable' || $ar[0] == 'Constant' || $ar[0] == 'Template'))
746 {
747 if ($ar[0] == 'Variable' && is_array($variables) && array_key_exists($ar[1], $variables))
748 return array($variables[$ar[1]]["Default"]);
749 if ($ar[0] == 'Constant' && is_array($constants) && array_key_exists($ar[1], $constants))
750 return array($constants[$ar[1]]["Default"]);
751
752 return array();
753 }
754
755 $arResult = array();
756 foreach ($ar as $ar1)
757 $arResult[] = self::ExtractValuesFromVariables($ar1, $variables, $constants);
758
759 return $arResult;
760 }
761 }
762
763 return $ar;
764 }
765
766 public static function getDocumentTypeStates($documentType, $autoExecute = -1, $stateName = "")
767 {
768 $arFilter = array("DOCUMENT_TYPE" => $documentType);
769 $autoExecute = intval($autoExecute);
770
771 $cacheKey = implode('@', $documentType).'@'.$autoExecute;
772
773 if (!isset(static::$typesStates[$cacheKey]))
774 {
775 $result = array();
776 if ($autoExecute >= 0)
777 $arFilter["AUTO_EXECUTE"] = $autoExecute;
778 $arFilter["ACTIVE"] = "Y";
779
780 $dbTemplatesList = self::GetList(
781 array(),
782 $arFilter,
783 false,
784 false,
785 array('ID', 'NAME', 'DESCRIPTION', 'TEMPLATE', 'PARAMETERS', 'VARIABLES', 'CONSTANTS')
786 );
787 while ($arTemplatesListItem = $dbTemplatesList->Fetch())
788 $result[$arTemplatesListItem["ID"]] = self::ParseDocumentTypeStates($arTemplatesListItem);
789
790 static::$typesStates[$cacheKey] = $result;
791 }
792 return static::$typesStates[$cacheKey];
793 }
794
795 public static function getTemplateState($workflowTemplateId, $stateName = "")
796 {
797 $workflowTemplateId = intval($workflowTemplateId);
798 if ($workflowTemplateId <= 0)
799 throw new CBPArgumentOutOfRangeException("workflowTemplateId", $workflowTemplateId);
800
801 $result = null;
802
803 $dbTemplatesList = self::GetList(
804 array(),
805 array('ID' => $workflowTemplateId),
806 false,
807 false,
808 array('ID', 'NAME', 'DESCRIPTION', 'TEMPLATE', 'PARAMETERS', 'VARIABLES', 'CONSTANTS')
809 );
810 if ($arTemplatesListItem = $dbTemplatesList->Fetch())
811 $result = self::ParseDocumentTypeStates($arTemplatesListItem);
812 else
813 throw new Exception(str_replace("#ID#", $workflowTemplateId, GetMessage("BPCGWTL_INVALID_WF_ID")));
814
815 return $result;
816 }
817
818 public static function getTemplateUserId($workflowTemplateId)
819 {
820 $userId = 0;
821 $dbTemplatesList = self::GetList(
822 [],
823 ['ID' => (int) $workflowTemplateId], false,false, ['USER_ID']
824 );
825 if ($row = $dbTemplatesList->Fetch())
826 {
827 $userId = (int) $row['USER_ID'];
828 }
829
830 return $userId;
831 }
832
833 public static function getTemplateConstants($workflowTemplateId)
834 {
835 $workflowTemplateId = (int) $workflowTemplateId;
836 if ($workflowTemplateId <= 0)
837 throw new CBPArgumentOutOfRangeException("workflowTemplateId", $workflowTemplateId);
838
839 if (!isset(self::$workflowConstants[$workflowTemplateId]))
840 {
841 $cache = \Bitrix\Main\Application::getInstance()->getManagedCache();
842 $cacheTag = self::CONSTANTS_CACHE_TAG_PREFIX.$workflowTemplateId;
843 if ($cache->read(3600*24*7, $cacheTag))
844 {
845 self::$workflowConstants[$workflowTemplateId] = (array) $cache->get($cacheTag);
846 }
847 else
848 {
849 $iterator = self::GetList(
850 array(),
851 array('ID' => $workflowTemplateId),
852 false,
853 false,
854 array('CONSTANTS')
855 );
856 if ($row = $iterator->fetch())
857 {
858 self::$workflowConstants[$workflowTemplateId] = (array) $row['CONSTANTS'];
859 $cache->set($cacheTag, self::$workflowConstants[$workflowTemplateId]);
860 }
861 else
862 self::$workflowConstants[$workflowTemplateId] = array();
863
864 }
865 }
866
867 return self::$workflowConstants[$workflowTemplateId];
868 }
869
875 public static function isConstantsTuned($workflowTemplateId)
876 {
877 $result = true;
878 $constants = self::getTemplateConstants($workflowTemplateId);
879 if (!empty($constants) && is_array($constants))
880 {
881 foreach ($constants as $key => $const)
882 {
883 $value = isset($const['Default']) ? $const['Default'] : null;
884 if (CBPHelper::getBool($const['Required']) && CBPHelper::isEmptyValue($value))
885 {
886 $result = false;
887 break;
888 }
889 }
890 }
891 return $result;
892 }
893
894 public static function checkWorkflowParameters($arTemplateParameters, $arPossibleValues, $documentType, &$arErrors)
895 {
896 $arErrors = array();
897 $arWorkflowParameters = array();
898
899 if (count($arTemplateParameters) <= 0)
900 return array();
901
902 $runtime = CBPRuntime::GetRuntime();
903 $runtime->StartRuntime();
904 $documentService = $runtime->GetService("DocumentService");
905
906 foreach ($arTemplateParameters as $parameterKey => $arParameter)
907 {
908 $arErrorsTmp = array();
909
910 $arWorkflowParameters[$parameterKey] = $documentService->GetFieldInputValue(
911 $documentType,
912 $arParameter,
913 $parameterKey,
914 $arPossibleValues,
915 $arErrorsTmp
916 );
917
918 if (CBPHelper::getBool($arParameter['Required']) && CBPHelper::isEmptyValue($arWorkflowParameters[$parameterKey]))
919 {
920 $arErrorsTmp[] = array(
921 "code" => "RequiredValue",
922 "message" => str_replace("#NAME#", $arParameter["Name"], GetMessage("BPCGWTL_INVALID8")),
923 "parameter" => $parameterKey,
924 );
925 }
926
927 $arErrors = array_merge($arErrors, $arErrorsTmp);
928 }
929
930 return $arWorkflowParameters;
931 }
932
933 public static function searchTemplatesByDocumentType($documentType, $autoExecute = -1)
934 {
935 $result = [];
936
937 $arFilter = ['DOCUMENT_TYPE' => $documentType];
938 $autoExecute = intval($autoExecute);
939 if ($autoExecute >= 0)
940 {
941 $arFilter['AUTO_EXECUTE'] = $autoExecute;
942 }
943
944 $dbTemplatesList = self::GetList(
945 [],
946 $arFilter,
947 false,
948 false,
949 ['ID', 'NAME', 'DESCRIPTION', 'AUTO_EXECUTE']
950 );
951 while ($arTemplatesListItem = $dbTemplatesList->Fetch())
952 {
953 $result[] = [
954 'ID' => $arTemplatesListItem['ID'],
955 'NAME' => $arTemplatesListItem['NAME'],
956 'DESCRIPTION' => $arTemplatesListItem['DESCRIPTION'],
957 'AUTO_EXECUTE' => $arTemplatesListItem['AUTO_EXECUTE'],
958 ];
959 }
960
961 return $result;
962 }
963
964 public static function &FindActivityByName(&$arWorkflowTemplate, $activityName)
965 {
966 $res = null;
967
968 if (!$activityName)
969 {
970 return $res;
971 }
972
973 foreach ($arWorkflowTemplate as $key => $value)
974 {
975 $valueName = $value['Name'] ?? null;
976 if ($valueName == $activityName)
977 {
978 return $arWorkflowTemplate[$key];
979 }
980
981 if (is_array($value["Children"] ?? null))
982 {
983 if ($res = &self::FindActivityByName($arWorkflowTemplate[$key]["Children"], $activityName))
984 {
985 return $res;
986 }
987 }
988 }
989
990 return $res;
991 }
992
993 public static function &FindParentActivityByName(&$arWorkflowTemplate, $activityName)
994 {
995 foreach ($arWorkflowTemplate as $key => $value)
996 {
997 if (is_array($value["Children"]))
998 {
999 for ($i = 0, $s = sizeof($value['Children']); $i < $s; $i++)
1000 {
1001 if ($value["Children"][$i]["Name"] == $activityName)
1002 return $arWorkflowTemplate[$key];
1003 }
1004
1005 if ($res = &self::FindParentActivityByName($arWorkflowTemplate[$key]["Children"], $activityName))
1006 return $res;
1007 }
1008 }
1009 return null;
1010 }
1011
1012 public static function exportTemplate($id, $bCompress = true)
1013 {
1014 $tpl = WorkflowTemplateTable::getById($id)->fetchObject();
1015 if (!$tpl)
1016 {
1017 return false;
1018 }
1019
1020 $packer = new \Bitrix\Bizproc\Workflow\Template\Packer\Bpt();
1021 if (!$bCompress)
1022 {
1023 $packer->disableCompression();
1024 }
1025
1026 return $packer->pack($tpl)->getPackage();
1027 }
1028
1029 private static function walkThroughWorkflowTemplate(&$arWorkflowTemplate, $callback, $user)
1030 {
1031 foreach ($arWorkflowTemplate as $key => $value)
1032 {
1033 if (!call_user_func_array($callback, array($value, $user)))
1034 return false;
1035
1036 if (isset($value['Children']) && is_array($value['Children']))
1037 {
1038 if (
1039 !self::WalkThroughWorkflowTemplate(
1040 $arWorkflowTemplate[$key]['Children'],
1041 $callback,
1042 $user
1043 )
1044 )
1045 {
1046 return false;
1047 }
1048 }
1049 }
1050 return true;
1051 }
1052
1053 private static function importTemplateChecker($arActivity, $user)
1054 {
1055 $arErrors = CBPActivity::CallStaticMethod($arActivity["Type"], "ValidateProperties", array($arActivity["Properties"], $user));
1056 if (count($arErrors) > 0)
1057 {
1058 $m = "";
1059 foreach ($arErrors as $er)
1060 $m .= $er["message"].". ";
1061
1062 throw new Exception($m);
1063
1064 return false;
1065 }
1066
1067 return true;
1068 }
1069
1070 public static function importTemplate($id, $documentType, $autoExecute, $name, $description, $datum, $systemCode = null, $systemImport = false)
1071 {
1072
1073 $packer = new \Bitrix\Bizproc\Workflow\Template\Packer\Bpt();
1074 $unpackResult = $packer->unpack($datum);
1075
1076 if (!$unpackResult->isSuccess())
1077 {
1078 throw new \Bitrix\Main\ArgumentException(reset($unpackResult->getErrorMessages()));
1079 }
1080
1081 $templateFields = $unpackResult->getTpl()->collectValues();
1082 $templateFields['DOCUMENT_FIELDS'] = $unpackResult->getDocumentFields();
1083
1084 return self::importTemplateFromArray($id, $documentType, $autoExecute, $name, $description, $templateFields, $systemCode, $systemImport);
1085 }
1086
1087 public static function importTemplateFromArray($id, $documentType, $autoExecute, $name, $description, $templateFields, $systemCode = null, $systemImport = false)
1088 {
1089 $id = intval($id);
1090 if ($id <= 0)
1091 $id = 0;
1092
1093 if (!$systemImport)
1094 {
1095 if (!self::WalkThroughWorkflowTemplate($templateFields["TEMPLATE"], array("CBPWorkflowTemplateLoader", "ImportTemplateChecker"), new CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser)))
1096 return false;
1097 }
1098 elseif ($id > 0 && !empty($templateFields["CONSTANTS"]))
1099 {
1100 $userConstants = self::getTemplateConstants($id);
1101 if (!empty($userConstants))
1102 {
1103 foreach ($userConstants as $constantName => $constantData)
1104 {
1105 if (isset($templateFields["CONSTANTS"][$constantName]))
1106 {
1107 $templateFields["CONSTANTS"][$constantName]['Default'] = $constantData['Default'];
1108 }
1109 }
1110 }
1111 }
1112
1113 $templateData = array(
1114 "DOCUMENT_TYPE" => $documentType,
1115 "AUTO_EXECUTE" => $autoExecute,
1116 "NAME" => $name,
1117 "DESCRIPTION" => $description,
1118 "TEMPLATE" => $templateFields["TEMPLATE"],
1119 "PARAMETERS" => $templateFields["PARAMETERS"],
1120 "VARIABLES" => $templateFields["VARIABLES"],
1121 "CONSTANTS" => $templateFields["CONSTANTS"],
1122 "USER_ID" => $systemImport ? 1 : $GLOBALS["USER"]->GetID(),
1123 "MODIFIER_USER" => new CBPWorkflowTemplateUser($systemImport ? 1 : CBPWorkflowTemplateUser::CurrentUser),
1124 );
1125 if (!is_null($systemCode))
1126 $templateData["SYSTEM_CODE"] = $systemCode;
1127 if ($id <= 0)
1128 $templateData['ACTIVE'] = 'Y';
1129
1130 if ($id > 0)
1131 self::Update($id, $templateData, $systemImport);
1132 else
1133 $id = self::Add($templateData, $systemImport);
1134
1135 if ($templateFields['DOCUMENT_FIELDS'] && is_array($templateFields['DOCUMENT_FIELDS']))
1136 {
1137 static::importDocumentFields($documentType, $templateFields['DOCUMENT_FIELDS']);
1138 }
1139
1140 return $id;
1141 }
1142
1143 public static function importDocumentFields(array $documentType, array $fields)
1144 {
1145 $documentService = CBPRuntime::GetRuntime(true)->getDocumentService();
1146 $currentDocumentFields = $documentService->GetDocumentFields($documentType, true);
1147
1149 $len = mb_strlen("_PRINTABLE");
1150
1151 foreach ($fields as $code => $field)
1152 {
1153 //skip printable
1154 if (mb_strtoupper(mb_substr($code, -$len)) == "_PRINTABLE")
1155 {
1156 continue;
1157 }
1158
1159 //skip references
1160 if (mb_strpos($code, '.') !== false)
1161 {
1162 continue;
1163 }
1164
1165 $documentField = [
1166 "name" => $field["Name"],
1167 "code" => $code,
1168 "type" => $field["Type"],
1169 "multiple" => $field["Multiple"] ?? null,
1170 "required" => $field["Required"] ?? null,
1171 ];
1172
1173 if (isset($field['Options']) && is_array($field["Options"]) && count($field["Options"]) > 0)
1174 {
1175 $documentField['options'] = '';
1176 foreach ($field["Options"] as $k => $v)
1177 {
1178 if (!is_scalar($v))
1179 {
1180 continue;
1181 }
1182
1183 $documentField["options"] .= "[".$k."]".$v."\n";
1184 }
1185 }
1186
1187 unset($field["Name"], $field["Type"], $field["Multiple"], $field["Required"], $field["Options"]);
1188 $documentField = array_merge($documentField, $field);
1189
1190 if ($currentDocumentFields && !array_key_exists($code, $currentDocumentFields))
1191 {
1192 $documentService->AddDocumentField($documentType, $documentField);
1193 }
1194 else
1195 {
1196 $documentService->UpdateDocumentField($documentType, $documentField);
1197 }
1198 }
1199 }
1200
1201 public function getTemplatesList(
1202 array $order = ['ID' => 'DESC'],
1203 array $filter = [],
1204 $group = false,
1205 $navStartParams = false,
1206 array $select = []
1207 )
1208 {
1211
1212 if (is_array($group) && empty($group))
1213 {
1214 $countQuery =
1215 WorkflowTemplateTable::query()
1216 ->addSelect(new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(*)'))
1217 ->setFilter($filter);
1218
1219 $countResult = $countQuery->fetch();
1220
1221 return $countResult ? $countResult['CNT'] : false;
1222 }
1223
1224 $query = WorkflowTemplateTable::query()
1225 ->setSelect($select)
1226 ->setFilter($filter)
1227 ->setOrder($order)
1228 ;
1229
1230 if (is_array($group) && !empty($group))
1231 {
1232 $query->setSelect($group);
1233 $query->addSelect(new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(*)'));
1234 $query->setGroup($group);
1235 }
1236
1237 $topCount = 0;
1238 $hasNavStartParams = (is_array($navStartParams) && !empty($navStartParams));
1239 if ($hasNavStartParams && isset($navStartParams['nTopCount']))
1240 {
1241 $topCount = (int)$navStartParams['nTopCount'];
1242 }
1243
1244 if ($hasNavStartParams && $topCount > 0)
1245 {
1246 $query->setLimit($topCount);
1247 }
1248 elseif ($hasNavStartParams && isset($navStartParams['iNumPage']) && isset($navStartParams['nPageSize']))
1249 {
1250 $query->setOffset(((int)$navStartParams['iNumPage'] - 1) * (int)$navStartParams['nPageSize']);
1251 $query->setLimit((int)$navStartParams['nPageSize']);
1252 }
1253
1254 $result = $query->exec();
1255
1257 }
1258
1259 protected function prepareTemplatesFilter(array &$filter): void
1260 {
1261 if (array_key_exists('DOCUMENT_TYPE', $filter) && is_array($filter['DOCUMENT_TYPE']))
1262 {
1263 [$moduleId, $entity, $documentId] = CBPHelper::ParseDocumentId($filter['DOCUMENT_TYPE']);
1264 $filter['=MODULE_ID'] = $moduleId;
1265 $filter['=ENTITY'] = $entity;
1266 $filter['=DOCUMENT_TYPE'] = $documentId;
1267
1268 unset($filter['DOCUMENT_TYPE']);
1269 }
1270
1271 $entity = WorkflowTemplateTable::getEntity();
1272 $strictMatchFields = [];
1273
1274 foreach ($entity->getFields() as $field)
1275 {
1276 if ($field->getDataType() === 'string' || $field->getDataType() === 'boolean')
1277 {
1278 $strictMatchFields[] = $field->getName();
1279 }
1280 }
1281
1282 foreach ($strictMatchFields as $fieldName)
1283 {
1284 if (isset($filter[$fieldName]) && is_string($filter[$fieldName]))
1285 {
1286 $filter['=' . $fieldName] = $filter[$fieldName];
1287 unset($filter[$fieldName]);
1288 }
1289 }
1290
1291 if (array_key_exists('AUTO_EXECUTE', $filter))
1292 {
1293 $filter['AUTO_EXECUTE'] = match ((int)$filter['AUTO_EXECUTE'])
1294 {
1296 CBPDocumentEventType::Create => [1, 3, 5, 7],
1297 CBPDocumentEventType::Edit => [2, 3, 6, 7],
1298 CBPDocumentEventType::Delete => [4, 5, 6, 7],
1301 default => [-1],
1302 };
1303 }
1304 }
1305
1306 protected function prepareTemplatesSelect(array &$select): void
1307 {
1308 if (empty($select))
1309 {
1310 $select = [
1311 'ID', 'MODULE_ID', 'ENTITY', 'DOCUMENT_TYPE', 'DOCUMENT_STATUS', 'AUTO_EXECUTE',
1312 'NAME', 'DESCRIPTION', 'TEMPLATE', 'PARAMETERS', 'VARIABLES', 'CONSTANTS',
1313 'MODIFIED', 'USER_ID', 'ACTIVE', 'IS_MODIFIED', 'IS_SYSTEM', 'SORT', 'TYPE'
1314 ];
1315 }
1316
1317 if ($select === ['*'])
1318 {
1319 $select = array_merge($select, ['USER_NAME', 'USER_LAST_NAME', 'USER_SECOND_NAME', 'USER_LOGIN']);
1320 }
1321
1322 if (count(array_intersect($select, ['MODULE_ID', 'ENTITY', 'DOCUMENT_TYPE'])) > 0)
1323 {
1324 foreach (['MODULE_ID', 'ENTITY', 'DOCUMENT_TYPE'] as $field)
1325 {
1326 if (!in_array($field, $select, true))
1327 {
1328 $select[] = $field;
1329 }
1330 }
1331 }
1332
1333 $userFields = ['USER_NAME', 'USER_LAST_NAME', 'USER_SECOND_NAME', 'USER_LOGIN'];
1334 if (array_intersect($select, $userFields))
1335 {
1336 foreach ($userFields as $userField)
1337 {
1338 if (in_array($userField, $select, true))
1339 {
1340 $select[$userField] = str_replace('USER_', 'USER.', $userField);
1341
1342 $index = array_search($userField, $select, true);
1343 unset($select[$index]);
1344 }
1345 }
1346 }
1347 }
1348
1357 public function addTemplate(array $fields, bool $isSystemImport = false): int
1358 {
1359 self::ParseFields($fields, 0, $isSystemImport);
1360
1361 unset($fields['ID']);
1362
1363 $tplFields = $this->prepareTplFields($fields);
1364 $result = WorkflowTemplateTable::add($tplFields);
1365
1366 $id = 0;
1367 if ($result->isSuccess())
1368 {
1369 $id = $result->getId();
1370
1371 $event = new Event(
1372 'bizproc',
1373 'onAfterWorkflowTemplateAdd',
1374 [
1375 'FIELDS' => $fields,
1376 ]
1377 );
1378 EventManager::getInstance()->send($event);
1379
1380 return $id;
1381 }
1382
1383 return $id;
1384 }
1385
1396 public function updateTemplate($id, array $fields, bool $systemImport = false, bool $validationRequired = true): int
1397 {
1398 $id = (int)$id;
1399 if ($id <= 0)
1400 {
1401 throw new CBPArgumentNullException('id');
1402 }
1403
1404 self::ParseFields($fields, $id, $systemImport, $validationRequired);
1405
1406 $tplFields = $this->prepareTplFields($fields);
1407 $result = WorkflowTemplateTable::update($id, $tplFields);
1408
1409 if ($result->isSuccess())
1410 {
1411 $event = new Event(
1412 'bizproc',
1413 'onAfterWorkflowTemplateUpdate',
1414 [
1415 'ID' => $id,
1416 'FIELDS' => $fields,
1417 ]
1418 );
1419 EventManager::getInstance()->send($event);
1420
1421 return $id;
1422 }
1423
1424 return $id;
1425 }
1426
1427 private function prepareTplFields(array $fields): array
1428 {
1429 $fields['MODIFIED'] = new \Bitrix\Main\Type\DateTime();
1430 unset($fields['TEMPLATE_SETTINGS']);
1431
1432 return $fields;
1433 }
1434
1435 public static function useGZipCompression()
1436 {
1437 $useGZipCompressionOption = \Bitrix\Main\Config\Option::get("bizproc", "use_gzip_compression", "");
1438 if ($useGZipCompressionOption === "Y")
1439 {
1440 $result = true;
1441 }
1442 elseif ($useGZipCompressionOption === "N")
1443 {
1444 $result = false;
1445 }
1446 else
1447 {
1448 $result = function_exists("gzcompress");
1449 }
1450
1451 return $result;
1452 }
1453
1454 public static function getCompressedFieldLength($field): false|int
1455 {
1456 if (self::useGZipCompression())
1457 {
1458 return mb_strlen(gzcompress(serialize($field), 9));
1459 }
1460
1461 return mb_strlen(serialize($field));
1462 }
1463
1464 private function prepareFieldsForTemplate(array $fields): array
1465 {
1466 unset($fields['MODIFIER_USER']);
1467 [$moduleId, $entity, $documentType] = $fields['DOCUMENT_TYPE'];
1468 $fields['MODULE_ID'] = $moduleId;
1469 $fields['ENTITY'] = $entity;
1470 $fields['DOCUMENT_TYPE'] = $documentType;
1471
1472 return $fields;
1473 }
1474
1475 public static function prepareDocumentType(array &$fields)
1476 {
1477 if (array_key_exists('DOCUMENT_TYPE', $fields) && !is_array($fields['DOCUMENT_TYPE']))
1478 {
1479 $fields['DOCUMENT_TYPE'] = [
1480 $fields['MODULE_ID'],
1481 $fields['ENTITY'],
1482 $fields['DOCUMENT_TYPE']
1483 ];
1484 }
1485 }
1486
1487 public static function prepareSettingsCollection(array &$fields)
1488 {
1489 if (array_key_exists('TEMPLATE_SETTINGS', $fields))
1490 {
1491 $newValues = [];
1492 $settingsValues = $fields['TEMPLATE_SETTINGS']?->getAll();
1493
1494 if (!empty($settingsValues))
1495 {
1496 foreach ($settingsValues as $setting)
1497 {
1498 $newValues[$setting->getName()] = $setting->getValue();
1499 }
1500 }
1501
1502 $fields['TEMPLATE_SETTINGS'] = $newValues;
1503 }
1504 }
1505
1506 private function isExternalModified(array $fields): ?bool
1507 {
1508 $template = new \Bitrix\Bizproc\Automation\Engine\Template($fields['DOCUMENT_TYPE']);
1509 $template->setTemplate($fields['TEMPLATE']);
1510 $template->setExecuteType($fields['AUTO_EXECUTE']);
1511
1512 return $template->isExternalModified();
1513 }
1514}
1515
1517{
1518 private $useGZipCompression = false;
1519
1520 public function __construct($res, $useGZipCompression)
1521 {
1522 $this->useGZipCompression = $useGZipCompression;
1523 parent::__construct($res);
1524 }
1525
1526 private function getFromSerializedForm($value)
1527 {
1528 return WorkflowTemplateTable::getFromSerializedForm($value);
1529 }
1530
1531 private function getFromSerializedSettings($value)
1532 {
1533 return WorkflowTemplateTable::decodeJson($value);
1534 }
1535
1536 function fetch()
1537 {
1538 $res = parent::Fetch();
1539
1540 if ($res)
1541 {
1542 if (array_key_exists("DOCUMENT_TYPE", $res) && !is_array($res["DOCUMENT_TYPE"]))
1543 {
1544 $res["DOCUMENT_TYPE"] = array($res["MODULE_ID"], $res["ENTITY"], $res["DOCUMENT_TYPE"]);
1545 }
1546
1547 if (array_key_exists("TEMPLATE", $res) && !is_array($res["TEMPLATE"]))
1548 {
1549 $res["TEMPLATE"] = $this->GetFromSerializedForm($res["TEMPLATE"]);
1550 }
1551
1552 if (array_key_exists("VARIABLES", $res) && !is_array($res["VARIABLES"]))
1553 {
1554 $res["VARIABLES"] = $this->GetFromSerializedForm($res["VARIABLES"]);
1555 }
1556
1557 if (array_key_exists("CONSTANTS", $res) && !is_array($res["CONSTANTS"]))
1558 {
1559 $res["CONSTANTS"] = $this->GetFromSerializedForm($res["CONSTANTS"]);
1560 }
1561
1562 if (array_key_exists("PARAMETERS", $res) && !is_array($res["PARAMETERS"]))
1563 {
1564 $res["PARAMETERS"] = $this->GetFromSerializedForm($res["PARAMETERS"]);
1565 }
1566
1567 if (array_key_exists('TEMPLATE_SETTINGS', $res) && !is_array($res['TEMPLATE_SETTINGS']))
1568 {
1569 $res['TEMPLATE_SETTINGS'] = $this->getFromSerializedSettings($res['TEMPLATE_SETTINGS']);
1570 }
1571
1572 if (array_key_exists('MODIFIED', $res) && $res['MODIFIED'] instanceof \Bitrix\Main\Type\DateTime)
1573 {
1574 $res['MODIFIED'] =
1575 $res['MODIFIED']->toString(new \Bitrix\Main\Context\Culture(['FORMAT_DATETIME' => FORMAT_DATETIME]))
1576 ;
1577 }
1578 }
1579
1580 return $res;
1581 }
1582}
1583
1585{
1586 const CurrentUser = "CurrentUser";
1587
1588 private $userId = 0;
1589 private $isAdmin = false;
1590 private $fullName = '';
1591
1592 public function __construct($userId = null)
1593 {
1594 $this->userId = 0;
1595 $this->isAdmin = false;
1596 $this->fullName = '';
1597
1598 if (is_int($userId))
1599 {
1600 $userGroups = CUser::GetUserGroup($userId);
1601 $this->userId = (int)$userId;
1602 $this->isAdmin = in_array(1, $userGroups);
1603 }
1604 elseif ($userId === self::CurrentUser)
1605 {
1606 global $USER;
1607 if (is_object($USER) && $USER->IsAuthorized())
1608 {
1609 $this->userId = (int)$USER->GetID();
1610 $this->isAdmin = (
1611 $USER->IsAdmin()
1612 || CModule::IncludeModule('bitrix24') && CBitrix24::IsPortalAdmin($USER->GetID())
1613 );
1614 $this->fullName = $USER->GetFullName();
1615 }
1616 }
1617 }
1618
1619 public function getId()
1620 {
1621 return $this->userId;
1622 }
1623
1624 public function getBizprocId()
1625 {
1626 return $this->userId > 0 ? 'user_'.$this->userId : null;
1627 }
1628
1629 public function isAdmin()
1630 {
1631 return ($this->isAdmin || self::isBpAdmin($this->userId));
1632 }
1633
1634 public function getFullName()
1635 {
1636 return $this->fullName;
1637 }
1638
1639 private static function isBpAdmin(int $userId): bool
1640 {
1641 static $ids;
1642 if ($ids === null)
1643 {
1644 $idsString = \Bitrix\Main\Config\Option::get('bizproc', 'wtu_admins');
1645 $ids = array_map('intval', explode(',', $idsString));
1646 }
1647 return $userId && in_array($userId, $ids, true);
1648 }
1649}
1650
1652{
1653 private $errors;
1654 public function __construct($message = "", array $errors = array())
1655 {
1656 parent::__construct($message, 10010);
1657 $this->errors = $errors;
1658 }
1659
1660 public function getErrors()
1661 {
1662 return $this->errors;
1663 }
1664}
$type
Определения options.php:106
$arResult
Определения generate_coupon.php:16
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static getInstance()
Определения Factory.php:9
static getInstance()
Определения application.php:98
static delete($moduleId, array $filter=array())
Определения option.php:388
static get($moduleId, $name, $default="", $siteId=false)
Определения option.php:30
Определения event.php:5
static sortByColumn(array &$array, $columns, $callbacks='', $defaultValueIfNotSetValue=null, $preserveKeys=false)
Определения collection.php:24
Определения activity.php:8
static includeActivityFile($code)
Определения activity.php:1348
static createInstance($code, $name)
Определения activity.php:1359
const ValuePattern
Определения activity.php:26
static callStaticMethod($code, $method, $arParameters=array())
Определения activity.php:1375
const Edit
Определения constants.php:154
const Automation
Определения constants.php:156
const Create
Определения constants.php:153
const Script
Определения constants.php:158
const None
Определения constants.php:152
const Delete
Определения constants.php:155
const CONSTANTS_CACHE_TAG_PREFIX
Определения workflowtemplateloader.php:24
static prepareDocumentType(array &$fields)
Определения workflowtemplateloader.php:1475
static getDocumentTypeStates($documentType, $autoExecute=-1, $stateName="")
Определения workflowtemplateloader.php:766
static isConstantsTuned($workflowTemplateId)
Определения workflowtemplateloader.php:875
static getCompressedFieldLength($field)
Определения workflowtemplateloader.php:1454
parseFields(&$arFields, $id=0, $systemImport=false, $validationRequired=true)
Определения workflowtemplateloader.php:146
static & FindActivityByName(&$arWorkflowTemplate, $activityName)
Определения workflowtemplateloader.php:964
setTemplateType(array &$fields, ?string $templateType=null)
Определения workflowtemplateloader.php:304
static importTemplateFromArray($id, $documentType, $autoExecute, $name, $description, $templateFields, $systemCode=null, $systemImport=false)
Определения workflowtemplateloader.php:1087
static & FindParentActivityByName(&$arWorkflowTemplate, $activityName)
Определения workflowtemplateloader.php:993
setShowInTimelineBeforeAdd(array &$fields)
Определения workflowtemplateloader.php:417
prepareTemplatesSelect(array &$select)
Определения workflowtemplateloader.php:1306
static getTemplateState($workflowTemplateId, $stateName="")
Определения workflowtemplateloader.php:795
updateTemplate($id, array $fields, bool $systemImport=false, bool $validationRequired=true)
Определения workflowtemplateloader.php:1396
static getTemplateUserId($workflowTemplateId)
Определения workflowtemplateloader.php:818
setShowInTimelineBeforeUpdate(array &$fields)
Определения workflowtemplateloader.php:396
loadWorkflow($workflowTemplateId)
Определения workflowtemplateloader.php:490
getTemplateType(array $fields, int $id=0)
Определения workflowtemplateloader.php:356
getTemplatesList(array $order=['ID'=> 'DESC'], array $filter=[], $group=false, $navStartParams=false, array $select=[])
Определения workflowtemplateloader.php:1201
static update($id, $fields, $systemImport=false, $validationRequired=true)
Определения workflowtemplateloader.php:285
prepareTemplatesFilter(array &$filter)
Определения workflowtemplateloader.php:1259
static importDocumentFields(array $documentType, array $fields)
Определения workflowtemplateloader.php:1143
static getTemplateConstants($workflowTemplateId)
Определения workflowtemplateloader.php:833
static checkWorkflowParameters($arTemplateParameters, $arPossibleValues, $documentType, &$arErrors)
Определения workflowtemplateloader.php:894
static add($fields, $systemImport=false)
Определения workflowtemplateloader.php:246
static getList($arOrder=array("ID"=> "DESC"), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения workflowtemplateloader.php:59
loadWorkflowFromArray($templatesListItem)
Определения workflowtemplateloader.php:517
static exportTemplate($id, $bCompress=true)
Определения workflowtemplateloader.php:1012
addTemplate(array $fields, bool $isSystemImport=false)
Определения workflowtemplateloader.php:1357
static cleanTemplateCache($id)
Определения workflowtemplateloader.php:447
addTemplateSettings(int $templateId, array $templateFields)
Определения workflowtemplateloader.php:259
static useGZipCompression()
Определения workflowtemplateloader.php:1435
static prepareSettingsCollection(array &$fields)
Определения workflowtemplateloader.php:1487
static checkTemplateActivities(array $template)
Определения workflowtemplateloader.php:65
static getStatesOfTemplate($arWorkflowTemplate)
Определения workflowtemplateloader.php:593
static importTemplate($id, $documentType, $autoExecute, $name, $description, $datum, $systemCode=null, $systemImport=false)
Определения workflowtemplateloader.php:1070
validateTemplate($arActivity, $user)
Определения workflowtemplateloader.php:82
static searchTemplatesByDocumentType($documentType, $autoExecute=-1)
Определения workflowtemplateloader.php:933
GetTemplatesList($arOrder=array("ID"=> "DESC"), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array())
Определения workflowtemplateloader.php:36
static getTransfersOfState($arWorkflowTemplate, $stateName)
Определения workflowtemplateloader.php:624
__construct($res, $useGZipCompression)
Определения workflowtemplateloader.php:1520
__construct($userId=null)
Определения workflowtemplateloader.php:1592
__construct($message="", array $errors=array())
Определения workflowtemplateloader.php:1654
Определения dbresult.php:88
$templateId
Определения component_props2.php:51
$arTemplate
Определения component_props.php:26
$arFields
Определения dblapprove.php:5
$template
Определения file_edit.php:49
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
$entity
$moduleId
if(Loader::includeModule( 'bitrix24')) elseif(Loader::includeModule('intranet') &&CIntranetUtils::getPortalZone() !=='ru') $description
Определения .description.php:24
$activity
Определения options.php:214
$errors
Определения iblock_catalog_edit.php:74
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
global $USER
Определения csv_new_run.php:40
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
const FORMAT_DATETIME
Определения include.php:64
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$name
Определения menu_edit.php:35
$order
Определения payment.php:8
$message
Определения payment.php:8
$event
Определения prolog_after.php:141
return false
Определения prolog_main_admin.php:185
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$instance
Определения ps_b24_final.php:14
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$messages
Определения template.php:8
$option
Определения options.php:1711
$rows
Определения options.php:264
$k
Определения template_pdf.php:567
$GLOBALS['_____370096793']
Определения update_client.php:1
$arFilter
Определения user_search.php:106
$iterator
Определения yandex_run.php:610
$fields
Определения yandex_run.php:501