<?php
namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\Application;
use App\Entity\BaseUser;
use App\Entity\JobPosting;
use App\Entity\User;
use App\Entity\ViewJobPosting;
use App\Event\JobPosting\ProvidedJobPostingEvent;
use App\Event\JobPosting\SevenDaysLeftEvent;
use App\Repository\BaseUserRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use ExpoSDK\Expo;
use ExpoSDK\ExpoMessage;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Security\Core\Security;
final class JobPostingSubscriber implements EventSubscriberInterface
{
private Security $security;
private EntityManagerInterface $em;
private MailerInterface $mailer;
private BaseUserRepository $baseUserRepository;
private UserRepository $userRepository;
public function __construct(Security $security, EntityManagerInterface $em, MailerInterface $mailer, BaseUserRepository $baseUserRepository, UserRepository $userRepository)
{
$this->security = $security;
$this->em = $em;
$this->mailer = $mailer;
$this->baseUserRepository = $baseUserRepository;
$this->userRepository = $userRepository;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['VIEW', EventPriorities::POST_READ],
KernelEvents::VIEW => [
['create', EventPriorities::POST_WRITE],
['delete', EventPriorities::POST_WRITE]
],
SevenDaysLeftEvent::class => ['sevenDaysLeft'],
ProvidedJobPostingEvent::class => ['provided']
];
}
public function provided(ProvidedJobPostingEvent $event)
{
$jobPosting = $event->getJobPosting();
$accepted = $jobPosting->getValidateApplication();
switch ($accepted->getUser()->getNotificationType()) {
case BaseUser::NOTIFICATION_MAIL:
$this->sendMailApplicationAccepted($accepted);
break;
case BaseUser::NOTIFICATION_PUSH:
if ($d = $accepted->getUser()->getDevicesTokensExpo()) {
$this->sendPushApplicationAccepted($d, $jobPosting);
}
break;
case BaseUser::NOTIFICATION_PUSH_MAIL:
$this->sendMailApplicationAccepted($accepted);
if ($d = $accepted->getUser()->getDevicesTokensExpo()) {
$this->sendPushApplicationAccepted($d, $jobPosting);
}
break;
}
$jobPosting->setValidateApplication(null);
$this->em->flush();
}
public function delete(ViewEvent $event): void
{
$jobPosting = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$jobPosting instanceof JobPosting || Request::METHOD_DELETE !== $method) {
return;
}
$this->sendMailRemove($jobPosting->getPharmacy()->getEmail(), $jobPosting);
}
/**
* Utilisé pour enregistrer les vues des alertes.
*
* @param RequestEvent $event
*/
public function VIEW(RequestEvent $event)
{
$request = $event->getRequest();
$jobPosting = $request->get('data');
$method = $request->getMethod();
/**
* Si je suis sur un single
*/
if (
!$jobPosting instanceof JobPosting
|| Request::METHOD_GET !== $method
|| !$this->security->isGranted('ROLE_USER')
|| $this->security->isGranted('ROLE_PHARMACY')
|| $this->security->isGranted('ROLE_ADMIN')
|| $request->get('_api_normalization_context')['item_operation_name'] !== 'get'
|| !isset($request->get('_api_normalization_context')['item_operation_name'])
) {
return;
}
/** @var User $user */
$user = $this->security->getUser();
/** @var JobPosting $jobPosting */
$jobPosting = $request->get('data');
if ($viewJobPosting = $this->em->getRepository(ViewJobPosting::class)->findOneBy(['userHaveView' => $user, 'jobPosting' => $jobPosting])) {
$viewJobPosting->setCount($viewJobPosting->getCount() + 1);
} else {
$viewJobPosting = (new ViewJobPosting())
->setUserHaveView($user)
->setJobPosting($jobPosting);
$this->em->persist($viewJobPosting);
}
$this->em->flush();
}
public function create(ViewEvent $event): void
{
$jobPosting = $event->getControllerResult();
$request = $event->getRequest();
$method = $request->getMethod();
$admins = $this->baseUserRepository->findByRole('ROLE_ADMIN');
if (
!$jobPosting instanceof JobPosting
|| Request::METHOD_POST !== $method
|| $request->get('_route') !== 'api_job_postings_post_collection'
) {
return;
}
if ($this->security->isGranted("ROLE_ADMIN")) {
$this->sendMailCreateByAdmin($jobPosting->getPharmacy()->getEmail(), $jobPosting);
} else {
$this->sendMailCreate($jobPosting);
$this->sendMailCreateForAdmin(array_map(fn(BaseUser $baseUser) => $baseUser->getEmail(), $admins), $jobPosting);
}
$pushs = [];
$concernedUsers = $this->userRepository->findByJobPosting($jobPosting);
foreach ($concernedUsers as $concernedUser) {
switch ($concernedUser->getNotificationType()) {
case BaseUser::NOTIFICATION_PUSH_MAIL:
case BaseUser::NOTIFICATION_PUSH:
if ($concernedUser->getDevicesTokensExpo()) {
$pushs[] = $concernedUser->getDevicesTokensExpo();
}
break;
}
}
if (!empty($pushs)) {
$this->sendPushNewJobPostingForYou(array_merge(...$pushs));
}
}
public function sevenDaysLeft(SevenDaysLeftEvent $event)
{
$jobPosting = $event->getJobPosting();
$pharmacy = $jobPosting->getPharmacy();
/**
* MAIL:Pharmacy
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($pharmacy->getEmail())
->subject('Votre offre arrive à expiration - ORES BFC')
->htmlTemplate('mails/job_posting/seven_days_left.html.twig')
->context([
'jobPosting' => $jobPosting
]);
$this->mailer->send($email);
$this->sendPushRemindClosure($pharmacy->getDevicesTokensExpo());
}
public function sendMailApplicationRefused(Application $application)
{
/**
* MAIL:User
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($application->getUser()->getEmail())
->subject('Candidature refusée - ORES BFC')
->htmlTemplate('mails/application/refused.html.twig')
->context([
'application' => $application
]);
$this->mailer->send($email);
}
public function sendPushApplicationRefused($tos, JobPosting $jobPosting)
{
/**
* PUSH:BaseUser
*/
$message = (new ExpoMessage([
'title' => 'Candidature refusé',
'body' => "Votre demande de candidature pour l’offre “".$jobPosting->getTitle()."” pour l’officine “".$jobPosting->getPharmacy()->getLegalname()."” a été refusée.",
]))
->setChannelId('default')
->setBadge(0)
->playSound();
$tos = array_merge(...$tos);
if (!empty($tos)) {
return (new Expo)->send($message)->to($tos)->push();
}
}
public function sendMailApplicationAccepted(Application $application)
{
/**
* MAIL:User
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($application->getUser()->getEmail())
->subject('Candidature retenue - ORES BFC')
->htmlTemplate('mails/application/accepted.html.twig')
->context([
'application' => $application
]);
$this->mailer->send($email);
}
public function sendPushApplicationAccepted($tos, JobPosting $jobPosting)
{
/**
* PUSH:BaseUser
*/
$message = (new ExpoMessage([
'title' => 'Candidature retenu',
'body' => "Votre demande de candidature pour l’offre “".$jobPosting->getTitle()."” pour l’officine “".$jobPosting->getPharmacy()->getLegalname()."” a été retenue.",
]))
->setChannelId('default')
->setBadge(0)
->playSound();
if (!empty($tos)) {
return (new Expo)->send($message)->to($tos)->push();
}
}
public function sendMailCreateByAdmin($to, JobPosting $jobPosting)
{
/**
* MAIL:Pharmacy
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($to)
->subject('Une nouvelle offre d\'emploi a été crée pour vous - ORES BFC')
->htmlTemplate('mails/job_posting/create_by_admin.html.twig')
->context([
'jobPosting' => $jobPosting,
]);
$this->mailer->send($email);
}
public function sendMailCreate(JobPosting $jobPosting)
{
/**
* MAIL:Pharmacy
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($jobPosting->getPharmacy()->getEmail())
->subject('Confirmation de la création de votre offre')
->htmlTemplate('mails/job_posting/create.html.twig')
->context([
'jobPosting' => $jobPosting
]);
$this->mailer->send($email);
}
public function sendMailCreateForAdmin(array $admins, JobPosting $jobPosting)
{
$createdBy = $jobPosting->getCreatedBy();
/**
* MAIL:Admin
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to(...$admins)
->subject('Nouvelle offre d\'emploi - ORES BFC')
->htmlTemplate('mails/job_posting/create_admin.html.twig')
->context([
'jobPosting' => $jobPosting,
'createdBy' => [
'lastname' => $createdBy->getLastname(),
'firstname' => $createdBy->getFirstname(),
]
]);
$this->mailer->send($email);
}
public function sendMailRemove($to, JobPosting $jobPosting)
{
/**
* MAIL:Pharmacy
*/
$email = (new TemplatedEmail())
->from(new Address('noreply@ores.com', 'ORES'))
->to($to)
->subject('Suppression de votre offre - ORES BFC')
->htmlTemplate('mails/job_posting/remove.html.twig')
->context([
'jobPosting' => $jobPosting,
]);
$this->mailer->send($email);
}
public function sendPushRemindClosure($tos)
{
/**
* PUSH:Pharmacy
*/
$message = (new ExpoMessage([
'title' => "Pensez à clôturer votre offre sur l’application",
'body' => "Si votre offre a été pourvue en dehors de l’application, merci de la pourvoir sur l’application pour prévenir les candidats en attente",
]))
->setChannelId('default')
->setBadge(0)
->playSound();
if (!empty($tos)) {
return (new Expo)->send($message)->to($tos)->push();
}
}
public function sendPushNewJobPostingForYou($tos)
{
/**
* PUSH:User
*/
$message = (new ExpoMessage([
'title' => "Nouvelle offre d'emploi !",
'body' => "Une nouvelle offre dans votre zone est en ligne sur ORES BFC.",
]))
->setChannelId('default')
->setBadge(0)
->playSound();
if (!empty($tos)) {
return (new Expo)->send($message)->to($tos)->push();
}
}
}