src/Aqarmap/Bundle/ListingBundle/EventListener/ListingStatusListener.php line 262
<?phpnamespace Aqarmap\Bundle\ListingBundle\EventListener;use App\Message\Listing\AfterChangeStatusMessage;use Aqarmap\Bundle\CreditBundle\Constant\CreditStatus;use Aqarmap\Bundle\CreditBundle\Contract\CreditManagerInterface;use Aqarmap\Bundle\CreditBundle\Entity\Credit;use Aqarmap\Bundle\ListingBundle\Constant\ListingActivityType;use Aqarmap\Bundle\ListingBundle\Constant\ListingCategories;use Aqarmap\Bundle\ListingBundle\Constant\ListingFeatures;use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;use Aqarmap\Bundle\ListingBundle\Document\ListingActivityLog;use Aqarmap\Bundle\ListingBundle\Entity\Listing;use Aqarmap\Bundle\ListingBundle\Event\ListingEvent;use Aqarmap\Bundle\ListingBundle\Message\ListingDeleted;use Aqarmap\Bundle\ListingBundle\Service\ListingManager;use Aqarmap\Bundle\ListingBundle\Service\ListingRuleMatcher;use Aqarmap\Bundle\ListingBundle\Service\SpecialAddListingService;use Aqarmap\Bundle\MainBundle\Adapter\MailerServiceInterface;use Aqarmap\Bundle\MainBundle\Constant\ActivityType;use Aqarmap\Bundle\MainBundle\Constant\Locales;use Aqarmap\Bundle\MainBundle\Helpers\MailerHelper;use Aqarmap\Bundle\MainBundle\Service\ActivityLogger;use Aqarmap\Bundle\NotificationBundle\Types\ListingHasExpired;use Aqarmap\Bundle\UserBundle\Constant\UserTypes;use Aqarmap\Bundle\UserBundle\Entity\User;use Doctrine\Common\Collections\ArrayCollection;use Doctrine\ODM\MongoDB\DocumentManager;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\Messenger\MessageBusInterface;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;use Symfony\Contracts\Translation\TranslatorInterface;use Twig\Environment;class ListingStatusListener implements EventSubscriberInterface{/*** @var MailerServiceInterface*/protected $mailer;/*** Constructor.*/public function __construct(MailerServiceInterface $mailer,private readonly EntityManagerInterface $entityManager,private readonly TokenStorageInterface $tokenStorage,private readonly ListingRuleMatcher $listingRuleMatcher,private readonly CreditManagerInterface $creditManager,private readonly ActivityLogger $activityLogger,private readonly EventDispatcherInterface $eventDispatcher,private readonly TranslatorInterface $translator,private readonly ListingManager $listingManager,private readonly Environment $engine,private readonly MailerHelper $mailerHelper,private readonly ParameterBagInterface $parameterBag,private readonly SpecialAddListingService $specialAddListingService,private readonly MessageBusInterface $messageBus,private readonly DocumentManager $documentManager,) {$this->mailer = $mailer;}public function preSaveListingEvent(ListingEvent $event): void{$listing = $event->getListing();if (null === $listing->getStatus()) {$this->getListingManager()->changeStatus($listing, ListingStatus::DRAFT, false);}}public function onSubmittedEvent(ListingEvent $event): void{$listing = $event->getListing();// Add or edit status$isDraftOrLive = \in_array($listing->getStatus(), [ListingStatus::DRAFT,ListingStatus::LIVE,ListingStatus::REJECTED,]);// Checking the title to prevent in-complete listings (multi-steps form) from being approvedif ($isDraftOrLive && !empty($listing->getTitle())) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING, true);}if ($this->specialAddListingService->hasSpecialAddListingGroup($listing->getUser())&& ListingStatus::PENDING_PAYMENT === $listing->getStatus()&& $listing->getSpecialPublicationCredit()) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING, true);}}public function onListingPublishEvent(ListingEvent $event): void{$listing = $event->getListing();$user = $listing->getUser();// unsetting pending payment and photos statuses$listing->setPendingPaymentStatus(null);$listing->setPendingPhotosStatus(null);// If no publish did already or the listing is expired and being relisted give it a bumpif (!$listing->getPublishedAt() || ListingStatus::EXPIRED == $listing->getStatus()) {$listing->setPublishedAt(new \DateTime());}$em = $this->entityManager;$userListingsCount = $em->getRepository(Listing::class)->getUserListingsCountByStatus($user, [ListingStatus::LIVE]);$token = $this->tokenStorage->getToken();// Only flag if user has more than 3 listings and he is not already flaggedif ($token&& !$user->hasRole('ROLE_IN_HOUSE')&& $userListingsCount >= 2&& UserTypes::INDIVIDUAL == $user->getUserType()) {$user->setUserType(UserTypes::BROKER);$em->persist($user);$em->flush($user);}$listing->addRejections(new ArrayCollection());}public function onListingPublishForFreeEvent(ListingEvent $event): void{$listing = $event->getListing();$listingRules = $this->listingRuleMatcher->match($listing);if ($listingRules['publication_fees']) {$creditManager = $this->creditManager;$credits = $creditManager->deduction($listing->getUser(), (float) 0, 'Free publishing', CreditStatus::SUCCESS);foreach ($credits as $credit) {if ($credit instanceof Credit) {$this->getListingManager()->addFeature($listing, ListingFeatures::PAID, null, $credit);}}// Record this action in the activity logger with the acting userif (ListingCategories::SCRAPPED != $listing->getCategory()) {$actor = $this->tokenStorage->getToken()?->getUser();if (!$actor instanceof User) {$actor = $listing->getUser();}$this->activityLogger->record(ActivityType::LISTING_FREE_PUBLISH, $actor, $listing->getId());}}}public function onPublishedForFreeEmailEvent(ListingEvent $event): void{$listing = $event->getListing();$originalLocale = $this->getTranslator()->getLocale();$this->getTranslator()->setLocale($this->getListingLanguage($listing));$template = '@AqarmapListingBundle/Admin/Email/listingApprovedForFree.html.twig';$templateContext = ['listing' => $listing];$compose = $this->getComposeMessage($listing, $template, $templateContext, 'listings-free-publish');$this->getMailer()->sendMessage($compose);$this->getTranslator()->setLocale($originalLocale);}/*** Unset DeletedAt date on undelete event.*/public function onListingUndeleteEvent(ListingEvent $event): void{$listing = $event->getListing();$listing->setDeletedAt(null);}/*** Refund listing credit on delete event.*/public function onListingDeleteEvent(ListingEvent $event): void{$listing = $event->getListing();$listingFeatured = $listing->getNotExpiredCredit();/*Refund Policy,listings should have paid features that are not expired yet,Also the listing should never been published before.*/if (!empty($listingFeatured) && !$listing->getPublishedAt()) {foreach ((array) $listingFeatured as $listingFees) {$credits[] = $listingFees->getCredit();}$creditManager = $this->creditManager;$em = $this->getEntityManager();foreach ($credits as $credit) {if ($credit->canBeCancelled()) {$creditManager->deposit($credit->getUser(), -$credit->getAmount(), CreditStatus::SUCCESS, CreditStatus::REFUND_LABEL);$credit->setStatus(CreditStatus::REFUND);$em->persist($credit);}}$em->flush();}$listing->setDeletedAt(new \DateTime());}/*** Refund listing credit on delete event.*/public function onListingStatusDeleteEvent(ListingEvent $event): void{$this->messageBus->dispatch(new ListingDeleted($event->getListing()));}public function onApprovedSendEmailEvent(ListingEvent $event): void{$listing = $event->getListing();$originalLocale = $this->getTranslator()->getLocale();$this->getTranslator()->setLocale($this->getListingLanguage($listing));$template = '@AqarmapListingBundle/Admin/Email/listingApproved.html.twig';$templateContext = ['listing' => $listing];$compose = $this->getComposeMessage($listing, $template, $templateContext, 'listings-approval');$this->getMailer()->sendMessage($compose);$this->getTranslator()->setLocale($originalLocale);}public function onListingExpiredEvent(ListingEvent $event): void{$listing = $event->getListing();$this->eventDispatcher->dispatch((new ListingHasExpired())->setSubject($listing), 'listing.has.expired');}public function onListingPhotosDeleted(ListingEvent $event): void{$listing = $event->getListing();$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PHOTOS, true);}/*** @return object*/public function getEntityManager(){return $this->entityManager;}/*** @return MailerServiceInterface*/public function getMailer(){return $this->mailer;}/*** @return \Symfony\Component\Translation\LoggingTranslator*/public function getTranslator(){return $this->translator;}public function getTemplating(){return $this->engine;}public function changeListingWaitingTime(ListingEvent $event): void{$now = new \DateTime();$listing = $event->getListing();$activityRepo = $this->documentManager->getRepository(ListingActivityLog::class);$lastActivityWaitingTime = $activityRepo->getLastActivity($listing->getId(), ListingActivityType::PENDING_APPROVAL);$listing->setWaitingTime($lastActivityWaitingTime ? $now->getTimestamp() - $lastActivityWaitingTime->getCreatedAt()->getTimestamp() : null);$this->entityManager->persist($listing);$this->entityManager->flush();}public function onListingStatusPendingEvent(ListingEvent $event): void{$listing = $event->getListing();if (!$listing->getPendingStatusCreatedAt() && !$event->getIsAdmin()) {$listing->setPendingStatusCreatedAt(new \DateTime());}$listing->setAutoReviewedAt(null);}public function onListingStatusChangedEvent(ListingEvent $event): void{$listing = $event->getListing();if ($listing->getId()) {$this->messageBus->dispatch(new AfterChangeStatusMessage($listing->getId()));}}public static function getSubscribedEvents(): array{return ['aqarmap.listing.pre_save' => ['preSaveListingEvent'],'aqarmap.listing.publish' => [['onListingPublishEvent', 100], ['changeListingWaitingTime'],],'aqarmap.listing.submitted' => ['onSubmittedEvent', 100],'aqarmap.listing.expired' => ['onListingExpiredEvent'],'aqarmap.listing.undelete' => ['onListingUndeleteEvent'],'aqarmap.listing.delete' => [['onListingStatusDeleteEvent'], ['onListingDeleteEvent']],'aqarmap.listing.delete_by_user' => ['onListingStatusDeleteEvent'],'aqarmap.listing.free_publish' => [['onListingPublishForFreeEvent'], ['onListingPublishEvent'], ['onPublishedForFreeEmailEvent'],],'aqarmap.listing.publish_without_photos' => [['onListingPublishForFreeEvent'], ['onListingPublishEvent'],],'aqarmap.listing.photos_deleted' => ['onListingPhotosDeleted'],'aqarmap.listing.rejected' => ['changeListingWaitingTime'],'aqarmap.listing.pending_approval' => ['onListingStatusPendingEvent'],'aqarmap.listing.after_change_status' => ['onListingStatusChangedEvent'],];}/*** @return ListingManager*/protected function getListingManager(){return $this->listingManager;}private function getComposeMessage($listing, $template, $templateContext, $headerCategory){$composeMessage = $this->mailerHelper->createMessageWithGlobalAttributes();$composeMessage->setSubject($this->getTranslator()->trans('email.subject.listing_approved'));$composeMessage->setTo($listing->getUser()->getEmailCanonical());$composeMessage->setReplyTo($listing->getUser()->getEmailCanonical());$composeMessage->setTemplate($template);$composeMessage->setTemplateContext($templateContext);$compose = $this->getMailer()->composeMessage($composeMessage);$compose->getHeaders()->addTextHeader('X-Mail-Category', $headerCategory);$compose->getHeaders()->addTextHeader('X-Site-Country', $this->parameterBag->get('country'));return $compose;}private function getListingLanguage($listing){$language = Locales::AR;if (null !== $listing->getUser()->getLanguage()) {$language = $listing->getUser()->getLanguage();}return $language;}}