3namespace Bitrix\Bizproc\Automation;
5use Bitrix\Bizproc\Automation\Engine\DelayInterval;
9use Bitrix\Bizproc\WorkflowTemplateTable;
15 private const CACHE_TTL = 3600;
23 $users = (
array)$users;
24 $documentUserFields = static::getDocumentFields($documentType,
'user');
25 $documentUserGroups = self::getDocumentUserServiceGroups($documentType);
27 foreach ($users as
$user)
29 if (!is_scalar(
$user))
32 if (mb_substr(
$user, 0, 5) ===
"user_")
37 $userInfo = self::getUserInfo(
$user);
41 'name' => htmlspecialcharsBx($userInfo[
'fullName']),
42 'photoSrc' => $userInfo[
'photoSrc'],
43 'url' => $userInfo[
'url'],
44 'entityType' =>
'users',
50 isset($documentUserFields[
'ASSIGNED_BY_ID']) ||
51 isset($documentUserFields[
'RESPONSIBLE_ID'])
55 $responsibleKey = isset($documentUserFields[
'ASSIGNED_BY_ID']) ?
'ASSIGNED_BY_ID' :
'RESPONSIBLE_ID';
58 'id' => $documentUserFields[$responsibleKey][
'Expression'],
59 'entityId' => $documentUserFields[$responsibleKey][
'Expression'],
60 'name' => htmlspecialcharsBx($documentUserFields[$responsibleKey][
'Name']),
61 'entityType' =>
'bpuserroles'
69 'name' => htmlspecialcharsBx($documentUserGroups[
$user]),
70 'entityType' =>
'bpuserroles'
76 foreach ($documentUserFields as $field)
78 if (
$user === $field[
'Expression'] ||
$user === $field[
'SystemExpression'])
81 'id' => $field[
'Expression'],
82 'entityId' => $field[
'Expression'],
83 'name' => htmlspecialcharsBx($field[
'Name']),
84 'entityType' =>
'bpuserroles'
90 if (!$found && isset(
$config[
'additionalFields']))
92 foreach (
$config[
'additionalFields'] as $field)
94 if (
$user === $field[
'entityId'])
98 'entityId' => $field[
'entityId'],
99 'name' => htmlspecialcharsBx($field[
'name']),
100 'entityType' =>
'bpuserroles'
112 $documentUserFields = static::getDocumentFields($documentType,
'user');
115 if (isset($documentUserFields[
'ASSIGNED_BY_ID']) || isset($documentUserFields[
'RESPONSIBLE_ID']))
117 $responsibleKey = isset($documentUserFields[
'ASSIGNED_BY_ID']) ?
'ASSIGNED_BY_ID' :
'RESPONSIBLE_ID';
118 $result =
'{=Document:'.$responsibleKey.
'}';
120 elseif (isset($documentUserFields[
'CREATED_BY']))
122 $result =
'{=Document:CREATED_BY}';
136 if (!Loader::includeModule(
'disk'))
139 foreach ((
array)$attachments as $attachmentId)
141 $attachmentId = (int)$attachmentId;
142 if ($attachmentId <= 0)
147 $file = Disk\File::loadById($attachmentId);
151 'id' => $file->getId(),
152 'name' => $file->getName(),
153 'size' => \CFile::FormatSize($file->getSize()),
172 $documentUserFields = static::getDocumentFields($documentType,
'file');
176 if (!is_scalar($file))
180 foreach ($documentUserFields as $id => $field)
182 if ($file !== $field[
'Expression'])
188 'expression' => $field[
'Expression'],
189 'name' => $field[
'Name'],
194 if (!$found && mb_strpos($file,
'{') === 0)
198 'expression' => $file,
215 [$mapIds, $mapNames, $mapObjectNames] = static::getExpressionsMaps($documentType);
217 $converter =
function (
$matches) use ($mapIds, $mapNames, $mapObjectNames, $useTilda)
228 $modifiers = ($mods ?
' > ' . implode(
',', $mods) :
'');
233 if (in_array($objectName, $mapObjectNames))
235 $key = array_search($fieldId, $mapIds[$objectName]);
238 $fieldName = $mapNames[$objectName][
$key];
240 return '{{' . $fieldName . $modifiers .
'}}';
243 elseif ($useTilda && $objectName ===
'Template')
245 return '{{~*:' . $fieldId . $modifiers .
'}}';
247 elseif ($useTilda && $objectName ===
'Constant')
249 return '{{~&:' . $fieldId . $modifiers .
'}}';
251 elseif ($useTilda && preg_match(
'/^A[_0-9]+$/', $objectName))
253 return '{{~' . $objectName .
':' . $fieldId . $modifiers .
'}}';
259 return preg_replace_callback(
$pattern, $converter, $source);
266 $mapObjectNames = [];
269 [$ids, $names] = static::getFieldsMap($documentType);
270 $mapIds[$objectName] = $ids;
271 $mapNames[$objectName] = $names;
272 $mapObjectNames[] = $objectName;
275 [$ids, $names] = static::getGlobalsMap($objectName, $documentType);
276 $mapIds[$objectName] = $ids;
277 $mapNames[$objectName] = $names;
278 $mapObjectNames[] = $objectName;
281 [$ids, $names] = static::getGlobalsMap($objectName, $documentType);
282 $mapIds[$objectName] = $ids;
283 $mapNames[$objectName] = $names;
284 $mapObjectNames[] = $objectName;
286 return [$mapIds, $mapNames, $mapObjectNames];
291 $pattern =
'/\{\{(?<mixed>[^=].*?)\}\}/is';
292 [$mapIds, $mapNames, $mapObjectNames] = static::getExpressionsMaps($documentType);
294 $converter =
function (
$matches) use ($mapIds, $mapNames, $mapObjectNames)
298 if (mb_strpos(
$matches[
'mixed'],
'~') === 0)
300 $len = mb_strpos(
$matches[
'mixed'],
'#');
301 $expression = ($len ===
false)
303 : mb_substr(
$matches[
'mixed'], 1, $len - 1)
306 if (mb_strpos($expression,
'*:') === 0)
308 $expression = ltrim($expression,
'*');
309 $expression =
'Template' . $expression;
312 if (mb_strpos($expression,
'&:') === 0)
314 $expression = ltrim($expression,
'&');
315 $expression =
'Constant' . $expression;
318 return '{=' . trim($expression) .
'}';
321 $pairs = explode(
'>',
$matches[
'mixed']);
326 while (($pair = array_shift($pairs)) !==
null)
328 $fieldName .= $fieldName ?
'>' . $pair : $pair;
330 foreach ($mapObjectNames as $object)
332 $key = array_search(trim($fieldName), $mapNames[$object]);
335 $objectName = $object;
336 $fieldId = $mapIds[$object][
$key];
347 if (!$fieldId && mb_substr($fieldName, -10) ===
'_printable')
349 $fieldName = mb_substr($fieldName, 0, -10);
350 $key = array_search(trim($fieldName), $mapNames[
'Document']);
353 $objectName =
'Document';
354 $fieldId = $mapIds[
'Document'][
$key];
355 $pairs[] =
'printable';
361 $mods = isset($pairs[0]) ? trim($pairs[0]) :
'';
362 $modifiers = $mods ?
' > ' . $mods :
'';
364 return '{=' . $objectName .
':' . $fieldId . $modifiers .
'}';
370 return preg_replace_callback(
$pattern, $converter, $source);
375 foreach ($properties as
$code => $property)
377 if (is_array($property))
383 $properties[
$code] = static::convertExpressions($property, $documentType, $useTilda);
391 foreach ($properties as
$code => $property)
393 if (is_array($property))
399 $properties[
$code] = static::unConvertExpressions($property, $documentType);
413 $key = implode(
'@', $documentType);
414 if (!isset(static::$documentFields[
$key]))
416 $documentService = \CBPRuntime::getRuntime()->getDocumentService();
419 static::$documentFields[
$key] = $documentService->GetDocumentFields($documentType);
423 static::$documentFields[
$key] = [];
429 if (is_array(static::$documentFields[
$key]))
431 foreach (static::$documentFields[
$key] as $id => $field)
433 if ($field[
'Type'] ===
'UF:boolean')
436 $field[
'Type'] = $field[
'BaseType'] =
'bool';
439 if ($field[
'Type'] ===
'UF:date')
442 $field[
'Type'] = $field[
'BaseType'] =
'date';
445 if ($typeFilter !==
null && $field[
'Type'] !== $typeFilter)
448 $field[
'Name'] = trim($field[
'Name']);
450 $resultFields[$id] = [
452 'Name' => $field[
'Name'],
453 'Type' => $field[
'Type'],
454 'BaseType' => $field[
'BaseType'] ?? $field[
'Type'],
455 'Expression' =>
'{{' . $field[
'Name'] .
'}}',
456 'SystemExpression' =>
'{=Document:' . $id .
'}',
457 'Options' => $field[
'Options'] ??
null,
458 'Settings' => $field[
'Settings'] ??
null,
459 'Multiple' => $field[
'Multiple'] ??
false,
464 return $resultFields;
474 foreach ($globalVariables as $id => $variable)
476 $name = trim($variable[
'Name']);
477 $visibilityName = $visibilityNames[$variable[
'Visibility']];
482 'Type' => $variable[
'Type'],
483 'BaseType' => $variable[
'Type'],
484 'Expression' =>
'{{' . $visibilityName .
': ' .
$name .
'}}',
486 'Options' => $variable[
'Options'] ??
null,
487 'Multiple' => $variable[
'Multiple'] ??
false,
488 'Visibility' => $variable[
'Visibility'],
489 'VisibilityName' => $visibilityName,
503 foreach ($globalConstants as $id => $constant)
505 $name = trim($constant[
'Name']);
506 $visibilityName = $visibilityNames[$constant[
'Visibility']];
511 'Type' => $constant[
'Type'],
512 'BaseType' => $constant[
'Type'],
513 'Expression' =>
'{{' . $visibilityName .
': ' .
$name .
'}}',
515 'Options' => $constant[
'Options'] ??
null,
516 'Multiple' => $constant[
'Multiple'] ??
false,
517 'Visibility' => $constant[
'Visibility'],
518 'VisibilityName' => $visibilityName,
525 private static function getDocumentUserServiceGroups(
array $documentType)
527 $documentService = \CBPRuntime::getRuntime()->getDocumentService();
529 return $documentService->GetAllowableUserGroups($documentType);
534 $docGroups = self::getDocumentUserServiceGroups($documentType);
539 foreach ($docGroups as $id => $groupName)
541 if (!$groupName || mb_strpos($id,
'group_') === 0)
547 'id' => preg_match(
'/^[0-9]+$/', $id) ?
'G'.$id : $id,
558 $documentGroups = static::getDocumentUserGroups($documentType);
559 if (empty($documentGroups))
564 foreach ($documentGroups as $group)
566 if ($group[
'id'] === $value)
577 $key = implode(
'@', $documentType);
578 if (!isset(static::$maps[
$key]))
583 $fields = static::getDocumentFields($documentType);
586 $id[] = $field[
'Id'];
587 $name[] = $field[
'Name'];
593 return static::$maps[
$key];
600 case \Bitrix\Bizproc\Workflow\Template\SourceType::GlobalConstant:
601 $key =
'globals@const@' . implode(
'@', $documentType);
602 if (isset(static::$maps[
$key]))
604 return static::$maps[
$key];
606 $globals = static::getGlobalConstants($documentType);
608 case \Bitrix\Bizproc\Workflow\Template\SourceType::GlobalVariable:
609 $key =
'globals@var@' . implode(
'@', $documentType);
610 if (isset(static::$maps[
$key]))
612 return static::$maps[
$key];
614 $globals = static::getGlobalVariables($documentType);
623 foreach ($globals as $id => $property)
626 $names[] = $property[
'VisibilityName'] .
': ' . trim($property[
'Name']);
629 static::$maps[
$key] = [$ids, $names];
631 return static::$maps[
$key];
636 $interval = ltrim((
string)$interval,
'=');
649 if (mb_strpos($interval,
'settime(') === 0)
651 $interval = mb_substr($interval, 8, -1);
652 $intervalParts = explode(
')', $interval);
653 $arguments = explode(
',', array_pop($intervalParts));
655 $userOffset =
count($arguments) > 3 ? array_pop($arguments) : 0;
656 $minute = array_pop($arguments);
657 $hour = array_pop($arguments);
659 $interval = implode(
')', $intervalParts) . implode(
',', $arguments);
660 $result[
'inTime'] = [(int)$hour, (
int)$minute];
664 $result[
'inTime'][] = (int)$userOffset;
668 if (mb_strpos($interval,
'dateadd(') === 0 || mb_strpos($interval,
'workdateadd(') === 0)
670 if (mb_strpos($interval,
'workdateadd(') === 0)
672 $interval = mb_substr($interval, 12, -1);
677 $interval = mb_substr($interval, 8, -1);
680 $arguments = explode(
',', $interval);
681 $result[
'basis'] = trim($arguments[0]);
683 $arguments[1] = trim(($arguments[1] ??
''),
'"\'');
686 preg_match_all(
'/\s*([\d]+)\s*(i|h|d)\s*/i', $arguments[1],
$matches);
692 elseif (\CBPDocument::IsExpression($interval))
696 if (
$result[
'basis'] !== static::CURRENT_DATETIME_BASIS)
706 $minutes = $values[
'i'] + $values[
'h'] * 60 + $values[
'd'] * 60 * 24;
708 if ($minutes % 1440 === 0)
710 $result[
'value'] = $minutes / 1440;
713 elseif ($minutes % 60 === 0)
715 $result[
'value'] = $minutes / 60;
727 $result[
'basis'] !== static::CURRENT_DATETIME_BASIS
730 && \CBPDocument::IsExpression(
$result[
'basis'])
741 if (empty($interval[
'basis']) || !\CBPDocument::IsExpression($interval[
'basis']))
743 $interval[
'basis'] = static::CURRENT_DATE_BASIS;
746 $days = isset($interval[
'd']) ? (int)$interval[
'd'] : 0;
747 $hours = isset($interval[
'h']) ? (int)$interval[
'h'] : 0;
748 $minutes = isset($interval[
'i']) ? (int)$interval[
'i'] : 0;
750 if (isset($interval[
'value']) && isset($interval[
'valueType']))
752 switch ($interval[
'valueType'])
755 $minutes = (int)$interval[
'value'];
758 $hours = (int)$interval[
'value'];
761 $days = (int)$interval[
'value'];
773 $add .= $minutes.
'i';
780 $fn = !empty($interval[
'workTime']) ?
'workdateadd' :
'dateadd';
782 if ($fn ===
'workdateadd' && $add ===
'')
788 if ($fn ===
'workdateadd' && isset($interval[
'worker']))
790 $worker = $interval[
'worker'];
794 $isFunctionInResult =
false;
797 $result = $fn .
'(' . $interval[
'basis'] .
',"' . $add .
'"' . ($worker ?
',' . $worker :
'') .
')';
798 $isFunctionInResult =
true;
801 if (isset($interval[
'inTime']))
804 'settime(%s, %d, %d%s)',
806 $interval[
'inTime'][0] ?? 0,
807 $interval[
'inTime'][1] ?? 0,
808 isset($interval[
'inTime'][2]) ?
", {$interval['inTime'][2]}" :
'',
810 $isFunctionInResult =
true;
818 $pairs = preg_split(
'#[\s:]+#',
$time);
819 $pairs[0] = (int)$pairs[0];
820 $pairs[1] = (int)$pairs[1];
822 if (
count($pairs) === 3)
824 if ($pairs[2] ==
'pm' && $pairs[0] < 12)
826 if ($pairs[2] ==
'am' && $pairs[0] == 12)
830 return array(
'h' => $pairs[0],
'i' => $pairs[1]);
836 $result = WorkflowTemplateTable::getList([
838 '=MODULE_ID' => $documentType[0],
839 '=ENTITY' => $documentType[1],
840 '=DOCUMENT_TYPE' => $documentType[2],
841 '@DOCUMENT_STATUS' => $statuses,
843 'select' => [
'TEMPLATE'],
844 'cache' => [
'ttl' => self::CACHE_TTL],
846 while ($row =
$result->fetchObject())
848 $row[
'MODULE_ID'] = $documentType[0];
849 $row[
'ENTITY'] = $documentType[1];
850 $row[
'DOCUMENT_TYPE'] = $documentType[2];
858 private static function getUserInfo($userID, $format =
'', $htmlEncode =
false)
860 $userID = intval($userID);
866 $format = strval($format);
869 $format = \CSite::GetNameFormat(
false);
872 $dbUser = \CUser::GetList(
875 array(
'ID'=> $userID),
879 'NAME',
'SECOND_NAME',
'LAST_NAME',
880 'LOGIN',
'TITLE',
'EMAIL',
886 $user = $dbUser ? $dbUser->Fetch() :
null;
889 'fullName' =>
$user ? \CUser::FormatName($format,
$user,
true, $htmlEncode) :
'',
891 'url' => sprintf(
'/company/personal/user/%s/', $userID),
static createByTpl(Tpl $tpl)
static getResponsibleUserExpression(array $documentType)
static parseDateTimeInterval($interval)
static convertExpressions($source, array $documentType, $useTilda=true)
static isDocumentUserGroup(string $value, array $documentType)
static countAllRobots(array $documentType, array $statuses)
static getGlobalVariables(array $documentType)
static getDocumentFields(array $documentType, $typeFilter=null)
static parseTimeString($time)
const CURRENT_DATETIME_BASIS
static getGlobalsMap(string $type, array $documentType)
static getFieldsMap(array $documentType)
static getExpressionsMaps($documentType)
static prepareFileAttachments(array $documentType, $files)
static unConvertProperties(array $properties, array $documentType)
static getDateTimeIntervalString($interval)
static getGlobalConstants(array $documentType)
static getDocumentUserGroups(array $documentType)
static prepareDiskAttachments($attachments)
static unConvertExpressions($source, array $documentType)
static convertProperties(array $properties, array $documentType, $useTilda=true)
static prepareUserSelectorEntities(array $documentType, $users, $config=[])
static getVisibilityFullNames(array $parameterDocumentType)
static getVisibilityFullNames(array $parameterDocumentType)
static getAll(array $parameterDocumentType=[])
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
htmlspecialcharsback($str)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</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."%"
if(!Loader::includeModule('sale')) $pattern