Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/cvetdv.ru/bitrix/modules/bizproc/classes/general/ |
Upload File : |
<?php use Bitrix\Bizproc\Debugger\Workflow\DebugWorkflow; use Bitrix\Bizproc\Workflow\Entity\WorkflowInstanceTable; use Bitrix\Main; use Bitrix\Bizproc; use Bitrix\Bizproc\RestActivityTable; /** * Workflow runtime. * * @method \CBPSchedulerService getSchedulerService() * @method \CBPStateService getStateService() * @method \CBPTrackingService getTrackingService() * @method \CBPTaskService getTaskService() * @method \CBPHistoryService getHistoryService() * @method \CBPDocumentService getDocumentService() * @method Bizproc\Service\Analytics getAnalyticsService() * @method Bizproc\Service\User getUserService() */ class CBPRuntime { public const EXCEPTION_CODE_INSTANCE_TARIFF_LIMIT_EXCEED = 402; public const EXCEPTION_CODE_INSTANCE_NOT_FOUND = 404; public const EXCEPTION_CODE_INSTANCE_LOCKED = 423; public const EXCEPTION_CODE_INSTANCE_TERMINATED = 499; public const REST_ACTIVITY_PREFIX = 'rest_'; public const ACTIVITY_API_VERSION = 1; private $isStarted = false; /** @var CBPRuntime $instance*/ private static $instance; private static $featuresCache = []; private $services = []; private $debugServices = []; private $workflows = []; private $loadedActivities = []; private $activityFolders = []; private $workflowChains = []; /********************* SINGLETON PATTERN **************************************************/ /** * Private constructor prevents from instantiating this class. Singleton pattern. * */ private function __construct() { $this->workflows = array(); $this->services = array( "SchedulerService" => null, "StateService" => null, "TrackingService" => null, "TaskService" => null, "HistoryService" => null, "DocumentService" => null, "AnalyticsService" => null, "UserService" => null, ); $this->loadedActivities = array(); $this->activityFolders = array( $_SERVER["DOCUMENT_ROOT"]."/local/activities", $_SERVER["DOCUMENT_ROOT"]."/local/activities/custom", $_SERVER["DOCUMENT_ROOT"].BX_ROOT."/activities/custom", $_SERVER["DOCUMENT_ROOT"].BX_ROOT."/activities/bitrix", $_SERVER["DOCUMENT_ROOT"].BX_ROOT."/modules/bizproc/activities", ); } /** * Static method returns runtime object. Singleton pattern. * * @return CBPRuntime */ public static function getRuntime() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; self::$instance->startRuntime(); } return self::$instance; } public function __clone() { trigger_error('Clone in not allowed.', E_USER_ERROR); } public function __call($name, $arguments) { if (preg_match('|^get([a-z]+)service$|i', $name, $matches)) { return $this->GetService($matches[1]. 'Service'); } throw new Main\SystemException("Unknown method `{$name}`"); } /** * Method checks if feature is enabled. * @param string $featureName Feature name. Checks default if empty. * @return bool */ public static function isFeatureEnabled($featureName = '') { $featureName = (string)$featureName; if ($featureName === '') { $featureName = 'bizproc'; } if (!isset(static::$featuresCache[$featureName])) { static::$featuresCache[$featureName] = ( !Main\Loader::includeModule('bitrix24') || \Bitrix\Bitrix24\Feature::isFeatureEnabled($featureName) ); } return static::$featuresCache[$featureName]; } /********************* START / STOP RUNTIME **************************************************/ /** * Public method starts runtime * */ public function startRuntime() { if ($this->isStarted) { return; } $serviceManager = Bizproc\Service\Manager::getInstance(); foreach ($serviceManager->getAllServiceNames() as $serviceName) { $compatibleServiceName = mb_strtoupper($serviceName[0]) . mb_substr($serviceName, 1); if (!$this->services[$compatibleServiceName]) { $this->services[$compatibleServiceName] = $serviceManager->getService($serviceName); } if (!isset($this->debugServices[$compatibleServiceName]) && $serviceManager->hasDebugService($serviceName)) { $this->debugServices[$compatibleServiceName] = $serviceManager->getDebugService($serviceName); } $this->services[$compatibleServiceName]->start($this); } $this->isStarted = true; } /** * Public method stops runtime * @deprecated Unused and not actual */ public function stopRuntime() { if (!$this->isStarted) { return; } foreach ($this->services as $serviceId => $service) { $service->stop(); } $this->isStarted = false; } /******************* PROCESS WORKFLOWS *********************************************************/ /** * Creates new workflow instance from the specified template. * * @param int $workflowTemplateId - ID of the workflow template * @param array $documentId - ID of the document * @param mixed $workflowParameters - Optional parameters of the created workflow instance * @param array|null $parentWorkflow - Parent Workflow information. * @return CBPWorkflow * @throws CBPArgumentNullException * @throws CBPArgumentOutOfRangeException * @throws Exception * @throws \Bitrix\Main\ArgumentNullException */ public function createWorkflow($workflowTemplateId, $documentId, $workflowParameters = array(), $parentWorkflow = null) { $workflowTemplateId = intval($workflowTemplateId); if ($workflowTemplateId <= 0) { throw new Exception("workflowTemplateId"); } $arDocumentId = CBPHelper::ParseDocumentId($documentId); $limit = \Bitrix\Main\Config\Option::get("bizproc", "limit_simultaneous_processes", "0"); $ignoreLimits = !empty($workflowParameters[CBPDocument::PARAM_IGNORE_SIMULTANEOUS_PROCESSES_LIMIT]); if (!$ignoreLimits && intval($limit) > 0) { if (CBPStateService::CountDocumentWorkflows($documentId) >= $limit) { throw new Exception(GetMessage("BPCGDOC_LIMIT_SIMULTANEOUS_PROCESSES", ["#NUM#" => $limit])); } } unset($workflowParameters[CBPDocument::PARAM_IGNORE_SIMULTANEOUS_PROCESSES_LIMIT]); if (!$this->isStarted) { $this->StartRuntime(); } $workflowId = $workflowParameters[CBPDocument::PARAM_PRE_GENERATED_WORKFLOW_ID] ?? static::generateWorkflowId(); if ($parentWorkflow) { $this->addWorkflowToChain($workflowId, $parentWorkflow); if ($this->checkWorkflowRecursion($workflowId, $workflowTemplateId)) { throw new Exception(GetMessage("BPCGDOC_WORKFLOW_RECURSION_LOCK")); } } $workflow = new CBPWorkflow($workflowId, $this); $loader = CBPWorkflowTemplateLoader::GetLoader(); /** @var CBPCompositeActivity $rootActivity */ [$rootActivity, $workflowVariablesTypes, $workflowParametersTypes] = $loader->LoadWorkflow($workflowTemplateId); foreach ($workflowParametersTypes as $parameterName => $parametersProperty) { if (!array_key_exists($parameterName, $workflowParameters)) { $workflowParameters[$parameterName] = $parametersProperty['Default'] ?? null; } } if (!$rootActivity) { throw new Exception("EmptyRootActivity"); } foreach(GetModuleEvents("bizproc", "OnCreateWorkflow", true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$workflowTemplateId, $documentId, &$workflowParameters, $workflowId]); } $workflow->initialize($rootActivity, $arDocumentId, $workflowParameters, $workflowVariablesTypes, $workflowParametersTypes, $workflowTemplateId); $starterUserId = 0; if (isset($workflowParameters[CBPDocument::PARAM_TAGRET_USER])) { $starterUserId = (int)CBPHelper::stripUserPrefix($workflowParameters[CBPDocument::PARAM_TAGRET_USER]); } $this->getStateService()->addWorkflow($workflowId, $workflowTemplateId, $arDocumentId, $starterUserId); $this->workflows[$workflowId] = $workflow; return $workflow; } public function createDebugWorkflow(int $templateId, array $documentId, $workflowParameters = []) { $complexDocumentId = CBPHelper::ParseDocumentId($documentId); $workflowId = $workflowParameters[CBPDocument::PARAM_PRE_GENERATED_WORKFLOW_ID] ?? static::generateWorkflowId(); $workflow = new DebugWorkflow($workflowId, $this); $loader = CBPWorkflowTemplateLoader::GetLoader(); [$rootActivity, $workflowVariablesTypes, $workflowParametersTypes] = $loader->LoadWorkflow($templateId); if (is_null($rootActivity)) { throw new Exception('Empty root activity'); } foreach(GetModuleEvents("bizproc", "OnCreateWorkflow", true) as $arEvent) { ExecuteModuleEventEx($arEvent, [$templateId, $documentId, &$workflowParameters, $workflowId]); } $workflow->Initialize( $rootActivity, $complexDocumentId, $workflowParameters, $workflowVariablesTypes, $workflowParametersTypes, $templateId ); $starterUserId = 0; if (isset($workflowParameters[CBPDocument::PARAM_TAGRET_USER])) { $starterUserId = intval(mb_substr($workflowParameters[CBPDocument::PARAM_TAGRET_USER], mb_strlen("user_"))); } $this ->GetService("StateService") ->AddWorkflow($workflowId, $templateId, $complexDocumentId, $starterUserId) ; $this->workflows[$workflowId] = $workflow; return $workflow; } /** * Returns existing workflow instance by its ID * * @param string $workflowId ID of the workflow instance. * @param bool $silent * @return CBPWorkflow * @throws Exception */ public function getWorkflow($workflowId, $silent = false) { if ($workflowId == '') throw new Exception("workflowId"); if (!$this->isStarted) $this->StartRuntime(); if (array_key_exists($workflowId, $this->workflows)) return $this->workflows[$workflowId]; $workflow = $this->getWorkflowInstance($workflowId); $rootActivity = $workflow->getPersister()->LoadWorkflow($workflowId, $silent); if ($rootActivity == null) { throw new Exception("Empty root activity"); } $workflow->reload($rootActivity); $this->workflows[$workflowId] = $workflow; return $workflow; } public function hasWorkflow(string $workflowId): bool { if (!$workflowId) { return false; } return array_key_exists($workflowId, $this->workflows); } public function getWorkflows(): array { return $this->workflows; } protected function getWorkflowInstance(string $workflowId): CBPWorkflow { if (WorkflowInstanceTable::isDebugWorkflow($workflowId)) { return new DebugWorkflow($workflowId, $this); } return new CBPWorkflow($workflowId, $this); } public function onWorkflowStatusChanged($workflowId, $status) { if ( $status === \CBPWorkflowStatus::Completed || $status === \CBPWorkflowStatus::Terminated || $status === \CBPWorkflowStatus::Suspended ) { unset($this->workflows[$workflowId]); } } public function onDocumentDelete(array $documentId): void { /** @var CBPWorkflow $workflow */ foreach ($this->workflows as $workflow) { if (CBPHelper::isEqualDocument($documentId, $workflow->getDocumentId())) { $workflow->abandon(); } } } public static function generateWorkflowId(): string { return uniqid("", true); } /******************* SERVICES *********************************************************/ /** * Returns service instance by its code. * * @param mixed $name - Service code. * @return mixed|CBPSchedulerService|CBPStateService|CBPTrackingService|CBPTaskService|CBPHistoryService|CBPDocumentService|Bizproc\Service\Analytics - Service instance or null if service is not found. */ public function getService($name) { if (array_key_exists($name, $this->services)) { return $this->services[$name]; } return null; } public function getDebugService($name) { if (array_key_exists($name, $this->debugServices)) { return $this->debugServices[$name]; } return null; } /** * Adds new service to runtime. Runtime should be stopped. * * @param string $name - Service code. * @param CBPRuntimeService $service - Service object. */ public function addService($name, CBPRuntimeService $service) { if ($this->isStarted) throw new Exception("Runtime is started"); $name = trim($name); if ($name == '') throw new Exception("Service code is empty"); if (!$service) throw new Exception("Service is null"); if (array_key_exists($name, $this->services)) throw new Exception("Service is already exists"); $this->services[$name] = $service; } /******************* EVENTS ******************************************************************/ /** * Static method transfer event to the specified workflow instance. * * @param mixed $workflowId - ID of the workflow instance. * @param mixed $eventName - Event name. * @param mixed $arEventParameters - Event parameters. */ public static function sendExternalEvent($workflowId, $eventName, $arEventParameters = []) { $runtime = CBPRuntime::GetRuntime(); $workflow = $runtime->getWorkflow($workflowId); if ($workflow) { //check if state exists $stateExists = CBPStateService::exists($workflowId); $documentExists = false; if ($stateExists) { $documentService = $runtime->getDocumentService(); $documentExists = $documentService->isDocumentExists($workflow->getDocumentId()); } if (!$stateExists || !$documentExists) { $workflow->terminate(); return false; } $workflow->sendExternalEvent($eventName, (array)$arEventParameters); } } /******************* UTILITIES ***************************************************************/ /** * Includes activity file by activity code. * * @param string $code - Activity code. */ public function includeActivityFile($code) { if (in_array($code, $this->loadedActivities)) return true; if (preg_match("#[^a-zA-Z0-9_]#", $code)) return false; if ($code == '') return false; $code = mb_strtolower($code); if (mb_substr($code, 0, 3) == "cbp") $code = mb_substr($code, 3); if ($code == '') return false; if (in_array($code, $this->loadedActivities)) return true; $filePath = ""; $fileDir = ""; foreach ($this->activityFolders as $folder) { if (file_exists($folder."/".$code."/".$code.".php") && is_file($folder."/".$code."/".$code.".php")) { $filePath = $folder."/".$code."/".$code.".php"; $fileDir = $folder."/".$code; break; } } if ($filePath <> '') { $this->LoadActivityLocalization($fileDir, $code.".php"); include_once($filePath); $this->loadedActivities[] = $code; return true; } if (mb_strpos($code, static::REST_ACTIVITY_PREFIX) === 0) { $code = mb_substr($code, mb_strlen(static::REST_ACTIVITY_PREFIX)); $result = RestActivityTable::getList(array( 'select' => array('ID'), 'filter' => array('=INTERNAL_CODE' => $code), )); $activity = $result->fetch(); eval('class CBP'.static::REST_ACTIVITY_PREFIX.$code.' extends CBPRestActivity {const REST_ACTIVITY_ID = '.($activity? $activity['ID'] : 0).';}'); $this->loadedActivities[] = static::REST_ACTIVITY_PREFIX.$code; return true; } return false; } public function getActivityDescription($code, $lang = false) { if (preg_match("#[^a-zA-Z0-9_]#", $code)) return null; if ($code == '') return null; $code = mb_strtolower($code); if (mb_substr($code, 0, 3) == "cbp") $code = mb_substr($code, 3); if ($code == '') return null; $filePath = ""; $fileDir = ""; foreach ($this->activityFolders as $folder) { if (file_exists($folder."/".$code."/".$code.".php") && is_file($folder."/".$code."/".$code.".php")) { $filePath = $folder."/".$code."/.description.php"; $fileDir = $folder."/".$code; break; } } if ($filePath <> '') { $arActivityDescription = array(); if (file_exists($filePath) && is_file($filePath)) { $this->LoadActivityLocalization($fileDir, ".description.php"); include($filePath); } $arActivityDescription["PATH_TO_ACTIVITY"] = $fileDir; return $arActivityDescription; } if (mb_strpos($code, static::REST_ACTIVITY_PREFIX) === 0) { $code = mb_substr($code, mb_strlen(static::REST_ACTIVITY_PREFIX)); $result = RestActivityTable::getList(array( 'filter' => array('=INTERNAL_CODE' => $code), )); $activity = $result->fetch(); if ($activity) { return $this->makeRestActivityDescription($activity, $lang); } } return null; } public function getActivityReturnProperties($code, $lang = false): array { $activity = null; if (is_array($code)) { $activity = $code; $code = $activity['Type']; } $description = $this->GetActivityDescription($code, $lang); $props = []; if (isset($description['RETURN']) && is_array($description['RETURN'])) { foreach ($description['RETURN'] as $id => $prop) { $props[$id] = Bizproc\FieldType::normalizeProperty($prop); } } if (isset($description['ADDITIONAL_RESULT']) && is_array($description['ADDITIONAL_RESULT'])) { foreach($description['ADDITIONAL_RESULT'] as $propertyKey) { if (isset($activity['Properties'][$propertyKey]) && is_array($activity['Properties'][$propertyKey])) { foreach ($activity['Properties'][$propertyKey] as $id => $prop) { $props[$id] = Bizproc\FieldType::normalizeProperty($prop); } } } } return $props; } private function loadActivityLocalization($path, $file, $lang = false) { \Bitrix\Main\Localization\Loc::loadLanguageFile($path. '/'. $file); } public function getResourceFilePath($activityPath, $filePath) { $path = str_replace("\\", "/", $activityPath); $path = mb_substr($path, 0, mb_strrpos($path, "/") + 1); $filePath = str_replace("\\", "/", $filePath); $filePath = ltrim($filePath, "/"); if (file_exists($path.$filePath) && is_file($path.$filePath)) return array($path.$filePath, $path); else return null; } public function executeResourceFile($activityPath, $filePath, $arParameters = array()) { $result = null; $path = $this->GetResourceFilePath($activityPath, $filePath); if ($path != null) { ob_start(); foreach ($arParameters as $key => $value) ${$key} = $value; $this->LoadActivityLocalization($path[1], $filePath); include($path[0]); $result = ob_get_contents(); ob_end_clean(); } return $result; } public function searchActivitiesByType($type, array $documentType = null) { $type = mb_strtolower(trim($type)); if ($type === '') { return false; } $arProcessedDirs = []; foreach ($this->activityFolders as $folder) { if (is_dir($folder) && $handle = opendir($folder)) { while (false !== ($dir = readdir($handle))) { if ($dir === "." || $dir === "..") { continue; } if (!is_dir($folder."/".$dir)) { continue; } $dirKey = mb_strtolower($dir); if (array_key_exists($dirKey, $arProcessedDirs)) { continue; } if (!file_exists($folder."/".$dir."/.description.php")) { continue; } $arActivityDescription = []; $this->LoadActivityLocalization($folder."/".$dir, ".description.php"); include($folder."/".$dir."/.description.php"); //Support multiple types $activityType = (array)$arActivityDescription['TYPE']; foreach ($activityType as $i => $aType) { $activityType[$i] = mb_strtolower(trim($aType)); } if (in_array($type, $activityType, true)) { $arProcessedDirs[$dirKey] = $arActivityDescription; $arProcessedDirs[$dirKey]["PATH_TO_ACTIVITY"] = $folder."/".$dir; if ( isset($arActivityDescription['FILTER']) && is_array($arActivityDescription['FILTER']) && !$this->checkActivityFilter($arActivityDescription['FILTER'], $documentType) ) { $arProcessedDirs[$dirKey]['EXCLUDED'] = true; } } } closedir($handle); } } if ($type == 'activity') { $arProcessedDirs = array_merge($arProcessedDirs, $this->getRestActivities(false, $documentType)); } if ($type == 'activity' || $type == 'robot_activity') { $arProcessedDirs = array_merge($arProcessedDirs, $this->getRestRobots(false, $documentType)); } if ($type !== 'condition') { \Bitrix\Main\Type\Collection::sortByColumn($arProcessedDirs, ['SORT' => SORT_ASC, 'NAME' => SORT_ASC]); } return $arProcessedDirs; } /** * @param bool $lang Language ID. * @param null|array $documentType Document type. * @return array * @throws \Bitrix\Main\ArgumentException */ public function getRestActivities($lang = false, $documentType = null) { $result = array(); $iterator = RestActivityTable::getList(array( 'filter' => array('=IS_ROBOT' => 'N'), )); while ($activity = $iterator->fetch()) { $result[static::REST_ACTIVITY_PREFIX.$activity['INTERNAL_CODE']] = $this->makeRestActivityDescription($activity, $lang, $documentType); } return $result; } /** * @param bool $lang Language ID. * @param null|array $documentType Document type. * @return array * @throws \Bitrix\Main\ArgumentException */ public function getRestRobots($lang = false, $documentType = null) { $result = array(); $iterator = RestActivityTable::getList([ 'filter' => ['=IS_ROBOT' => 'Y'], 'cache' => ['ttl' => 3600], ]); while ($activity = $iterator->fetch()) { $result[static::REST_ACTIVITY_PREFIX.$activity['INTERNAL_CODE']] = $this->makeRestRobotDescription($activity, $lang, $documentType); } return $result; } public function unserializeWorkflowStream(string $stream) { $pos = mb_strpos($stream, ";"); $usedActivities = mb_substr($stream, 0, $pos); $stream = mb_substr($stream, $pos + 1); foreach (explode(',', $usedActivities) as $activityCode) { $this->IncludeActivityFile($activityCode); } $classesList = array_map( function ($name) { return 'cbp'.$name; }, $this->loadedActivities ); /** @bug 0135642 */ if (in_array('cbpstateactivity', $classesList)) { $classesList[] = CBPStateEventActivitySubscriber::class; } if (in_array('cbplistenactivity', $classesList)) { $classesList[] = CBPListenEventActivitySubscriber::class; } $classesList[] = \CBPWorkflow::class; $classesList[] = \CBPRuntime::class; $classesList[] = DebugWorkflow::class; $classesList[] = Bizproc\BaseType\Value\Date::class; $classesList[] = Bizproc\BaseType\Value\DateTime::class; $classesList[] = Main\Type\Date::class; $classesList[] = Main\Type\DateTime::class; $classesList[] = Main\Web\Uri::class; $classesList[] = \DateTime::class; $classesList[] = \DateTimeZone::class; return unserialize($stream, ['allowed_classes' => $classesList]); } private function makeRestActivityDescription($activity, $lang = false, $documentType = null) { if ($lang === false) $lang = LANGUAGE_ID; $code = static::REST_ACTIVITY_PREFIX.$activity['INTERNAL_CODE']; $result = array( 'NAME' => '['.RestActivityTable::getLocalization($activity['APP_NAME'], $lang).'] ' .RestActivityTable::getLocalization($activity['NAME'], $lang), 'DESCRIPTION' => RestActivityTable::getLocalization($activity['DESCRIPTION'], $lang), 'TYPE' => 'activity', 'CLASS' => $code, 'JSCLASS' => 'BizProcActivity', 'CATEGORY' => array( 'ID' => 'rest', ), 'RETURN' => array(), //compatibility 'PATH_TO_ACTIVITY' => '', ); if ( isset($activity['FILTER']) && is_array($activity['FILTER']) && !$this->checkActivityFilter($activity['FILTER'], $documentType) ) $result['EXCLUDED'] = true; if (!empty($activity['RETURN_PROPERTIES'])) { foreach ($activity['RETURN_PROPERTIES'] as $name => $property) { $result['RETURN'][$name] = array( 'NAME' => RestActivityTable::getLocalization($property['NAME'], $lang), 'TYPE' => isset($property['TYPE']) ? $property['TYPE'] : \Bitrix\Bizproc\FieldType::STRING, ); } } if ($activity['USE_SUBSCRIPTION'] != 'N') $result['RETURN']['IsTimeout'] = array( 'NAME' => GetMessage('BPRA_IS_TIMEOUT'), 'TYPE' => \Bitrix\Bizproc\FieldType::INT, ); return $result; } private function makeRestRobotDescription($activity, $lang = false, $documentType = null) { if ($lang === false) $lang = LANGUAGE_ID; $code = static::REST_ACTIVITY_PREFIX.$activity['INTERNAL_CODE']; $result = array( 'NAME' => '['.RestActivityTable::getLocalization($activity['APP_NAME'], $lang).'] ' .RestActivityTable::getLocalization($activity['NAME'], $lang), 'DESCRIPTION' => RestActivityTable::getLocalization($activity['DESCRIPTION'], $lang), 'TYPE' => array('activity', 'robot_activity'), 'CLASS' => $code, 'JSCLASS' => 'BizProcActivity', 'CATEGORY' => [ 'ID' => 'rest', ], 'RETURN' => array(), //compatibility 'PATH_TO_ACTIVITY' => '', 'ROBOT_SETTINGS' => array( 'CATEGORY' => 'other', ), ); if ( isset($activity['FILTER']) && is_array($activity['FILTER']) && !$this->checkActivityFilter($activity['FILTER'], $documentType) ) $result['EXCLUDED'] = true; if (!empty($activity['RETURN_PROPERTIES'])) { foreach ($activity['RETURN_PROPERTIES'] as $name => $property) { $result['RETURN'][$name] = [ 'NAME' => RestActivityTable::getLocalization($property['NAME'], $lang), 'TYPE' => $property['TYPE'] ?? \Bitrix\Bizproc\FieldType::STRING, 'OPTIONS' => $property['OPTIONS'] ?? null, ]; } } if ($activity['USE_SUBSCRIPTION'] !== 'N') { $result['RETURN']['IsTimeout'] = array( 'NAME' => GetMessage('BPRA_IS_TIMEOUT'), 'TYPE' => \Bitrix\Bizproc\FieldType::INT, ); } return $result; } public function checkActivityFilter($filter, $documentType) { $distrName = CBPHelper::getDistrName(); foreach ($filter as $type => $rules) { if ($type === 'MIN_API_VERSION') { $minApiVersion = (int)$rules; if ($minApiVersion > self::ACTIVITY_API_VERSION) { return false; } continue; } $found = $this->checkActivityFilterRules($rules, $documentType, $distrName); if (($type === 'INCLUDE' && !$found) || ($type === 'EXCLUDE' && $found)) { return false; } } return true; } private function checkActivityFilterRules($rules, $documentType, $distrName) { if (!is_array($rules) || CBPHelper::IsAssociativeArray($rules)) { $rules = [$rules]; } foreach ($rules as $rule) { $result = false; if (is_array($rule)) { if (!$documentType) { $result = true; } else { foreach ($documentType as $key => $value) { if (!isset($rule[$key])) { break; } $result = $rule[$key] == $value; if (!$result) { break; } } } } else { $result = (string)$rule == $distrName; } if ($result) { return true; } } return false; } private function addWorkflowToChain($childId, $parent) { $this->workflowChains[$childId] = $parent; return $this; } private function checkWorkflowRecursion($workflowId, $currentTemplateId) { $templates = array($currentTemplateId); while (isset($this->workflowChains[$workflowId])) { $parent = $this->workflowChains[$workflowId]; if (in_array($parent['templateId'], $templates)) return true; $templates[] = $parent['templateId']; $workflowId = $parent['workflowId']; } return false; } }