src/Aqarmap/Bundle/ListingBundle/Controller/ListingController.php line 467

Open in your IDE?
  1. <?php
  2. namespace Aqarmap\Bundle\ListingBundle\Controller;
  3. use App\Exception\LogicHttpException;
  4. use Aqarmap\Bundle\CreditBundle\Constant\CreditStatus;
  5. use Aqarmap\Bundle\CreditBundle\Entity\Credit;
  6. use Aqarmap\Bundle\CreditBundle\Services\CreditManager;
  7. use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
  8. use Aqarmap\Bundle\FinancialAidsBundle\Service\FinancialAidService;
  9. use Aqarmap\Bundle\ListingBundle\Constant\LeadTypes;
  10. use Aqarmap\Bundle\ListingBundle\Constant\ListingCategories;
  11. use Aqarmap\Bundle\ListingBundle\Constant\ListingFeaturedTypes;
  12. use Aqarmap\Bundle\ListingBundle\Constant\ListingFeatures;
  13. use Aqarmap\Bundle\ListingBundle\Constant\ListingSections;
  14. use Aqarmap\Bundle\ListingBundle\Constant\ListingSellerRoles;
  15. use Aqarmap\Bundle\ListingBundle\Constant\ListingSource;
  16. use Aqarmap\Bundle\ListingBundle\Constant\ListingStatus;
  17. use Aqarmap\Bundle\ListingBundle\Constant\PropertyRegistrationStatusOption;
  18. use Aqarmap\Bundle\ListingBundle\Constant\ResaleListingsConstant;
  19. use Aqarmap\Bundle\ListingBundle\Contracts\PhoneManagerInterface;
  20. use Aqarmap\Bundle\ListingBundle\Contracts\RelatedResultServiceInterface;
  21. use Aqarmap\Bundle\ListingBundle\Entity\CallRequest;
  22. use Aqarmap\Bundle\ListingBundle\Entity\Listing;
  23. use Aqarmap\Bundle\ListingBundle\Entity\ListingPhone;
  24. use Aqarmap\Bundle\ListingBundle\Entity\Phone;
  25. use Aqarmap\Bundle\ListingBundle\Entity\Section;
  26. use Aqarmap\Bundle\ListingBundle\Event\ListingEvent;
  27. use Aqarmap\Bundle\ListingBundle\Exception\InvalidLeadValidationHttpException;
  28. use Aqarmap\Bundle\ListingBundle\Form\AdvancedFilterType;
  29. use Aqarmap\Bundle\ListingBundle\Form\AdvancedSearchType;
  30. use Aqarmap\Bundle\ListingBundle\Form\CallRequestFormType;
  31. use Aqarmap\Bundle\ListingBundle\Form\ContactSellerFormType;
  32. use Aqarmap\Bundle\ListingBundle\Form\ContactSellerWideFormType;
  33. use Aqarmap\Bundle\ListingBundle\Form\LandingPageFormType;
  34. use Aqarmap\Bundle\ListingBundle\Form\ListingInitializeType;
  35. use Aqarmap\Bundle\ListingBundle\Form\ListingType;
  36. use Aqarmap\Bundle\ListingBundle\Form\LiteListingType;
  37. use Aqarmap\Bundle\ListingBundle\Form\Model\LandingPage;
  38. use Aqarmap\Bundle\ListingBundle\Form\MultipleSearchFormType;
  39. use Aqarmap\Bundle\ListingBundle\Form\PhotoType;
  40. use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;
  41. use Aqarmap\Bundle\ListingBundle\Repository\ListingPhotoRepository;
  42. use Aqarmap\Bundle\ListingBundle\Service\AdvancedFilterFormTypeManager;
  43. use Aqarmap\Bundle\ListingBundle\Service\AdvancedSearchFormTypeManager;
  44. use Aqarmap\Bundle\ListingBundle\Service\CallRequestManager;
  45. use Aqarmap\Bundle\ListingBundle\Service\Contracts\ListingLeadManagerInterface;
  46. use Aqarmap\Bundle\ListingBundle\Service\Contracts\LocationManagerInterface;
  47. use Aqarmap\Bundle\ListingBundle\Service\FreeListingService;
  48. use Aqarmap\Bundle\ListingBundle\Service\InteractionService;
  49. use Aqarmap\Bundle\ListingBundle\Service\ListingFeatureService;
  50. use Aqarmap\Bundle\ListingBundle\Service\ListingManager;
  51. use Aqarmap\Bundle\ListingBundle\Service\ListingRuleMatcher;
  52. use Aqarmap\Bundle\ListingBundle\Service\Mortgage\MortgageService;
  53. use Aqarmap\Bundle\ListingBundle\Service\SpecialAddListingService;
  54. use Aqarmap\Bundle\ListingBundle\Service\SpecialListingFeatureDecorator;
  55. use Aqarmap\Bundle\ListingBundle\Service\V4\CompoundDetailService;
  56. use Aqarmap\Bundle\MainBundle\Form\ConfirmFeaturedFormType;
  57. use Aqarmap\Bundle\MainBundle\Form\ConfirmFormType;
  58. use Aqarmap\Bundle\MainBundle\Service\MobileDetectionService;
  59. use Aqarmap\Bundle\MainBundle\Service\Setting;
  60. use Aqarmap\Bundle\MessageBundle\Service\Composer;
  61. use Aqarmap\Bundle\NeighborhoodBundle\Service\NeighborhoodManager;
  62. use Aqarmap\Bundle\NotificationBundle\DatabaseNotification;
  63. use Aqarmap\Bundle\NotifierBundle\Event\NotifierEvent;
  64. use Aqarmap\Bundle\OTPBundle\Contract\OtpServiceInterface;
  65. use Aqarmap\Bundle\SearchBundle\Services\CompoundFaqsService;
  66. use Aqarmap\Bundle\SearchBundle\Services\ElasticListingSearch\DefaultListingSearch;
  67. use Aqarmap\Bundle\TopSellerBundle\Model\TopSeller;
  68. use Aqarmap\Bundle\TopSellerBundle\Service\TopSellerRetrievalService;
  69. use Aqarmap\Bundle\UserBundle\Constant\UserServicesType;
  70. use Aqarmap\Bundle\UserBundle\Constant\UserTypes;
  71. use Aqarmap\Bundle\UserBundle\Entity\User;
  72. use Aqarmap\Bundle\UserBundle\Entity\UserServices;
  73. use Aqarmap\Bundle\UserBundle\Form\QuickRegistrationFormType;
  74. use Aqarmap\Bundle\UserBundle\Repository\UserPackagesRepository;
  75. use Aqarmap\Bundle\UserBundle\Services\UserActivityService;
  76. use Aqarmap\Bundle\UserBundle\Services\UserManager;
  77. use Aqarmap\Bundle\UserBundle\Services\UserPackagesService;
  78. use Aqarmap\Bundle\UserBundle\Services\UserServicesManager;
  79. use Doctrine\ORM\EntityManager;
  80. use Doctrine\ORM\EntityManagerInterface;
  81. use FOS\RestBundle\Controller\Annotations as Rest;
  82. use FOS\RestBundle\View\View;
  83. use FOS\UserBundle\Model\UserManagerInterface;
  84. use Gedmo\Translatable\TranslatableListener;
  85. use Knp\Component\Pager\PaginatorInterface;
  86. use Liip\ImagineBundle\Imagine\Cache\CacheManager;
  87. use Predis\ClientInterface as RedisClient;
  88. use Psr\Log\LoggerInterface;
  89. use Psr\Log\LogLevel;
  90. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  91. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  92. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  93. use Symfony\Component\Form\FormInterface;
  94. use Symfony\Component\HttpFoundation\JsonResponse;
  95. use Symfony\Component\HttpFoundation\RedirectResponse;
  96. use Symfony\Component\HttpFoundation\Request;
  97. use Symfony\Component\HttpFoundation\Response;
  98. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  99. use Symfony\Component\Routing\Annotation\Route;
  100. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  101. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  102. use Symfony\Contracts\Translation\TranslatorInterface;
  103. use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
  104. /**
  105.  * Listing controller.
  106.  */
  107. class ListingController extends AbstractController
  108. {
  109.     /**
  110.      * @var Composer
  111.      */
  112.     private $messageComposer;
  113.     /**
  114.      * @var DatabaseNotification
  115.      */
  116.     private $databaseNotification;
  117.     /**
  118.      * @var LoggerInterface
  119.      */
  120.     private $logger;
  121.     /**
  122.      * @var TranslatorInterface
  123.      */
  124.     private $translator;
  125.     /**
  126.      * @var FeatureToggleManager
  127.      */
  128.     private $featureToggleManager;
  129.     /**
  130.      * @var Setting
  131.      */
  132.     private $setting;
  133.     /**
  134.      * @var ListingManager
  135.      */
  136.     private $listingManager;
  137.     /**
  138.      * @var EventDispatcherInterface
  139.      */
  140.     private $dispatcher;
  141.     /**
  142.      * @var InteractionService
  143.      */
  144.     private $interactionService;
  145.     /**
  146.      * @var NeighborhoodManager
  147.      */
  148.     private $neighborhoodManager;
  149.     /**
  150.      * @var DefaultListingSearch
  151.      */
  152.     private $defaultListingSearch;
  153.     /**
  154.      * @var RelatedResultServiceInterface
  155.      */
  156.     private $relatedResultService;
  157.     /**
  158.      * @var TopSellerRetrievalService
  159.      */
  160.     private $topSellerRetrievalService;
  161.     /**
  162.      * @var FinancialAidService
  163.      */
  164.     private $financialAidService;
  165.     /**
  166.      * @var ListingLeadManagerInterface
  167.      */
  168.     private $listingLeadManager;
  169.     /**
  170.      * @var CompoundFaqsService
  171.      */
  172.     private $compoundFaqsService;
  173.     /**
  174.      * @var PaginatorInterface
  175.      */
  176.     private $paginator;
  177.     /**
  178.      * @var UserActivityService
  179.      */
  180.     private $userActivityService;
  181.     /**
  182.      * @var MobileDetectionService
  183.      */
  184.     private $mobileDetectionService;
  185.     /**
  186.      * @var RedisClient
  187.      */
  188.     private $redis;
  189.     /**
  190.      * @var CacheManager
  191.      */
  192.     private $imagine;
  193.     /**
  194.      * @var UploaderHelper
  195.      */
  196.     private $uploaderHelper;
  197.     /**
  198.      * @var CallRequestManager
  199.      */
  200.     private $callRequestManager;
  201.     /**
  202.      * @var AuthorizationCheckerInterface
  203.      */
  204.     private $authorizationChecker;
  205.     /**
  206.      * @var TokenStorage
  207.      */
  208.     private $tokenStorage;
  209.     /**
  210.      * @var MortgageService
  211.      */
  212.     private $mortgageService;
  213.     /**
  214.      * @var ListingRuleMatcher
  215.      */
  216.     private $listingRuleMatcher;
  217.     /**
  218.      * @var CreditManager
  219.      */
  220.     private $creditManager;
  221.     /**
  222.      * @var UserServicesManager
  223.      */
  224.     private $userServicesManager;
  225.     /**
  226.      * @var UserManagerInterface
  227.      */
  228.     private $FOSUserManager;
  229.     /**
  230.      * @var PhoneManagerInterface
  231.      */
  232.     private $phoneManager;
  233.     /**
  234.      * @var ListingFeatureService
  235.      */
  236.     private $listingFeatureService;
  237.     private UserManager $userManager;
  238.     /**
  239.      * @var AdvancedSearchFormTypeManager
  240.      */
  241.     private $advancedSearchFormTypeManager;
  242.     /**
  243.      * @var AdvancedFilterFormTypeManager
  244.      */
  245.     private $advancedFilterFormTypeManager;
  246.     /** @var CompoundDetailService */
  247.     private $compoundDetailService;
  248.     /** @var TranslatableListener */
  249.     private $translatableListener;
  250.     /** @var EntityManagerInterface */
  251.     private $entityManager;
  252.     /** @var UserPackagesRepository */
  253.     private $userPackagesRepository;
  254.     public function __construct(
  255.         Composer $messageComposer,
  256.         OtpServiceInterface $otpService,
  257.         DatabaseNotification $databaseNotification,
  258.         LoggerInterface $logger,
  259.         TranslatorInterface $translator,
  260.         FeatureToggleManager $featureToggleManager,
  261.         Setting $setting,
  262.         ListingManager $listingManager,
  263.         EventDispatcherInterface $dispatcher,
  264.         InteractionService $interactionService,
  265.         NeighborhoodManager $neighborhoodManager,
  266.         DefaultListingSearch $defaultListingSearch,
  267.         RelatedResultServiceInterface $relatedResultService,
  268.         LocationManagerInterface $locationManager,
  269.         TopSellerRetrievalService $topSellerRetrievalService,
  270.         FinancialAidService $financialAidService,
  271.         ListingLeadManagerInterface $listingLeadManager,
  272.         CompoundFaqsService $compoundFaqsService,
  273.         PaginatorInterface $paginator,
  274.         UserActivityService $userActivityService,
  275.         MobileDetectionService $mobileDetectionService,
  276.         RedisClient $redis,
  277.         CacheManager $imagine,
  278.         UploaderHelper $uploaderHelper,
  279.         CallRequestManager $callRequestManager,
  280.         AuthorizationCheckerInterface $authorizationChecker,
  281.         TokenStorageInterface $tokenStorage,
  282.         MortgageService $mortgageService,
  283.         ListingRuleMatcher $listingRuleMatcher,
  284.         CreditManager $creditManager,
  285.         UserServicesManager $userServicesManager,
  286.         UserManagerInterface $FOSUserManager,
  287.         PhoneManagerInterface $phoneManager,
  288.         FreeListingService $freeListingService,
  289.         ListingFeatureService $listingFeatureService,
  290.         UserManager $userManager,
  291.         AdvancedSearchFormTypeManager $advancedSearchFormTypeManager,
  292.         AdvancedFilterFormTypeManager $advancedFilterFormTypeManager,
  293.         SpecialAddListingService $specialAddListingService,
  294.         CompoundDetailService $compoundDetailService,
  295.         SpecialListingFeatureDecorator $specialListingFeatureDecorator,
  296.         TranslatableListener $translatableListener,
  297.         EntityManagerInterface $entityManager,
  298.         UserPackagesRepository $userPackagesRepository
  299.     ) {
  300.         $this->messageComposer $messageComposer;
  301.         $this->databaseNotification $databaseNotification;
  302.         $this->logger $logger;
  303.         $this->translator $translator;
  304.         $this->featureToggleManager $featureToggleManager;
  305.         $this->setting $setting;
  306.         $this->listingManager $listingManager;
  307.         $this->dispatcher $dispatcher;
  308.         $this->interactionService $interactionService;
  309.         $this->neighborhoodManager $neighborhoodManager;
  310.         $this->defaultListingSearch $defaultListingSearch;
  311.         $this->relatedResultService $relatedResultService;
  312.         $this->topSellerRetrievalService $topSellerRetrievalService;
  313.         $this->financialAidService $financialAidService;
  314.         $this->listingLeadManager $listingLeadManager;
  315.         $this->compoundFaqsService $compoundFaqsService;
  316.         $this->paginator $paginator;
  317.         $this->userActivityService $userActivityService;
  318.         $this->mobileDetectionService $mobileDetectionService;
  319.         $this->redis $redis;
  320.         $this->imagine $imagine;
  321.         $this->uploaderHelper $uploaderHelper;
  322.         $this->callRequestManager $callRequestManager;
  323.         $this->authorizationChecker $authorizationChecker;
  324.         $this->tokenStorage $tokenStorage;
  325.         $this->mortgageService $mortgageService;
  326.         $this->listingRuleMatcher $listingRuleMatcher;
  327.         $this->creditManager $creditManager;
  328.         $this->userServicesManager $userServicesManager;
  329.         $this->FOSUserManager $FOSUserManager;
  330.         $this->phoneManager $phoneManager;
  331.         $this->listingFeatureService $listingFeatureService;
  332.         $this->userManager $userManager;
  333.         $this->advancedSearchFormTypeManager $advancedSearchFormTypeManager;
  334.         $this->advancedFilterFormTypeManager $advancedFilterFormTypeManager;
  335.         $this->specialAddListingService $specialAddListingService;
  336.         $this->specialListingFeatureDecorator $specialListingFeatureDecorator;
  337.         $this->compoundDetailService $compoundDetailService;
  338.         $this->translatableListener $translatableListener;
  339.         $this->entityManager $entityManager;
  340.         $this->userPackagesRepository $userPackagesRepository;
  341.     }
  342.     /**
  343.      * Listing Details Action.
  344.      *
  345.      * @Route("/{id}/{notification}", defaults={"notification"=0}, requirements={"id" = "\d+"}, options={"i18n" = false, "expose" = true}, name="listing_view", methods={"GET"})
  346.      * @Route("/listing/{id}/notification/{notification}", defaults={"notification"=0}, name="listing_view_notification", methods={"GET"})
  347.      * @Route("/listing/{id}", requirements={"id" = "\d+"} , options={"expose" = true} , name="listing_details", methods={"GET"})
  348.      * @Route("/listing/{id}-{slug}", requirements={"id" = "\d+", "slug" = ".+"}, name="listing_slug", methods={"GET"})
  349.      */
  350.     public function read(Request $requestListing $listingEntityManagerInterface $em)
  351.     {
  352.         if ($request->get('notification')) {
  353.             try {
  354.                 $this->databaseNotification->markOneAsRead($request->get('notification'));
  355.             } catch (\Exception $exception) {
  356.                 $this->logger->log(LogLevel::ERROR$exception->getMessage());
  357.             }
  358.         }
  359.         // Redirect to the right URL if the URL is short-URL or the listing slug is incorrect
  360.         if (('listing_slug' != $request->get('_route')
  361.                 || $request->attributes->get('slug') != $listing->getSlug())
  362.             && !empty($listing->getSlug())
  363.         ) {
  364.             return $this->redirect($this->generateUrl('listing_slug'array_merge($request->query->all(), [
  365.                 'id' => $listing->getId(),
  366.                 'slug' => $listing->getSlug(),
  367.             ])), Response::HTTP_MOVED_PERMANENTLY);
  368.         }
  369.         $listingStatus = !\in_array($listing->getStatus(), [ListingStatus::LIVEListingStatus::PENDING]);
  370.         if ($listingStatus && !$request->query->get('noredirect') && $listing->getUser() != $this->getUser()) {
  371.             if (!$listing->getSection()->getSearchable()) {
  372.                 return $this->redirect($this->generateUrl('compound_search'), Response::HTTP_FOUND);
  373.             }
  374.             try {
  375.                 $searchableLocation $listing->getLocation()->getNearestSearchable();
  376.             } catch (\Exception $exception) {
  377.                 $this->addFlash(
  378.                     'danger',
  379.                     $this->translator->trans('listing.not_available')
  380.                 );
  381.                 return $this->redirect($this->generateUrl('homepage'), Response::HTTP_FOUND);
  382.             }
  383.             return $this->redirect($this->generateUrl('search', [
  384.                 'section_slug' => $listing->getSection()->getSlug(),
  385.                 'property_type_slug' => $listing->getPropertyType()->getSlug(),
  386.                 'location_slug' => $searchableLocation->getSlug(),
  387.             ]), Response::HTTP_MOVED_PERMANENTLY);
  388.         }
  389.         $listingRepo $em->getRepository(Listing::class);
  390.         if ($notifierId $request->query->get('notifier')) {
  391.             if (null !== $notifier $em->getRepository('AqarmapNotifierBundle:Notifier')->find($notifierId)) {
  392.                 $this->dispatcher->dispatch(new NotifierEvent($notifier), 'aqarmap.notifier.interaction');
  393.             } else {
  394.                 $this->logger->warning('Notifier with id: '.$notifierId.' was not found!');
  395.             }
  396.         }
  397.         $this->interactionService->increaseViews($listing$this->getUser());
  398.         $relatedListingCriteriaMapper $this->relatedResultService->getRelatedListingCriteriaMapper($listing);
  399.         $relatedListings $this->defaultListingSearch->search($relatedListingCriteriaMapper)['searchResults'];
  400.         $topSeller $this->createTopSeller($listing);
  401.         $topSearchableCompanies $this->topSellerRetrievalService->getTopSellerPersonalData($topSeller$request->getLocale());
  402.         $searchableLocation $listing->getLocation()->getNearestSearchable();
  403.         $isPlaceHoldered false;
  404.         $userProfilePhoto $listing->getUser()->isValidPersonalPhoto() ? $listing->getUser()->getPersonalPhoto() : null;
  405.         if ($listing->getLogo() || ($listing->getParent() && $listing->getParent()->getLogo())) {
  406.             if ($listing->getParent() && $listing->getParent()->getLogo()) {
  407.             }
  408.         } elseif (!empty($listing->getPhotosForSlider()) && $listing->getUser()->getIsValidLogo()) {
  409.             $isPlaceHoldered true;
  410.         }
  411.         $this->financialAidService->setFinancialAidInListing($listing);
  412.         $activeListingsCount $listing->getUser()->getActiveListingsCount();
  413.         $leadsCount 0;
  414.         if ($this->featureToggleManager->isEnabled('web.client.served.count')) {
  415.             $leadsCount $listing->getUser()->getClientServedCount();
  416.         }
  417.         $listing current(
  418.             $this->listingManager->setUserActivities(
  419.                 [$listing],
  420.                 [$listing->getId()]
  421.             )
  422.         );
  423.         $hasUserMadeLead false;
  424.         if ($user $this->getUser()) {
  425.             $hasUserMadeLead $this->listingLeadManager->hasUserMadeLead($listing$user);
  426.         }
  427.         $compoundFaqs = [];
  428.         $listingDetails $listing;
  429.         if ($listing->isProject()) {
  430.             $compoundFaqs $this->compoundFaqsService->generateFaqData($listing);
  431.             $resaleRegularListingsPaginated $this->paginator->paginate(
  432.                 $listingRepo->getSectionListings($listingnullListingSections::FOR_SALE),
  433.                 $request->query->get('page'ResaleListingsConstant::PAGE),
  434.                 ResaleListingsConstant::LIMIT
  435.             );
  436.             $this->compoundDetailService->getPropertyTypeChildrens($listing$request->getLocale());
  437.             $liveUnitsPaginated $listing->getPropertyTypeChildren();
  438.             $this->compoundDetailService->getPropertyTypeUnitsChildrens($listingListingSections::FOR_SALE$request->getLocale());
  439.             $resaleUnitsPaginated $listing->getPropertyTypeChildren();
  440.             $this->compoundDetailService->getPropertyTypeUnitsChildrens($listingListingSections::FOR_RENT$request->getLocale());
  441.             $rentUnitsPaginated $listing->getPropertyTypeChildren();
  442.         }
  443.         $request->cookies->get('user-agent');
  444.         $mobileDetection $this->mobileDetectionService->mobileDetection($request$return);
  445.         $return = [
  446.             'listing' => $listingDetails,
  447.             'searchableLocation' => $searchableLocation,
  448.             'contact_seller_form' => $this->contactSellerForm($listing)->createView(),
  449.             'quick_registration_form' => $this->quickRegistrationForm()->createView(),
  450.             'call_request' => $this->callRequestForm($listing)->createView(),
  451.             'related_listings' => $relatedListings,
  452.             'relatedListingsCount' => (null != $relatedListings) ? $relatedListings->getTotalItemCount() : 0,
  453.             'location_statistics' => $this->neighborhoodManager->getStatistics(
  454.                 $listing->getLocation()->getNearestNeighborhood(),
  455.                 $listing->getPropertyType()
  456.             ),
  457.             'topSearchableCompanies' => $topSearchableCompanies,
  458.             'topSearchableCompaniesCount' => \count($topSearchableCompanies),
  459.             'isPlaceHoldered' => $isPlaceHoldered,
  460.             'userProfilePhoto' => $userProfilePhoto,
  461.             'activeListingsCount' => $activeListingsCount,
  462.             'leadsCount' => $leadsCount,
  463.             'featureToggle' => $this->userActivityService->getFeatureToggles(),
  464.             'leadAnalytics' => $this->listingManager->getLeadAnalytics($listing),
  465.             'otherUnits' => $this->listingManager->getOtherUnits($listing$request->getLocale()),
  466.             'hasUserMadeLead' => $hasUserMadeLead,
  467.             'resaleRegularListings' => $resaleRegularListingsPaginated ?? null,
  468.             'resaleUnitsPaginated' => $resaleUnitsPaginated ?? null,
  469.             'liveUnitsPaginated' => $liveUnitsPaginated ?? null,
  470.             'rentUnitsPaginated' => $rentUnitsPaginated ?? null,
  471.             'compoundFaqs' => $compoundFaqs,
  472.             'isMobile' => $mobileDetection['isMobile'],
  473.         ];
  474.         if ($mobileDetection['isMobile']) {
  475.             $nearestLocations $em
  476.                 ->getRepository(\Aqarmap\Bundle\ListingBundle\Entity\Location::class)
  477.                 ->getNearestLocations([$listing->getLocation()])
  478.             ;
  479.             $return['nearestLocations'] = $nearestLocations;
  480.             foreach ($mobileDetection as $key => $val) {
  481.                 $return[$key] = $val;
  482.             }
  483.             return $this->render('@AqarmapListing/Listing/read-mob.html.twig'$return);
  484.         }
  485.         $return['discussions'] = $em
  486.             ->getRepository('AqarmapDiscussionBundle:Discussion')
  487.             ->getTrendingWithLocation($listing->getLocation()->getId(), 3)
  488.         ;
  489.         return $this->render('@AqarmapListing/Listing/read.html.twig'$return);
  490.     }
  491.     /**
  492.      * TopSeller Attributes from listing data.
  493.      *
  494.      * @param  Listing
  495.      *
  496.      * @return TopSeller
  497.      */
  498.     private function createTopSeller($listing)
  499.     {
  500.         $topSeller = new TopSeller();
  501.         $topSeller->setLocation($listing->getLocation()->getId());
  502.         $topSeller->setSection($listing->getSection()->getId());
  503.         $topSeller->setPropertyType($listing->getPropertyType()->getId());
  504.         return $topSeller;
  505.     }
  506.     /**
  507.      * Advanced Search Form.
  508.      */
  509.     protected function createAdvancedSearchForm(): FormInterface
  510.     {
  511.         return $this->advancedSearchFormTypeManager
  512.             ->setAction($this->generateUrl('listing_advanced_search'))
  513.             ->setFormType(AdvancedSearchType::class)
  514.             ->setMethodType('Post')
  515.             ->setSettings($this->setting)
  516.             ->applyOptions()
  517.             ->createForm();
  518.     }
  519.     /**
  520.      * Advanced Search Form.
  521.      */
  522.     protected function createAdvancedFilterForm(): FormInterface
  523.     {
  524.         $customFields $this->redis->get('customFields');
  525.         return $this->advancedFilterFormTypeManager
  526.             ->setAction($this->generateUrl('listing_filter_search'))
  527.             ->setFormType(AdvancedFilterType::class)
  528.             ->setMethodType('Post')
  529.             ->setSettings($this->setting)
  530.             ->setCustomFields($customFields unserialize($customFields) : [])
  531.             ->applyOptions()
  532.             ->createForm();
  533.     }
  534.     /**
  535.      * Multiple Search Form.
  536.      */
  537.     protected function createMultipleSearchForm(): FormInterface
  538.     {
  539.         return $this->advancedSearchFormTypeManager
  540.             ->setAction($this->generateUrl('listing_multiple_search'))
  541.             ->setFormType(MultipleSearchFormType::class)
  542.             ->setMethodType('Post')
  543.             ->setSettings($this->setting)
  544.             ->applyOptions()
  545.             ->createForm();
  546.     }
  547.     /**
  548.      * Latest Listings Action.
  549.      *
  550.      * @Route("/listing/latest", name="listing_latest", methods={"GET"})
  551.      */
  552.     public function latest(Request $request): Response
  553.     {
  554.         /** @var $em \Doctrine\ORM\EntityManager */
  555.         $em $this->getDoctrine()->getManager();
  556.         $pagination $this->paginator->paginate(
  557.             $em->getRepository(Listing::class)->getLatestListings(),
  558.             $request->query->get('page'1)
  559.         );
  560.         return $this->render('@AqarmapListing/Listing/latest.html.twig', [
  561.             'listings' => $pagination,
  562.         ]);
  563.     }
  564.     /**
  565.      * @Route("/listing/latest/{section}.{_format}")
  566.      *
  567.      * @return Response
  568.      */
  569.     public function CSVLatestListings(Request $requestSection $section)
  570.     {
  571.         /** @var EntityManager $em */
  572.         $em $this->getDoctrine()->getManager();
  573.         $listings $em->getRepository(Listing::class)->findBy([
  574.             'section' => $section,
  575.             'status' => ListingStatus::LIVE,
  576.         ], ['id' => 'desc'], 100);
  577.         $handle fopen('php://memory''r+');
  578.         fputcsv($handle, [
  579.             $request->query->get('id''id'),
  580.             $request->query->get('section''section'),
  581.             $request->query->get('description''description'),
  582.             $request->query->get('image''image'),
  583.             $request->query->get('link''link'),
  584.             $request->query->get('title''title'),
  585.             $request->query->get('price''price'),
  586.             $request->query->get('formatted_price''formatted_price'),
  587.             $request->query->get('price_currency''price_currency'),
  588.             $request->query->get('location''location'),
  589.             $request->query->get('address''address'),
  590.             $request->query->get('property_type''property_type'),
  591.             $request->query->get('availability''availability'),
  592.             $request->query->get('condition''condition'),
  593.         ]);
  594.         foreach ($listings as $listing) {
  595.             $thumb null;
  596.             if ($listing->getMainPhoto()) {
  597.                 $thumb $this->imagine->generateUrl(
  598.                     $this->uploaderHelper->asset($listing->getMainPhoto()->getFile(), 'file'),
  599.                     'large'
  600.                 );
  601.             }
  602.             $description preg_split('/\n/'mb_substr($listing->getDescription(), 0200), \PREG_SPLIT_DELIM_CAPTURE);
  603.             fputcsv($handle, [
  604.                 $listing->getId(),
  605.                 $section->getTitle(),
  606.                 $description[0],
  607.                 $thumb,
  608.                 $this->generateUrl('listing_view', ['id' => $listing->getId()], true),
  609.                 $listing->getTitle(),
  610.                 $listing->getPrice(),
  611.                 number_format($listing->getPrice()),
  612.                 sprintf('%s %s'number_format($listing->getPrice()), 'EGP'),
  613.                 $listing->getLocation()->getTitle(),
  614.                 $listing->getAddress(),
  615.                 $listing->getPropertyType()->getTitle(),
  616.                 'in stock',
  617.                 'new',
  618.             ]);
  619.         }
  620.         rewind($handle);
  621.         $content stream_get_contents($handle);
  622.         fclose($handle);
  623.         return new Response($contentResponse::HTTP_OK, [
  624.             'Content-Type' => 'application/force-download',
  625.             'Content-Disposition' => sprintf(
  626.                 'attachment; filename="latest-listings - %s - %s.csv"',
  627.                 $section->getTitle(),
  628.                 date('Y-m-d H-i-s')
  629.             ),
  630.         ]);
  631.     }
  632.     /**
  633.      * @deprecated
  634.      *
  635.      * @Route("/listing/{id}/one", name="landing_page", methods={"GET", "POST"})
  636.      *
  637.      * @Rest\View()
  638.      *
  639.      * @return array
  640.      */
  641.     public function landingPage(Request $requestListing $listing)
  642.     {
  643.         $form $this->createForm(LandingPageFormType::class, $landingPage = new LandingPage(), [
  644.             'action' => $this->generateUrl('landing_page', ['id' => $listing->getId()]),
  645.         ]);
  646.         $form->handleRequest($request);
  647.         if ($form->isSubmitted() && $form->isValid()) {
  648.             if (!($user $this->FOSUserManager->findUserByEmail($landingPage->getUser()->getEmail()))) {
  649.                 $user $this->userManager
  650.                     ->createUserWithoutPassword($form->get('user')->getData(), $form->get('user'), $request)
  651.                 ;
  652.             }
  653.             if (!$form->get('message')->getData()) {
  654.                 $callRequest = new CallRequest();
  655.                 $callRequest->setListing($listing);
  656.                 $callRequest->setUser($user);
  657.                 $this->callRequestManager->submitCallRequest($callRequest);
  658.             } else {
  659.                 // Compose a message
  660.                 $composer $this->messageComposer;
  661.                 $composer->setSender($user);
  662.                 $composer->compose($form->get('message')->getData(), $listing);
  663.             }
  664.         }
  665.         return [
  666.             'form' => $form->createView(),
  667.             'listing' => $listing,
  668.         ];
  669.     }
  670.     /**
  671.      * Add Listing First Step Action.
  672.      *
  673.      * @Route("/listing/initialize", name="listing_initialize", options={"expose"=true})
  674.      */
  675.     public function initialize(Request $request)
  676.     {
  677.         $user $this->getUser();
  678.         if (false === $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
  679.             return $this->redirect($this->generateUrl('aqarmap_add_listing'));
  680.         }
  681.         if(!$user->isPhoneVerified()){
  682.             return $this->render('@AqarmapListing/Listing/verifyPhone.html.twig');
  683.         }
  684.         $hasRentalPackage $this->userPackagesRepository->hasRentalPackage($user);
  685.         $initializeOptions = [
  686.             'action' => $this->generateUrl('listing_initialize'),
  687.             'method' => 'POST',
  688.             'em' => $this->getDoctrine()->getManager(),
  689.             'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),
  690.             'has_rental_package' => $hasRentalPackage,
  691.             'parentUser' => $user,
  692.         ];
  693.         $form $this->createForm(ListingInitializeType::class, $listing = new Listing(), $initializeOptions);
  694.         $listingEvent = new ListingEvent($listing);
  695.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.pre_submitted');
  696.         $form->handleRequest($request);
  697.         if ($form->isSubmitted() && $form->isValid()) {
  698.             $listing $this->listingManager->createDraft($listing);
  699.             // Add user phone number to the listing
  700.             if ($listing->getUser()->getPhoneNumber()) {
  701.                 // link user phone with this listing
  702.                 // TODO: Suggest only the main number for now, later on we will suggest the main + last 2 numbers.
  703.                 $this->listingManager->suggestListingPhoneNumbers(
  704.                     [$listing->getUser()->getPhoneNumber()],
  705.                     $listing
  706.                 );
  707.             }
  708.             return $this->redirect($this->generateUrl('listing_edit', [
  709.                 'id' => $listing->getId(),
  710.             ]));
  711.         }
  712.         return $this->render('@AqarmapListing/Listing/initialize.html.twig', [
  713.             'form' => $form->createView(),
  714.         ]);
  715.     }
  716.     /**
  717.      * Add Listing V2.
  718.      *
  719.      * @Route("/listing/initialize/{step}", name="add_listing", options={"expose"=true})
  720.      * @Route("/listing/initialize/{id}/{step}", name="edit_listing", options={"expose"=true})
  721.      *
  722.      * @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
  723.      *
  724.      * @throws \Doctrine\ORM\NonUniqueResultException
  725.      */
  726.     public function addListing(): Response
  727.     {
  728.         return $this->render('@AqarmapListing/Listing/add.html.twig', [
  729.             'title' => $this->translator->trans('listing.add_your_listing'),
  730.             'featureToggle' => [
  731.                 'accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),
  732.                 'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),
  733.             ],
  734.         ]);
  735.     }
  736.     /**
  737.      * Add Listing groups.
  738.      *
  739.      * @Route("/listing/add/", name="add_listing_steps", options={"expose"=true})
  740.      * @Route("/listing/{id}/edit/steps", name="edit_listing_steps", options={"expose"=true})
  741.      *
  742.      * @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
  743.      *
  744.      * @throws \Doctrine\ORM\NonUniqueResultException
  745.      */
  746.     public function addListingSteps(): Response
  747.     {
  748.         return $this->render('@AqarmapListing/Listing/addSteps.html.twig', [
  749.             'title' => $this->translator->trans('listing.add_your_listing'),
  750.             'featureToggle' => [
  751.                 'accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),
  752.                 'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),
  753.             ],
  754.         ]);
  755.     }
  756.     /**
  757.      * Listing Post Action
  758.      * This action manage adding & editing listings.
  759.      *
  760.      * @Route("/listing/{id}/edit/", name="listing_edit", requirements={"id" = "\d+"}, options={"expose"=true})
  761.      *
  762.      * @Security(
  763.      *     "(is_granted('IS_AUTHENTICATED_REMEMBERED') and is_granted('ROLE_OWNER', listing)) or is_granted('ROLE_ADMIN')"
  764.      * )
  765.      */
  766.     public function post(Request $requestListing $listing): Response
  767.     {
  768.         $form $this->createForm(ListingType::class, $listing, [
  769.             'action' => $this->generateUrl('listing_edit', ['id' => $listing->getId()]),
  770.             'method' => 'POST',
  771.             'listingIsLiveFor5Days' => $this->listingManager->checkListingLiveDays($listing),
  772.             'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),
  773.             'user_country' => $this->setting->getSetting('general''country'),
  774.             'user_type' => $listing->getUser() ? $listing->getUser()->getUserType() : null,
  775.             'isMortgageOptionsEnabled' => $this->featureToggleManager->isEnabled('web.mortgage.options'),
  776.             'isListingMarketPropertyTypesEnabled' => $this->featureToggleManager->isEnabled('web.listing.market.property.types'),
  777.         ]);
  778.         $form->handleRequest($request);
  779.         if ($request->isMethod('POST')) {
  780.             if ($form->isSubmitted() && $form->isValid()) {
  781.                 $this->updateWhatsAppPhones($listing->getUser()->getId(), (array) $request->request->get('phoneIds', []), (array) $request->request->get('hasWhatsApp', []));
  782.                 $listing $this->handleListingPhones($listing$request->request->all()['listing']['phones']);
  783.                 $this->handleUserPhones($listing->getUser(), $request->request->all()['listing']['phones']);
  784.                 $this->listingManager->saveListing($listing);
  785.                 if ($this->featureToggleManager->isEnabled('web.add.listing.translations')) {
  786.                     if ('en' == $request->getLocale()) {
  787.                         $criteria = [
  788.                             'reversedLocale' => 'ar',
  789.                             'title-ar' => $request->request->get('title-ar'),
  790.                             'description-ar' => $request->request->get('description-ar'),
  791.                         ];
  792.                     } else {
  793.                         $criteria = [
  794.                             'reversedLocale' => 'en',
  795.                             'title-en' => $request->request->get('title-en'),
  796.                             'description-en' => $request->request->get('description-en'),
  797.                         ];
  798.                     }
  799.                     $this->listingManager->updateListingTranslationsFields($listing$criteria);
  800.                 } else {
  801.                     $this->listingManager->updateListingTranslations($listing);
  802.                 }
  803.                 if ($this->featureToggleManager->isEnabled('web.mortgage.options')) {
  804.                     $propertyRegistrationStatus $form->has('propertyRegistrationStatus') ? $form->get('propertyRegistrationStatus')->getData() : null;
  805.                     if (\in_array($propertyRegistrationStatusPropertyRegistrationStatusOption::getValidMorgageOptions())) {
  806.                         $this->mortgageService->addEligibleMortgageTypes($listing);
  807.                     } else {
  808.                         $this->listingManager->setELigibleMortgageToNull($listing);
  809.                     }
  810.                     $listing $this->mortgageService->addMortgageApproval($listing$form);
  811.                 }
  812.                 $listingEvent = new ListingEvent($listing);
  813.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  814.                 if (ListingSource::SCRAPPING == $listing->getSource()
  815.                     || ListingSource::LITE == $listing->getSource()
  816.                 ) {
  817.                     return $this->redirect($this->generateUrl('listing_view', ['id' => $listing->getId()]));
  818.                 }
  819.                 return $this
  820.                     ->redirect(
  821.                         $this->generateUrl(
  822.                             'listing_upload',
  823.                             ['id' => $listing->getId(), '_locale' => $request->get('_locale')]
  824.                         )
  825.                     )
  826.                 ;
  827.             }
  828.             $this->addFlash('danger'$this->translator->trans('static.problem_error_message'));
  829.         }
  830.         $translatedLocale 'en' == $request->getLocale() ? 'ar' 'en';
  831.         return $this->render('@AqarmapListing/Listing/post.html.twig', [
  832.             'form' => $form->createView(),
  833.             'listing' => $listing,
  834.             'title_translation' => $this->listingTitleTranslations($listing$translatedLocale),
  835.             'description_translation' => $this->listingDescriptionTranslations($listing$translatedLocale),
  836.             'brokerChoices' => UserTypes::getBrokerChoices(),
  837.         ]);
  838.     }
  839.     /**
  840.      * @return array|mixed
  841.      */
  842.     private function listingTitleTranslations(Listing $listingstring $locale)
  843.     {
  844.         $this->translatableListener->setTranslatableLocale($locale);
  845.         $listing->setTranslatableLocale($locale);
  846.         $this->entityManager->refresh($listing);
  847.         return $listing->getTitle() ?? $this->listingManager->listingTitleTranslations($listing$locale);
  848.     }
  849.     private function listingDescriptionTranslations(Listing $listingstring $locale)
  850.     {
  851.         $this->translatableListener->setTranslatableLocale($locale);
  852.         $listing->setTranslatableLocale($locale);
  853.         $this->entityManager->refresh($listing);
  854.         return $listing->getDescription() ?? $this->listingManager->listingTitleTranslations($listing$locale);
  855.     }
  856.     private function handleListingPhones(Listing $listing, array $phones): Listing
  857.     {
  858.         $listing->clearPhones();
  859.         foreach ($phones as $phone) {
  860.             $phoneNumber $phone['number'];
  861.             $countryCode $phone['countryCode'];
  862.             $phone = new Phone($countryCode.$phoneNumber$countryCode);
  863.             $listing->addPhone(new ListingPhone($phoneNumber$listing$countryCode$phone));
  864.         }
  865.         return $listing;
  866.     }
  867.     private function handleUserPhones(User $user, array $phones): void
  868.     {
  869.         foreach ($phones as $phone) {
  870.             $originalPhoneNumber $phone['number'];
  871.             $countryCode $phone['countryCode'];
  872.             $phoneNumber $this->phoneManager->trimZero($originalPhoneNumber$countryCode);
  873.             $this->phoneManager->addNewUserPhone($phoneNumber$countryCode$usertruefalsenull$originalPhoneNumber);
  874.         }
  875.     }
  876.     /**
  877.      * Listing Post Action
  878.      * This action manage adding & editing listings.
  879.      *
  880.      * @Route("/listing/{id}/preview/", name="listing_preview", requirements={"id" = "\d+"}, options={"expose"=true})
  881.      *
  882.      * @Security(
  883.      *     "(is_granted('IS_AUTHENTICATED_REMEMBERED') and is_granted('ROLE_OWNER', listing)) or is_granted('ROLE_ADMIN')"
  884.      * )
  885.      *
  886.      * @return array|RedirectResponse
  887.      */
  888.     public function preview(Listing $listing): Response
  889.     {
  890.         return $this->render('@AqarmapListing/Listing/preview.html.twig', [
  891.             'listing' => $listing,
  892.         ]);
  893.     }
  894.     /**
  895.      * Listing Post Action
  896.      * This action manage adding & editing listings.
  897.      *
  898.      * @Route("/listing/lite", name="listing_lite_add",  options={"expose"=true})
  899.      */
  900.     public function postLite(Request $request)
  901.     {
  902.         /** @var $em \Doctrine\ORM\EntityManager */
  903.         $em $this->getDoctrine()->getManager();
  904.         $form $this->createForm(
  905.             LiteListingType::class,
  906.             null,
  907.             ['em' => $em,
  908.                 'action' => $this->generateUrl('listing_lite_add'),
  909.                 'method' => 'post', ]
  910.         );
  911.         if ($request->isMethod('POST')) {
  912.             $form->handleRequest($request);
  913.             if ($form->isSubmitted() && $form->isValid()) {
  914.                 $listing $form->getData();
  915.                 $listing->setSellerRole(ListingSellerRoles::OWNER);
  916.                 $this->listingManager->saveListing($listing);
  917.                 // add listing phone to new phones table ;
  918.                 $this->phoneManager->addListingPhonesList($listing->getPhones(), ''$listing);
  919.                 $this->listingManager->addLiteListingTitleAndDescriptionTranslation($listing);
  920.                 $listingEvent = new ListingEvent($listing);
  921.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  922.                 $this->addFlash(
  923.                     'success',
  924.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  925.                 );
  926.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  927.                     $this->addFlash(
  928.                         'info',
  929.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  930.                     );
  931.                 }
  932.                 return $this->redirect($this->generateUrl('homepage'));
  933.             }
  934.             $this->addFlash('danger'$this->translator->trans('static.problem_error_message'));
  935.         }
  936.         return $this->render('@AqarmapListing/Listing/postLite.html.twig', [
  937.             'form' => $form->createView(),
  938.         ]);
  939.     }
  940.     /**
  941.      * Add Listing First Step Action.
  942.      *
  943.      * @Route("/listing/{id}/edit/photos", name="listing_upload", requirements={"id" = "\d+"}, options={"expose"=true})
  944.      *
  945.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  946.      */
  947.     public function upload(Request $requestListing $listing)
  948.     {
  949.         $form $this->createForm(PhotoType::class, null, [
  950.             'method' => 'POST',
  951.         ]);
  952.         $form->handleRequest($request);
  953.         $listingRules $this->listingRuleMatcher->match($listing);
  954.         if ($form->isSubmitted() && $form->isValid() && $request->isMethod('POST')) {
  955.             $listingPhotos = [];
  956.             try {
  957.                 $listingPhotos $this->listingManager->addListingPhotos($listing$form->get('file')->getData());
  958.                 $listingEvent = new ListingEvent($listing);
  959.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  960.                 $this->listingManager->saveListing($listing);
  961.                 // If not Ajax request
  962.                 if (!$request->isXmlHttpRequest()) {
  963.                     $this->logger->error('Not AJAX');
  964.                     return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  965.                 }
  966.             } catch (\Exception $exception) {
  967.                 $this->logger->error($exception->getMessage());
  968.             }
  969.             return View::create(['files' => $listingPhotos], Response::HTTP_OK);
  970.         }
  971.         return $this->render('@AqarmapListing/Listing/upload.html.twig', [
  972.             'requiredPhotosCount' => $listingRules['required_photos'] ?? 0,
  973.             'listing' => $listing,
  974.             'form' => $form->createView(),
  975.         ]);
  976.     }
  977.     /**
  978.      * Should be called after photos are uploaded.
  979.      *
  980.      * @Route("/listing/{id}/finish", requirements={"id" = "\d+"}, name="listing_finish")
  981.      *
  982.      * @return RedirectResponse|Response
  983.      */
  984.     public function finish(Listing $listingUserPackagesService $userPackagesService)
  985.     {
  986.         $listingEvent = new ListingEvent($listing);
  987.         if (!$userPackagesService->canListInLocation($listing)) {
  988.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  989.             return $this->redirect($this->generateUrl('listing_upload', [
  990.                 'id' => $listing->getId(),
  991.             ]), Response::HTTP_FOUND);
  992.         }
  993.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  994.         $response $listingEvent->getResponse();
  995.         if (null === $response) {
  996.             if (ListingStatus::PENDING === $listing->getStatus()) {
  997.                 $this->addFlash(
  998.                     'success',
  999.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  1000.                 );
  1001.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1002.                     $this->addFlash(
  1003.                         'info',
  1004.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1005.                     );
  1006.                 }
  1007.             }
  1008.             $response = new RedirectResponse(
  1009.                 $this->generateUrl(
  1010.                     'listing_slug',
  1011.                     ['id' => $listing->getId(), 'slug' => $listing->getSlug()]
  1012.                 )
  1013.             );
  1014.         }
  1015.         return $response;
  1016.     }
  1017.     /**
  1018.      * SWAT special add listing feature page.
  1019.      *
  1020.      * @Route("/listing/{id}/feature", requirements={"id" = "\d+"}, name="special_add_listing_feature")
  1021.      *
  1022.      * @Security("is_granted('ROLE_OWNER', listing)")
  1023.      */
  1024.     public function specialAddListingFeature(Listing $listing): RedirectResponse
  1025.     {
  1026.         return $this->redirectToRoute('listing_finish', ['id' => $listing->getId()]);
  1027.     }
  1028.     /**
  1029.      * @Route("/listing/{id}/make_it_featured",
  1030.      * requirements={"id" = "\d+"}, name="listing_confirm_featured_credit", methods={"GET"})
  1031.      *
  1032.      * @Security("is_granted('ROLE_OWNER', listing)")
  1033.      *
  1034.      * @return RedirectResponse|Response
  1035.      */
  1036.     public function confirmFeaturedPublishing(Listing $listing)
  1037.     {
  1038.         if (!\in_array($listing->getStatus(), [ListingStatus::PENDINGListingStatus::LIVE])) {
  1039.             $this->addFlash(
  1040.                 'danger',
  1041.                 $this->translator->trans('listing.featured_failure_statement.not_live_or_pending')
  1042.             );
  1043.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1044.         }
  1045.         if (UserTypes::INDIVIDUAL == $listing->getUser()->getUserType()) {
  1046.             $listingRules $this->listingFeatureService->getFeaturedListingRules($listing, ['sold_by_owner''sold_by_owner_sponsored']);
  1047.         } else {
  1048.             $listingRules $this->listingFeatureService->getFeaturedListingRules($listing, ['featured''premium''sponsored''spotlight']);
  1049.         }
  1050.         /** @var User $user */
  1051.         $user $this->getUser();
  1052.         return $this->render(
  1053.             '@AqarmapListing/Listing/featuredListingCheckout.html.twig',
  1054.             [
  1055.                 'listingRules' => $listingRules,
  1056.                 'listingId' => $listing->getId(),
  1057.                 'haveFeesToFeature' => $this->listingManager->userHasFeesToFeature($user$listing),
  1058.             ]
  1059.         );
  1060.     }
  1061.     /**
  1062.      * @Route("/listing/{id}/make_it_featured",  options={"expose"=true} ,requirements={"id" = "\d+"},
  1063.      * name="listing_confirm_publish_featured_credit_post", methods={"POST"})
  1064.      *
  1065.      * @Security("is_granted('ROLE_OWNER', listing)")
  1066.      */
  1067.     public function prepareFeaturedListingPayment(Listing $listingRequest $request): RedirectResponse
  1068.     {
  1069.         $listingRules $this->listingManager->getListingRules($listing);
  1070.         $fees $request->query->get('fees'$listingRules['featured_fees']);
  1071.         $duration $request->query->get('duration'$listingRules['featured_duration']);
  1072.         $listingFeaturedType $request->query->get('listingFeaturedType'ListingFeaturedTypes::FEATURED);
  1073.         $listingFeature $request->query->get('listingFeature'ListingFeatures::FEATURED);
  1074.         $listingStatus $listing->getStatus();
  1075.         /** @var User $user */
  1076.         $user $this->getUser();
  1077.         if (!$this->listingManager->isAffordable($user$fees)) {
  1078.             $this->addFlash('danger'$this->translator->trans('credit.not_enough_featuring_credit', [
  1079.                 'link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),
  1080.             ]));
  1081.             return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1082.                 'id' => $listing->getId(),
  1083.             ]), Response::HTTP_FOUND);
  1084.         }
  1085.         $featuredText $this->translator->trans(ListingFeaturedTypes::getFeaturedText($listingFeaturedType));
  1086.         $rules = [
  1087.             'featuredFees' => $fees,
  1088.             'featuredDuration' => $duration,
  1089.             'listingFeaturedType' => $listingFeaturedType,
  1090.             'listingFeature' => $listingFeature,
  1091.             'featuredText' => $featuredText,
  1092.         ];
  1093.         if ($this->listingManager->requiresFeaturingReview($listingFeaturedType)) {
  1094.             try {
  1095.                 $this->listingManager->makeItFeatured($listing$rules);
  1096.                 if (ListingStatus::LIVE == $listingStatus) {
  1097.                     $this->addFlash(
  1098.                         'success',
  1099.                         $this->translator->trans('add_listing_page.success_messages.pending_featuring', [':featured_type:' => $featuredText])
  1100.                     );
  1101.                 } else {
  1102.                     $this->addFlash(
  1103.                         'success',
  1104.                         $this->translator->trans('add_listing_page.success_messages.padding_review')
  1105.                     );
  1106.                     if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1107.                         $this->addFlash(
  1108.                             'info',
  1109.                             $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1110.                         );
  1111.                     }
  1112.                 }
  1113.             } catch (\Exception $exception) {
  1114.                 $this->addFlash('danger'$this->translator->trans($exception->getMessage()));
  1115.             }
  1116.             if (ListingStatus::LIVE == $listingStatus) {
  1117.                 return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1118.             }
  1119.             return $this->redirect($this->generateUrl('listing_finish', [
  1120.                 'id' => $listing->getId(),
  1121.             ]));
  1122.         }
  1123.         try {
  1124.             $this->listingManager->makeItFeatured($listing$rules);
  1125.             if (ListingStatus::LIVE == $listing->getStatus()) {
  1126.                 $this->addFlash(
  1127.                     'success',
  1128.                     $this->translator->trans(
  1129.                         'add_listing_page.success_messages.featured',
  1130.                         [':listing_title:' => $listing->getTitle(), ':featured_type:' => $featuredText]
  1131.                     )
  1132.                 );
  1133.                 $redirectTo $user->hasValidAccessToLiveApp() ?
  1134.                     $this->redirect(sprintf('%s/%s'$this->getParameter('user_dashboard_url'), 'listings')) :
  1135.                     $this->redirectToRoute('aqarmap_listing_default_mylistings');
  1136.                 return $redirectTo;
  1137.             }
  1138.             $this->addFlash(
  1139.                 'success',
  1140.                 $this->translator->trans('add_listing_page.success_messages.padding_review')
  1141.             );
  1142.             if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1143.                 $this->addFlash(
  1144.                     'info',
  1145.                     $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1146.                 );
  1147.             }
  1148.             return $this->redirectToRoute('listing_finish', [
  1149.                 'id' => $listing->getId(),
  1150.             ]);
  1151.         } catch (\Exception $e) {
  1152.             $buyCreditLink $this->generateUrl('page_view', ['slug' => 'buy-credit'], true);
  1153.             if ($this->setting->getSetting('features''payments')) {
  1154.                 $buyCreditLink $this->generateUrl('aqarmap_buy_credit');
  1155.             }
  1156.             $this->addFlash('danger'$this->translator->trans(
  1157.                 $e->getMessage(),
  1158.                 ['%link%' => $buyCreditLink],
  1159.                 'exceptions'
  1160.             ));
  1161.         }
  1162.         return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1163.             'id' => $listing->getId(),
  1164.         ]), Response::HTTP_FOUND);
  1165.     }
  1166.     /**
  1167.      * @Route(
  1168.      *     "/listing/{id}/payment_confirmation",
  1169.      *     requirements={"id" = "\d+"}, name="listing_confirm_publish_credit", methods={"GET"}
  1170.      * )
  1171.      *
  1172.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1173.      *
  1174.      * @return array|RedirectResponse
  1175.      */
  1176.     public function confirmPublishing(Listing $listingUserPackagesService $userPackagesService): Response
  1177.     {
  1178.         $listingRule $this->listingRuleMatcher->match($listing);
  1179.         /** @var $em \Doctrine\ORM\EntityManager */
  1180.         $em $this->getDoctrine()->getManager();
  1181.         // User Balance
  1182.         $userDetails $listing->getUser();
  1183.         $available_balance $this->userPackagesRepository->getTotalCreditsByUser($userDetails);
  1184.         $userId $userDetails->getId();
  1185.         $em->getRepository(User::class)->findOneBy(['id' => $userId]);
  1186.         $listingManger $this->listingManager;
  1187.         if (!$userPackagesService->canListInLocation($listing)) {
  1188.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  1189.             return $this->redirect($this->generateUrl('listing_upload', [
  1190.                 'id' => $listing->getId(),
  1191.             ]), Response::HTTP_FOUND);
  1192.         }
  1193.         $userServiceRepository $em->getRepository(UserServices::class);
  1194.         if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId)
  1195.             && ListingCategories::UNLIMITED != $listing->getCategory()
  1196.             && ListingStatus::DRAFT != $listing->getStatus()
  1197.         ) {
  1198.             if ($userServiceRepository
  1199.                     ->passUnlimitedListing($listing$this->creditManager$listingManger) || $listing->getPublicationCredit()
  1200.             ) {
  1201.                 if ($this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1202.                     return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1203.                         'id' => $listing->getId(),
  1204.                     ]));
  1205.                 }
  1206.                 return $this->redirect($this->generateUrl('listing_finish', [
  1207.                     'id' => $listing->getId(),
  1208.                 ]));
  1209.             }
  1210.         }
  1211.         $isUserInSpecialAddListingGroup $this->specialAddListingService->hasSpecialAddListingGroup($userDetails);
  1212.         $userUnlimitedListings $this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId);
  1213.         $userHasNoFreeListingService = !$userUnlimitedListings;
  1214.         $userHasNoFreeListingQuote = ($userUnlimitedListings && == $userUnlimitedListings['remainingQuota']);
  1215.         if ($isUserInSpecialAddListingGroup) {
  1216.             if ($userHasNoFreeListingService || $userHasNoFreeListingQuote) {
  1217.                 return $this->redirectToRoute('special_add_listing_feature', ['id' => $listing->getId()]);
  1218.             }
  1219.         }
  1220.         $form $this->ConfirmPaymentForm($listing);
  1221.         return $this->render(
  1222.             '@AqarmapListing/Listing/confirmPublishing.html.twig',
  1223.             [
  1224.                 'listing' => $listing,
  1225.                 'fees' => $listingRule['publication_fees'],
  1226.                 'duration' => $listingRule['duration'],
  1227.                 'available_balance' => $available_balance,
  1228.                 'form' => $form->createView(),
  1229.             ]
  1230.         );
  1231.     }
  1232.     /**
  1233.      * @Route(
  1234.      *     "/listing/{id}/list_rejections",
  1235.      *     requirements={"id" = "\d+"},
  1236.      *     name="listing_list_rejections", methods={"GET"}
  1237.      * )
  1238.      *
  1239.      * @Security("is_granted('ROLE_OWNER', listing)")
  1240.      *
  1241.      * @return array
  1242.      */
  1243.     public function listRejections(Listing $listingRequest $request): Response
  1244.     {
  1245.         if ($request->get('notification')) {
  1246.             try {
  1247.                 $this->databaseNotification->markOneAsRead($request->get('notification'));
  1248.             } catch (\Exception $exception) {
  1249.                 $this->logger->log(LogLevel::ERROR$exception->getMessage());
  1250.             }
  1251.         }
  1252.         return $this->render(
  1253.             '@AqarmapListing/Listing/confirmPublishing.html.twig',
  1254.             [
  1255.                 'listing' => $listing,
  1256.             ]
  1257.         );
  1258.     }
  1259.     /**
  1260.      * @Route(
  1261.      *     "/listing/{id}/payment_confirmation",
  1262.      *     requirements={"id" = "\d+"}, name="listing_confirm_publish_credit_post", methods={"POST"}
  1263.      * )
  1264.      *
  1265.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1266.      *
  1267.      * @return array|RedirectResponse
  1268.      */
  1269.     public function prepareListingPayment(Listing $listingRequest $requestUserPackagesService $userPackagesService): RedirectResponse
  1270.     {
  1271.         $listingRule $this->listingRuleMatcher->match($listing);
  1272.         /** @var EntityManager $em */
  1273.         $em $this->getDoctrine()->getManager();
  1274.         // User Balance
  1275.         $available_balance $this->userPackagesRepository->getTotalCreditsByUser($listing->getUser());
  1276.         $userId $listing->getUser()->getId();
  1277.         $listingManger $this->listingManager;
  1278.         if (!$userPackagesService->canListInLocation($listing)) {
  1279.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  1280.             return $this->redirect($this->generateUrl('listing_upload', [
  1281.                 'id' => $listing->getId(),
  1282.             ]), Response::HTTP_FOUND);
  1283.         }
  1284.         $userServiceRepository $em->getRepository(UserServices::class);
  1285.         if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId)) {
  1286.             if ($userServiceRepository->passUnlimitedListing($listing$this->creditManager$listingManger)
  1287.             ) {
  1288.                 if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1289.                     return $this->redirect($this->generateUrl('listing_finish', [
  1290.                         'id' => $listing->getId(),
  1291.                     ]));
  1292.                 }
  1293.                 return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1294.                     'id' => $listing->getId(),
  1295.                 ]));
  1296.             }
  1297.         }
  1298.         $form $this->ConfirmPaymentForm($listing);
  1299.         $form->handleRequest($request);
  1300.         if ($form->isSubmitted() && $form->isValid()) {
  1301.             // Payment Confirmed?
  1302.             // If user cancel payment redirect him to his listing,
  1303.             if (!$form->get('confirm')->isClicked()) {
  1304.                 return $this->redirect($this->generateUrl('listing_view', [
  1305.                     'id' => $listing->getId(),
  1306.                 ]), Response::HTTP_FOUND);
  1307.             }
  1308.             // If user credit expired, complain.
  1309.             $enforceCredit $this->setting->getSetting('features''enforce_credits_expiration');
  1310.             /** @var User $user */
  1311.             $user $this->getUser();
  1312.             if ($enforceCredit && === $user->getAbsoluteCreditExpiryDays()) {
  1313.                 $this->addFlash('danger'$this->translator->trans('credit.credit_can_not_use', [
  1314.                     'link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),
  1315.                 ]));
  1316.                 return $this->redirect($this->generateUrl('listing_confirm_publish_credit', [
  1317.                     'id' => $listing->getId(),
  1318.                 ]), Response::HTTP_FOUND);
  1319.             }
  1320.             // User already paid
  1321.             if ($listing->getPublicationCredit()) {
  1322.                 $this->addFlash('info'$this->translator->trans('credit.already_paid'));
  1323.             } else {
  1324.                 // User don't have enough credits
  1325.                 if ($listingRule['publication_fees'] > $available_balance) {
  1326.                     $this->addFlash('danger'$this->translator->trans('credit.not_enough_credits'));
  1327.                 } else {
  1328.                     // Subtract publication fees
  1329.                     $credits $this->creditManager->deduction(
  1330.                         $listing->getUser(),
  1331.                         $listingRule['publication_fees'],
  1332.                         'Listing Fees'
  1333.                     );
  1334.                     foreach ($credits as $credit) {
  1335.                         if ($credit instanceof Credit) {
  1336.                             $credit->setStatus(CreditStatus::SUCCESS);
  1337.                             $this->listingManager->addFeature($listingListingFeatures::PAIDnull$credit);
  1338.                             if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1339.                                 return $this->redirect($this->generateUrl('listing_finish', [
  1340.                                     'id' => $listing->getId(),
  1341.                                 ]));
  1342.                             }
  1343.                         }
  1344.                     }
  1345.                     return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1346.                         'id' => $listing->getId(),
  1347.                         'ref' => 'add_listing',
  1348.                     ]));
  1349.                 }
  1350.             }
  1351.         }
  1352.         $this->addFlash('danger''Unexpected error occurred.');
  1353.         return $this->redirect($this->generateUrl('listing_confirm_publish_credit', [
  1354.             'id' => $listing->getId(),
  1355.         ]));
  1356.     }
  1357.     private function ConfirmPaymentForm(Listing $listing)
  1358.     {
  1359.         return $this->createForm(ConfirmFormType::class, null, [
  1360.             'method' => 'POST',
  1361.             'action' => $this->generateUrl('listing_confirm_publish_credit_post', ['id' => $listing->getId()]),
  1362.         ]);
  1363.     }
  1364.     /**
  1365.      * @return \Symfony\Component\Form\Form
  1366.      */
  1367.     private function confirmFeaturedPaymentForm(Listing $listing)
  1368.     {
  1369.         return $this->createForm(ConfirmFeaturedFormType::class, null, [
  1370.             'method' => 'POST',
  1371.             'action' => $this
  1372.                 ->generateUrl(
  1373.                     'listing_confirm_publish_featured_credit_post',
  1374.                     ['id' => $listing->getId()]
  1375.                 ),
  1376.         ]);
  1377.     }
  1378.     /**
  1379.      * Delete Listing entity.
  1380.      *
  1381.      * @Route("/listing/{id}/delete", requirements={"id" = "\d+"}, name="listing_delete", options={"expose"=true})
  1382.      *
  1383.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1384.      */
  1385.     public function delete(Listing $listingRequest $request): RedirectResponse
  1386.     {
  1387.         if (\in_array('ROLE_PREVENT_DELETE_LISTING'$this->getUser()->getRoles())) {
  1388.             throw new AccessDeniedHttpException("Forbidden, user don't have this permession.");
  1389.         }
  1390.         if (ListingStatus::EXPIRED == $listing->getStatus()) {
  1391.             throw $this->createNotFoundException('Listing is expired.');
  1392.         }
  1393.         $this->listingManager->remove($listingListingStatus::USER_DELETED);
  1394.         $this->addFlash(
  1395.             'success',
  1396.             $this->translator->trans('add_listing_page.success_messages.deleted')
  1397.         );
  1398.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  1399.     }
  1400.     /**
  1401.      * unDelete Listing entity.
  1402.      *
  1403.      * @Route("/listing/{id}/undelete", requirements={"id" = "\d+"}, name="listing_undelete")
  1404.      *
  1405.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1406.      *
  1407.      * @return RedirectResponse|Response|null
  1408.      */
  1409.     public function undelete(Listing $listing)
  1410.     {
  1411.         if (ListingStatus::USER_DELETED != $listing->getStatus()) {
  1412.             throw $this->createNotFoundException('Unable to find this listing.');
  1413.         }
  1414.         $this->getDoctrine()->getManager();
  1415.         $this->listingManager->changeStatus($listingListingStatus::PENDING);
  1416.         $listingEvent = new ListingEvent($listing);
  1417.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  1418.         $response $listingEvent->getResponse();
  1419.         if (null === $response) {
  1420.             if (ListingStatus::PENDING === $listing->getStatus()) {
  1421.                 $this->addFlash(
  1422.                     'success',
  1423.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  1424.                 );
  1425.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1426.                     $this->addFlash(
  1427.                         'info',
  1428.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1429.                     );
  1430.                 }
  1431.             }
  1432.             $response = new RedirectResponse(
  1433.                 $this->generateUrl(
  1434.                     'listing_slug',
  1435.                     ['id' => $listing->getId(), 'slug' => $listing->getSlug()]
  1436.                 )
  1437.             );
  1438.         }
  1439.         return $response;
  1440.     }
  1441.     /**
  1442.      * Creates "Request a Call" button.
  1443.      *
  1444.      * @return \Symfony\Component\Form\Form
  1445.      */
  1446.     public function callRequestForm(Listing $listing)
  1447.     {
  1448.         return $this->createForm(CallRequestFormType::class, null, [
  1449.             'method' => 'POST',
  1450.             'action' => $this->generateUrl('aqarmap_listing_call_request', ['id' => $listing->getId()]),
  1451.         ]);
  1452.     }
  1453.     /**
  1454.      * Creates contact seller form.
  1455.      *
  1456.      * @param Listing $listing The listing entity
  1457.      *
  1458.      * @return \Symfony\Component\Form\Form The form
  1459.      */
  1460.     public function contactSellerForm(Listing $listing)
  1461.     {
  1462.         return $this->createForm(ContactSellerFormType::class, null, [
  1463.             'method' => 'POST',
  1464.             'action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),
  1465.         ]);
  1466.     }
  1467.     /**
  1468.      * Creates contact seller form.
  1469.      *
  1470.      * @param Listing $listing The listing entity
  1471.      *
  1472.      * @return \Symfony\Component\Form\Form The form
  1473.      */
  1474.     public function contactSellerWideForm(Listing $listing)
  1475.     {
  1476.         return $this->createForm(ContactSellerWideFormType::class, null, [
  1477.             'method' => 'POST',
  1478.             'action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),
  1479.         ]);
  1480.     }
  1481.     /**
  1482.      * Creates quick registration form.
  1483.      *
  1484.      * @return \Symfony\Component\Form\Form The form
  1485.      */
  1486.     public function quickRegistrationForm()
  1487.     {
  1488.         return $this->createForm(QuickRegistrationFormType::class, null, [
  1489.             'method' => 'POST',
  1490.             'action' => $this->generateUrl('aqarmap_user_quick_registration'),
  1491.         ]);
  1492.     }
  1493.     /**
  1494.      * Contact Seller Action.
  1495.      *
  1496.      * @Route("/listing/{id}/contact_seller", requirements={"id" = "\d+"}, name="aqarmap_listing_contact_seller", options={"expose"=true}, defaults={"_format": "json"}, methods={"POST"})
  1497.      *
  1498.      * @Rest\View()
  1499.      *
  1500.      * @return array|\Symfony\Component\Form\Form
  1501.      */
  1502.     public function contactSeller(Listing $listingRequest $request)
  1503.     {
  1504.         $form $this->contactSellerForm($listing);
  1505.         if ($request->request->has('contact_seller_wide')) {
  1506.             $form $this->contactSellerWideForm($listing);
  1507.         }
  1508.         $lead $request->get('lead');
  1509.         $originalPhoneNumber $lead['phone'];
  1510.         $phoneNumber $lead $this->phoneManager->trimZero($lead['phone'], $request->get('countryCode')) : null;
  1511.         $message json_decode((string) $request->get('message'), true);
  1512.         $hasEmail = !$request->get('isAutoGeneratedEmail'0);
  1513.         $user $this->getUser();
  1514.         $form->handleRequest($request);
  1515.         if ($lead) {
  1516.             $form $this->createForm(QuickLeadType::class, null, [
  1517.                 'method' => 'POST',
  1518.                 'csrf_protection' => false,
  1519.             ]);
  1520.             /** @var User $user */
  1521.             $user $this->FOSUserManager->findUserByEmail($lead['email']);
  1522.             if (!$user && !$hasEmail) {
  1523.                 $user $this->userManager->findLatestByPhone($phoneNumber$request->get('countryCode'));
  1524.             }
  1525.             if (!$user && $hasEmail) {
  1526.                 $user $this->userManager->findAndReplaceUserAndEmail($phoneNumber$lead['email'], $request->get('countryCode'));
  1527.             }
  1528.             $phone $this->phoneManager->findOrSavePhoneNumber($phoneNumber$request->get('countryCode'), null$originalPhoneNumber);
  1529.             if (!$user) {
  1530.                 $user $this->FOSUserManager->createUser();
  1531.                 $user
  1532.                     ->setFullName($lead['name'])
  1533.                     ->setPhoneNumber($lead['phone'])
  1534.                     ->setTempOriginalPhoneNumber($originalPhoneNumber)
  1535.                     ->setEmail($lead['email'])
  1536.                     ->setHasEmail($hasEmail)
  1537.                     ->setIsQucikRegistered(true)
  1538.                 ;
  1539.                 $this->userManager->quickRegister($user$form$requesttruefalsefalse);
  1540.                 $registerMessage $this->translator->trans('popup_form.success');
  1541.             }
  1542.             $this->phoneManager->addNewUserPhone($phoneNumber$request->get('countryCode'), $usertruefalsenull$originalPhoneNumber);
  1543.         }
  1544.         if ($request->isMethod('POST')) {
  1545.             // Get current logged in user
  1546.             $user ??= $this->getUser();
  1547.             $composer $this->messageComposer;
  1548.             $composer
  1549.                 ->setSender($user)
  1550.                 ->compose($message['content'], $listingnull$message['type'] ?? LeadTypes::SEND_MESSAGE)
  1551.             ;
  1552.             $this->addFlash(
  1553.                 'success',
  1554.                 $this->translator->trans('add_listing_page.success_messages.message_sent')
  1555.             );
  1556.             return [
  1557.                 'status' => 'ok',
  1558.                 'message' => $this->translator->trans('listing.success_message_seller'),
  1559.             ];
  1560.         }
  1561.         return $form;
  1562.     }
  1563.     /**
  1564.      * Contact Seller Action.
  1565.      *
  1566.      * @Route("/listing/{id}/call_request", requirements={"id" = "\d+", "_format" = "json"},
  1567.      *      name="aqarmap_listing_call_request",
  1568.      *      options={"expose"=true},
  1569.      *      defaults={"_format": "json"},
  1570.      *      methods={"POST"}
  1571.      * )
  1572.      *
  1573.      * @Rest\View()
  1574.      */
  1575.     public function callRequest(Request $requestListing $listing)
  1576.     {
  1577.         $lead $request->get('lead');
  1578.         $countryCode $request->get('countryCode'$lead['countryCode'] ?? '+20');
  1579.         $originalPhoneNumber $lead['phone'];
  1580.         $phoneNumber $lead $this->phoneManager->trimZero($lead['phone'], $countryCode) : null;
  1581.         $user $this->getUser();
  1582.         $registerMessage '';
  1583.         $callRequest = new CallRequest();
  1584.         if ($lead) {
  1585.             $form $this->createForm(QuickLeadType::class, null, [
  1586.                 'method' => 'POST',
  1587.                 'csrf_protection' => false,
  1588.             ]);
  1589.             $form->handleRequest($request);
  1590.             $hasEmail = !$request->get('isAutoGeneratedEmail'0);
  1591.             /** @var User $user */
  1592.             $user $this->FOSUserManager->findUserByEmail($lead['email']);
  1593.             if (!$user && !$hasEmail) {
  1594.                 $user $this->userManager->findLatestByPhone($phoneNumber$countryCode);
  1595.             }
  1596.             if (!$user && $hasEmail) {
  1597.                 $user $this->userManager->findAndReplaceUserAndEmail($phoneNumber$lead['email'], $request->get('countryCode'));
  1598.             }
  1599.             $phone $this->phoneManager->findOrSavePhoneNumber($phoneNumber$countryCodenull$originalPhoneNumber);
  1600.             if (!$user) {
  1601.                 $user $this->FOSUserManager->createUser();
  1602.                 $user
  1603.                     ->setFullName($lead['name'])
  1604.                     ->setPhoneNumber($lead['phone'])
  1605.                     ->setTempCountryCode($countryCode)
  1606.                     ->setTempOriginalPhoneNumber($originalPhoneNumber)
  1607.                     ->setEmail($lead['email'])
  1608.                     ->setHasEmail($hasEmail)
  1609.                     ->setIsQucikRegistered(true)
  1610.                 ;
  1611.                 $this->userManager->quickRegister($user$form$requesttruefalsefalse);
  1612.                 $registerMessage $this->translator->trans('popup_form.success');
  1613.             }
  1614.             $callRequest->setPhone($phone);
  1615.             $callRequest->setLeadEmail($lead['email']);
  1616.             $callRequest->setLeadFullName($lead['name']);
  1617.             $this->phoneManager->addNewUserPhone($phoneNumber$countryCode$usertruefalsenull$originalPhoneNumber);
  1618.         }
  1619.         // Create Call Request
  1620.         $callRequest->setUser($user);
  1621.         $callRequest->setListing($listing);
  1622.         $form $this->callRequestForm($listing);
  1623.         $form->handleRequest($request);
  1624.         $isPostRequestAndValidForm $request->isMethod('POST') && ($form->isSubmitted() && $form->isValid());
  1625.         $isNotCheckForm = (false == $request->get('check_form'));
  1626.         if ($isPostRequestAndValidForm || $isNotCheckForm) {
  1627.             try {
  1628.                 $this->callRequestManager->submitCallRequest($callRequestnull$request->query->get('sourceRoute'''));
  1629.                 return [
  1630.                     'status' => 'ok',
  1631.                     'message' => $this->translator->trans('listing.success_call_request'),
  1632.                     'registerMessage' => $registerMessage,
  1633.                 ];
  1634.             } catch (InvalidLeadValidationHttpException $exception) {
  1635.                 return [
  1636.                     'status' => $exception->getStatusCode(),
  1637.                     'message' => $exception->getMessage(),
  1638.                 ];
  1639.             }
  1640.         }
  1641.         return $form;
  1642.     }
  1643.     /**
  1644.      * Show how to add a listing for new users.
  1645.      *
  1646.      * @Route("/add_listing", name="aqarmap_add_listing")
  1647.      */
  1648.     public function addListingRoles(): Response
  1649.     {
  1650.         return $this->render(
  1651.             '@AqarmapListing/Listing/addListingRoles.html.twig',
  1652.             [
  1653.             ]
  1654.         );
  1655.     }
  1656.     /**
  1657.      * @Route("/listing/{id}/relist", requirements={"id" = "\d+"}, name="aqarmap_listing_relist", options={"expose"=true} )
  1658.      *
  1659.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1660.      *
  1661.      * @return RedirectResponse|Response
  1662.      */
  1663.     public function relist(Listing $listing)
  1664.     {
  1665.         if (!\in_array($listing->getStatus(), [ListingStatus::EXPIREDListingStatus::USER_DELETED])) {
  1666.             throw new LogicHttpException('Whoops! Looks like the listing you are trying to relist in not expired!');
  1667.         }
  1668.         $em $this->getDoctrine()->getManager();
  1669.         $listingRepo $em->getRepository(Listing::class);
  1670.         $relistChild $listingRepo->getRelistChild($listing);
  1671.         if ($relistChild) {
  1672.             $this->addFlash(
  1673.                 'success',
  1674.                 $this->translator->trans('add_listing_page.success_messages.relist')
  1675.             );
  1676.             return new RedirectResponse(
  1677.                 $this
  1678.                     ->generateUrl(
  1679.                         'listing_slug',
  1680.                         ['id' => $relistChild->getId(),
  1681.                             'slug' => $relistChild->getSlug(), ]
  1682.                     )
  1683.             )
  1684.             ;
  1685.         }
  1686.         $listing $this->listingManager->relist($listing);
  1687.         // Check if the listing require more photos or require repayment, and redirection.
  1688.         $listingEvent = new ListingEvent($listing);
  1689.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.resubmitted');
  1690.         $response $listingEvent->getResponse();
  1691.         if (null === $response) {
  1692.             if (\in_array($listing->getStatus(), [ListingStatus::PENDINGListingStatus::LIVE])) {
  1693.                 $this->addFlash(
  1694.                     'success',
  1695.                     $this->translator->trans('add_listing_page.success_messages.relist')
  1696.                 );
  1697.             }
  1698.             $response = new RedirectResponse(
  1699.                 $this
  1700.                     ->generateUrl(
  1701.                         'listing_slug',
  1702.                         [
  1703.                             'id' => $listing->getId(),
  1704.                             'slug' => $listing->getSlug(),
  1705.                         ]
  1706.                     )
  1707.             );
  1708.         }
  1709.         return $response;
  1710.     }
  1711.     /**
  1712.      * @Route(
  1713.      *     "/listing/transfer/scraped/{id}",
  1714.      *     requirements={"id" = "\d+"},
  1715.      *     name="aqarmap_listing_transfer_ownership",
  1716.      *     options={"expose"=true},
  1717.      *     methods={"POST"},
  1718.      * )
  1719.      */
  1720.     public function transferScrapedListingOwnership(Listing $listing)
  1721.     {
  1722.         /** @var User $user */
  1723.         $user $this->getUser();
  1724.         /** @var EntityManager $em */
  1725.         $em $this->getDoctrine()->getManager();
  1726.         if (!$listing->canChangeScrapedListing()) {
  1727.             throw new LogicHttpException();
  1728.         }
  1729.         $listing->setUser($user);
  1730.         $em->persist($listing);
  1731.         $em->flush($listing);
  1732.         return new JsonResponse();
  1733.     }
  1734.     /**
  1735.      * @Route("/listing/{id}/pump_up",
  1736.      * requirements={"id" = "\d+"}, name="confirm_listing_pump_up", methods={"POST"})
  1737.      *
  1738.      * @Security("is_granted('ROLE_OWNER', listing)")
  1739.      */
  1740.     public function confirmPumpUpListing(Listing $listingRequest $request): RedirectResponse
  1741.     {
  1742.         $pumpUpForm $this->confirmFeaturedPaymentForm($listing);
  1743.         $pumpUpForm->handleRequest($request);
  1744.         if ($request->isMethod('POST') && $pumpUpForm->isValid()) {
  1745.             if (!$pumpUpForm->get('confirm')->isClicked()) {
  1746.                 return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'), Response::HTTP_FOUND);
  1747.             }
  1748.             try {
  1749.                 $this->listingManager->pumpUp($listing);
  1750.                 $this->addFlash(
  1751.                     'success',
  1752.                     $this->translator->trans('credit.pump_up_success', [':listing_title:' => $listing->getTitle()])
  1753.                 );
  1754.             } catch (\Exception $e) {
  1755.                 $this->addFlash('danger'$e->getMessage());
  1756.             }
  1757.         }
  1758.         return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1759.     }
  1760.     /**
  1761.      * @Route("/listing/{id}/pump_up",
  1762.      * requirements={"id" = "\d+"}, name="listing_pump_up", methods={"GET"})
  1763.      *
  1764.      * @Security("is_granted('ROLE_OWNER', listing)")
  1765.      *
  1766.      * @return array|RedirectResponse
  1767.      */
  1768.     public function pumpUpListing(Listing $listing)
  1769.     {
  1770.         $listingRules $this->listingManager->getListingRules($listing);
  1771.         $listingOwner $listing->getUser();
  1772.         $pumpUpFees $listingRules['pump_up_fees'];
  1773.         $pumpUpOccurrence $listingRules['pump_up_occurrence'];
  1774.         $pumpUpDuration $listingRules['pump_up_duration'];
  1775.         if (!$this->listingManager->isPumpUpAvailable($listingRules)) {
  1776.             $this->addFlash(
  1777.                 'danger',
  1778.                 $this->translator->trans('credit.pump_up_not_available')
  1779.             );
  1780.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1781.         }
  1782.         if (!$this->listingManager->isAffordable($listingOwner$pumpUpFees)) {
  1783.             $this->addFlash(
  1784.                 'danger',
  1785.                 $this->translator->trans('credit.pump_up_can_not_use')
  1786.             );
  1787.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1788.         }
  1789.         /** @var $em \Doctrine\ORM\EntityManager */
  1790.         $em $this->getDoctrine()->getManager();
  1791.         $em->getRepository(Credit::class);
  1792.         $pumpUpForm $this->createForm(ConfirmFeaturedFormType::class, null, [
  1793.             'method' => 'POST',
  1794.             'action' => $this
  1795.                 ->generateUrl(
  1796.                     'listing_pump_up',
  1797.                     ['id' => $listing->getId()]
  1798.                 ),
  1799.             'confirm_message' => $this->translator->trans('listing.pump_up.confirm'),
  1800.             'cancel_message' => $this->translator->trans('listing.pump_up.cancel'),
  1801.         ]);
  1802.         return $this->render(
  1803.             '@AqarmapListing/Listing/pumpUpListing.html.twig',
  1804.             [
  1805.                 'fees' => $pumpUpFees,
  1806.                 'duration' => $pumpUpDuration,
  1807.                 'occurrence' => $pumpUpOccurrence,
  1808.                 'form' => $pumpUpForm->createView(),
  1809.             ]
  1810.         );
  1811.     }
  1812.     /**
  1813.      * Listing Details Single Page App.
  1814.      *
  1815.      * @Route("/listingApp/{id}", requirements={"id" = "\d+"} , options={"expose" = true} , name="listing_details_app", methods={"GET"})
  1816.      */
  1817.     public function listingDetailsApp(Listing $listing): Response
  1818.     {
  1819.         return $this->render(
  1820.             '@AqarmapListing/Listing/listingDetailsApp.html.twig',
  1821.             [
  1822.                 'listingId' => $listing->getReferenceId(),
  1823.             ]
  1824.         );
  1825.     }
  1826.     /**
  1827.      * Delete Listing Photos.
  1828.      *
  1829.      * @Route("/photos/delete", name="listing_bulk_delete_photo", requirements={"id" = "\d+"})
  1830.      *
  1831.      * @throws \Doctrine\ORM\OptimisticLockException
  1832.      */
  1833.     public function bulkDeletePhoto(Request $requestListingPhotoRepository $listingPhotoRepositoryListingManager $listingManager): RedirectResponse
  1834.     {
  1835.         $photosIds $request->get('photos');
  1836.         try {
  1837.             if ($photosIds) {
  1838.                 $photos $listingPhotoRepository->getPhotos($photosIds);
  1839.                 $listingManager->bulkDeletePhotos($photos);
  1840.             } else {
  1841.                 $this->addFlash('danger''No photos selected for deletion');
  1842.             }
  1843.         } catch (\Exception $e) {
  1844.             $this->addFlash('danger''Something went wrong');
  1845.         }
  1846.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  1847.     }
  1848.     /**
  1849.      * Update WhatsApp Phones.
  1850.      */
  1851.     private function updateWhatsAppPhones(int $userId, array $phones = [], array $whatsApp = []): void
  1852.     {
  1853.         foreach ($phones as $index => $phone) {
  1854.             $whatsApp[$index] = isset($whatsApp[$index]) && 'true' === $whatsApp[$index];
  1855.             $this->phoneManager->updateWhatsApp($userId, (int) $phone$whatsApp[$index], true);
  1856.         }
  1857.     }
  1858. }