PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/bitrix/components/bitrix/bizproc.automation/class.php

https://gitlab.com/neuser/bitrix-core
PHP | 525 lines | 432 code | 85 blank | 8 comment | 50 complexity | f38dfdd6493755b08c19ee7d297abf24 MD5 | raw file
  1. <?php
  2. if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
  3. use Bitrix\Main;
  4. use Bitrix\Main\Localization\Loc;
  5. Main\UI\Extension::load('ui.alerts');
  6. Loc::loadMessages(__FILE__);
  7. class BizprocAutomationComponent extends \CBitrixComponent
  8. {
  9. protected function getDocumentType()
  10. {
  11. return isset($this->arParams['DOCUMENT_TYPE']) && is_array($this->arParams['DOCUMENT_TYPE']) ? $this->arParams['DOCUMENT_TYPE'] : null;
  12. }
  13. protected function getDocumentId()
  14. {
  15. return isset($this->arParams['DOCUMENT_ID']) ? $this->arParams['DOCUMENT_ID'] : 0;
  16. }
  17. private function getStatusesEditUrl()
  18. {
  19. return isset($this->arParams['STATUSES_EDIT_URL']) ? $this->arParams['STATUSES_EDIT_URL'] : null;
  20. }
  21. private function getWorkflowEditUrl()
  22. {
  23. return isset($this->arParams['WORKFLOW_EDIT_URL']) ? $this->arParams['WORKFLOW_EDIT_URL'] : null;
  24. }
  25. private function getConstantsEditUrl()
  26. {
  27. return isset($this->arParams['CONSTANTS_EDIT_URL']) ? $this->arParams['CONSTANTS_EDIT_URL'] : null;
  28. }
  29. private function getParametersEditUrl()
  30. {
  31. return isset($this->arParams['PARAMETERS_EDIT_URL']) ? $this->arParams['PARAMETERS_EDIT_URL'] : null;
  32. }
  33. private function getTitleView()
  34. {
  35. return isset($this->arParams['TITLE_VIEW']) ? $this->arParams['TITLE_VIEW'] : null;
  36. }
  37. private function getTitleEdit()
  38. {
  39. return isset($this->arParams['TITLE_EDIT']) ? $this->arParams['TITLE_EDIT'] : null;
  40. }
  41. protected function getDocumentCategoryId()
  42. {
  43. return isset($this->arParams['DOCUMENT_CATEGORY_ID']) ? (int)$this->arParams['DOCUMENT_CATEGORY_ID'] : null;
  44. }
  45. protected function isApiMode()
  46. {
  47. return (isset($this->arParams['API_MODE']) && $this->arParams['API_MODE'] === 'Y');
  48. }
  49. protected function isOneTemplateMode()
  50. {
  51. return (isset($this->arParams['ONE_TEMPLATE_MODE']) && $this->arParams['ONE_TEMPLATE_MODE'] === true);
  52. }
  53. protected function getTemplateInfo()
  54. {
  55. return isset($this->arParams['TEMPLATE']) ? $this->arParams['TEMPLATE'] : null;
  56. }
  57. protected function getTemplates(array $statuses)
  58. {
  59. $relation = array();
  60. $documentType = $this->getDocumentType();
  61. foreach ($statuses as $status)
  62. {
  63. $template = new \Bitrix\Bizproc\Automation\Engine\Template($documentType, $status);
  64. if ($template->getId() > 0)
  65. {
  66. $templateArray = $template->toArray();
  67. foreach ($templateArray['ROBOTS'] as $i => $robot)
  68. {
  69. $templateArray['ROBOTS'][$i]['viewData'] = static::getRobotViewData($robot, $documentType);
  70. }
  71. $relation[$status] = $templateArray;
  72. }
  73. else
  74. {
  75. $template->save(array(), 1); // save bizproc template
  76. $relation[$status] = $template->toArray();
  77. }
  78. }
  79. return array_values($relation);
  80. }
  81. protected function prepareTemplateForView()
  82. {
  83. $template = $this->getTemplateInfo();
  84. if ($template)
  85. {
  86. $tplRow = $template['ID'] > 0 ? \Bitrix\Bizproc\WorkflowTemplateTable::getById($template['ID']) : null;
  87. $tpl = $tplRow ? $tplRow->fetchObject() : null;
  88. if (!$tpl)
  89. {
  90. $documentType = $this->getDocumentType();
  91. $template = new \Bitrix\Bizproc\Automation\Engine\Template($documentType);
  92. $template->setDocumentStatus('SCRIPT');
  93. }
  94. else
  95. {
  96. $documentType = $tpl->getDocumentComplexType();
  97. $template = \Bitrix\Bizproc\Automation\Engine\Template::createByTpl($tpl);
  98. }
  99. $templateArray = $template->toArray();
  100. foreach ($templateArray['ROBOTS'] as $i => $robot)
  101. {
  102. $templateArray['ROBOTS'][$i]['viewData'] = static::getRobotViewData($robot, $documentType);
  103. }
  104. foreach (['PARAMETERS', 'CONSTANTS'] as $key)
  105. {
  106. foreach ($templateArray[$key] as $id => $property)
  107. {
  108. if ($property['Type'] === 'user')
  109. {
  110. $templateArray[$key][$id]['Default'] = CBPHelper::UsersArrayToString(
  111. $templateArray[$key][$id]['Default'], [], $documentType
  112. );
  113. }
  114. }
  115. }
  116. return $templateArray;
  117. }
  118. return null;
  119. }
  120. protected function getTemplateStatusList()
  121. {
  122. $template = $this->getTemplateInfo();
  123. $list = [];
  124. if ($template)
  125. {
  126. $status = 'SCRIPT';
  127. $list[$status] = [
  128. 'STATUS_ID' => $status,
  129. 'NAME' => 'script'
  130. ];
  131. }
  132. return $list;
  133. }
  134. public static function getTemplateViewData(array $template, $documentType)
  135. {
  136. foreach ($template['ROBOTS'] as $i => $robot)
  137. {
  138. $template['ROBOTS'][$i]['viewData'] = self::getRobotViewData($robot, $documentType);
  139. }
  140. return $template;
  141. }
  142. public static function getRobotViewData($robot, array $documentType)
  143. {
  144. $availableRobots = \Bitrix\Bizproc\Automation\Engine\Template::getAvailableRobots($documentType);
  145. $result = array(
  146. 'responsibleLabel' => '',
  147. 'responsibleUrl' => '',
  148. 'responsibleId' => 0,
  149. );
  150. $type = mb_strtolower($robot['Type']);
  151. if (isset($availableRobots[$type]) && isset($availableRobots[$type]['ROBOT_SETTINGS']))
  152. {
  153. $settings = $availableRobots[$type]['ROBOT_SETTINGS'];
  154. if ($settings['RESPONSIBLE_TO_HEAD'] && $robot['Properties'][$settings['RESPONSIBLE_TO_HEAD']] == 'Y')
  155. {
  156. $result['responsibleLabel'] = Loc::getMessage('BIZPROC_AUTOMATION_TO_HEAD');
  157. }
  158. if (isset($settings['RESPONSIBLE_PROPERTY']))
  159. {
  160. $users = self::getUsersFromResponsibleProperty($robot, $settings['RESPONSIBLE_PROPERTY']);
  161. $usersLabel = CBPHelper::UsersArrayToString($users, [], $documentType, false);
  162. if ($result['responsibleLabel'] && $usersLabel)
  163. {
  164. $result['responsibleLabel'] .= ', ';
  165. }
  166. $result['responsibleLabel'] .= $usersLabel;
  167. if ($users && count($users) == 1 && $users[0] && mb_strpos($users[0], 'user_') === 0)
  168. {
  169. $id = (int) \CBPHelper::StripUserPrefix($users[0]);
  170. $result['responsibleUrl'] = CComponentEngine::MakePathFromTemplate(
  171. '/company/personal/user/#user_id#/',
  172. array('user_id' => $id)
  173. );
  174. $result['responsibleId'] = $id;
  175. }
  176. }
  177. }
  178. return $result;
  179. }
  180. private static function getUsersFromResponsibleProperty(array $robot, $propertyName)
  181. {
  182. $value = null;
  183. $props = $robot['Properties'];
  184. $path = explode('.', $propertyName);
  185. foreach ($path as $chain)
  186. {
  187. $value = ($props && is_array($props) && isset($props[$chain])) ? $props[$chain] : null;
  188. $props = $value;
  189. }
  190. return $value ? (array)$value : null;
  191. }
  192. public function executeComponent()
  193. {
  194. if (!Main\Loader::includeModule('bizproc'))
  195. {
  196. return $this->showError(Loc::getMessage('BIZPROC_MODULE_NOT_INSTALLED'));
  197. }
  198. $documentType = $this->getDocumentType();
  199. $documentCategoryId = $this->getDocumentCategoryId();
  200. $documentService = CBPRuntime::GetRuntime(true)->getDocumentService();
  201. if ($this->isApiMode())
  202. {
  203. $this->arResult['DOCUMENT_FIELDS'] = $this->getDocumentFields();
  204. $this->arResult['DOCUMENT_USER_GROUPS'] = $this->getDocumentUserGroups();
  205. $this->arResult['DOCUMENT_SIGNED'] = static::signDocument($documentType, $documentCategoryId, null);
  206. $this->arResult['DOCUMENT_NAME'] = $documentService->getEntityName($documentType[0], $documentType[1]);
  207. $this->includeComponentTemplate('api');
  208. return;
  209. }
  210. $target = null;
  211. if (!$this->isOneTemplateMode())
  212. {
  213. /** @var \Bitrix\Bizproc\Automation\Target\BaseTarget $target */
  214. $target = $documentService->createAutomationTarget($documentType);
  215. if (!$target)
  216. {
  217. return $this->showError(Loc::getMessage('BIZPROC_AUTOMATION_NOT_SUPPORTED'));
  218. }
  219. if (!$target->isAvailable())
  220. {
  221. return $this->showError(Loc::getMessage('BIZPROC_AUTOMATION_NOT_AVAILABLE'));
  222. }
  223. }
  224. $tplUser = new \CBPWorkflowTemplateUser(\CBPWorkflowTemplateUser::CurrentUser);
  225. $canRead = $canEdit = (
  226. $tplUser->isAdmin() ||
  227. CBPDocument::CanUserOperateDocumentType(
  228. CBPCanUserOperateOperation::CreateAutomation,
  229. $GLOBALS["USER"]->GetID(),
  230. $documentType,
  231. ['DocumentCategoryId' => $documentCategoryId]
  232. )
  233. );
  234. $documentId = $this->getDocumentId();
  235. if ($target)
  236. {
  237. $target->setDocumentId($documentId);
  238. }
  239. if (!$canEdit)
  240. {
  241. if ($documentId)
  242. {
  243. $canRead = CBPDocument::CanUserOperateDocument(
  244. CBPCanUserOperateOperation::ReadDocument,
  245. $GLOBALS["USER"]->GetID(),
  246. [$documentType[0], $documentType[1], $documentId],
  247. ['DocumentCategoryId' => $documentCategoryId]
  248. );
  249. }
  250. else
  251. {
  252. $canRead = CBPDocument::CanUserOperateDocumentType(
  253. CBPCanUserOperateOperation::ReadDocument,
  254. $GLOBALS["USER"]->GetID(),
  255. $documentType,
  256. ['DocumentCategoryId' => $documentCategoryId]
  257. );
  258. }
  259. if (!$canRead)
  260. {
  261. return $this->showError(Loc::getMessage('BIZPROC_AUTOMATION_ACCESS_DENIED'));
  262. }
  263. }
  264. if (!$canRead && !$canEdit)
  265. {
  266. return $this->showError(Loc::getMessage('BIZPROC_AUTOMATION_NO_EDIT_PERMISSIONS'));
  267. }
  268. if (isset($this->arParams['ACTION']) && $this->arParams['ACTION'] == 'ROBOT_SETTINGS')
  269. {
  270. $template = new \Bitrix\Bizproc\Automation\Engine\Template($documentType);
  271. $dialog = $template->getRobotSettingsDialog($this->arParams['~ROBOT_DATA']);
  272. if ($dialog === '')
  273. {
  274. return;
  275. }
  276. if (!($dialog instanceof \Bitrix\Bizproc\Activity\PropertiesDialog))
  277. {
  278. ShowError('Robot dialog not supported in current context.');
  279. return;
  280. }
  281. if (is_array($this->arParams['~CONTEXT']))
  282. $dialog->setContext($this->arParams['~CONTEXT']);
  283. if (mb_strpos($this->arParams['~ROBOT_DATA']['Type'], 'rest_') === 0)
  284. {
  285. $this->arResult = array('dialog' => $dialog);
  286. $this->includeComponentTemplate('rest_robot_properties_dialog');
  287. return;
  288. }
  289. $dialog->setDialogFileName('robot_properties_dialog');
  290. echo $dialog;
  291. return;
  292. }
  293. $statusList = $target ? $target->getDocumentStatusList($documentCategoryId) : $this->getTemplateStatusList();
  294. $log = [];
  295. if ($documentId && $target)
  296. {
  297. $tracker = new \Bitrix\Bizproc\Automation\Tracker($target);
  298. $log = $tracker->getLog(array_keys($statusList));
  299. }
  300. $availableRobots = \Bitrix\Bizproc\Automation\Engine\Template::getAvailableRobots($documentType);
  301. $triggers = [];
  302. if ($target)
  303. {
  304. $triggers = $target->getTriggers(array_keys($statusList));
  305. $target->prepareTriggersToShow($triggers);
  306. }
  307. $this->arResult = array(
  308. 'CAN_EDIT' => $canEdit,
  309. 'TITLE_VIEW' => $this->getTitleView(),
  310. 'TITLE_EDIT' => $this->getTitleEdit(),
  311. 'DOCUMENT_STATUS' => $target ? $target->getDocumentStatus() : null,
  312. 'DOCUMENT_TYPE' => $documentType,
  313. 'DOCUMENT_ID' => $documentId,
  314. 'DOCUMENT_CATEGORY_ID' => $documentCategoryId,
  315. 'DOCUMENT_SIGNED' => static::signDocument($documentType, $documentCategoryId, $documentId),
  316. 'ENTITY_NAME' => $documentService->getEntityName($documentType[0], $documentType[1]),
  317. 'STATUSES' => $statusList,
  318. 'TEMPLATES' => $target ? $this->getTemplates(array_keys($statusList)) : [$this->prepareTemplateForView()],
  319. 'TRIGGERS' => $triggers,
  320. 'AVAILABLE_TRIGGERS' => $target ? $target->getAvailableTriggers() : [],
  321. 'AVAILABLE_ROBOTS' => array_values($availableRobots),
  322. 'GLOBAL_CONSTANTS' => \Bitrix\Bizproc\Workflow\Type\GlobalConst::getAll(),
  323. 'DOCUMENT_FIELDS' => $this->getDocumentFields(),
  324. 'LOG' => $log,
  325. 'WORKFLOW_EDIT_URL' => $this->getWorkflowEditUrl(),
  326. 'CONSTANTS_EDIT_URL' => $this->getConstantsEditUrl(),
  327. 'PARAMETERS_EDIT_URL' => $this->getParametersEditUrl(),
  328. 'STATUSES_EDIT_URL' => $this->getStatusesEditUrl(),
  329. 'USER_OPTIONS' => [
  330. 'defaults' => \CUserOptions::GetOption('bizproc.automation', 'defaults', []),
  331. 'save_state_checkboxes' => \CUserOptions::GetOption('bizproc.automation', 'save_state_checkboxes', [])
  332. ],
  333. 'FRAME_MODE' => $this->request->get('IFRAME') === 'Y' && $this->request->get('IFRAME_TYPE') === 'SIDE_SLIDER',
  334. 'USE_DISK' => Main\Loader::includeModule('disk'),
  335. 'IS_EMBEDDED' => $this->isOneTemplateMode(),
  336. 'SHOW_TEMPLATE_PROPERTIES_MENU_ON_SELECTING' => (
  337. isset($this->arParams['SHOW_TEMPLATE_PROPERTIES_MENU_ON_SELECTING'])
  338. && $this->arParams['SHOW_TEMPLATE_PROPERTIES_MENU_ON_SELECTING'] === 'Y'
  339. )
  340. );
  341. $this->prepareDelayMinLimitResult();
  342. $this->includeComponentTemplate();
  343. }
  344. public static function signDocument(array $documentType, $documentCategoryId, $documentId)
  345. {
  346. $signer = new Main\Security\Sign\Signer;
  347. $jsonData = Main\Web\Json::encode([$documentType, $documentCategoryId, $documentId]);
  348. return $signer->sign($jsonData, 'bizproc.automation.document');
  349. }
  350. /**
  351. * @param string $unsignedData
  352. * @return array
  353. */
  354. public static function unSignDocument($unsignedData)
  355. {
  356. $signer = new Main\Security\Sign\Signer;
  357. try
  358. {
  359. $unsigned = $signer->unsign($unsignedData, 'bizproc.automation.document');
  360. $result = Main\Web\Json::decode($unsigned);
  361. }
  362. catch (\Exception $e)
  363. {
  364. $result = array();
  365. }
  366. return $result;
  367. }
  368. /**
  369. * @deprecated
  370. */
  371. public static function getDestinationData(array $documentType)
  372. {
  373. $result = ['LAST' => []];
  374. if (!Main\Loader::includeModule('socialnetwork'))
  375. {
  376. return [];
  377. }
  378. $arStructure = CSocNetLogDestination::GetStucture(array());
  379. $result['DEPARTMENT'] = $arStructure['department'];
  380. $result['DEPARTMENT_RELATION'] = $arStructure['department_relation'];
  381. $result['DEPARTMENT_RELATION_HEAD'] = $arStructure['department_relation_head'];
  382. $result['DEST_SORT'] = CSocNetLogDestination::GetDestinationSort(array(
  383. "DEST_CONTEXT" => "BIZPROC_AUTOMATION",
  384. ));
  385. CSocNetLogDestination::fillLastDestination(
  386. $result['DEST_SORT'],
  387. $result['LAST']
  388. );
  389. $destUser = array();
  390. foreach ($result["LAST"]["USERS"] as $value)
  391. {
  392. $destUser[] = str_replace("U", "", $value);
  393. }
  394. $result["USERS"] = \CSocNetLogDestination::getUsers(array("id" => $destUser));
  395. $result["ROLES"] = array();
  396. $documentUserFields = \Bitrix\Bizproc\Automation\Helper::getDocumentFields($documentType, 'user');
  397. foreach ($documentUserFields as $field)
  398. {
  399. $result["ROLES"]['BPR_'.$field['Id']] = array(
  400. 'id' => 'BPR_'.$field['Id'],
  401. 'entityId' => $field['Expression'],
  402. 'name' => $field['Name'],
  403. 'avatar' => '',
  404. 'desc' => '&nbsp;'
  405. );
  406. }
  407. $result["LAST"]["USERS"]["ROLES"] = array();
  408. return $result;
  409. }
  410. private function getDocumentFields($filter = null)
  411. {
  412. return array_values(\Bitrix\Bizproc\Automation\Helper::getDocumentFields($this->getDocumentType(), $filter));
  413. }
  414. private function getDocumentUserGroups()
  415. {
  416. return \Bitrix\Bizproc\Automation\Helper::getDocumentUserGroups($this->getDocumentType());
  417. }
  418. private function showError($message)
  419. {
  420. echo <<<HTML
  421. <div class="ui-alert ui-alert-danger ui-alert-icon-danger">
  422. <span class="ui-alert-message">{$message}</span>
  423. </div>
  424. HTML;
  425. return;
  426. }
  427. private function prepareDelayMinLimitResult()
  428. {
  429. $this->arResult['DELAY_MIN_LIMIT_M'] = 0;
  430. $this->arResult['DELAY_MIN_LIMIT_LABEL'] = '';
  431. $delayMinLimit = CBPSchedulerService::getDelayMinLimit();
  432. if ($delayMinLimit)
  433. {
  434. $this->arResult['DELAY_MIN_LIMIT_M'] = intdiv($delayMinLimit,60);
  435. $this->arResult['DELAY_MIN_LIMIT_LABEL'] = Loc::getMessage('BIZPROC_AUTOMATION_DELAY_MIN_LIMIT', [
  436. '#VAL#' => \CBPHelper::FormatTimePeriod($delayMinLimit)
  437. ]);
  438. }
  439. }
  440. }