1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* (c) 2019, Wesley O. Nichols |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Wesnick\WorkflowBundle; |
13
|
|
|
|
14
|
|
|
use ApiPlatform\Core\Api\IriConverterInterface; |
15
|
|
|
use ApiPlatform\Core\Api\UrlGeneratorInterface; |
16
|
|
|
use Symfony\Component\Validator\ConstraintViolation; |
17
|
|
|
use Symfony\Component\Workflow\Registry; |
18
|
|
|
use Symfony\Component\Workflow\Transition; |
19
|
|
|
use Wesnick\WorkflowBundle\Model\Action; |
20
|
|
|
use Wesnick\WorkflowBundle\Model\EntryPoint; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Class WorkflowActionGenerator. |
24
|
|
|
* |
25
|
|
|
* @author Wesley O. Nichols <[email protected]> |
26
|
|
|
*/ |
27
|
|
|
class WorkflowActionGenerator |
28
|
|
|
{ |
29
|
|
|
private $registry; |
30
|
|
|
private $iriConverter; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* Classmap. |
34
|
|
|
* |
35
|
|
|
* [ className => [workflowName]] |
36
|
|
|
* |
37
|
|
|
* @var array |
38
|
|
|
*/ |
39
|
|
|
private $enabledWorkflowMap; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* WorkflowActionGenerator constructor. |
43
|
|
|
* |
44
|
|
|
* @param $registry |
45
|
|
|
* @param $iriConverter |
46
|
|
|
* @param array $enabledWorkflowMap |
47
|
|
|
*/ |
48
|
|
|
public function __construct(Registry $registry, IriConverterInterface $iriConverter, array $enabledWorkflowMap) |
49
|
|
|
{ |
50
|
|
|
$this->registry = $registry; |
51
|
|
|
$this->iriConverter = $iriConverter; |
52
|
|
|
$this->enabledWorkflowMap = $enabledWorkflowMap; |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
public function getActionsForSubject($subject) |
56
|
|
|
{ |
57
|
|
|
$workflows = $this->registry->all($subject); |
58
|
|
|
$actions = []; |
59
|
|
|
|
60
|
|
|
foreach ($workflows as $workflow) { |
61
|
|
|
|
62
|
|
|
$possibleTransitions = []; |
63
|
|
|
$marking = $workflow->getMarking($subject); |
64
|
|
|
|
65
|
|
|
foreach ($workflow->getDefinition()->getTransitions() as $transition) { |
66
|
|
|
$froms = array_flip($transition->getFroms()); |
67
|
|
|
$intersection = array_intersect_key($froms, $marking->getPlaces()); |
68
|
|
|
if ($intersection) { |
|
|
|
|
69
|
|
|
$possibleTransitions[] = $transition; |
70
|
|
|
} |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
foreach ($possibleTransitions as $transition) { |
74
|
|
|
$transitionBlockerList = $workflow->buildTransitionBlockerList($subject, $transition->getName()); |
75
|
|
|
|
76
|
|
|
$transitionMeta = $workflow->getMetadataStore()->getTransitionMetadata($transition); |
77
|
|
|
|
78
|
|
|
$url = sprintf( |
79
|
|
|
'%s?%s', |
80
|
|
|
$this->iriConverter->getIriFromItem($subject, UrlGeneratorInterface::ABS_URL), |
81
|
|
|
http_build_query([ |
82
|
|
|
'workflow' => $workflow->getName(), |
83
|
|
|
'transition' => $transition->getName(), |
84
|
|
|
]) |
85
|
|
|
); |
86
|
|
|
|
87
|
|
|
$entryPoint = new EntryPoint(); |
88
|
|
|
$entryPoint->setUrl($url); |
89
|
|
|
$entryPoint->setHttpMethod('PATCH'); |
90
|
|
|
|
91
|
|
|
$currentAction = new Action(); |
92
|
|
|
$currentAction->setTarget($entryPoint); |
93
|
|
|
$currentAction->setName($transition->getName()); |
94
|
|
|
$currentAction->setDescription($transitionMeta['description'] ?? ucfirst($transition->getName()).' Action'); |
95
|
|
|
// @TODO: add sub status (available, unavailable, access denied, invalid) |
96
|
|
|
|
97
|
|
|
foreach ($transitionBlockerList as $blocker) { |
98
|
|
|
$parameters = $blocker->getParameters(); |
99
|
|
|
|
100
|
|
|
if (array_key_exists('original_violation', $parameters)) { |
101
|
|
|
$violation = $parameters['original_violation']; |
102
|
|
|
} else { |
103
|
|
|
// @TODO: add a factory or event for building Violations from TransitionBlockers |
104
|
|
|
$violation = new ConstraintViolation( |
105
|
|
|
$blocker->getMessage(), |
106
|
|
|
$blocker->getMessage(), |
107
|
|
|
$blocker->getParameters(), |
108
|
|
|
$subject, |
109
|
|
|
'/', |
110
|
|
|
'' |
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
$currentAction->addError($violation); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$actions[] = $currentAction; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
return $actions; |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
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.