1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the Global Trading Technologies Ltd workflow-extension-bundle package. |
4
|
|
|
* |
5
|
|
|
* For the full copyright and license information, please view the LICENSE |
6
|
|
|
* file that was distributed with this source code. |
7
|
|
|
* |
8
|
|
|
* (c) fduch <[email protected]> |
9
|
|
|
* @date 03.08.16 |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Gtt\Bundle\WorkflowExtensionsBundle\Actions; |
13
|
|
|
|
14
|
|
|
use Gtt\Bundle\WorkflowExtensionsBundle\WorkflowContext; |
15
|
|
|
use Gtt\Bundle\WorkflowExtensionsBundle\WorkflowSubject\SubjectManipulator; |
16
|
|
|
use Symfony\Component\Workflow\Exception\LogicException as WorkflowLogicException; |
17
|
|
|
use Psr\Log\LoggerInterface; |
18
|
|
|
use Exception; |
19
|
|
|
use Throwable; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Applies workflow transitions |
23
|
|
|
*/ |
24
|
|
|
class TransitionApplier |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* Subject manipulator |
28
|
|
|
* |
29
|
|
|
* @var SubjectManipulator |
30
|
|
|
*/ |
31
|
|
|
private $subjectManipulator; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Logger |
35
|
|
|
* |
36
|
|
|
* @var LoggerInterface |
37
|
|
|
*/ |
38
|
|
|
private $logger; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* TransitionApplier constructor. |
42
|
|
|
* |
43
|
|
|
* @param SubjectManipulator $subjectManipulator subject manipulator |
44
|
|
|
* @param LoggerInterface $logger logger |
45
|
|
|
*/ |
46
|
|
|
public function __construct(SubjectManipulator $subjectManipulator, LoggerInterface $logger) |
47
|
|
|
{ |
48
|
|
|
$this->subjectManipulator = $subjectManipulator; |
49
|
|
|
$this->logger = $logger; |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Applies single transition |
54
|
|
|
* |
55
|
|
|
* @param WorkflowContext $workflowContext workflow context |
56
|
|
|
* @param string $transition transition to be applied |
57
|
|
|
*/ |
58
|
|
|
public function applyTransition(WorkflowContext $workflowContext, $transition) |
59
|
|
|
{ |
60
|
|
|
$this->applyTransitions($workflowContext, [$transition]); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Applies list of transitions |
65
|
|
|
* |
66
|
|
|
* @param WorkflowContext $workflowContext workflow context |
67
|
|
|
* @param array $transitions list of transitions to be applied |
68
|
|
|
* @param bool $cascade if this flag is set all the available transitions should be applied (it |
69
|
|
|
* may be cascade); otherwise the first applied transition breaks execution |
70
|
|
|
*/ |
71
|
|
|
public function applyTransitions(WorkflowContext $workflowContext, array $transitions = [], $cascade = false) |
72
|
|
|
{ |
73
|
|
|
if (!$transitions) { |
|
|
|
|
74
|
|
|
return; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
$workflow = $workflowContext->getWorkflow(); |
78
|
|
|
$subject = $workflowContext->getSubject(); |
79
|
|
|
$loggerContext = $workflowContext->getLoggerContext(); |
80
|
|
|
|
81
|
|
|
$this->logger->debug('Resolved workflow for subject', $loggerContext); |
82
|
|
|
|
83
|
|
|
$applied = false; |
84
|
|
|
foreach ($transitions as $transition) { |
85
|
|
|
try { |
86
|
|
|
// We do not call Workflow:can method here due to performance reasons in order to prevent |
87
|
|
|
// execution of all the doCan-listeners (guards) in case when transition can be applied. |
88
|
|
|
// Therefore we catch LogicException and interpreting it as case when transition can not be applied |
89
|
|
|
$workflow->apply($subject, $transition); |
90
|
|
|
$this->logger->info(sprintf('Workflow successfully applied transition "%s"', $transition), $loggerContext); |
91
|
|
|
$applied = true; |
92
|
|
|
if (!$cascade) { |
93
|
|
|
break; |
94
|
|
|
} |
95
|
|
|
} catch (WorkflowLogicException $e) { |
96
|
|
|
// transition cannot be applied because it is not allowed |
97
|
|
|
$this->logger->info( |
98
|
|
|
sprintf('Workflow transition "%s" cannot be applied due to it is not allowed', $transition), |
99
|
|
|
$loggerContext |
100
|
|
|
); |
101
|
|
|
} catch (Exception $e) { |
102
|
|
|
$this->logger->error( |
103
|
|
|
sprintf('Workflow cannot apply transition "%s" due to exception. Details: %s', $transition, $e->getMessage()), |
104
|
|
|
$loggerContext |
105
|
|
|
); |
106
|
|
|
throw $e; |
107
|
|
|
} catch (Throwable $e) { |
|
|
|
|
108
|
|
|
$this->logger->critical( |
109
|
|
|
sprintf('Workflow cannot apply transition "%s" due to error. Details: %s', $transition, $e->getMessage()), |
110
|
|
|
$loggerContext |
111
|
|
|
); |
112
|
|
|
throw $e; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
if (!$applied) { |
117
|
|
|
$this->logger->warning('All transitions to apply are not allowed', $loggerContext); |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.