src/Aqarmap/Bundle/ListingBundle/EventListener/ListingRuleListener.php line 218
<?phpnamespace Aqarmap\Bundle\ListingBundle\EventListener;use App\Constant\LabelCode;use Aqarmap\Bundle\CreditBundle\Constant\CreditStatus;use Aqarmap\Bundle\CreditBundle\Contract\CreditManagerInterface;use Aqarmap\Bundle\CreditBundle\Entity\Credit;use Aqarmap\Bundle\ListingBundle\Constant\ListingCategories;use Aqarmap\Bundle\ListingBundle\Constant\ListingFeaturedStatus;use Aqarmap\Bundle\ListingBundle\Constant\ListingSource;use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;use Aqarmap\Bundle\ListingBundle\Entity\Listing;use Aqarmap\Bundle\ListingBundle\Event\ListingEvent;use Aqarmap\Bundle\ListingBundle\Event\ListingFeatureEvent;use Aqarmap\Bundle\ListingBundle\Service\Contracts\ListingFeatureServiceInterface;use Aqarmap\Bundle\ListingBundle\Service\ListingFeatureService;use Aqarmap\Bundle\ListingBundle\Service\ListingManager;use Aqarmap\Bundle\ListingBundle\Service\ListingRuleMatcher;use Aqarmap\Bundle\ListingBundle\Service\SpecialAddListingService;use Aqarmap\Bundle\UserBundle\Constant\UserServicesType;use Aqarmap\Bundle\UserBundle\Services\UserServicesManager;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\EventDispatcher\EventDispatcherInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\RequestStack;use Symfony\Component\Routing\RouterInterface;use Symfony\Contracts\Translation\TranslatorInterface;class ListingRuleListener implements EventSubscriberInterface{public function __construct(private readonly ListingRuleMatcher $listingRuleMatcher, private readonly CreditManagerInterface $creditManager, private readonly ListingManager $listingManager, private readonly EntityManagerInterface $entityManager, private readonly ListingFeatureServiceInterface $listingFeatureService, private readonly RequestStack $requestStack, private readonly TranslatorInterface $translator, private readonly RouterInterface $router, private readonly SpecialAddListingService $specialAddListingService, private readonly UserServicesManager $userServicesManager, private readonly EventDispatcherInterface $dispatcher){}public function preSaveListingEvent(ListingEvent $event): void{$listing = $event->getListing();if (!$listing->isDraft()&& !$listing->isLive()&& ListingCategories::FIRST_LISTING_FOR_FREE === $listing->getCategory()) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING, false);return;}$publicationCredit = $listing->getPublicationCredit();/** @var ListingRuleMatcher $matcher */$matcher = $this->listingRuleMatcher;$listingRule = $matcher->match($listing);$listingRulesRequirePhotos = ($listingRule['required_photos'] && $listing->getPhotos()->count() < $listingRule['required_photos']);$listingHasTitle = $listing->getTitle();if ($listingRulesRequirePhotos && $listingHasTitle) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PHOTOS);}if (!$listing->isDraft()&& !$listing->isLive()&& !$listing->isProjectOrUnit()&& ListingStatus::PENDING != $listing->getStatus()&& ListingStatus::PENDING_PAYMENT != $listing->getStatus()&& $listing->getPhotos()->count() >= $listingRule['required_photos']) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PAYMENT, false);}// If listing is PENDING_PAYMENT, the user already paid the feesif (ListingStatus::PENDING_PAYMENT === $listing->getStatus()) {if ($publicationCredit) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING, false);}}// ----------------------------------------------------------------------// Toggle the listing's category on location change.// ----------------------------------------------------------------------$isPaid = ListingCategories::PAID === $listing->getCategory();$isScrapped = ListingCategories::SCRAPPED === $listing->getCategory();$isUnlimited = ListingCategories::UNLIMITED === $listing->getCategory();if (!$isPaid && !$isScrapped && !$isUnlimited && $listingRule['publication_fees'] > 0) {$listing->setCategory(ListingCategories::PAID);if (ListingStatus::PENDING === $listing->getStatus() && !$publicationCredit) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PAYMENT, false);}}if (!$isPaid && !$isScrapped && !$isUnlimited && $listingHasTitle && $listingRule['publication_fees'] <= 0&& \in_array($listing->getStatus(), [ListingStatus::PENDING_PAYMENT, ListingStatus::DRAFT])) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING, false);}if ($isPaid && !$isScrapped && !$isUnlimited && $listingRule['publication_fees'] <= 0) {$listing->setCategory(ListingCategories::NORMAL);if (ListingStatus::PENDING_PAYMENT === $listing->getStatus()) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PAYMENT, false);}}if ($this->getListingManager()->isListingUserEbawab($listing)) {$listing->setCategory(ListingCategories::EBAWAB);}if ($this->getListingManager()->isListingUserManualScraped($listing)) {$listing->setCategory(ListingCategories::SCRAPPED);$this->listingManager->addLabelByCode($listing, LabelCode::LISTING_SCRAPPED);}}public function onSubmittedEvent(ListingEvent $event): void{/** @var Listing $listing */$listing = $event->getListing();$matcher = $this->listingRuleMatcher;$listingRule = $matcher->match($listing);if (!$listingRule['flf2'] && ListingCategories::PAID === $listing->getCategory() && $this->listingManager->isEligibleForFreePublishing($listing)) {$this->listingManager->createFirstListingForFree($listing);}if (ListingSource::LITE == $listing->getSource()|| ListingSource::SCRAPPING == $listing->getSource()|| ListingCategories::FIRST_LISTING_FOR_FREE === $listing->getCategory()) {return;}if ($listingRule['publication_fees'] > 0 && $listing->getPhotos()->count() >= $listingRule['required_photos']) {if (($this->specialAddListingService->hasSpecialAddListingGroup($listing->getUser())&& !$listing->getSpecialPublicationCredit())|| (!$this->specialAddListingService->hasSpecialAddListingGroup($listing->getUser())&& !$listing->getPublicationCredit())) {$this->getListingManager()->changeStatus($listing, ListingStatus::PENDING_PAYMENT, true, true);}}}public function onSubmittedStatusRedirectionEvent(ListingEvent $event): void{/** @var Listing $listing */$listing = $event->getListing();$userId = $listing->getUser();if ($this->specialAddListingService->hasSpecialAddListingGroup($userId)) {$userUnlimitedListings = $this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS, $userId);if (!$userUnlimitedListings || ($userUnlimitedListings && 0 == $userUnlimitedListings['remainingQuota'])) {$event->setResponse($this->redirect('listing_slug',['id' => $listing->getId(), 'slug' => $listing->getSlug()]));return;}}switch ($listing->getStatus()) {case ListingStatus::PENDING_PAYMENT:$event->setResponse($this->redirect('listing_confirm_publish_credit',['id' => $listing->getId()]));break;case ListingStatus::PENDING_PHOTOS:$this->setFlashMessage('info', $this->getTranslator()->trans('add_listing_page.success_messages.add_photos_message'));$event->setResponse($this->redirect('listing_upload',['id' => $event->getListing()->getId()]));break;}}/*** @throws \Exception*/public function onListingPublishEvent(ListingEvent $event): void{$listing = $event->getListing();$listingPublishPaid = $listing->getPublicationCredit();$listingPublishFeatured = $listing->getFeaturedPublicationCredit();$listingRule = $this->listingRuleMatcher->match($listing);if (ListingCategories::FIRST_LISTING_FOR_FREE === $listing->getCategory()) {$listing->setExpiresAt(new \DateTime('+'.$listingRule['first_free_duration'].' days'));return;}if ($listingRule['duration'] && (!$listing->getExpiresAt() || new \DateTime() >= $listing->getExpiresAt())) {$listing->setExpiresAt(new \DateTime('+'.$listingRule['duration'].' days'));}if ($listingPublishPaid) {if (!$listingPublishPaid->getExpiresAt()) {$listingPublishPaid->setExpiresAt($listing->getExpiresAt());}}if ($listingPublishFeatured) {if (!$listingPublishFeatured->getExpiresAt() && !$listingPublishFeatured->getFeaturingStatus()) {$duration = $this->getListingFeaturingService()->getFeaturedTypeDuration($listingRule, $listingPublishFeatured->getType());$listingPublishFeatured->setExpiresAt(new \DateTime('+'.$duration.' days'));$this->dispatcher->dispatch(new ListingFeatureEvent($listingPublishFeatured), 'aqarmap.listing.feature.bumpup');}}}public function onFeaturingListingApprovalEvent(ListingEvent $event): void{$listing = $event->getListing();$listingPublishFeatured = $listing->getFeaturedPublicationCredit();$listingManager = $this->getListingManager();$listingFeatureService = $this->getListingFeaturingService();$listingRule = $listingManager->getListingRules($listing);if ($listingPublishFeatured && ListingStatus::LIVE == $listing->getStatus()) {$listing->setFeatured($listingFeatureService->getListingFeaturedType($listingPublishFeatured->getType()));$listingPublishFeatured->setFeaturingStatus(ListingFeaturedStatus::APPROVED);$listingPublishFeatured->setApprovedAt(new \DateTime());if (!$listingPublishFeatured->getExpiresAt()) {$duration = $this->getListingFeaturingService()->getFeaturedTypeDuration($listingRule, $listingPublishFeatured->getType());$listingPublishFeatured->setExpiresAt(new \DateTime('+'.$duration.' days'));}}$em = $this->getEntityManager();$em->persist($listing);$em->flush();}/*** @throws \Exception*/public function onFeaturingListingRejectEvent(ListingEvent $event): void{$listing = $event->getListing();$listingFeatured = $listing->getLastListingFeature();if (ListingStatus::LIVE == $listing->getStatus()) {$listingFeatured->setFeaturingStatus(ListingFeaturedStatus::REJECTED);$listingFeatured->setExpiresAt(new \DateTime('-2 days'));}$em = $this->getEntityManager();$em->persist($listingFeatured);$featureTypeLabel = $this->getTranslator()->trans($listingFeatured->getPendingFeaturedLabel());$balance = $this->creditManager->getBalance($listing->getUser());$amount = abs($listingFeatured->getCredit()->getAmount());$credit = new Credit();$credit->setUser($listing->getUser())->setAmount(abs($listingFeatured->getCredit()->getAmount()))->setDescription('Rejected to be '.$featureTypeLabel)->setBalance($balance + $amount)->setStatus(CreditStatus::SUCCESS)->setCreatedAt(new \DateTime());$em->persist($credit);$em->flush();}public function getEntityManager(){return $this->entityManager;}/*** @return TranslatorInterface*/public function getTranslator(){return $this->translator;}public static function getSubscribedEvents(): array{return ['aqarmap.listing.pre_save' => ['preSaveListingEvent'],'aqarmap.listing.submitted' => [['onSubmittedEvent'], ['onSubmittedStatusRedirectionEvent']],'aqarmap.listing.resubmitted' => [['onSubmittedEvent'], ['onSubmittedStatusRedirectionEvent']],'aqarmap.listing.publish' => ['onListingPublishEvent'],'aqarmap.listing.featuring.approved' => ['onFeaturingListingApprovalEvent'],'aqarmap.listing.free_publish' => ['onListingPublishEvent'],'aqarmap.listing.publish_without_photos' => ['onListingPublishEvent'],'aqarmap.listing.featuring.rejected' => ['onFeaturingListingRejectEvent'],];}/*** @return ListingManager*/protected function getListingManager(){return $this->listingManager;}/*** @return ListingFeatureService*/protected function getListingFeaturingService(){return $this->listingFeatureService;}/*** @param string $type* @param string $message*/private function setFlashMessage($type, $message): void{if (($req = $this->requestStack->getCurrentRequest()) && $req->hasPreviousSession()) {$req->getSession()->getFlashBag()->add($type, $message);}}private function redirect($route, $parameters = []){return new RedirectResponse($this->router->generate($route, $parameters),\Symfony\Component\HttpFoundation\Response::HTTP_FOUND);}}