Skip to content

Commit 348cb02

Browse files
committed
Added Context to Workflow Event
There's also a default context for the initial marking event.
1 parent 812a4d5 commit 348cb02

File tree

7 files changed

+110
-31
lines changed

7 files changed

+110
-31
lines changed

src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* WorkflowExtension.
2222
*
2323
* @author Grégoire Pineau <lyrixx@lyrixx.info>
24+
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
2425
*/
2526
final class WorkflowExtension extends AbstractExtension
2627
{

src/Symfony/Component/Workflow/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
-----
66

77
* Added `Workflow::getEnabledTransition()` to easily retrieve a specific transition object
8+
* Added context to the event dispatched
9+
* Added default context to the Initial Marking
810

911
5.1.0
1012
-----

src/Symfony/Component/Workflow/Event/Event.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@
1919
/**
2020
* @author Fabien Potencier <fabien@symfony.com>
2121
* @author Grégoire Pineau <lyrixx@lyrixx.info>
22+
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
2223
*/
2324
class Event extends BaseEvent
2425
{
2526
private $subject;
2627
private $marking;
2728
private $transition;
2829
private $workflow;
30+
private $context;
2931

30-
public function __construct(object $subject, Marking $marking, Transition $transition = null, WorkflowInterface $workflow = null)
32+
public function __construct(object $subject, Marking $marking, Transition $transition = null, WorkflowInterface $workflow = null, array $context = [])
3133
{
3234
$this->subject = $subject;
3335
$this->marking = $marking;
3436
$this->transition = $transition;
3537
$this->workflow = $workflow;
38+
$this->context = $context;
3639
}
3740

3841
public function getMarking()
@@ -64,4 +67,9 @@ public function getMetadata(string $key, $subject)
6467
{
6568
return $this->workflow->getMetadataStore()->getMetadata($key, $subject);
6669
}
70+
71+
public function getContext(): array
72+
{
73+
return $this->context;
74+
}
6775
}

src/Symfony/Component/Workflow/Event/GuardEvent.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
/**
2121
* @author Fabien Potencier <fabien@symfony.com>
2222
* @author Grégoire Pineau <lyrixx@lyrixx.info>
23+
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
2324
*/
2425
final class GuardEvent extends Event
2526
{
@@ -28,9 +29,9 @@ final class GuardEvent extends Event
2829
/**
2930
* {@inheritdoc}
3031
*/
31-
public function __construct(object $subject, Marking $marking, Transition $transition, WorkflowInterface $workflow = null)
32+
public function __construct(object $subject, Marking $marking, Transition $transition, WorkflowInterface $workflow = null, array $context = [])
3233
{
33-
parent::__construct($subject, $marking, $transition, $workflow);
34+
parent::__construct($subject, $marking, $transition, $workflow, $context);
3435

3536
$this->transitionBlockerList = new TransitionBlockerList();
3637
}

src/Symfony/Component/Workflow/Tests/WorkflowTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ public function testApplyWithEventDispatcher()
392392
$eventNameExpected = [
393393
'workflow.entered',
394394
'workflow.workflow_name.entered',
395+
'workflow.workflow_name.entered.a',
395396
'workflow.guard',
396397
'workflow.workflow_name.guard',
397398
'workflow.workflow_name.guard.t1',
@@ -463,6 +464,7 @@ public function testApplyDoesNotTriggerExtraGuardWithEventDispatcher()
463464
$eventNameExpected = [
464465
'workflow.entered',
465466
'workflow.workflow_name.entered',
467+
'workflow.workflow_name.entered.a',
466468
'workflow.guard',
467469
'workflow.workflow_name.guard',
468470
'workflow.workflow_name.guard.a-b',
@@ -533,6 +535,59 @@ public function testEventName()
533535
$workflow->apply($subject, 't1');
534536
}
535537

538+
public function testEventContext()
539+
{
540+
$definition = $this->createComplexWorkflowDefinition();
541+
$subject = new Subject();
542+
$dispatcher = new EventDispatcher();
543+
$name = 'workflow_name';
544+
$context = ['context'];
545+
$workflow = new Workflow($definition, new MethodMarkingStore(), $dispatcher, $name);
546+
547+
$assertWorkflowContext = function (Event $event) use ($context) {
548+
$this->assertEquals($context, $event->getContext());
549+
};
550+
551+
$eventNames = [
552+
'workflow.guard',
553+
'workflow.leave',
554+
'workflow.transition',
555+
'workflow.enter',
556+
'workflow.entered',
557+
'workflow.announce',
558+
];
559+
560+
foreach ($eventNames as $eventName) {
561+
$dispatcher->addListener($eventName, $assertWorkflowContext);
562+
}
563+
564+
$workflow->apply($subject, 't1', $context);
565+
}
566+
567+
public function testEventDefaultInitialContext()
568+
{
569+
$definition = $this->createComplexWorkflowDefinition();
570+
$subject = new Subject();
571+
$dispatcher = new EventDispatcher();
572+
$name = 'workflow_name';
573+
$context = Workflow::DEFAULT_INITIAL_CONTEXT;
574+
$workflow = new Workflow($definition, new MethodMarkingStore(), $dispatcher, $name);
575+
576+
$assertWorkflowContext = function (Event $event) use ($context) {
577+
$this->assertEquals($context, $event->getContext());
578+
};
579+
580+
$eventNames = [
581+
'workflow.workflow_name.entered.a',
582+
];
583+
584+
foreach ($eventNames as $eventName) {
585+
$dispatcher->addListener($eventName, $assertWorkflowContext);
586+
}
587+
588+
$workflow->apply($subject, 't1');
589+
}
590+
536591
public function testMarkingStateOnApplyWithEventDispatcher()
537592
{
538593
$definition = new Definition(range('a', 'f'), [new Transition('t', range('a', 'c'), range('d', 'f'))]);

src/Symfony/Component/Workflow/Workflow.php

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@
3030
* @author Fabien Potencier <fabien@symfony.com>
3131
* @author Grégoire Pineau <lyrixx@lyrixx.info>
3232
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
33+
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
3334
*/
3435
class Workflow implements WorkflowInterface
3536
{
3637
public const DISABLE_ANNOUNCE_EVENT = 'workflow_disable_announce_event';
38+
public const DEFAULT_INITIAL_CONTEXT = ['initial' => true];
3739

3840
private $definition;
3941
private $markingStore;
@@ -51,7 +53,7 @@ public function __construct(Definition $definition, MarkingStoreInterface $marki
5153
/**
5254
* {@inheritdoc}
5355
*/
54-
public function getMarking(object $subject)
56+
public function getMarking(object $subject, array $context = [])
5557
{
5658
$marking = $this->markingStore->getMarking($subject);
5759

@@ -71,7 +73,11 @@ public function getMarking(object $subject)
7173
// update the subject with the new marking
7274
$this->markingStore->setMarking($subject, $marking);
7375

74-
$this->entered($subject, null, $marking);
76+
if (empty($context)) {
77+
$context = self::DEFAULT_INITIAL_CONTEXT;
78+
}
79+
80+
$this->entered($subject, null, $marking, $context);
7581
}
7682

7783
// check that the subject has a known place
@@ -154,7 +160,7 @@ public function buildTransitionBlockerList(object $subject, string $transitionNa
154160
*/
155161
public function apply(object $subject, string $transitionName, array $context = [])
156162
{
157-
$marking = $this->getMarking($subject);
163+
$marking = $this->getMarking($subject, $context);
158164

159165
$transitionExist = false;
160166
$approvedTransitions = [];
@@ -167,7 +173,7 @@ public function apply(object $subject, string $transitionName, array $context =
167173

168174
$transitionExist = true;
169175

170-
$tmpTransitionBlockerList = $this->buildTransitionBlockerListForTransition($subject, $marking, $transition);
176+
$tmpTransitionBlockerList = $this->buildTransitionBlockerListForTransition($subject, $marking, $transition, $context);
171177

172178
if ($tmpTransitionBlockerList->isEmpty()) {
173179
$approvedTransitions[] = $transition;
@@ -197,20 +203,20 @@ public function apply(object $subject, string $transitionName, array $context =
197203
}
198204

199205
foreach ($approvedTransitions as $transition) {
200-
$this->leave($subject, $transition, $marking);
206+
$this->leave($subject, $transition, $marking, $context);
201207

202208
$context = $this->transition($subject, $transition, $marking, $context);
203209

204-
$this->enter($subject, $transition, $marking);
210+
$this->enter($subject, $transition, $marking, $context);
205211

206212
$this->markingStore->setMarking($subject, $marking, $context);
207213

208-
$this->entered($subject, $transition, $marking);
214+
$this->entered($subject, $transition, $marking, $context);
209215

210-
$this->completed($subject, $transition, $marking);
216+
$this->completed($subject, $transition, $marking, $context);
211217

212218
if (!($context[self::DISABLE_ANNOUNCE_EVENT] ?? false)) {
213-
$this->announce($subject, $transition, $marking);
219+
$this->announce($subject, $transition, $marking, $context);
214220
}
215221
}
216222

@@ -220,13 +226,13 @@ public function apply(object $subject, string $transitionName, array $context =
220226
/**
221227
* {@inheritdoc}
222228
*/
223-
public function getEnabledTransitions(object $subject)
229+
public function getEnabledTransitions(object $subject, array $context = [])
224230
{
225231
$enabledTransitions = [];
226232
$marking = $this->getMarking($subject);
227233

228234
foreach ($this->definition->getTransitions() as $transition) {
229-
$transitionBlockerList = $this->buildTransitionBlockerListForTransition($subject, $marking, $transition);
235+
$transitionBlockerList = $this->buildTransitionBlockerListForTransition($subject, $marking, $transition, $context);
230236
if ($transitionBlockerList->isEmpty()) {
231237
$enabledTransitions[] = $transition;
232238
}
@@ -286,7 +292,7 @@ public function getMetadataStore(): MetadataStoreInterface
286292
return $this->definition->getMetadataStore();
287293
}
288294

289-
private function buildTransitionBlockerListForTransition(object $subject, Marking $marking, Transition $transition): TransitionBlockerList
295+
private function buildTransitionBlockerListForTransition(object $subject, Marking $marking, Transition $transition, array $context = []): TransitionBlockerList
290296
{
291297
foreach ($transition->getFroms() as $place) {
292298
if (!$marking->has($place)) {
@@ -300,7 +306,7 @@ private function buildTransitionBlockerListForTransition(object $subject, Markin
300306
return new TransitionBlockerList();
301307
}
302308

303-
$event = $this->guardTransition($subject, $marking, $transition);
309+
$event = $this->guardTransition($subject, $marking, $transition, $context);
304310

305311
if ($event->isBlocked()) {
306312
return $event->getTransitionBlockerList();
@@ -309,13 +315,13 @@ private function buildTransitionBlockerListForTransition(object $subject, Markin
309315
return new TransitionBlockerList();
310316
}
311317

312-
private function guardTransition(object $subject, Marking $marking, Transition $transition): ?GuardEvent
318+
private function guardTransition(object $subject, Marking $marking, Transition $transition, array $context = []): ?GuardEvent
313319
{
314320
if (null === $this->dispatcher) {
315321
return null;
316322
}
317323

318-
$event = new GuardEvent($subject, $marking, $transition, $this);
324+
$event = new GuardEvent($subject, $marking, $transition, $this, $context);
319325

320326
$this->dispatcher->dispatch($event, WorkflowEvents::GUARD);
321327
$this->dispatcher->dispatch($event, sprintf('workflow.%s.guard', $this->name));
@@ -324,12 +330,12 @@ private function guardTransition(object $subject, Marking $marking, Transition $
324330
return $event;
325331
}
326332

327-
private function leave(object $subject, Transition $transition, Marking $marking): void
333+
private function leave(object $subject, Transition $transition, Marking $marking, array $context = []): void
328334
{
329335
$places = $transition->getFroms();
330336

331337
if (null !== $this->dispatcher) {
332-
$event = new LeaveEvent($subject, $marking, $transition, $this);
338+
$event = new LeaveEvent($subject, $marking, $transition, $this, $context);
333339

334340
$this->dispatcher->dispatch($event, WorkflowEvents::LEAVE);
335341
$this->dispatcher->dispatch($event, sprintf('workflow.%s.leave', $this->name));
@@ -360,12 +366,12 @@ private function transition(object $subject, Transition $transition, Marking $ma
360366
return $event->getContext();
361367
}
362368

363-
private function enter(object $subject, Transition $transition, Marking $marking): void
369+
private function enter(object $subject, Transition $transition, Marking $marking, array $context): void
364370
{
365371
$places = $transition->getTos();
366372

367373
if (null !== $this->dispatcher) {
368-
$event = new EnterEvent($subject, $marking, $transition, $this);
374+
$event = new EnterEvent($subject, $marking, $transition, $this, $context);
369375

370376
$this->dispatcher->dispatch($event, WorkflowEvents::ENTER);
371377
$this->dispatcher->dispatch($event, sprintf('workflow.%s.enter', $this->name));
@@ -380,13 +386,13 @@ private function enter(object $subject, Transition $transition, Marking $marking
380386
}
381387
}
382388

383-
private function entered(object $subject, ?Transition $transition, Marking $marking): void
389+
private function entered(object $subject, ?Transition $transition, Marking $marking, array $context = []): void
384390
{
385391
if (null === $this->dispatcher) {
386392
return;
387393
}
388394

389-
$event = new EnteredEvent($subject, $marking, $transition, $this);
395+
$event = new EnteredEvent($subject, $marking, $transition, $this, $context);
390396

391397
$this->dispatcher->dispatch($event, WorkflowEvents::ENTERED);
392398
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered', $this->name));
@@ -395,34 +401,38 @@ private function entered(object $subject, ?Transition $transition, Marking $mark
395401
foreach ($transition->getTos() as $place) {
396402
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered.%s', $this->name, $place));
397403
}
404+
} elseif (!empty($this->definition->getInitialPlaces())) {
405+
foreach ($this->definition->getInitialPlaces() as $place) {
406+
$this->dispatcher->dispatch($event, sprintf('workflow.%s.entered.%s', $this->name, $place));
407+
}
398408
}
399409
}
400410

401-
private function completed(object $subject, Transition $transition, Marking $marking): void
411+
private function completed(object $subject, Transition $transition, Marking $marking, array $context): void
402412
{
403413
if (null === $this->dispatcher) {
404414
return;
405415
}
406416

407-
$event = new CompletedEvent($subject, $marking, $transition, $this);
417+
$event = new CompletedEvent($subject, $marking, $transition, $this, $context);
408418

409419
$this->dispatcher->dispatch($event, WorkflowEvents::COMPLETED);
410420
$this->dispatcher->dispatch($event, sprintf('workflow.%s.completed', $this->name));
411421
$this->dispatcher->dispatch($event, sprintf('workflow.%s.completed.%s', $this->name, $transition->getName()));
412422
}
413423

414-
private function announce(object $subject, Transition $initialTransition, Marking $marking): void
424+
private function announce(object $subject, Transition $initialTransition, Marking $marking, array $context): void
415425
{
416426
if (null === $this->dispatcher) {
417427
return;
418428
}
419429

420-
$event = new AnnounceEvent($subject, $marking, $initialTransition, $this);
430+
$event = new AnnounceEvent($subject, $marking, $initialTransition, $this, $context);
421431

422432
$this->dispatcher->dispatch($event, WorkflowEvents::ANNOUNCE);
423433
$this->dispatcher->dispatch($event, sprintf('workflow.%s.announce', $this->name));
424434

425-
foreach ($this->getEnabledTransitions($subject) as $transition) {
435+
foreach ($this->getEnabledTransitions($subject, $context) as $transition) {
426436
$this->dispatcher->dispatch($event, sprintf('workflow.%s.announce.%s', $this->name, $transition->getName()));
427437
}
428438
}

src/Symfony/Component/Workflow/WorkflowInterface.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface WorkflowInterface
2727
*
2828
* @throws LogicException
2929
*/
30-
public function getMarking(object $subject);
30+
public function getMarking(object $subject, array $context = []);
3131

3232
/**
3333
* Returns true if the transition is enabled.
@@ -55,7 +55,9 @@ public function apply(object $subject, string $transitionName, array $context =
5555
*
5656
* @return Transition[] All enabled transitions
5757
*/
58-
public function getEnabledTransitions(object $subject);
58+
public function getEnabledTransitions(object $subject, array $context = []);
59+
60+
public function getEnabledTransition(object $subject, string $name): ?Transition;
5961

6062
/**
6163
* @return string

0 commit comments

Comments
 (0)