1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
stateservice.php
См. документацию.
1<?php
2
7
9{
10 const COUNTERS_CACHE_TAG_PREFIX = 'b_bp_wfi_cnt_';
11
12 protected static array $statesCache = [];
13
14 public function setStateTitle($workflowId, $stateTitle)
15 {
16 $workflowId = trim($workflowId);
17 if ($workflowId === '')
18 {
19 throw new Exception("workflowId");
20 }
21
22 WorkflowStateTable::update($workflowId, ['STATE_TITLE' => $stateTitle]);
23 }
24
25 public function setStatePermissions($workflowId, $arStatePermissions = array(), $bRewrite = true)
26 {
27 global $DB;
28
29 $workflowId = trim($workflowId);
30 if ($workflowId == '')
31 throw new Exception("workflowId");
32
33 if ($bRewrite === true || ($bRewrite['setMode'] ?? null) === CBPSetPermissionsMode::Clear)
34 {
35 $DB->Query(
36 "DELETE FROM b_bp_workflow_permissions ".
37 "WHERE WORKFLOW_ID = '".$DB->ForSql($workflowId)."' "
38 );
39 }
40 $arState = self::GetWorkflowState($workflowId);
41 $documentService = $this->runtime->GetService("DocumentService");
42 $documentService->SetPermissions($arState["DOCUMENT_ID"], $workflowId, $arStatePermissions, $bRewrite);
43 $documentType = $documentService->GetDocumentType($arState["DOCUMENT_ID"]);
44 if ($documentType)
45 $arStatePermissions = $documentService->toInternalOperations($documentType, $arStatePermissions);
46
47 foreach ($arStatePermissions as $permission => $arObjects)
48 {
49 foreach ($arObjects as $object)
50 {
51 $DB->Query(
52 "INSERT INTO b_bp_workflow_permissions (WORKFLOW_ID, OBJECT_ID, PERMISSION) ".
53 "VALUES ('".$DB->ForSql($workflowId)."', '".$DB->ForSql($object)."', '".$DB->ForSql($permission)."')"
54 );
55 }
56 }
57 }
58
59 public function getStateTitle($workflowId)
60 {
61 $workflowId = trim($workflowId);
62 if ($workflowId === '')
63 {
64 throw new Exception("workflowId");
65 }
66
67 $result = WorkflowStateTable::query()
68 ->setSelect(['STATE_TITLE'])
69 ->where('ID', $workflowId)
70 ->fetch();
71
72 return $result['STATE_TITLE'] ?? '';
73 }
74
75 public static function getStateDocumentId($workflowId)
76 {
77 static $cache = [];
78 $workflowId = trim($workflowId);
79 if ($workflowId === '')
80 {
81 throw new Exception("workflowId");
82 }
83
84 if (isset($cache[$workflowId]))
85 {
86 return $cache[$workflowId];
87 }
88
89 $result = WorkflowStateTable::query()
90 ->setSelect(['MODULE_ID', 'ENTITY', 'DOCUMENT_ID'])
91 ->where('ID', $workflowId)
92 ->fetch();
93
94 if ($result)
95 {
96 $cache[$workflowId] = [$result['MODULE_ID'], $result['ENTITY'], $result['DOCUMENT_ID']];
97
98 return $cache[$workflowId];
99 }
100
101 return false;
102 }
103
104 public function AddWorkflow($workflowId, $workflowTemplateId, $documentId, $starterUserId = 0)
105 {
106 $docId = CBPHelper::ParseDocumentId($documentId);
107
108 $workflowId = trim($workflowId);
109 if ($workflowId === '')
110 {
111 throw new Exception("workflowId");
112 }
113
114 $workflowTemplateId = (int)$workflowTemplateId;
115 if ($workflowTemplateId <= 0)
116 {
117 throw new Exception("workflowTemplateId");
118 }
119
120 $starterUserId = (int)$starterUserId;
121
122 if (WorkflowStateTable::exists($workflowId))
123 {
124 throw new Exception("WorkflowAlreadyExists");
125 }
126
127 $addResult = WorkflowStateTable::add([
128 'ID' => $workflowId,
129 'MODULE_ID' => $docId[0] ?: null,
130 'ENTITY' => $docId[1],
131 'DOCUMENT_ID' => $docId[2],
132 'DOCUMENT_ID_INT' => (int)$docId[2],
133 'WORKFLOW_TEMPLATE_ID' => $workflowTemplateId,
134 'STARTED_BY' => $starterUserId ?: null,
135 ]);
136
137 if ($starterUserId > 0 && $addResult->isSuccess())
138 {
139 self::cleanRunningCountersCache($starterUserId);
140 }
141 self::clearStatesCache();
142 }
143
144 public static function deleteWorkflow($workflowId)
145 {
147
148 $workflowId = trim($workflowId);
149 if ($workflowId === '')
150 {
151 throw new Exception("workflowId");
152 }
153
154 $info = self::getWorkflowStateInfo($workflowId);
155
156 if (!empty($info['STARTED_BY']))
157 {
159 }
160
161 $workflowIdSql = $connection->getSqlHelper()->forSql($workflowId);
162 $connection->query(
163 "DELETE FROM b_bp_workflow_permissions WHERE WORKFLOW_ID = '{$workflowIdSql}'",
164 );
165
166 WorkflowStateTable::delete($workflowId);
167 self::clearStatesCache();
168 }
169
170 public function deleteAllDocumentWorkflows($documentId)
171 {
172 self::DeleteByDocument($documentId);
173 }
174
175 public function onStatusChange(string $workflowId, int $status): void
176 {
177 self::clearStatesCache();
179 {
180 $info = $this->getWorkflowStateInfo($workflowId);
181 $userId = isset($info['STARTED_BY']) ? (int)$info['STARTED_BY'] : 0;
182 if ($userId > 0)
183 {
185 }
186
187 foreach (GetModuleEvents('bizproc', 'OnWorkflowComplete', true) as $event)
188 {
190 }
191
192 // Clean workflow subscriptions
194
195 if ($info)
196 {
197 $this->fillWorkflowDurationStat($info, $status);
198 }
199 }
200 }
201
202 private static function extractState(&$arStates, $arResult): void
203 {
204 if (!array_key_exists($arResult["ID"], $arStates))
205 {
206 $arStates[$arResult["ID"]] = array(
207 "ID" => $arResult["ID"],
208 "TEMPLATE_ID" => $arResult["WORKFLOW_TEMPLATE_ID"],
209 "TEMPLATE_NAME" => $arResult["NAME"],
210 "TEMPLATE_DESCRIPTION" => $arResult["DESCRIPTION"],
211 "STATE_MODIFIED" => $arResult["MODIFIED"],
212 "STATE_NAME" => $arResult["STATE"],
213 "STATE_TITLE" => $arResult["STATE_TITLE"],
214 "STATE_PARAMETERS" => ($arResult["STATE_PARAMETERS"] <> '' ? unserialize($arResult["STATE_PARAMETERS"], ['allowed_classes' => false]) : array()),
215 "WORKFLOW_STATUS" => $arResult["STATUS"],
216 "STATE_PERMISSIONS" => array(),
217 "DOCUMENT_ID" => array($arResult["MODULE_ID"], $arResult["ENTITY"], $arResult["DOCUMENT_ID"]),
218 "STARTED" => $arResult["STARTED"],
219 "STARTED_BY" => $arResult["STARTED_BY"],
220 "STARTED_FORMATTED" => $arResult["STARTED_FORMATTED"],
221 );
222 }
223
224 if ($arResult["PERMISSION"] <> '' && $arResult["OBJECT_ID"] <> '')
225 {
226 $arResult["PERMISSION"] = mb_strtolower($arResult["PERMISSION"]);
227
228 if (!array_key_exists($arResult["PERMISSION"], $arStates[$arResult["ID"]]["STATE_PERMISSIONS"]))
229 $arStates[$arResult["ID"]]["STATE_PERMISSIONS"][$arResult["PERMISSION"]] = array();
230
231 $arStates[$arResult["ID"]]["STATE_PERMISSIONS"][$arResult["PERMISSION"]][] = $arResult["OBJECT_ID"];
232 }
233 }
234
235 public static function countDocumentWorkflows($documentId)
236 {
237 $documentId = \CBPHelper::ParseDocumentId($documentId);
238
239 return WorkflowInstanceTable::getCount([
240 '=MODULE_ID' => $documentId[0],
241 '=ENTITY' => $documentId[1],
242 '=DOCUMENT_ID' => $documentId[2],
243 '!=STARTED_EVENT_TYPE' => CBPDocumentEventType::Automation,
244 ]);
245 }
246
247 public static function getDocumentStates(array $documentId, array|string $workflowId = ''): array
248 {
249 global $DB;
250
251 [$moduleId, $entity, $ids] = $documentId;
252
253 $cacheKey = self::getStatesCacheKey($documentId, $workflowId);
254
255 if (!isset(static::$statesCache[$cacheKey]))
256 {
257 $idsCondition = [];
258 foreach ((array)$ids as $id)
259 {
260 $idsCondition[] = "WS.DOCUMENT_ID = '{$DB->ForSql($id)}'";
261 }
262
263 if (empty($idsCondition))
264 {
265 static::$statesCache[$cacheKey] = [];
266
267 return [];
268 }
269
270 $sqlAdditionalFilter = "";
271 if (is_array($workflowId) && count($workflowId) > 0)
272 {
273 $workflowId = array_map(function($id) use ($DB) {
274 return "'{$DB->ForSql((string)$id)}'";
275 }, $workflowId);
276 $sqlAdditionalFilter = " AND WS.ID IN (" . implode(',', $workflowId) . ")";
277 }
278 elseif (is_string($workflowId) && $workflowId)
279 {
280 $sqlAdditionalFilter = " AND WS.ID = '{$DB->ForSql(trim($workflowId))}' ";
281 }
282
283 $dbResult = $DB->Query(
284 "SELECT WS.ID, WS.WORKFLOW_TEMPLATE_ID, WS.STATE, WS.STATE_TITLE, WS.STATE_PARAMETERS, "
285 . " "
286 . $DB->DateToCharFunction("WS.MODIFIED", "FULL")
287 . " as MODIFIED, "
288 . " WS.MODULE_ID, WS.ENTITY, WS.DOCUMENT_ID, "
289 . " WT.NAME, WT.DESCRIPTION, WP.OBJECT_ID, WP.PERMISSION, WI.STATUS, "
290 . " WS.STARTED, "
291 . $DB->DateToCharFunction("WS.STARTED", "FULL")
292 . " as STARTED_FORMATTED, WS.STARTED_BY "
293 . "FROM b_bp_workflow_state WS "
294 . " LEFT JOIN b_bp_workflow_permissions WP ON (WS.ID = WP.WORKFLOW_ID) "
295 . " LEFT JOIN b_bp_workflow_template WT ON (WS.WORKFLOW_TEMPLATE_ID = WT.ID) "
296 . " LEFT JOIN b_bp_workflow_instance WI ON (WS.ID = WI.ID) "
297 . "WHERE ("
298 . implode(' OR ', $idsCondition)
299 . ") "
300 . " AND WS.ENTITY = '"
301 . $DB->ForSql($entity)
302 . "' "
303 . " AND WS.MODULE_ID "
304 . ($moduleId ? "= '" . $DB->ForSql($moduleId) . "'" : "IS NULL")
305 . " "
306 . $sqlAdditionalFilter
307 );
308
309 $states = [];
310 while ($row = $dbResult->Fetch())
311 {
312 self::extractState($states, $row);
313 }
314
315 static::$statesCache[$cacheKey] = $states;
316 }
317
318 return static::$statesCache[$cacheKey];
319 }
320
321 public static function getIdsByDocument(array $documentId, int $limit = null)
322 {
323 return WorkflowStateTable::getIdsByDocument($documentId, $limit);
324 }
325
326 public static function getWorkflowState($workflowId)
327 {
328 global $DB;
329
330 $workflowId = trim($workflowId);
331 if ($workflowId == '')
332 throw new Exception("workflowId");
333
334 $dbResult = $DB->Query(
335 "SELECT WS.ID, WS.WORKFLOW_TEMPLATE_ID, WS.STATE, WS.STATE_TITLE, WS.STATE_PARAMETERS, ".
336 " ".$DB->DateToCharFunction("WS.MODIFIED", "FULL")." as MODIFIED, ".
337 " WS.MODULE_ID, WS.ENTITY, WS.DOCUMENT_ID, ".
338 " WT.NAME, WT.DESCRIPTION, WP.OBJECT_ID, WP.PERMISSION, WI.STATUS, ".
339 " WS.STARTED, WS.STARTED_BY, ".$DB->DateToCharFunction("WS.STARTED", "FULL")." as STARTED_FORMATTED ".
340 "FROM b_bp_workflow_state WS ".
341 " LEFT JOIN b_bp_workflow_permissions WP ON (WS.ID = WP.WORKFLOW_ID) ".
342 " LEFT JOIN b_bp_workflow_template WT ON (WS.WORKFLOW_TEMPLATE_ID = WT.ID) ".
343 " LEFT JOIN b_bp_workflow_instance WI ON (WS.ID = WI.ID) ".
344 "WHERE WS.ID = '".$DB->ForSql($workflowId)."' "
345 );
346
347 $arStates = array();
348 while ($arResult = $dbResult->Fetch())
349 {
350 self::extractState($arStates, $arResult);
351 }
352
353 $keys = array_keys($arStates);
354 if (count($keys) > 0)
355 $arStates = $arStates[$keys[0]];
356
357 return $arStates;
358 }
359
360 public static function getWorkflowStateInfo($workflowId)
361 {
362 global $DB;
363
364 $workflowId = trim($workflowId);
365 if ($workflowId === '')
366 {
367 throw new Exception('workflowId');
368 }
369
370 $dbResult = $DB->Query(
371 "SELECT
372 WS.ID, WS.STATE_TITLE, WS.MODULE_ID, WS.ENTITY, WS.DOCUMENT_ID, WI.STATUS, WS.STARTED_BY,
373 WS.WORKFLOW_TEMPLATE_ID, WT.NAME WORKFLOW_TEMPLATE_NAME, WS.STARTED ".
374 "FROM b_bp_workflow_state WS ".
375 "LEFT JOIN b_bp_workflow_instance WI ON (WS.ID = WI.ID) ".
376 "LEFT JOIN b_bp_workflow_template WT ON (WS.WORKFLOW_TEMPLATE_ID = WT.ID) ".
377 "WHERE WS.ID = '".$DB->ForSql($workflowId)."' "
378 );
379
380 $state = false;
381 $result = $dbResult->Fetch();
382 if ($result)
383 {
384 $state = [
385 'ID' => $result["ID"],
386 'WORKFLOW_TEMPLATE_ID' => $result['WORKFLOW_TEMPLATE_ID'],
387 'WORKFLOW_TEMPLATE_NAME' => $result['WORKFLOW_TEMPLATE_NAME'],
388 'STATE_TITLE' => $result['STATE_TITLE'],
389 'WORKFLOW_STATUS' => $result['STATUS'],
390 'DOCUMENT_ID' => [$result['MODULE_ID'], $result['ENTITY'], $result['DOCUMENT_ID']],
391 'STARTED_BY' => $result['STARTED_BY'],
392 'STARTED' => $result['STARTED'],
393 ];
394 }
395
396 return $state;
397 }
398
399 public static function exists(string $workflowId)
400 {
401 return WorkflowStateTable::exists($workflowId);
402 }
403
404 public static function getWorkflowIntegerId($workflowId)
405 {
406 global $DB;
407
408 $workflowId = trim($workflowId);
409 if ($workflowId == '')
410 throw new Exception("workflowId");
411
412 $dbResult = $DB->Query(
413 "SELECT ID FROM b_bp_workflow_state_identify WHERE WORKFLOW_ID = '".$DB->ForSql($workflowId)."' "
414 );
415
416 $result = $dbResult->fetch();
417 if (!$result)
418 {
419 $strSql =
420 "INSERT INTO b_bp_workflow_state_identify (WORKFLOW_ID) ".
421 "VALUES ('".$DB->ForSql($workflowId)."')";
422 $res = $DB->Query($strSql, true);
423 //crutch for #0071996
424 if ($res)
425 {
426 $result = array('ID' => $DB->LastID());
427 }
428 else
429 {
430 $dbResult = $DB->Query(
431 "SELECT ID FROM b_bp_workflow_state_identify WHERE WORKFLOW_ID = '".$DB->ForSql($workflowId)."' "
432 );
433
434 $result = $dbResult->fetch();
435 }
436 }
437 return (int)$result['ID'];
438 }
439
440 public static function getWorkflowByIntegerId($integerId)
441 {
442 global $DB;
443
444 $integerId = intval($integerId);
445 if ($integerId <= 0)
446 throw new Exception("integerId");
447
448 $dbResult = $DB->Query(
449 "SELECT WORKFLOW_ID FROM b_bp_workflow_state_identify WHERE ID = ".$integerId." "
450 );
451
452 $result = $dbResult->fetch();
453 if ($result)
454 {
455 return $result['WORKFLOW_ID'];
456 }
457 return false;
458 }
459
460 public static function deleteByDocument(array $documentId): void
461 {
462 global $DB;
463
464 [$moduleId, $entity, $docId] = CBPHelper::ParseDocumentId($documentId);
465 $users = [];
466
467 $workflows = $DB->Query(
468 "SELECT ID, STARTED_BY "
469 . "FROM b_bp_workflow_state "
470 . "WHERE DOCUMENT_ID = '"
471 . $DB->ForSql($docId)
472 . "' "
473 . " AND ENTITY = '"
474 . $DB->ForSql($entity)
475 . "' "
476 . " AND MODULE_ID "
477 . (($moduleId <> '') ? "= '" . $DB->ForSql($moduleId) . "'" : "IS NULL")
478 . " "
479 );
480 while ($row = $workflows->Fetch())
481 {
482 $DB->Query(
483 "DELETE FROM b_bp_workflow_permissions WHERE WORKFLOW_ID = '{$DB->ForSql($row["ID"])}' "
484 );
485
486 WorkflowStateTable::delete($row["ID"]);
487
488 if (!empty($row['STARTED_BY']))
489 {
490 $users[] = $row['STARTED_BY'];
491 }
492 self::clearStatesCache();
493 }
494
496 }
497
498 public static function mergeStates($firstDocumentId, $secondDocumentId)
499 {
500 global $DB;
501
502 $arFirstDocumentId = CBPHelper::ParseDocumentId($firstDocumentId);
503 $arSecondDocumentId = CBPHelper::ParseDocumentId($secondDocumentId);
504
505 $DB->Query(
506 "UPDATE b_bp_workflow_state SET ".
507 " DOCUMENT_ID = '".$DB->ForSql($arFirstDocumentId[2])."', ".
508 " DOCUMENT_ID_INT = ".intval($arFirstDocumentId[2]).", ".
509 " ENTITY = '".$DB->ForSql($arFirstDocumentId[1])."', ".
510 " MODULE_ID = '".$DB->ForSql($arFirstDocumentId[0])."' ".
511 "WHERE DOCUMENT_ID = '".$DB->ForSql($arSecondDocumentId[2])."' ".
512 " AND ENTITY = '".$DB->ForSql($arSecondDocumentId[1])."' ".
513 " AND MODULE_ID = '".$DB->ForSql($arSecondDocumentId[0])."' "
514 );
515 self::clearStatesCache();
516 }
517
518 public static function migrateDocumentType($oldType, $newType, $workflowTemplateIds)
519 {
520 global $DB;
521
522 $arOldType = CBPHelper::ParseDocumentId($oldType);
523 $arNewType = CBPHelper::ParseDocumentId($newType);
524
525 $DB->Query(
526 "UPDATE b_bp_workflow_state SET ".
527 " ENTITY = '".$DB->ForSql($arNewType[1])."', ".
528 " MODULE_ID = '".$DB->ForSql($arNewType[0])."' ".
529 "WHERE ENTITY = '".$DB->ForSql($arOldType[1])."' ".
530 " AND MODULE_ID = '".$DB->ForSql($arOldType[0])."' ".
531 " AND WORKFLOW_TEMPLATE_ID IN (".implode(",", $workflowTemplateIds).") "
532 );
533 }
534
535 public function setState($workflowId, $arState, $arStatePermissions = array())
536 {
537 global $DB;
538
539 $workflowId = trim($workflowId);
540 if ($workflowId == '')
541 throw new Exception("workflowId");
542
543 $state = trim($arState["STATE"]);
544 $stateTitle = trim($arState["TITLE"]);
545 $stateParameters = "";
546 if (count($arState["PARAMETERS"]) > 0)
547 $stateParameters = serialize($arState["PARAMETERS"]);
548
549 $DB->Query(
550 "UPDATE b_bp_workflow_state SET ".
551 " STATE = ".($state <> '' ? "'".$DB->ForSql($state)."'" : "NULL").", ".
552 " STATE_TITLE = ".($stateTitle <> '' ? "'".$DB->ForSql($stateTitle)."'" : "NULL").", ".
553 " STATE_PARAMETERS = ".($stateParameters <> '' ? "'".$DB->ForSql($stateParameters)."'" : "NULL").", ".
554 " MODIFIED = ".$DB->CurrentTimeFunction()." ".
555 "WHERE ID = '".$DB->ForSql($workflowId)."' "
556 );
557
558 if ($arStatePermissions !== false)
559 {
560 $arState = self::GetWorkflowState($workflowId);
562 if (!isset($runtime) || !is_object($runtime))
563 $runtime = CBPRuntime::GetRuntime();
564 $documentService = $runtime->GetService("DocumentService");
565
566 $permissionRewrite = true;
567 if (isset($arStatePermissions['__mode']) || isset($arStatePermissions['__scope']))
568 {
569 $permissionRewrite = [
570 'setMode' => $arStatePermissions['__mode'] ?? CBPSetPermissionsMode::Clear,
571 'setScope' => $arStatePermissions['__scope'] ?? CBPSetPermissionsMode::ScopeWorkflow,
572 ];
573 unset($arStatePermissions['__mode'], $arStatePermissions['__scope']);
574 }
575
576 $documentService->SetPermissions($arState["DOCUMENT_ID"], $workflowId, $arStatePermissions, $permissionRewrite);
577 $documentType = $documentService->GetDocumentType($arState["DOCUMENT_ID"]);
578 if ($documentType)
579 {
580 $arStatePermissions = $documentService->toInternalOperations($documentType, $arStatePermissions);
581 }
582
583 $DB->Query(
584 "DELETE FROM b_bp_workflow_permissions ".
585 "WHERE WORKFLOW_ID = '".$DB->ForSql($workflowId)."' "
586 );
587
588 foreach ($arStatePermissions as $permission => $arObjects)
589 {
590 foreach ($arObjects as $object)
591 {
592 $DB->Query(
593 "INSERT INTO b_bp_workflow_permissions (WORKFLOW_ID, OBJECT_ID, PERMISSION) ".
594 "VALUES ('".$DB->ForSql($workflowId)."', '".$DB->ForSql($object)."', '".$DB->ForSql($permission)."')"
595 );
596 }
597 }
598 }
599 self::clearStatesCache();
600 }
601
602 public function setStateParameters($workflowId, $arStateParameters = array())
603 {
604 global $DB;
605
606 $workflowId = trim($workflowId);
607 if ($workflowId == '')
608 throw new Exception("workflowId");
609
610 $stateParameters = "";
611 if (count($arStateParameters) > 0)
612 $stateParameters = serialize($arStateParameters);
613
614 $DB->Query(
615 "UPDATE b_bp_workflow_state SET ".
616 " STATE_PARAMETERS = ".($stateParameters <> '' ? "'".$DB->ForSql($stateParameters)."'" : "NULL").", ".
617 " MODIFIED = ".$DB->CurrentTimeFunction()." ".
618 "WHERE ID = '".$DB->ForSql($workflowId)."' "
619 );
620 }
621
622 public function addStateParameter($workflowId, $arStateParameter)
623 {
624 $workflowId = trim($workflowId);
625 if (empty($workflowId))
626 {
627 throw new Exception('workflowId');
628 }
629
630 $state = WorkflowStateTable::getByPrimary($workflowId, ['select' => ['STATE_PARAMETERS']])->fetch();
631 if ($state)
632 {
633 $stateParameters = [];
634 if (!empty($state['STATE_PARAMETERS']))
635 {
636 $stateParameters = unserialize($state['STATE_PARAMETERS'], ['allowed_classes' => false]);
637 }
638
639 $stateParameters[] = $arStateParameter;
640
641 WorkflowStateTable::update($workflowId, ['STATE_PARAMETERS' => serialize($stateParameters)]);
642 }
643 }
644
645 public function deleteStateParameter($workflowId, $name)
646 {
647 $workflowId = trim($workflowId);
648 if (empty($workflowId))
649 {
650 throw new Exception('workflowId');
651 }
652
653 $state = WorkflowStateTable::getByPrimary($workflowId, ['select' => ['STATE_PARAMETERS']])->fetch();
654 if ($state)
655 {
656 $stateParameters = [];
657 if (!empty($state['STATE_PARAMETERS']))
658 {
659 $stateParameters = unserialize($state['STATE_PARAMETERS'], ['allowed_classes' => false]);
660 }
661
662 $newStateParameters = [];
663 foreach ($stateParameters as $parameter)
664 {
665 if ($parameter['NAME'] !== $name)
666 {
667 $newStateParameters[] = $parameter;
668 }
669 }
670
671 WorkflowStateTable::update(
672 $workflowId,
673 ['STATE_PARAMETERS' => $newStateParameters ? serialize($newStateParameters) : null]
674 );
675 }
676 }
677
678 public static function getRunningCounters($userId)
679 {
680 global $DB;
681
682 $counters = array('*' => 0);
683 $cache = \Bitrix\Main\Application::getInstance()->getManagedCache();
684 $cacheTag = self::COUNTERS_CACHE_TAG_PREFIX.$userId;
685 if ($cache->read(3600*24*7, $cacheTag))
686 {
687 $counters = (array) $cache->get($cacheTag);
688 }
689 else
690 {
691 $query =
692 "SELECT WI.MODULE_ID AS MODULE_ID, WI.ENTITY AS ENTITY, COUNT('x') AS CNT ".
693 'FROM b_bp_workflow_instance WI '.
694 'WHERE WI.STARTED_BY = '.(int)$userId.' '.
695 'GROUP BY MODULE_ID, ENTITY';
696
697 $iterator = $DB->Query($query);
698 if ($iterator)
699 {
700 while ($row = $iterator->fetch())
701 {
702 $cnt = (int)$row['CNT'];
703 $counters[$row['MODULE_ID']][$row['ENTITY']] = $cnt;
704 if (!isset($counters[$row['MODULE_ID']]['*']))
705 $counters[$row['MODULE_ID']]['*'] = 0;
706 $counters[$row['MODULE_ID']]['*'] += $cnt;
707 $counters['*'] += $cnt;
708 }
709 $cache->set($cacheTag, $counters);
710 }
711 }
712 return $counters;
713 }
714
715 protected static function cleanRunningCountersCache($users)
716 {
717 $users = (array) $users;
718 $users = array_unique($users);
719 $cache = \Bitrix\Main\Application::getInstance()->getManagedCache();
720 foreach ($users as $userId)
721 {
722 $cache->clean(self::COUNTERS_CACHE_TAG_PREFIX.$userId);
723 }
724 }
725
726 private static function getStatesCacheKey(array $documentId, array|string $workflowId = ''): string
727 {
728 [$moduleId, $entity, $ids] = $documentId;
729 $cacheKey = "$moduleId@$entity@";
730
731 foreach ((array)$ids as $id)
732 {
733 $cacheKey .= "$id@";
734 }
735
736 if (is_array($workflowId))
737 {
738 $cacheKey .= implode('@', $workflowId);
739 }
740 else
741 {
742 $cacheKey .= $workflowId;
743 }
744
745 return $cacheKey;
746 }
747
748 private static function clearStatesCache(): void
749 {
750 static::$statesCache = [];
751 }
752
753 private function fillWorkflowDurationStat(array $workflowStateInfo, int $status)
754 {
755 $dateFormat = 'Y-m-d H:i:s';
756
757 if ($status === CBPWorkflowStatus::Completed && Main\Type\DateTime::isCorrect($workflowStateInfo['STARTED'], $dateFormat))
758 {
759 $templateId = (int)$workflowStateInfo['WORKFLOW_TEMPLATE_ID'];
760 $startedDate = new Main\Type\DateTime($workflowStateInfo['STARTED'], $dateFormat);
761
762 WorkflowDurationStatTable::add([
763 'WORKFLOW_ID' => (string)$workflowStateInfo['ID'],
764 'TEMPLATE_ID' => $templateId,
765 'DURATION' => (new Main\Type\DateTime())->getTimestamp() - $startedDate->getTimestamp(),
766 ]);
767 }
768 }
769}
$connection
Определения actionsdefinitions.php:38
$arResult
Определения generate_coupon.php:16
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
static deleteByWorkflow($workflowId)
Определения schedulerevent.php:89
static getInstance()
Определения application.php:98
static getConnection($name="")
Определения application.php:638
const Automation
Определения constants.php:156
$runtime
Определения runtimeservice.php:5
const ScopeWorkflow
Определения constants.php:226
const Clear
Определения constants.php:224
Определения stateservice.php:9
static migrateDocumentType($oldType, $newType, $workflowTemplateIds)
Определения stateservice.php:518
static deleteWorkflow($workflowId)
Определения stateservice.php:144
static cleanRunningCountersCache($users)
Определения stateservice.php:715
setStateParameters($workflowId, $arStateParameters=array())
Определения stateservice.php:602
static getRunningCounters($userId)
Определения stateservice.php:678
setStatePermissions($workflowId, $arStatePermissions=array(), $bRewrite=true)
Определения stateservice.php:25
addStateParameter($workflowId, $arStateParameter)
Определения stateservice.php:622
static deleteByDocument(array $documentId)
Определения stateservice.php:460
static getStateDocumentId($workflowId)
Определения stateservice.php:75
static getWorkflowIntegerId($workflowId)
Определения stateservice.php:404
setStateTitle($workflowId, $stateTitle)
Определения stateservice.php:14
getStateTitle($workflowId)
Определения stateservice.php:59
const COUNTERS_CACHE_TAG_PREFIX
Определения stateservice.php:10
static countDocumentWorkflows($documentId)
Определения stateservice.php:235
static array $statesCache
Определения stateservice.php:12
static getWorkflowState($workflowId)
Определения stateservice.php:326
setState($workflowId, $arState, $arStatePermissions=array())
Определения stateservice.php:535
static mergeStates($firstDocumentId, $secondDocumentId)
Определения stateservice.php:498
static getDocumentStates(array $documentId, array|string $workflowId='')
Определения stateservice.php:247
deleteStateParameter($workflowId, $name)
Определения stateservice.php:645
static exists(string $workflowId)
Определения stateservice.php:399
onStatusChange(string $workflowId, int $status)
Определения stateservice.php:175
AddWorkflow($workflowId, $workflowTemplateId, $documentId, $starterUserId=0)
Определения stateservice.php:104
static getWorkflowStateInfo($workflowId)
Определения stateservice.php:360
deleteAllDocumentWorkflows($documentId)
Определения stateservice.php:170
static getIdsByDocument(array $documentId, int $limit=null)
Определения stateservice.php:321
static getWorkflowByIntegerId($integerId)
Определения stateservice.php:440
const Completed
Определения constants.php:83
const Terminated
Определения constants.php:85
$templateId
Определения component_props2.php:51
</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
global $DB
Определения cron_frame.php:29
$status
Определения session.php:10
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
Определения backup.php:924
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
$name
Определения menu_edit.php:35
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
</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
$counters
Определения options.php:100
$dbResult
Определения updtr957.php:3
$iterator
Определения yandex_run.php:610