src/EventSubscriber/JobUnableToCompleteSubscriber.php line 42

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use ApiPlatform\Symfony\EventListener\EventPriorities;
  4. use App\Entity\Job;
  5. use App\Entity\Schedule;
  6. use App\Entity\User;
  7. use App\Service\Message;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use JetBrains\PhpStorm\ArrayShape;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpKernel\Event\ViewEvent;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  15. use function array_multisort;
  16. use function in_array;
  17. final class JobUnableToCompleteSubscriber implements EventSubscriberInterface
  18. {
  19.     /** @var string The relative path inside templates/messages without any extensions */
  20.     private const TEMPLATE 'job/unable-to-complete';
  21.     public function __construct(
  22.         private readonly TokenStorageInterface $tokenStorage,
  23.         private readonly Message $messageService,
  24.         private readonly ManagerRegistry $managerRegistry,
  25.     )
  26.     {
  27.     }
  28.     #[ArrayShape([KernelEvents::VIEW => "array"])]
  29.     public static function getSubscribedEvents(): array
  30.     {
  31.         return [
  32.             KernelEvents::VIEW => ['sendMessage'EventPriorities::POST_WRITE],
  33.         ];
  34.     }
  35.     public function sendMessage(ViewEvent $event): void
  36.     {
  37.         $job $event->getControllerResult();
  38.         $method $event->getRequest()->getMethod();
  39.         # PUT and PATCH methods are used to update instances, and we are only interested in updated jobs
  40.         if (!$job instanceof Job || !in_array($method, [Request::METHOD_PUTRequest::METHOD_PATCH])) {
  41.             return;
  42.         }
  43.         $previousData $event->getRequest()->get('previous_data');
  44.         # If the status hasn't changed, we're not interested
  45.         if ($previousData->getStatus() === $job->getStatus()) {
  46.             return;
  47.         }
  48.         # If the status hasn't changed to "unable to complete", we're not interested
  49.         if ($job->getStatus() !== Job::JOB_STATUS_UNABLE_TO_COMPLETE) {
  50.             return;
  51.         }
  52.         $customer $job->getPond()->getCustomer();
  53.         $schedule $this->getLatestSchedule($job);
  54.         $message $this->messageService
  55.             ->withRecipient($customer)
  56.             ->withSubject('We were unable to complete your job')
  57.             ->withTemplate(self::TEMPLATE)
  58.             ->withTemplateData([
  59.                 'addressLine1' => $job->getPond()->getAddress1(),
  60.                 'firstName' => $customer->getFirstName() === 'ANNETTE' null $customer->getFirstName(),
  61.                 'fullAddress' => $job->getPond()->getAddress(),
  62.                 'reason' => $this->getReasonText($schedule),
  63.                 'employeeName' => $schedule->getEmployee()->getUser()->getFirstName(),
  64.                 'notes' => $schedule->getNotes(),
  65.             ]);
  66.         $currentUser $this->tokenStorage->getToken()->getUser();
  67.         if ($currentUser instanceof User) {
  68.             $message $message->withCurrentUser($currentUser);
  69.         }
  70.         $message->send();
  71.     }
  72.     private function getLatestSchedule(Job $job): Schedule
  73.     {
  74.         /** @var iterable<int, Schedule> $schedules */
  75.         $schedules $this->managerRegistry->getRepository(Schedule::class)
  76.             ->findBy(['job' => $job]);
  77.         $sort = [];
  78.         foreach ($schedules as $schedule) {
  79.             $sort[] = $schedule->getDate()->getTimestamp();
  80.         }
  81.         array_multisort($schedulesSORT_DESC$sort);
  82.         return current($schedules);
  83.     }
  84.     private function getReasonText(Schedule $schedule): string|bool
  85.     {
  86.         return match($schedule->getIncompleteReason()) {
  87.             Schedule::INCOMPLETE_REASON_TIME => 'we ran out of time',
  88.             Schedule::INCOMPLETE_REASON_MATERIALS => 'we had an issue with materials',
  89.             Schedule::INCOMPLETE_REASON_NO_ACCESS => 'we had issues with accessing the pond',
  90.             default => false// we will handle "other" in the template
  91.         };
  92.     }
  93. }