16 $workflowId = trim($workflowId);
17 if ($workflowId ===
'')
19 throw new Exception(
"workflowId");
22 WorkflowStateTable::update($workflowId, [
'STATE_TITLE' => $stateTitle]);
29 $workflowId = trim($workflowId);
30 if ($workflowId ==
'')
31 throw new Exception(
"workflowId");
36 "DELETE FROM b_bp_workflow_permissions ".
37 "WHERE WORKFLOW_ID = '".
$DB->ForSql($workflowId).
"' "
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"]);
45 $arStatePermissions = $documentService->toInternalOperations($documentType, $arStatePermissions);
47 foreach ($arStatePermissions as $permission => $arObjects)
49 foreach ($arObjects as $object)
52 "INSERT INTO b_bp_workflow_permissions (WORKFLOW_ID, OBJECT_ID, PERMISSION) ".
53 "VALUES ('".
$DB->ForSql($workflowId).
"', '".
$DB->ForSql($object).
"', '".
$DB->ForSql($permission).
"')"
61 $workflowId = trim($workflowId);
62 if ($workflowId ===
'')
64 throw new Exception(
"workflowId");
67 $result = WorkflowStateTable::query()
68 ->setSelect([
'STATE_TITLE'])
69 ->where(
'ID', $workflowId)
72 return $result[
'STATE_TITLE'] ??
'';
78 $workflowId = trim($workflowId);
79 if ($workflowId ===
'')
81 throw new Exception(
"workflowId");
84 if (isset($cache[$workflowId]))
86 return $cache[$workflowId];
89 $result = WorkflowStateTable::query()
90 ->setSelect([
'MODULE_ID',
'ENTITY',
'DOCUMENT_ID'])
91 ->where(
'ID', $workflowId)
98 return $cache[$workflowId];
104 public function AddWorkflow($workflowId, $workflowTemplateId, $documentId, $starterUserId = 0)
106 $docId = CBPHelper::ParseDocumentId($documentId);
108 $workflowId = trim($workflowId);
109 if ($workflowId ===
'')
111 throw new Exception(
"workflowId");
114 $workflowTemplateId = (int)$workflowTemplateId;
115 if ($workflowTemplateId <= 0)
117 throw new Exception(
"workflowTemplateId");
120 $starterUserId = (int)$starterUserId;
122 if (WorkflowStateTable::exists($workflowId))
124 throw new Exception(
"WorkflowAlreadyExists");
127 $addResult = WorkflowStateTable::add([
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,
137 if ($starterUserId > 0 && $addResult->isSuccess())
141 self::clearStatesCache();
148 $workflowId = trim($workflowId);
149 if ($workflowId ===
'')
151 throw new Exception(
"workflowId");
156 if (!empty(
$info[
'STARTED_BY']))
161 $workflowIdSql =
$connection->getSqlHelper()->forSql($workflowId);
163 "DELETE FROM b_bp_workflow_permissions WHERE WORKFLOW_ID = '{$workflowIdSql}'",
166 WorkflowStateTable::delete($workflowId);
167 self::clearStatesCache();
172 self::DeleteByDocument($documentId);
177 self::clearStatesCache();
202 private static function extractState(&$arStates,
$arResult): void
204 if (!array_key_exists(
$arResult[
"ID"], $arStates))
208 "TEMPLATE_ID" =>
$arResult[
"WORKFLOW_TEMPLATE_ID"],
210 "TEMPLATE_DESCRIPTION" =>
$arResult[
"DESCRIPTION"],
211 "STATE_MODIFIED" =>
$arResult[
"MODIFIED"],
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(),
220 "STARTED_FORMATTED" =>
$arResult[
"STARTED_FORMATTED"],
228 if (!array_key_exists(
$arResult[
"PERMISSION"], $arStates[
$arResult[
"ID"]][
"STATE_PERMISSIONS"]))
237 $documentId = \CBPHelper::ParseDocumentId($documentId);
239 return WorkflowInstanceTable::getCount([
240 '=MODULE_ID' => $documentId[0],
241 '=ENTITY' => $documentId[1],
242 '=DOCUMENT_ID' => $documentId[2],
253 $cacheKey = self::getStatesCacheKey($documentId, $workflowId);
255 if (!isset(static::$statesCache[$cacheKey]))
258 foreach ((
array)$ids as $id)
260 $idsCondition[] =
"WS.DOCUMENT_ID = '{$DB->ForSql($id)}'";
263 if (empty($idsCondition))
265 static::$statesCache[$cacheKey] = [];
270 $sqlAdditionalFilter =
"";
271 if (is_array($workflowId) &&
count($workflowId) > 0)
273 $workflowId = array_map(
function($id) use (
$DB) {
274 return "'{$DB->ForSql((string)$id)}'";
276 $sqlAdditionalFilter =
" AND WS.ID IN (" . implode(
',', $workflowId) .
")";
278 elseif (is_string($workflowId) && $workflowId)
280 $sqlAdditionalFilter =
" AND WS.ID = '{$DB->ForSql(trim($workflowId))}' ";
284 "SELECT WS.ID, WS.WORKFLOW_TEMPLATE_ID, WS.STATE, WS.STATE_TITLE, WS.STATE_PARAMETERS, "
286 .
$DB->DateToCharFunction(
"WS.MODIFIED",
"FULL")
288 .
" WS.MODULE_ID, WS.ENTITY, WS.DOCUMENT_ID, "
289 .
" WT.NAME, WT.DESCRIPTION, WP.OBJECT_ID, WP.PERMISSION, WI.STATUS, "
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) "
298 . implode(
' OR ', $idsCondition)
300 .
" AND WS.ENTITY = '"
303 .
" AND WS.MODULE_ID "
306 . $sqlAdditionalFilter
312 self::extractState($states, $row);
315 static::$statesCache[$cacheKey] = $states;
318 return static::$statesCache[$cacheKey];
323 return WorkflowStateTable::getIdsByDocument($documentId, $limit);
330 $workflowId = trim($workflowId);
331 if ($workflowId ==
'')
332 throw new Exception(
"workflowId");
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).
"' "
350 self::extractState($arStates,
$arResult);
353 $keys = array_keys($arStates);
354 if (
count($keys) > 0)
355 $arStates = $arStates[$keys[0]];
364 $workflowId = trim($workflowId);
365 if ($workflowId ===
'')
367 throw new Exception(
'workflowId');
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).
"' "
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'],
391 'STARTED_BY' =>
$result[
'STARTED_BY'],
392 'STARTED' =>
$result[
'STARTED'],
399 public static function exists(
string $workflowId)
401 return WorkflowStateTable::exists($workflowId);
408 $workflowId = trim($workflowId);
409 if ($workflowId ==
'')
410 throw new Exception(
"workflowId");
413 "SELECT ID FROM b_bp_workflow_state_identify WHERE WORKFLOW_ID = '".
$DB->ForSql($workflowId).
"' "
420 "INSERT INTO b_bp_workflow_state_identify (WORKFLOW_ID) ".
421 "VALUES ('".$DB->ForSql($workflowId).
"')";
422 $res =
$DB->Query($strSql,
true);
431 "SELECT ID FROM b_bp_workflow_state_identify WHERE WORKFLOW_ID = '".
$DB->ForSql($workflowId).
"' "
444 $integerId = intval($integerId);
446 throw new Exception(
"integerId");
449 "SELECT WORKFLOW_ID FROM b_bp_workflow_state_identify WHERE ID = ".$integerId.
" "
467 $workflows =
$DB->Query(
468 "SELECT ID, STARTED_BY "
469 .
"FROM b_bp_workflow_state "
470 .
"WHERE DOCUMENT_ID = '"
471 .
$DB->ForSql($docId)
480 while ($row = $workflows->Fetch())
483 "DELETE FROM b_bp_workflow_permissions WHERE WORKFLOW_ID = '{$DB->ForSql($row["ID
"])}' "
486 WorkflowStateTable::delete($row[
"ID"]);
488 if (!empty($row[
'STARTED_BY']))
490 $users[] = $row[
'STARTED_BY'];
492 self::clearStatesCache();
498 public static function mergeStates($firstDocumentId, $secondDocumentId)
502 $arFirstDocumentId = CBPHelper::ParseDocumentId($firstDocumentId);
503 $arSecondDocumentId = CBPHelper::ParseDocumentId($secondDocumentId);
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]).
"' "
515 self::clearStatesCache();
522 $arOldType = CBPHelper::ParseDocumentId($oldType);
523 $arNewType = CBPHelper::ParseDocumentId($newType);
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).
") "
535 public function setState($workflowId, $arState, $arStatePermissions =
array())
539 $workflowId = trim($workflowId);
540 if ($workflowId ==
'')
541 throw new Exception(
"workflowId");
543 $state = trim($arState[
"STATE"]);
544 $stateTitle = trim($arState[
"TITLE"]);
545 $stateParameters =
"";
546 if (
count($arState[
"PARAMETERS"]) > 0)
547 $stateParameters = serialize($arState[
"PARAMETERS"]);
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).
"' "
558 if ($arStatePermissions !==
false)
560 $arState = self::GetWorkflowState($workflowId);
563 $runtime = CBPRuntime::GetRuntime();
564 $documentService =
$runtime->GetService(
"DocumentService");
566 $permissionRewrite =
true;
567 if (isset($arStatePermissions[
'__mode']) || isset($arStatePermissions[
'__scope']))
569 $permissionRewrite = [
573 unset($arStatePermissions[
'__mode'], $arStatePermissions[
'__scope']);
576 $documentService->SetPermissions($arState[
"DOCUMENT_ID"], $workflowId, $arStatePermissions, $permissionRewrite);
577 $documentType = $documentService->GetDocumentType($arState[
"DOCUMENT_ID"]);
580 $arStatePermissions = $documentService->toInternalOperations($documentType, $arStatePermissions);
584 "DELETE FROM b_bp_workflow_permissions ".
585 "WHERE WORKFLOW_ID = '".
$DB->ForSql($workflowId).
"' "
588 foreach ($arStatePermissions as $permission => $arObjects)
590 foreach ($arObjects as $object)
593 "INSERT INTO b_bp_workflow_permissions (WORKFLOW_ID, OBJECT_ID, PERMISSION) ".
594 "VALUES ('".
$DB->ForSql($workflowId).
"', '".
$DB->ForSql($object).
"', '".
$DB->ForSql($permission).
"')"
599 self::clearStatesCache();
606 $workflowId = trim($workflowId);
607 if ($workflowId ==
'')
608 throw new Exception(
"workflowId");
610 $stateParameters =
"";
611 if (
count($arStateParameters) > 0)
612 $stateParameters = serialize($arStateParameters);
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).
"' "
624 $workflowId = trim($workflowId);
625 if (empty($workflowId))
627 throw new Exception(
'workflowId');
630 $state = WorkflowStateTable::getByPrimary($workflowId, [
'select' => [
'STATE_PARAMETERS']])->fetch();
633 $stateParameters = [];
634 if (!empty($state[
'STATE_PARAMETERS']))
636 $stateParameters = unserialize($state[
'STATE_PARAMETERS'], [
'allowed_classes' =>
false]);
639 $stateParameters[] = $arStateParameter;
641 WorkflowStateTable::update($workflowId, [
'STATE_PARAMETERS' => serialize($stateParameters)]);
647 $workflowId = trim($workflowId);
648 if (empty($workflowId))
650 throw new Exception(
'workflowId');
653 $state = WorkflowStateTable::getByPrimary($workflowId, [
'select' => [
'STATE_PARAMETERS']])->fetch();
656 $stateParameters = [];
657 if (!empty($state[
'STATE_PARAMETERS']))
659 $stateParameters = unserialize($state[
'STATE_PARAMETERS'], [
'allowed_classes' =>
false]);
662 $newStateParameters = [];
663 foreach ($stateParameters as $parameter)
665 if ($parameter[
'NAME'] !==
$name)
667 $newStateParameters[] = $parameter;
671 WorkflowStateTable::update(
673 [
'STATE_PARAMETERS' => $newStateParameters ? serialize($newStateParameters) :
null]
684 $cacheTag = self::COUNTERS_CACHE_TAG_PREFIX.$userId;
685 if ($cache->read(3600*24*7, $cacheTag))
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';
702 $cnt = (int)$row[
'CNT'];
703 $counters[$row[
'MODULE_ID']][$row[
'ENTITY']] = $cnt;
704 if (!isset(
$counters[$row[
'MODULE_ID']][
'*']))
706 $counters[$row[
'MODULE_ID']][
'*'] += $cnt;
717 $users = (
array) $users;
718 $users = array_unique($users);
722 $cache->clean(self::COUNTERS_CACHE_TAG_PREFIX.
$userId);
726 private static function getStatesCacheKey(
array $documentId,
array|
string $workflowId =
''): string
729 $cacheKey =
"$moduleId@$entity@";
731 foreach ((
array)$ids as $id)
736 if (is_array($workflowId))
738 $cacheKey .= implode(
'@', $workflowId);
742 $cacheKey .= $workflowId;
748 private static function clearStatesCache(): void
750 static::$statesCache = [];
753 private function fillWorkflowDurationStat(
array $workflowStateInfo,
int $status)
755 $dateFormat =
'Y-m-d H:i:s';
759 $templateId = (int)$workflowStateInfo[
'WORKFLOW_TEMPLATE_ID'];
760 $startedDate =
new Main\Type\DateTime($workflowStateInfo[
'STARTED'], $dateFormat);
762 WorkflowDurationStatTable::add([
763 'WORKFLOW_ID' => (
string)$workflowStateInfo[
'ID'],
765 'DURATION' => (
new Main\Type\DateTime())->
getTimestamp() - $startedDate->getTimestamp(),
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static deleteByWorkflow($workflowId)
static getConnection($name="")
static migrateDocumentType($oldType, $newType, $workflowTemplateIds)
static deleteWorkflow($workflowId)
static cleanRunningCountersCache($users)
setStateParameters($workflowId, $arStateParameters=array())
static getRunningCounters($userId)
setStatePermissions($workflowId, $arStatePermissions=array(), $bRewrite=true)
addStateParameter($workflowId, $arStateParameter)
static deleteByDocument(array $documentId)
static getStateDocumentId($workflowId)
static getWorkflowIntegerId($workflowId)
setStateTitle($workflowId, $stateTitle)
getStateTitle($workflowId)
const COUNTERS_CACHE_TAG_PREFIX
static countDocumentWorkflows($documentId)
static array $statesCache
static getWorkflowState($workflowId)
setState($workflowId, $arState, $arStatePermissions=array())
static mergeStates($firstDocumentId, $secondDocumentId)
static getDocumentStates(array $documentId, array|string $workflowId='')
deleteStateParameter($workflowId, $name)
static exists(string $workflowId)
onStatusChange(string $workflowId, int $status)
AddWorkflow($workflowId, $workflowTemplateId, $documentId, $starterUserId=0)
static getWorkflowStateInfo($workflowId)
deleteAllDocumentWorkflows($documentId)
static getIdsByDocument(array $documentId, int $limit=null)
static getWorkflowByIntegerId($integerId)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
ExecuteModuleEventEx($arEvent, $arParams=[])
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
</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."%"