|
19 | 19 | use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; |
20 | 20 | use Symfony\Component\VarDumper\Caster\Caster; |
21 | 21 | use Symfony\Component\VarDumper\Cloner\Stub; |
| 22 | +use Symfony\Component\Workflow\Debug\ListenerExtractor; |
22 | 23 | use Symfony\Component\Workflow\Debug\TraceableWorkflow; |
23 | 24 | use Symfony\Component\Workflow\Dumper\MermaidDumper; |
24 | | -use Symfony\Component\Workflow\EventListener\GuardExpression; |
25 | | -use Symfony\Component\Workflow\EventListener\GuardListener; |
26 | 25 | use Symfony\Component\Workflow\Marking; |
27 | | -use Symfony\Component\Workflow\Transition; |
28 | 26 | use Symfony\Component\Workflow\TransitionBlocker; |
29 | 27 | use Symfony\Component\Workflow\WorkflowInterface; |
30 | 28 |
|
|
33 | 31 | */ |
34 | 32 | final class WorkflowDataCollector extends DataCollector implements LateDataCollectorInterface |
35 | 33 | { |
| 34 | + private readonly ListenerExtractor $listenerExtractor; |
| 35 | + |
36 | 36 | public function __construct( |
37 | 37 | private readonly iterable $workflows, |
38 | | - private readonly EventDispatcherInterface $eventDispatcher, |
39 | | - private readonly FileLinkFormatter $fileLinkFormatter, |
| 38 | + EventDispatcherInterface $eventDispatcher, |
| 39 | + ?FileLinkFormatter $fileLinkFormatter = null, |
40 | 40 | ) { |
| 41 | + $this->listenerExtractor = new ListenerExtractor($eventDispatcher, $fileLinkFormatter); |
41 | 42 | } |
42 | 43 |
|
43 | 44 | public function collect(Request $request, Response $response, ?\Throwable $exception = null): void |
@@ -130,112 +131,21 @@ protected function getCasters(): array |
130 | 131 |
|
131 | 132 | private function getEventListeners(WorkflowInterface $workflow): array |
132 | 133 | { |
133 | | - $listeners = []; |
| 134 | + $listeners = $this->listenerExtractor->extractListeners($workflow->getName(), $workflow->getDefinition()); |
| 135 | + $normalizedListeners = []; |
134 | 136 | $placeId = 0; |
135 | | - foreach ($workflow->getDefinition()->getPlaces() as $place) { |
136 | | - $eventNames = []; |
137 | | - $subEventNames = [ |
138 | | - 'leave', |
139 | | - 'enter', |
140 | | - 'entered', |
141 | | - ]; |
142 | | - foreach ($subEventNames as $subEventName) { |
143 | | - $eventNames[] = \sprintf('workflow.%s', $subEventName); |
144 | | - $eventNames[] = \sprintf('workflow.%s.%s', $workflow->getName(), $subEventName); |
145 | | - $eventNames[] = \sprintf('workflow.%s.%s.%s', $workflow->getName(), $subEventName, $place); |
146 | | - } |
147 | | - foreach ($eventNames as $eventName) { |
148 | | - foreach ($this->eventDispatcher->getListeners($eventName) as $listener) { |
149 | | - $listeners["place{$placeId}"][$eventName][] = $this->summarizeListener($listener); |
150 | | - } |
| 137 | + foreach ($workflow->getDefinition()->getPlaces() as $k => $_) { |
| 138 | + if (\array_key_exists('place__'.$k, $listeners)) { |
| 139 | + $normalizedListeners["place{$placeId}"] = $listeners['place__'.$k]; |
151 | 140 | } |
152 | | - |
153 | 141 | ++$placeId; |
154 | 142 | } |
155 | | - |
156 | | - foreach ($workflow->getDefinition()->getTransitions() as $transitionId => $transition) { |
157 | | - $eventNames = []; |
158 | | - $subEventNames = [ |
159 | | - 'guard', |
160 | | - 'transition', |
161 | | - 'completed', |
162 | | - 'announce', |
163 | | - ]; |
164 | | - foreach ($subEventNames as $subEventName) { |
165 | | - $eventNames[] = \sprintf('workflow.%s', $subEventName); |
166 | | - $eventNames[] = \sprintf('workflow.%s.%s', $workflow->getName(), $subEventName); |
167 | | - $eventNames[] = \sprintf('workflow.%s.%s.%s', $workflow->getName(), $subEventName, $transition->getName()); |
168 | | - } |
169 | | - foreach ($eventNames as $eventName) { |
170 | | - foreach ($this->eventDispatcher->getListeners($eventName) as $listener) { |
171 | | - $listeners["transition{$transitionId}"][$eventName][] = $this->summarizeListener($listener, $eventName, $transition); |
172 | | - } |
173 | | - } |
174 | | - } |
175 | | - |
176 | | - return $listeners; |
177 | | - } |
178 | | - |
179 | | - private function summarizeListener(callable $callable, ?string $eventName = null, ?Transition $transition = null): array |
180 | | - { |
181 | | - $extra = []; |
182 | | - |
183 | | - if ($callable instanceof \Closure) { |
184 | | - $r = new \ReflectionFunction($callable); |
185 | | - if ($r->isAnonymous()) { |
186 | | - $title = (string) $r; |
187 | | - } elseif ($class = $r->getClosureCalledClass()) { |
188 | | - $title = $class->name.'::'.$r->name.'()'; |
189 | | - } else { |
190 | | - $title = $r->name; |
191 | | - } |
192 | | - } elseif (\is_string($callable)) { |
193 | | - $title = $callable.'()'; |
194 | | - $r = new \ReflectionFunction($callable); |
195 | | - } elseif (\is_object($callable) && method_exists($callable, '__invoke')) { |
196 | | - $r = new \ReflectionMethod($callable, '__invoke'); |
197 | | - $title = $callable::class.'::__invoke()'; |
198 | | - } elseif (\is_array($callable)) { |
199 | | - if ($callable[0] instanceof GuardListener) { |
200 | | - if (null === $eventName || null === $transition) { |
201 | | - throw new \LogicException('Missing event name or transition.'); |
202 | | - } |
203 | | - $extra['guardExpressions'] = $this->extractGuardExpressions($callable[0], $eventName, $transition); |
204 | | - } |
205 | | - $r = new \ReflectionMethod($callable[0], $callable[1]); |
206 | | - $title = (\is_string($callable[0]) ? $callable[0] : \get_class($callable[0])).'::'.$callable[1].'()'; |
207 | | - } else { |
208 | | - throw new \RuntimeException('Unknown callable type.'); |
209 | | - } |
210 | | - |
211 | | - $file = null; |
212 | | - if ($r->isUserDefined()) { |
213 | | - $file = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); |
214 | | - } |
215 | | - |
216 | | - return [ |
217 | | - 'title' => $title, |
218 | | - 'file' => $file, |
219 | | - ...$extra, |
220 | | - ]; |
221 | | - } |
222 | | - |
223 | | - private function extractGuardExpressions(GuardListener $listener, string $eventName, Transition $transition): array |
224 | | - { |
225 | | - $configuration = (new \ReflectionProperty(GuardListener::class, 'configuration'))->getValue($listener); |
226 | | - |
227 | | - $expressions = []; |
228 | | - foreach ($configuration[$eventName] as $guard) { |
229 | | - if ($guard instanceof GuardExpression) { |
230 | | - if ($guard->getTransition() !== $transition) { |
231 | | - continue; |
232 | | - } |
233 | | - $expressions[] = $guard->getExpression(); |
234 | | - } else { |
235 | | - $expressions[] = $guard; |
| 143 | + foreach ($workflow->getDefinition()->getTransitions() as $k => $_) { |
| 144 | + if (\array_key_exists('transition__'.$k, $listeners)) { |
| 145 | + $normalizedListeners["transition$k"] = $listeners['transition__'.$k]; |
236 | 146 | } |
237 | 147 | } |
238 | 148 |
|
239 | | - return $expressions; |
| 149 | + return $normalizedListeners; |
240 | 150 | } |
241 | 151 | } |
0 commit comments