src/App/EventSubscriber/App/ProfileEventSubscriber.php line 60

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber\App;
  3. use App\Entity\ExtendedApplication\ExtendedApplication;
  4. use App\Entity\PlatformEvent;
  5. use App\Entity\Profile;
  6. use App\Entity\Profile\JoboffererProfile;
  7. use App\Entity\Profile\JobseekerProfile;
  8. use App\Entity\UsageEvent;
  9. use App\Entity\User;
  10. use App\Event\ProfileEditedEvent;
  11. use App\Event\ProfileEvent;
  12. use App\Event\ProfilePhotoAddedEvent;
  13. use App\Event\ProfilePhotoRemovedEvent;
  14. use App\Service\ConversionEventService;
  15. use App\Service\JoboffererProfileService;
  16. use App\Service\NotificationService;
  17. use App\Service\PlatformEventService;
  18. use App\Service\ProfileService;
  19. use App\Service\UsageEventService;
  20. use App\SymfonyMessage\AskNewUserForGoogleRatingSymfonyMessage;
  21. use Doctrine\ORM\EntityManagerInterface;
  22. use Exception;
  23. use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
  24. use JanusHercules\DatawarehouseIntegration\Domain\Entity\BusinessEvent;
  25. use JanusHercules\DatawarehouseIntegration\Domain\Service\BusinessEventDomainService;
  26. use JanusHercules\RecurrentJobsSearch\Presentation\Services\RecurrentJobsSearchPresentationService;
  27. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  28. use Symfony\Component\Messenger\MessageBusInterface;
  29. readonly class ProfileEventSubscriber implements EventSubscriberInterface
  30. {
  31. public function __construct(
  32. private BusinessEventDomainService $businessEventDomainService,
  33. private UsageEventService $usageEventService,
  34. private NotificationService $notificationService,
  35. private ConversionEventService $conversionEventService,
  36. private ObjectPersisterInterface $recurrentJobsPersister,
  37. private ObjectPersisterInterface $wantedJobsPersister,
  38. private JoboffererProfileService $joboffererProfileService,
  39. private ProfileService $profileService,
  40. private MessageBusInterface $messageBus,
  41. private EntityManagerInterface $entityManager,
  42. private RecurrentJobsSearchPresentationService $recurrentJobsSearchPresentationService,
  43. private PlatformEventService $platformEventService
  44. ) {
  45. }
  46. public static function getSubscribedEvents(): array
  47. {
  48. return [
  49. ProfileEditedEvent::class => 'onProfileEdited',
  50. ProfilePhotoAddedEvent::class => 'onProfilePhotoAdded',
  51. ProfilePhotoRemovedEvent::class => 'onProfilePhotoRemoved'
  52. ];
  53. }
  54. /** @throws Exception */
  55. public function onProfileEdited(ProfileEvent $event): void
  56. {
  57. $this->businessEventDomainService->writeNewEvent(
  58. BusinessEvent::EVENT_TYPE_PROFILE_EDITED,
  59. $event->getProfile()->getUser(),
  60. null,
  61. null,
  62. json_encode($event->getProfile()->getId())
  63. );
  64. if ($event->getProfile()->isJobseeker() && $event->getProfile()->getState() === Profile::STATE_BASE) {
  65. $this->profileService->activateHiddenWantedJobsForProfile($event->getProfile());
  66. }
  67. if ($event->getProfile()->isBaseProfile()) {
  68. $this->conversionEventService->handleConversionGoalReached(
  69. ConversionEventService::CAMPAIGN_ID_WEBDE_MAILING_FOR_NONACTIVATED_PROFILE,
  70. 0
  71. );
  72. $this->conversionEventService->handleConversionGoalReached(
  73. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  74. NotificationService::NOTIFICATION_TYPE_MISSING_ACTIVATION,
  75. null,
  76. $event->getProfile()->getUser()
  77. );
  78. }
  79. if ($event->getProfile()->isJobseeker()) {
  80. $this->notificationService->uncancelNotification(
  81. $event->getProfile()->getUser(),
  82. NotificationService::NOTIFICATION_TYPE_UNREAD_CONVERSATION_MESSAGES
  83. );
  84. $this->notificationService->uncancelNotification(
  85. $event->getProfile()->getUser(),
  86. NotificationService::NOTIFICATION_TYPE_UNREAD_JOBRADAR_MATCHES
  87. );
  88. if ($event->getProfile()->isBaseProfile()) {
  89. $this->conversionEventService->handleConversionGoalReached(
  90. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  91. NotificationService::NOTIFICATION_TYPE_MISSING_JOBSEEKER_BASE_PROFILE
  92. );
  93. }
  94. if ($event->getProfile()->isBasePlusProfile()) {
  95. $this->conversionEventService->handleConversionGoalReached(
  96. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  97. NotificationService::NOTIFICATION_TYPE_MISSING_JOBSEEKER_BASE_PLUS_PROFILE
  98. );
  99. }
  100. }
  101. if ($event->getProfile()->isJobofferer()) {
  102. if ($event->getProfile()->isBaseProfile()) {
  103. $this->conversionEventService->handleConversionGoalReached(
  104. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  105. NotificationService::NOTIFICATION_TYPE_MISSING_JOBOFFERER_BASE_PROFILE
  106. );
  107. }
  108. if ($event->getProfile()->isBasePlusProfile()) {
  109. $this->conversionEventService->handleConversionGoalReached(
  110. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  111. NotificationService::NOTIFICATION_TYPE_MISSING_JOBOFFERER_BASE_PLUS_PROFILE
  112. );
  113. }
  114. /** @var JoboffererProfile $profile */
  115. $profile = $event->getProfile();
  116. if ($profile->getAdditionalFiles()->count() > 0) {
  117. $this->conversionEventService->handleConversionGoalReached(
  118. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  119. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBOFFERER_3
  120. );
  121. }
  122. $this->joboffererProfileService->checkIfProfileMustBeIdentifiedAsRecruitmentAgency($profile);
  123. }
  124. $this->conversionEventService->handleConversionGoalReached(
  125. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  126. NotificationService::NOTIFICATION_TYPE_MISSING_JOBSEEKER_ACTIVITY
  127. );
  128. if (!is_null($event->getProfile()->getSelfdescription()) && $event->getProfile()->getSelfdescription() !== '') {
  129. $this->conversionEventService->handleConversionGoalReached(
  130. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  131. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBSEEKER_1
  132. );
  133. $this->conversionEventService->handleConversionGoalReached(
  134. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  135. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBOFFERER_1
  136. );
  137. if ($event->getPriorState()['hadAboutMeBefore'] === false) {
  138. $this->businessEventDomainService->writeNewEvent(BusinessEvent::EVENT_TYPE_ABOUT_ME_WAS_ADDED, $event->getProfile()->getUser());
  139. }
  140. }
  141. if (!is_null($event->getProfile()->getDocumentFileName()) && $event->getProfile()->getDocumentFileName() !== '') {
  142. $this->conversionEventService->handleConversionGoalReached(
  143. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  144. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBSEEKER_2
  145. );
  146. $this->conversionEventService->handleConversionGoalReached(
  147. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  148. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBSEEKER_4
  149. );
  150. if ($event->getPriorState()['hadCVBefore'] === false) {
  151. $this->businessEventDomainService->writeNewEvent(BusinessEvent::EVENT_TYPE_CV_WAS_ADDED, $event->getProfile()->getUser());
  152. }
  153. }
  154. // This will only ever apply to jobseeker because of the way we handle additional files for jobofferers, that's why this event is also handled in JoboffererProfileAdditionalFilesController
  155. if ($event->getProfile()->getAdditionalFiles()->count() > 0 && $event->getPriorState()['hadAdditionalDocumentsBefore'] === false) {
  156. $this->businessEventDomainService->writeNewEvent(
  157. BusinessEvent::EVENT_TYPE_ADDITIONAL_DOCUMENT_WAS_ADDED,
  158. $event->getProfile()->getUser()
  159. );
  160. }
  161. if (!is_null($event->getProfile()->getMobilenumber()) && $event->getProfile()->getMobilenumber() !== '' && $event->getPriorState()['hadPhoneNumberBefore'] === false) {
  162. $this->businessEventDomainService->writeNewEvent(
  163. BusinessEvent::EVENT_TYPE_PHONE_NUMBER_WAS_ADDED,
  164. $event->getProfile()->getUser()
  165. );
  166. }
  167. if ($event->getProfile()->hasPhoto()) {
  168. $this->conversionEventService->handleConversionGoalReached(
  169. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  170. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBSEEKER_3
  171. );
  172. $this->conversionEventService->handleConversionGoalReached(
  173. ConversionEventService::CAMPAIGN_ID_NOTIFICATION,
  174. NotificationService::NOTIFICATION_TYPE_MISSING_PROFILE_FIELDS_JOBOFFERER_2
  175. );
  176. }
  177. // Some attributes of RecurrentJobs and WantedJobs are transitive and come from the profile of their owner
  178. // (e.g. the zipcode).
  179. // Thus, changes to a profile might require the index data in ES to be updated, but Elastica cannot know
  180. // that a change in the profile zipcode requires an update of this index data, and thus, we need to explicitly
  181. // tell Elastica.
  182. if ($event->getProfile()->isJobseeker()) {
  183. /** @var JobseekerProfile $profile */
  184. $profile = $event->getProfile();
  185. foreach ($profile->getWantedJobs() as $wantedJob) {
  186. if ($wantedJob->isFindable()) {
  187. $this->wantedJobsPersister->replaceOne($wantedJob);
  188. }
  189. }
  190. }
  191. if ($event->getProfile()->isJobofferer()) {
  192. /** @var JoboffererProfile $profile */
  193. $profile = $event->getProfile();
  194. foreach ($profile->getRecurrentJobs() as $recurrentJob) {
  195. if ($recurrentJob->isFindable()) {
  196. $this->recurrentJobsPersister->replaceOne($recurrentJob);
  197. }
  198. }
  199. }
  200. if ($event->getProfile()->getState() > Profile::STATE_EMPTY && $event->getProfile()->getUser()->getCreatedVia() === User::CREATED_VIA_RECRUIT_DL_RECURRENT_JOB_LANDINGPAGE) {
  201. /** @var ExtendedApplication|null $extendedApplication */
  202. $extendedApplication = $this->entityManager->getRepository(ExtendedApplication::class)->findOneBy(['jobseekerProfile' => $event->getProfile()->getId()]);
  203. if (!is_null($extendedApplication)) {
  204. $jobseekerProfileId = $event->getProfile()->getId();
  205. if (!$this->platformEventService->hasEventOccuredInLastNDaysForAdditionalData(
  206. PlatformEvent::EVENT_TYPE_ASK_USER_FOR_GOOGLE_RATINGS_WHATSAPP_MESSAGE_WAS_SENT,
  207. 10,
  208. $jobseekerProfileId
  209. )) {
  210. $this->platformEventService->eventHasOccurred(
  211. PlatformEvent::EVENT_TYPE_ASK_USER_FOR_GOOGLE_RATINGS_WHATSAPP_MESSAGE_WAS_SENT,
  212. $jobseekerProfileId
  213. );
  214. $this->messageBus->dispatch(
  215. new AskNewUserForGoogleRatingSymfonyMessage($extendedApplication)
  216. );
  217. }
  218. }
  219. }
  220. }
  221. /** @throws Exception */
  222. public function onProfilePhotoAdded(ProfileEvent $event)
  223. {
  224. $this->usageEventService->eventHasOccurredForUser(
  225. $event->getProfile()->getUser(),
  226. UsageEvent::EVENT_TYPE_USER_HAS_ADDED_PROFILE_PICTURE
  227. );
  228. $this->businessEventDomainService->writeNewEvent(
  229. BusinessEvent::EVENT_TYPE_PROFILE_PHOTO_WAS_ADDED,
  230. $event->getProfile()->getUser()
  231. );
  232. }
  233. /** @throws Exception */
  234. public function onProfilePhotoRemoved(ProfileEvent $event)
  235. {
  236. $this->usageEventService->eventHasOccurredForUser(
  237. $event->getProfile()->getUser(),
  238. UsageEvent::EVENT_TYPE_USER_HAS_DELETED_PROFILE_PICTURE
  239. );
  240. $this->businessEventDomainService->writeNewEvent(
  241. BusinessEvent::EVENT_TYPE_PROFILE_PHOTO_WAS_DELETED,
  242. $event->getProfile()->getUser()
  243. );
  244. }
  245. }