src/EventSubscriber/WorkflowSubscriber.php line 37

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Enum\MercureToEnum;
  4. use App\Enum\MercureTypeEnum;
  5. use App\Event\CourseStateMachineEvent;
  6. use App\Event\DeliveryWorkflowEvent;
  7. use App\Event\WorkflowDeliverySubject;
  8. use App\Service\DeliveryService;
  9. use Psr\Log\LoggerInterface;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\Response;
  12. use Symfony\Component\Workflow\WorkflowInterface;
  13. class WorkflowSubscriber implements EventSubscriberInterface
  14. {
  15. public function __construct(
  16. private WorkflowInterface $deliveryWorkflow,
  17. private WorkflowInterface $courseStateMachine,
  18. private LoggerInterface $logger,
  19. private DeliveryService $deliveryService
  20. ) {
  21. }
  22. public static function getSubscribedEvents(): array
  23. {
  24. return [
  25. DeliveryWorkflowEvent::NAME => 'onStatusChange',
  26. CourseStateMachineEvent::NAME => 'onCourseStatusChange',
  27. ];
  28. }
  29. /**
  30. * @throws \Exception|\LogicException
  31. */
  32. public function onStatusChange(DeliveryWorkflowEvent $event): void
  33. {
  34. $delivery = $event->getDelivery();
  35. $transition = $event->getTransition();
  36. $transitions = $this->deliveryWorkflow->getDefinition()->getTransitions();
  37. $froms = [];
  38. foreach ($transitions as $defTransition) {
  39. if ($transition == $defTransition->getName()) {
  40. $froms = $this->getRepresentation($defTransition->getFroms());
  41. continue;
  42. }
  43. }
  44. if (!$this->deliveryWorkflow->can(new WorkflowDeliverySubject($delivery, $froms), $transition)) {
  45. $this->logger->critical(sprintf('Transition %s can\'t be done for delivery %s', $transition, $delivery->getId()));
  46. throw new \Exception("Transition can't be done", Response::HTTP_BAD_REQUEST);
  47. }
  48. try {
  49. $this->deliveryWorkflow->apply(new WorkflowDeliverySubject($delivery, $froms), $transition);
  50. } catch (\LogicException $exception) {
  51. throw $exception;
  52. }
  53. }
  54. /**
  55. * @throws \LogicException
  56. */
  57. public function onCourseStatusChange(CourseStateMachineEvent $event): void
  58. {
  59. $course = $event->getCourse();
  60. $transition = $event->getTransition();
  61. if (!$recipient = $course->getDelivery()?->getRecipient()) {
  62. throw new \Exception('Recipient not found', Response::HTTP_NOT_FOUND);
  63. }
  64. if (!$sender = $course->getDelivery()?->getSender()) {
  65. throw new \Exception('Sender not found', Response::HTTP_NOT_FOUND);
  66. }
  67. if ($this->courseStateMachine->can($course, $transition)) {
  68. try {
  69. $this->courseStateMachine->apply($course, $transition);
  70. $tos = [
  71. ['id' => $sender->getId(), 'to' => MercureToEnum::SENDER],
  72. ['id' => $recipient->getId(), 'to' => MercureToEnum::RECIPIENT],
  73. ];
  74. foreach ($tos as $to) {
  75. $this->deliveryService->publishMessage(
  76. $to['id'],
  77. $to['to'],
  78. MercureTypeEnum::COURSE_STATUS_CHANGED,
  79. [
  80. 'message' => sprintf('Course status change: %s', $transition),
  81. 'status' => $transition,
  82. ]
  83. );
  84. }
  85. } catch (\LogicException $exception) {
  86. throw $exception;
  87. }
  88. }
  89. }
  90. /**
  91. * @param array<int, string> $froms
  92. *
  93. * @return array<string, int>
  94. */
  95. public function getRepresentation(array $froms): array
  96. {
  97. $representation = [];
  98. foreach ($froms as $key => $from) {
  99. $representation[$from] = $key;
  100. }
  101. return $representation;
  102. }
  103. }