Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
conditiongroup.php
1<?php
3
9
10Loc::loadMessages(__FILE__);
11
13{
14 public const TYPE_FIELD = 'field';
15 public const TYPE_MIXED = 'mixed';
16
17 public const JOINER_AND = 'AND';// 0
18 public const JOINER_OR = 'OR';// 1
19
20 private $type;
21 private $items = [];
22 private array $activityNames = [];
23 protected array $evaluateResults = [];
24 protected bool $activated = true;
25 protected bool $internalized = false;
26
27 public function __construct(array $params = null)
28 {
29 $this->setType(static::TYPE_FIELD);
30 if ($params)
31 {
32 if (isset($params['type']))
33 {
34 $this->setType($params['type']);
35 }
36 if (isset($params['items']) && is_array($params['items']))
37 {
38 foreach ($params['items'] as [$item, $joiner])
39 {
40 if (!empty($item['field']))
41 {
42 $condition = new Condition($item);
43 $this->addItem($condition, $joiner);
44 }
45 }
46 }
47 }
48 }
49
54 public function evaluate(BaseTarget $target)
55 {
56 $documentType = $target->getDocumentType();
57 $documentId = $documentType;
58 $documentId[2] = $target->getDocumentId();
59
60 return $this->evaluateByDocument($documentType, $documentId);
61 }
62
69 public function evaluateByDocument(array $documentType, array $documentId, array $document = null): bool
70 {
71 if (empty($this->items))
72 {
73 return true;
74 }
75
76 if ($this->getType() === static::TYPE_MIXED)
77 {
78 throw new NotSupportedException('Mixed conditions can`t be evaluated by document only');
79 }
80
81 $documentService = \CBPRuntime::getRuntime(true)->getDocumentService();
82
83 if ($document === null)
84 {
85 $document = $documentService->getDocument($documentId, $documentType);
86 }
87
88 $result = [0 => true];
89 $i = 0;
90 $joiner = static::JOINER_AND;
91
92 $this->evaluateResults = [];
93
94 foreach ($this->items as $item)
95 {
97 $condition = $item[0];
98 $conditionField = $condition->getField();
99
100 $conditionResult = true;
101
102 $fld = $document[$conditionField] ?? null;
103 $fieldType = $this->getFieldTypeObject($documentService, $documentType, $conditionField);
104
105 if (!$condition->checkValue($fld, $fieldType, $documentId))
106 {
107 $conditionResult = false;
108 }
109
110 if ($joiner == static::JOINER_OR)
111 {
112 ++$i;
113 $result[$i] = $conditionResult;
114 }
115 elseif (!$conditionResult)
116 {
117 $result[$i] = false;
118 }
119
120 $this->evaluateResults[] = [
121 'condition' => $condition->toArray(),
122 'joiner' => $joiner,
123 'fieldValue' => $fld ? $fieldType->formatValue($fld) : null,
124 'result' => $conditionResult ? 'Y' : 'N',
125 ];
126
127 $joiner = ($item[1] === static::JOINER_OR) ? static::JOINER_OR : static::JOINER_AND;
128 }
129
130 return (count(array_filter($result)) > 0);
131 }
132
137 public function setType($type)
138 {
139 if ($type === static::TYPE_FIELD || $type === static::TYPE_MIXED)
140 {
141 $this->type = $type;
142 }
143 return $this;
144 }
145
149 public function getType()
150 {
151 return $this->type;
152 }
153
159 public function addItem(Condition $condition, $joiner = self::JOINER_AND)
160 {
161 $this->items[] = [$condition, $joiner];
162 return $this;
163 }
164
168 public function getItems()
169 {
170 return $this->items;
171 }
172
173 public function setActivityNames($activity)
174 {
175 $this->activityNames = [
176 'Activity' => $activity['Name'],
177 'Branch1' => $activity['Children'][0]['Name'],
178 'Branch2' => $activity['Children'][1]['Name'],
179 ];
180 }
181
182 public function getActivityNames(): array
183 {
184 if (isset($this->activityNames))
185 {
186 return $this->activityNames;
187 }
188
189 return [];
190 }
191
192 public function setActivated(bool $isActivated): void
193 {
194 $this->activated = $isActivated;
195 }
196
197 public function isActivated(): bool
198 {
199 return $this->activated;
200 }
201
205 public function toArray()
206 {
207 $itemsArray = [];
208
210 foreach ($this->getItems() as [$condition, $joiner])
211 {
212 $itemsArray[] = [$condition->toArray(), $joiner];
213 }
214
215 return [
216 'type' => $this->getType(),
217 'items' => $itemsArray,
218 'activityNames' => $this->getActivityNames(),
219 ];
220 }
221
228 public function createBizprocActivity(array $childActivity, array $documentType, Template $template)
229 {
230 $mixedCondition = [];
231 $bizprocJoiner = 0;
232
234 foreach ($this->getItems() as [$condition, $joiner])
235 {
236 $object = $condition->getObject();
237 $field = $condition->getField();
238 $value = $condition->getValue();
239 $property = $template->getProperty($object, $field);
240
241 $operator = $condition->getOperator();
242 $isOperatorWithValue = !in_array(
243 $operator,
244 [Bizproc\Activity\Operator\EmptyOperator::getCode(), Bizproc\Activity\Operator\NotEmptyOperator::getCode()],
245 true
246 );
247 if ($property && $isOperatorWithValue)
248 {
249 $fieldInputValueResult = $this->getFieldInputValue($property, $documentType, $condition);
250 if ($fieldInputValueResult->isSuccess())
251 {
252 $value = $fieldInputValueResult->getData()['value'];
253 }
254 }
255
256 $mixedCondition[] = [
257 'object' => $object,
258 'field' => $field,
259 'operator' => $condition->getOperator(),
260 'value' => self::unConvertExpressions($value, $documentType),
261 'joiner' => $bizprocJoiner,
262 ];
263 $bizprocJoiner = ($joiner === static::JOINER_OR) ? 1 : 0;
264 }
265
266 $title = Loc::getMessage('BIZPROC_AUTOMATION_CONDITION_TITLE');
267 $activated = $childActivity['Activated'] === 'N' ? 'N' : 'Y';
268 $activity = [
269 'Type' => 'IfElseActivity',
270 'Name' => Robot::generateName(),
271 'Activated' => $activated,
272 'Properties' => ['Title' => $title],
273 'Children' => [
274 [
275 'Type' => 'IfElseBranchActivity',
276 'Name' => Robot::generateName(),
277 'Properties' => [
278 'Title' => $title,
279 'mixedcondition' => $mixedCondition
280 ],
281 'Children' => [$childActivity],
282 'Activated' => $activated,
283 ],
284 [
285 'Type' => 'IfElseBranchActivity',
286 'Name' => Robot::generateName(),
287 'Properties' => [
288 'Title' => $title,
289 'truecondition' => '1',
290 ],
291 'Children' => [],
292 'Activated' => $activated,
293 ]
294 ]
295 ];
296
297 return $activity;
298 }
299
306 public static function convertBizprocActivity(array &$activity, array $documentType, Template $template)
307 {
308 $conditionGroup = false;
309
310 if (
311 count($activity['Children']) === 2
312 && $activity['Children'][0]['Type'] === 'IfElseBranchActivity'
313 && $activity['Children'][1]['Type'] === 'IfElseBranchActivity'
314 && (
315 !empty($activity['Children'][0]['Properties']['fieldcondition'])
316 ||
317 !empty($activity['Children'][0]['Properties']['mixedcondition'])
318 )
319 && !empty($activity['Children'][1]['Properties']['truecondition'])
320 && count($activity['Children'][0]['Children']) === 1
321 )
322 {
323 $conditionGroup = new static();
324 $conditionGroup->setType(static::TYPE_MIXED);
325 $conditionGroup->setActivityNames($activity);
326 $conditionGroup->setActivated(\CBPHelper::getBool($activity['Activated'] ?? true));
327
328 $isMixed = isset($activity['Children'][0]['Properties']['mixedcondition']);
329 $bizprocConditions = $activity['Children'][0]['Properties'][$isMixed?'mixedcondition':'fieldcondition'];
330
331 foreach ($bizprocConditions as $index => $condition)
332 {
333 if (!$isMixed)
334 {
335 $condition = self::convertDocumentCondition($condition);
336 }
337
338 $property = $template->getProperty($condition['object'], $condition['field']);
339 if ($property && $property['Type'] === 'user')
340 {
341 $condition['value'] = \CBPHelper::UsersArrayToString(
342 $condition['value'],
343 null,
344 $documentType
345 );
346 }
347
348 if ($property && $property['Type'] === 'time')
349 {
350 $offset = \CTimeZone::GetOffset();
351 $condition['value'] = array_map(
352 static fn($value) => Bizproc\BaseType\Value\Time::tryMakeCorrectFormat($value, $offset),
353 (array)$condition['value']
354 );
355 }
356
357 $conditionItem = new Condition(array(
358 'object' => $condition['object'],
359 'field' => $condition['field'],
360 'operator' => $condition['operator'],
361 'value' => self::convertExpressions($condition['value'], $documentType),
362 ));
363
364 $nextCondition = isset($bizprocConditions[$index + 1]) ? $bizprocConditions[$index + 1] : null;
365 $joiner = ($nextCondition && (!empty($nextCondition[3]) || !empty($nextCondition['joiner'])))
366 ? static::JOINER_OR : static::JOINER_AND;
367
368 $conditionGroup->addItem($conditionItem, $joiner);
369 }
370
371 $activity = $activity['Children'][0]['Children'][0];
372 }
373
374 return $conditionGroup;
375 }
376
377 private static function convertDocumentCondition(array $condition): array
378 {
379 return [
380 'object' => 'Document',
381 'field' => $condition[0],
382 'operator' => $condition[1],
383 'value' => $condition[2],
384 'joiner' => $condition[3],
385 ];
386 }
387
393 public function internalizeValues(array $documentType): self
394 {
395 $documentService = \CBPRuntime::GetRuntime(true)->getDocumentService();
396 $documentFields = $documentService->GetDocumentFields($documentType);
397
399 foreach ($this->getItems() as [$condition, $joiner])
400 {
401 $field = $condition->getField();
402 $value = $condition->getValue();
403 $property = $documentFields[$field] ?? null;
404 if ($property && !in_array($condition->getOperator(), ['empty', '!empty']))
405 {
406 $condition->setValue(self::unConvertExpressions($value, $documentType));
407 $fieldInputValueResult = $this->getFieldInputValue($property, $documentType, $condition);
408
409 $condition->setValue(
410 $fieldInputValueResult->isSuccess() ? $fieldInputValueResult->getData()['value'] : $value
411 );
412 }
413 }
414
415 $this->internalized = true;
416
417 return $this;
418 }
419
420 public function isInternalized(): bool
421 {
422 return $this->internalized;
423 }
424
430 public function externalizeValues(array $documentType): self
431 {
432 $documentService = \CBPRuntime::GetRuntime(true)->getDocumentService();
433 $documentFields = $documentService->GetDocumentFields($documentType);
434
436 foreach ($this->getItems() as [$condition, $joiner])
437 {
438 $field = $condition->getField();
439 $value = $condition->getValue();
440 $property = isset($documentFields[$field]) ? $documentFields[$field] : null;
441 if ($property && !in_array($condition->getOperator(), ['empty', '!empty']))
442 {
443 $value = self::convertExpressions($value, $documentType);
444 if ($property['Type'] === 'user')
445 {
446 $value = \CBPHelper::UsersArrayToString(
447 $value,
448 null,
449 $documentType
450 );
451 }
452 if ($property['Type'] === 'time')
453 {
454 $offset = \CTimeZone::GetOffset();
455 $value = array_map(
456 static fn($value) => Bizproc\BaseType\Value\Time::tryMakeCorrectFormat($value, $offset),
457 (array)$value
458 );
459 }
460
461 $condition->setValue($value);
462 }
463 }
464
465 $this->internalized = false;
466
467 return $this;
468 }
469
470 private static function convertExpressions($value, array $documentType)
471 {
472 if (is_array($value))
473 {
474 foreach ($value as $k => $v)
475 {
476 $value[$k] = self::convertExpressions($v, $documentType);
477 }
478 }
479 else
480 {
481 $value = Helper::convertExpressions($value, $documentType);
482 }
483 return $value;
484 }
485
486 private static function unConvertExpressions($value, array $documentType)
487 {
488 if (is_array($value))
489 {
490 foreach ($value as $k => $v)
491 {
492 $value[$k] = self::unConvertExpressions($v, $documentType);
493 }
494 }
495 else
496 {
497 $value = Helper::unConvertExpressions($value, $documentType);
498 }
499 return $value;
500 }
501
502 private function getFieldTypeObject(\CBPDocumentService $documentService, array $documentType, $conditionField): ?\Bitrix\Bizproc\FieldType
503 {
504 $documentFields = $documentService->getDocumentFields($documentType);
505
506 $fieldType = null;
507
508 if (isset($documentFields[$conditionField]))
509 {
510 $fieldType = $documentService->getFieldTypeObject($documentType, $documentFields[$conditionField]);
511 }
512
513 if (!$fieldType)
514 {
515 $fieldType = $documentService->getFieldTypeObject($documentType, ['Type' => 'string']);
516 }
517
518 return $fieldType;
519 }
520
521 public function getEvaluateResults(): array
522 {
524 }
525
526 private function getFieldInputValue(array $property, array $documentType, Condition $condition): \Bitrix\Main\Result
527 {
528 $documentService = \CBPRuntime::getRuntime()->getDocumentService();
529 $conditionValue = $condition->getValue();
530 $currentValues = ['field' => $conditionValue];
531 $errors = [];
532
533 $isBetweenOperator = $condition->getOperator() === Bizproc\Activity\Operator\BetweenOperator::getCode();
534 $valueInternal =
535 $isBetweenOperator
536 ? []
537 : $documentService->getFieldInputValue($documentType, $property, 'field', $currentValues,$errors)
538 ;
539 if ($isBetweenOperator)
540 {
541 $currentValues['field_greater_then'] =
542 is_array($conditionValue) && isset($conditionValue[0])
543 ? $conditionValue[0]
544 : $conditionValue
545 ;
546 $currentValues['field_less_then'] =
547 is_array($conditionValue) && isset($conditionValue[1])
548 ? $conditionValue[1]
549 : ''
550 ;
551 $property['Multiple'] = false;
552 $valueInternal1 = $documentService->getFieldInputValue(
553 $documentType,
554 $property,
555 'field_greater_then',
556 $currentValues,
557 $errors
558 );
559 $valueInternal2 = $documentService->getFieldInputValue(
560 $documentType,
561 $property,
562 'field_less_then',
563 $currentValues,
564 $errors
565 );
566
567 $valueInternal = [$valueInternal1 ?? '', $valueInternal2 ?? ''];
568 }
569
570 $result = new \Bitrix\Main\Result();
571 $result->setData(['value' => $valueInternal]);
572
573 if ($errors)
574 {
575 foreach ($errors as $error)
576 {
577 if (isset($error['message'], $error['code']))
578 {
579 $result->addError(new \Bitrix\Main\Error($error['message'], $error['code']));
580 }
581 }
582 }
583
584 return $result;
585 }
586}
static convertBizprocActivity(array &$activity, array $documentType, Template $template)
addItem(Condition $condition, $joiner=self::JOINER_AND)
static convertExpressions($source, array $documentType, $useTilda=true)
Definition helper.php:205
static unConvertExpressions($source, array $documentType)
Definition helper.php:287
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29