GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — dev ( 37e84b...c7bcbf )
by Андрей
06:51
created

Transition::transitionWorkflow()   F

Complexity

Conditions 46
Paths > 20000

Size

Total Lines 227
Code Lines 129

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 77
CRAP Score 341.3005

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 227
ccs 77
cts 160
cp 0.4813
rs 2
cc 46
eloc 129
nc 5357666
nop 8
crap 341.3005

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @link https://github.com/old-town/old-town-workflow
4
 * @author  Malofeykin Andrey  <[email protected]>
5
 */
6
namespace OldTown\Workflow\Engine;
7
8
use OldTown\PropertySet\PropertySetInterface;
9
use OldTown\Workflow\Exception\InternalWorkflowException;
10
use OldTown\Workflow\Exception\InvalidInputException;
11
use OldTown\Workflow\Exception\StoreException;
12
use OldTown\Workflow\Exception\WorkflowException;
13
use OldTown\Workflow\JoinNodes;
14
use OldTown\Workflow\Loader\ActionDescriptor;
15
use OldTown\Workflow\Loader\ResultDescriptor;
16
use OldTown\Workflow\Loader\ValidatorDescriptor;
17
use OldTown\Workflow\Loader\WorkflowDescriptor;
18
use OldTown\Workflow\Spi\StepInterface;
19
use OldTown\Workflow\Spi\WorkflowEntryInterface;
20
use OldTown\Workflow\Spi\WorkflowStoreInterface;
21
use OldTown\Workflow\TransientVars\TransientVarsInterface;
22
use SplObjectStorage;
23
use DateTime;
24
use OldTown\Workflow\Exception\InvalidArgumentException;
25
26
27
/**
28
 * Class Transition
29
 *
30
 * @package OldTown\Workflow
31
 */
32
class Transition extends AbstractEngine implements TransitionInterface
33
{
34
    /**
35
     *
36
     * @var array
37
     */
38
    protected $stateCache = [];
39
40
    /**
41
     * Переход между двумя статусами
42
     *
43
     * @param WorkflowEntryInterface $entry
44
     * @param SplObjectStorage|StepInterface[] $currentSteps
45
     * @param WorkflowStoreInterface $store
46
     * @param WorkflowDescriptor $wf
47
     * @param ActionDescriptor $action
48
     * @param TransientVarsInterface $transientVars
49
     * @param TransientVarsInterface $inputs
50
     * @param PropertySetInterface $ps
51
     *
52
     * @return boolean
53
     *
54
     * @throws InternalWorkflowException
55
     */
56 18
    public function transitionWorkflow(WorkflowEntryInterface $entry, SplObjectStorage $currentSteps, WorkflowStoreInterface $store, WorkflowDescriptor $wf, ActionDescriptor $action, TransientVarsInterface $transientVars, TransientVarsInterface $inputs, PropertySetInterface $ps)
57
    {
58
        try {
59 18
            $step = $this->getCurrentStep($wf, $action->getId(), $currentSteps, $transientVars, $ps);
60
61 18
            $validators = $action->getValidators();
62 18
            if ($validators->count() > 0) {
63 3
                $this->verifyInputs($validators, $transientVars, $ps);
64 2
            }
65
66 17
            $workflowManager = $this->getWorkflowManager();
67 17
            $engineManager = $workflowManager->getEngineManager();
68 17
            $functionsEngine = $engineManager->getFunctionsEngine();
69
70 17
            if (null !== $step) {
71 6
                $stepPostFunctions = $wf->getStep($step->getStepId())->getPostFunctions();
72 6
                foreach ($stepPostFunctions as $function) {
73 1
                    $functionsEngine->executeFunction($function, $transientVars, $ps);
74 6
                }
75 6
            }
76
77 17
            $preFunctions = $action->getPreFunctions();
78 17
            foreach ($preFunctions as $preFunction) {
79 7
                $functionsEngine->executeFunction($preFunction, $transientVars, $ps);
80 17
            }
81
82 17
            $conditionalResults = $action->getConditionalResults();
83 17
            $extraPreFunctions = null;
84 17
            $extraPostFunctions = null;
85
86 17
            $theResult = null;
87
88
89
90 17
            $currentStepId = null !== $step ? $step->getStepId()  : -1;
91
92
93 17
            $conditionsEngine = $engineManager->getConditionsEngine();
94 17
            $log = $workflowManager->getLog();
95 17
            $context = $workflowManager->getContext();
96
97 17
            foreach ($conditionalResults as $conditionalResult) {
98 6
                if ($conditionsEngine->passesConditionsWithType(null, $conditionalResult->getConditions(), $transientVars, $ps, $currentStepId)) {
99 4
                    $theResult = $conditionalResult;
100
101 4
                    $validatorsStorage = $conditionalResult->getValidators();
102 4
                    if ($validatorsStorage->count() > 0) {
103 1
                        $this->verifyInputs($validatorsStorage, $transientVars, $ps);
104
                    }
105
106 3
                    $extraPreFunctions = $conditionalResult->getPreFunctions();
107 3
                    $extraPostFunctions = $conditionalResult->getPostFunctions();
108
109 3
                    break;
110
                }
111 17
            }
112
113
114 16
            if (null ===  $theResult) {
115 13
                $theResult = $action->getUnconditionalResult();
116 13
                $this->verifyInputs($theResult->getValidators(), $transientVars, $ps);
117 13
                $extraPreFunctions = $theResult->getPreFunctions();
118 15
                $extraPostFunctions = $theResult->getPostFunctions();
119 13
            }
120
121 16
            $logMsg = sprintf('theResult=%s %s', $theResult->getStep(), $theResult->getStatus());
122 16
            $log->debug($logMsg);
123
124
125 16
            if ($extraPreFunctions && $extraPreFunctions->count() > 0) {
126 3
                foreach ($extraPreFunctions as $function) {
127 2
                    $functionsEngine->executeFunction($function, $transientVars, $ps);
128 2
                }
129 2
            }
130
131 16
            $split = $theResult->getSplit();
132 16
            $join = $theResult->getJoin();
133 16
            if (null !== $split && 0 !== $split) {
134
                $splitDesc = $wf->getSplit($split);
135
                $results = $splitDesc->getResults();
136
                $splitPreFunctions = [];
137
                $splitPostFunctions = [];
138
139
                foreach ($results as $resultDescriptor) {
140
                    if ($resultDescriptor->getValidators()->count() > 0) {
141
                        $this->verifyInputs($resultDescriptor->getValidators(), $transientVars, $ps);
142
                    }
143
144
                    foreach ($resultDescriptor->getPreFunctions() as $function) {
145
                        $splitPreFunctions[] = $function;
146
                    }
147
                    foreach ($resultDescriptor->getPostFunctions() as $function) {
148
                        $splitPostFunctions[] = $function;
149
                    }
150
                }
151
152
                foreach ($splitPreFunctions as $function) {
153
                    $functionsEngine->executeFunction($function, $transientVars, $ps);
154
                }
155
156
                if (!$action->isFinish()) {
157
                    $moveFirst = true;
158
159
                    foreach ($results as $resultDescriptor) {
160
                        $moveToHistoryStep = null;
161
162 1
                        if ($moveFirst) {
163
                            $moveToHistoryStep = $step;
164
                        }
165
166
                        $previousIds = [];
167
168
                        if (null !== $step) {
169
                            $previousIds[] = $step->getStepId();
170
                        }
171
172
                        $this->createNewCurrentStep($resultDescriptor, $entry, $store, $action->getId(), $moveToHistoryStep, $previousIds, $transientVars, $ps);
173
                        $moveFirst = false;
174
                    }
175
                }
176
177
178
                foreach ($splitPostFunctions as $function) {
179
                    $functionsEngine->executeFunction($function, $transientVars, $ps);
180
                }
181 16
            } elseif (null !== $join && 0 !== $join) {
182
                $joinDesc = $wf->getJoin($join);
183
                $oldStatus = $theResult->getOldStatus();
184
                $caller = $context->getCaller();
185
                if (null !== $step) {
186
                    $step = $store->markFinished($step, $action->getId(), new DateTime(), $oldStatus, $caller);
187
                } else {
188
                    $errMsg = 'Invalid step';
189
                    throw new InternalWorkflowException($errMsg);
190
                }
191
192
193
                $store->moveToHistory($step);
194
195
                /** @var StepInterface[] $joinSteps */
196 1
                $joinSteps = [];
197
                $joinSteps[] = $step;
198
199
                $joinSteps = $this->buildJoinsSteps($currentSteps, $step, $wf, $join, $joinSteps);
200
201
                $historySteps = $store->findHistorySteps($entry->getId());
202
203
                $joinSteps = $this->buildJoinsSteps($historySteps, $step, $wf, $join, $joinSteps);
204
205
206
                $jn = new JoinNodes($joinSteps);
207
                $transientVars['jn'] = $jn;
208
209
210
                if ($conditionsEngine->passesConditionsWithType(null, $joinDesc->getConditions(), $transientVars, $ps, 0)) {
211
                    $joinResult = $joinDesc->getResult();
212
213
                    $joinResultValidators = $joinResult->getValidators();
214
                    if ($joinResultValidators->count() > 0) {
215
                        $this->verifyInputs($joinResultValidators, $transientVars, $ps);
216
                    }
217
218
                    foreach ($joinResult->getPreFunctions() as $function) {
219
                        $functionsEngine->executeFunction($function, $transientVars, $ps);
220
                    }
221
222
                    $previousIds = [];
223
                    $i = 1;
224
225
                    foreach ($joinSteps as  $currentJoinStep) {
226
                        if (!$historySteps->contains($currentJoinStep) && $currentJoinStep->getId() !== $step->getId()) {
227
                            $store->moveToHistory($step);
228
                        }
229
230
                        $previousIds[$i] = $currentJoinStep->getId();
231
                    }
232
233
                    if (!$action->isFinish()) {
234
                        $previousIds[0] = $step->getId();
235
                        $theResult = $joinDesc->getResult();
236
237
                        $this->createNewCurrentStep($theResult, $entry, $store, $action->getId(), null, $previousIds, $transientVars, $ps);
238
                    }
239
240
                    foreach ($joinResult->getPostFunctions() as $function) {
241
                        $functionsEngine->executeFunction($function, $transientVars, $ps);
242
                    }
243
                }
244
            } else {
245 16
                $previousIds = [];
246
247 16
                if (null !== $step) {
248 5
                    $previousIds[] = $step->getId();
249 5
                }
250
251 16
                if (!$action->isFinish()) {
252 16
                    $this->createNewCurrentStep($theResult, $entry, $store, $action->getId(), $step, $previousIds, $transientVars, $ps);
253 16
                }
254
            }
255
256 16
            if ($extraPostFunctions && $extraPostFunctions->count() > 0) {
257 2
                foreach ($extraPostFunctions as $function) {
258 2
                    $functionsEngine->executeFunction($function, $transientVars, $ps);
259 2
                }
260 2
            }
261
262 16
            if (WorkflowEntryInterface::COMPLETED !== $entry->getState() && null !== $wf->getInitialAction($action->getId())) {
263 16
                $workflowManager->changeEntryState($entry->getId(), WorkflowEntryInterface::ACTIVATED);
264 16
            }
265
266 16
            if ($action->isFinish()) {
267
                $entryEngine = $engineManager->getEntryEngine();
268
                $entryEngine->completeEntry($action, $entry->getId(), $workflowManager->getCurrentSteps($entry->getId()), WorkflowEntryInterface::COMPLETED);
269
                return true;
270
            }
271
272 16
            $availableAutoActions = $this->getAvailableAutoActions($entry->getId(), $inputs);
273
274 16
            if (count($availableAutoActions) > 0) {
275
                $workflowManager->doAction($entry->getId(), $availableAutoActions[0], $inputs);
276
            }
277
278 16
            return false;
279 3
        } catch (\Exception $e) {
280 3
            throw new InternalWorkflowException($e->getMessage(), $e->getCode(), $e);
281
        }
282
    }
283
284
285
    /**
286
     * @param ResultDescriptor       $theResult
287
     * @param WorkflowEntryInterface $entry
288
     * @param WorkflowStoreInterface $store
289
     * @param integer                $actionId
290
     * @param StepInterface          $currentStep
291
     * @param array                  $previousIds
292
     * @param TransientVarsInterface                  $transientVars
293
     * @param PropertySetInterface   $ps
294
     *
295
     * @return StepInterface
296
     *
297
     * @throws InternalWorkflowException
298
     * @throws StoreException
299
     * @throws \OldTown\Workflow\Exception\ArgumentNotNumericException
300
     * @throws WorkflowException
301
     */
302 16
    protected function createNewCurrentStep(
303
        ResultDescriptor $theResult,
304
        WorkflowEntryInterface $entry,
305
        WorkflowStoreInterface $store,
306
        $actionId,
307
        StepInterface $currentStep = null,
308
        array $previousIds = [],
309
        TransientVarsInterface $transientVars,
310
        PropertySetInterface $ps
311
    ) {
312 16
        $workflowManager = $this->getWorkflowManager();
313 16
        $context = $workflowManager->getContext();
314
315
316
        try {
317 16
            $nextStep = $theResult->getStep();
318
319 16
            if (-1 === $nextStep) {
320
                if (null !== $currentStep) {
321
                    $nextStep = $currentStep->getStepId();
322
                } else {
323
                    $errMsg = 'Неверный аргумент. Новый шаг является таким же как текущий. Но текущий шаг не указан';
324
                    throw new StoreException($errMsg);
325
                }
326
            }
327
328 16
            $owner = $theResult->getOwner();
329
330 16
            $logMsg = sprintf(
331 16
                'Результат: stepId=%s, status=%s, owner=%s, actionId=%s, currentStep=%s',
332 16
                $nextStep,
333 16
                $theResult->getStatus(),
334 16
                $owner,
335 16
                $actionId,
336 16
                null !== $currentStep ? $currentStep->getId() : 0
337 16
            );
338
339 16
            $log = $workflowManager->getLog();
340
341
342 16
            $log->debug($logMsg);
343
344 16
            $variableResolver = $workflowManager->getConfiguration()->getVariableResolver();
345
346 16
            if (null !== $owner) {
347
                $o = $variableResolver->translateVariables($owner, $transientVars, $ps);
348
                $owner = null !== $o ? (string)$o : null;
349
            }
350
351
352 16
            $oldStatus = $theResult->getOldStatus();
353 16
            $oldStatus = (string)$variableResolver->translateVariables($oldStatus, $transientVars, $ps);
354
355 16
            $status = $theResult->getStatus();
356 16
            $status = (string)$variableResolver->translateVariables($status, $transientVars, $ps);
357
358
359 16
            if (null !== $currentStep) {
360 5
                $store->markFinished($currentStep, $actionId, new DateTime(), $oldStatus, $context->getCaller());
361 5
                $store->moveToHistory($currentStep);
362 5
            }
363
364 16
            $startDate = new DateTime();
365 16
            $dueDate = null;
366
367 16
            $theResultDueDate = (string)$theResult->getDueDate();
368 16
            $theResultDueDate = trim($theResultDueDate);
369 16
            if (strlen($theResultDueDate) > 0) {
370
                $dueDateObject = $variableResolver->translateVariables($theResultDueDate, $transientVars, $ps);
371
372
                if ($dueDateObject instanceof DateTime) {
373
                    $dueDate = $dueDateObject;
374
                } elseif (is_string($dueDateObject)) {
375
                    $dueDate = new DateTime($dueDate);
376
                } elseif (is_numeric($dueDateObject)) {
377
                    $dueDate = DateTime::createFromFormat('U', $dueDateObject);
378
                    if (false === $dueDate) {
379
                        $errMsg = 'Invalid due date conversion';
380
                        throw new InternalWorkflowException($errMsg);
381
                    }
382
                }
383
            }
384
385 16
            $newStep = $store->createCurrentStep($entry->getId(), $nextStep, $owner, $startDate, $dueDate, $status, $previousIds);
386 16
            $transientVars['createdStep'] =  $newStep;
387
388 16
            if (null === $currentStep && 0 === count($previousIds)) {
389 16
                $currentSteps = [];
390 16
                $currentSteps[] = $newStep;
391 16
                $transientVars['currentSteps'] =  $currentSteps;
392 16
            }
393
394 16
            if (! $transientVars->offsetExists('descriptor')) {
395
                $errMsg = 'Ошибка при получение дескриптора workflow из transientVars';
396
                throw new InternalWorkflowException($errMsg);
397
            }
398
399
            /** @var WorkflowDescriptor $descriptor */
400 16
            $descriptor = $transientVars['descriptor'];
401 16
            $step = $descriptor->getStep($nextStep);
402
403 16
            if (null === $step) {
404
                $errMsg = sprintf('Шаг #%s не найден', $nextStep);
405
                throw new WorkflowException($errMsg);
406
            }
407
408 16
            $preFunctions = $step->getPreFunctions();
409
410 16
            $functionsEngine = $workflowManager->getEngineManager()->getFunctionsEngine();
411 16
            foreach ($preFunctions as $function) {
412
                $functionsEngine->executeFunction($function, $transientVars, $ps);
413 16
            }
414 16
        } catch (WorkflowException $e) {
415
            $context->setRollbackOnly();
416
            /** @var WorkflowException $e */
417
            throw $e;
418
        }
419 16
    }
420
421
422
    /**
423
     *
424
     * Возвращает текущий шаг
425
     *
426
     * @param WorkflowDescriptor $wfDesc
427
     * @param integer $actionId
428
     * @param StepInterface[]|SplObjectStorage $currentSteps
429
     * @param TransientVarsInterface $transientVars
430
     * @param PropertySetInterface $ps
431
     *
432
     * @return StepInterface
433
     *
434
     * @throws \OldTown\Workflow\Exception\ArgumentNotNumericException
435
     * @throws InternalWorkflowException
436
     */
437 18
    protected function getCurrentStep(WorkflowDescriptor $wfDesc, $actionId, SplObjectStorage $currentSteps, TransientVarsInterface $transientVars, PropertySetInterface $ps)
438
    {
439 18
        if (1 === $currentSteps->count()) {
440 6
            $currentSteps->rewind();
441 6
            return $currentSteps->current();
442
        }
443
444
445 18
        foreach ($currentSteps as $step) {
446
            $stepId = $step->getId();
447
            $action = $wfDesc->getStep($stepId)->getAction($actionId);
448
449
            if ($this->isActionAvailable($action, $transientVars, $ps, $stepId)) {
450
                return $step;
451
            }
452 18
        }
453
454 18
        return null;
455
    }
456
457
458
    /**
459
     * @param $validatorsStorage
460
     * @param TransientVarsInterface $transientVars
461
     * @param PropertySetInterface $ps
462
     *
463
     * @throws InvalidInputException
464
     * @throws WorkflowException
465
     */
466 18
    protected function verifyInputs($validatorsStorage, TransientVarsInterface $transientVars, PropertySetInterface $ps)
467
    {
468 15
        $workflowManager = $this->getWorkflowManager();
469 15
        $engineManager = $workflowManager->getEngineManager();
470 15
        $argsEngine = $engineManager->getArgsEngine();
471 15
        $dataEngine = $engineManager->getDataEngine();
472
473
474 15
        $validators = $dataEngine->convertDataInArray($validatorsStorage);
475
476
477 15
        $resolver = $workflowManager->getResolver();
478
479
        /** @var ValidatorDescriptor[] $validators */
480 15
        foreach ($validators as $input) {
481 6
            if (null !== $input) {
482 6
                $type = $input->getType();
483 6
                $argsOriginal = $input->getArgs();
484
485 6
                $args = $argsEngine->prepareArgs($argsOriginal, $transientVars, $ps);
486
487
488 18
                $validator = $resolver->getValidator($type, $args);
489
490 6
                if (null === $validator) {
491
                    $workflowManager->getContext()->setRollbackOnly();
492
                    $errMsg = 'Ошибка при загрузке валидатора';
493
                    throw new WorkflowException($errMsg);
494
                }
495
496
                try {
497 6
                    $validator->validate($transientVars, $args, $ps);
498 6
                } catch (InvalidInputException $e) {
499
                    /** @var  InvalidInputException $e*/
500
                    throw $e;
501 2
                } catch (\Exception $e) {
502 2
                    $workflowManager->getContext()->setRollbackOnly();
503
504 2
                    if ($e instanceof WorkflowException) {
505
                        /** @var  WorkflowException $e*/
506
                        throw $e;
507
                    }
508
509 2
                    throw new WorkflowException($e->getMessage(), $e->getCode(), $e);
510
                }
511 4
            }
512 13
        }
513 13
    }
514
515
516
    /**
517
     * Подготавливает данные о шагах используемых в объеденение
518
     *
519
     * @param StepInterface[]|SplObjectStorage    $steps
520
     * @param StepInterface      $step
521
     * @param WorkflowDescriptor $wf
522
     * @param integer            $join
523
     *
524
     * @param array              $joinSteps
525
     *
526
     * @return array
527
     *
528
     * @throws \OldTown\Workflow\Exception\ArgumentNotNumericException
529
     */
530
    protected function buildJoinsSteps($steps, StepInterface $step, WorkflowDescriptor $wf, $join, array $joinSteps = [])
531
    {
532
        foreach ($steps as $currentStep) {
533
            if ($currentStep->getId() !== $step->getId()) {
534
                $stepDesc = $wf->getStep($currentStep->getStepId());
535
536
                if ($stepDesc->resultsInJoin($join)) {
537
                    $joinSteps[] = $currentStep;
538
                }
539
            }
540
        }
541
542
        return $joinSteps;
543
    }
544
545
546
    /**
547
     * @param       $id
548
     * @param TransientVarsInterface $inputs
549
     *
550
     * @return array
551
     */
552 16
    protected function getAvailableAutoActions($id, TransientVarsInterface $inputs)
553
    {
554 16
        $workflowManager = $this->getWorkflowManager();
555
        try {
556 16
            $configurations = $workflowManager->getConfiguration();
557 16
            $store = $configurations->getWorkflowStore();
558
559 16
            $entry = $store->findEntry($id);
560
561 16
            if (null === $entry) {
562
                $errMsg = sprintf(
563
                    'Нет сущности workflow c id %s',
564
                    $id
565
                );
566
                throw new InvalidArgumentException($errMsg);
567
            }
568
569
570 16
            if (WorkflowEntryInterface::ACTIVATED !== $entry->getState()) {
571
                $logMsg = sprintf('--> состояние %s', $entry->getState());
572
                $workflowManager->getLog()->debug($logMsg);
573
                return [0];
574
            }
575
576 16
            $wf = $configurations->getWorkflow($entry->getWorkflowName());
577
578 16
            $l = [];
579 16
            $ps = $store->getPropertySet($id);
580 16
            $transientVars = $inputs;
581 16
            $currentSteps = $store->findCurrentSteps($id);
582
583 16
            $workflowManager->getEngineManager()->getDataEngine()->populateTransientMap($entry, $transientVars, $wf->getRegisters(), 0, $currentSteps, $ps);
584
585 16
            $globalActions = $wf->getGlobalActions();
586
587 16
            $l = $this->buildListIdsAvailableActions($globalActions, $transientVars, $ps, $l);
588
589 16
            foreach ($currentSteps as $step) {
590 16
                $availableAutoActionsForStep = $this->getAvailableAutoActionsForStep($wf, $step, $transientVars, $ps);
591
                foreach ($availableAutoActionsForStep as $v) {
592
                    $l[] = $v;
593
                }
594
            }
595
596
            $l = array_unique($l);
597
598
            return $l;
599 16
        } catch (\Exception $e) {
600 16
            $errMsg = 'Ошибка при проверке доступных действий';
601 16
            $workflowManager->getLog()->error($errMsg, [$e]);
602
        }
603
604 16
        return [];
605
    }
606
607
608
    /**
609
     * @param WorkflowDescriptor   $wf
610
     * @param StepInterface        $step
611
     * @param TransientVarsInterface                $transientVars
612
     * @param PropertySetInterface $ps
613
     *
614
     * @return array
615
     *
616
     * @throws \OldTown\Workflow\Exception\ArgumentNotNumericException
617
     * @throws InternalWorkflowException
618
     * @throws WorkflowException
619
     */
620 16
    protected function getAvailableAutoActionsForStep(WorkflowDescriptor $wf, StepInterface $step, TransientVarsInterface $transientVars, PropertySetInterface $ps)
621
    {
622 16
        $l = [];
623 16
        $s = $wf->getStep($step->getStepId());
624
625 16
        if (null === $s) {
626
            $msg = sprintf('getAvailableAutoActionsForStep вызвана с несуществующим id %s', $step->getStepId());
627
            $this->getWorkflowManager()->getLog()->debug($msg);
628
            return $l;
629
        }
630
631
632 16
        $actions = $s->getActions();
633 16
        if (null === $actions || 0 === $actions->count()) {
634
            return $l;
635
        }
636
637 16
        $l = $this->buildListIdsAvailableActions($actions, $transientVars, $ps, $l);
638
639
        return $l;
640
    }
641
642
643
    /**
644
     * Подготавливает список id действий в workflow
645
     *
646
     * @param ActionDescriptor[]|SplObjectStorage     $actions
647
     * @param TransientVarsInterface $transientVars
648
     * @param PropertySetInterface   $ps
649
     * @param array                  $storage
650
     *
651
     * @return array
652
     *
653
     * @throws InternalWorkflowException
654
     * @throws WorkflowException
655
     */
656 16
    protected function buildListIdsAvailableActions($actions, TransientVarsInterface $transientVars, PropertySetInterface $ps, array $storage = [])
657
    {
658 16
        foreach ($actions as $action) {
659 16
            if ($action instanceof ActionDescriptor) {
660 16
                $errMsg = sprintf('Invalid workflow action. Action not implement %s', ActionDescriptor::class);
661 16
                throw new InternalWorkflowException($errMsg);
662
            }
663
            $transientVars['actionId'] = $action->getId();
664
665
            if ($action->getAutoExecute() && $this->isActionAvailable($action, $transientVars, $ps, 0)) {
666
                $storage[] = $action->getId();
667
            }
668 16
        }
669
670 16
        return $storage;
671
    }
672
673
674
    /**
675
     *
676
     * @param ActionDescriptor|null $action
677
     * @param TransientVarsInterface $transientVars
678
     * @param PropertySetInterface $ps
679
     * @param $stepId
680
     *
681
     * @return boolean
682
     *
683
     * @throws InternalWorkflowException
684
     */
685 8
    public function isActionAvailable(ActionDescriptor $action = null, TransientVarsInterface $transientVars, PropertySetInterface $ps, $stepId)
686
    {
687 8
        if (null === $action) {
688
            return false;
689
        }
690
691 8
        $result = null;
692 8
        $actionHash = spl_object_hash($action);
693
694 8
        $result = array_key_exists($actionHash, $this->stateCache) ? $this->stateCache[$actionHash] : $result;
695
696 8
        $wf = $this->getWorkflowDescriptorForAction($action);
697
698 8
        $conditionsEngine = $this->getWorkflowManager()->getEngineManager()->getConditionsEngine();
699 8
        if (null === $result) {
700 8
            $restriction = $action->getRestriction();
701 8
            $conditions = null;
702
703 8
            if (null !== $restriction) {
704 5
                $conditions = $restriction->getConditionsDescriptor();
705 5
            }
706
707 8
            $result = $conditionsEngine->passesConditionsByDescriptor($wf->getGlobalConditions(), $transientVars, $ps, $stepId)
708 8
                && $conditionsEngine->passesConditionsByDescriptor($conditions, $transientVars, $ps, $stepId);
709
710 8
            $this->stateCache[$actionHash] = $result;
711 8
        }
712
713
714 8
        $result = (boolean)$result;
715
716 8
        return $result;
717
    }
718
719
720
721
    /**
722
     *
723
     * По дейсвтию получаем дексрипторв workflow
724
     *
725
     * @param ActionDescriptor $action
726
     *
727
     * @return WorkflowDescriptor
728
     *
729
     * @throws InternalWorkflowException
730
     */
731 8
    private function getWorkflowDescriptorForAction(ActionDescriptor $action)
732
    {
733 8
        $objWfd = $action;
734
735 8
        $count = 0;
736 8
        while (!$objWfd instanceof WorkflowDescriptor || null === $objWfd) {
737 8
            $objWfd = $objWfd->getParent();
738
739 8
            $count++;
740 8
            if ($count > 10) {
741
                $errMsg = 'Ошибка при получение WorkflowDescriptor';
742
                throw new InternalWorkflowException($errMsg);
743
            }
744 8
        }
745
746 8
        return $objWfd;
747
    }
748
}
749