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

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.         $hasRentalPackage $this->userPackagesRepository->hasRentalPackage($user);
  682.         $initializeOptions = [
  683.             'action' => $this->generateUrl('listing_initialize'),
  684.             'method' => 'POST',
  685.             'em' => $this->getDoctrine()->getManager(),
  686.             'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),
  687.             'has_rental_package' => $hasRentalPackage,
  688.             'parentUser' => $user,
  689.         ];
  690.         $form $this->createForm(ListingInitializeType::class, $listing = new Listing(), $initializeOptions);
  691.         $listingEvent = new ListingEvent($listing);
  692.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.pre_submitted');
  693.         $form->handleRequest($request);
  694.         if ($form->isSubmitted() && $form->isValid()) {
  695.             $listing $this->listingManager->createDraft($listing);
  696.             // Add user phone number to the listing
  697.             if ($listing->getUser()->getPhoneNumber()) {
  698.                 // link user phone with this listing
  699.                 // TODO: Suggest only the main number for now, later on we will suggest the main + last 2 numbers.
  700.                 $this->listingManager->suggestListingPhoneNumbers(
  701.                     [$listing->getUser()->getPhoneNumber()],
  702.                     $listing
  703.                 );
  704.             }
  705.             return $this->redirect($this->generateUrl('listing_edit', [
  706.                 'id' => $listing->getId(),
  707.             ]));
  708.         }
  709.         return $this->render('@AqarmapListing/Listing/initialize.html.twig', [
  710.             'form' => $form->createView(),
  711.         ]);
  712.     }
  713.     /**
  714.      * Add Listing V2.
  715.      *
  716.      * @Route("/listing/initialize/{step}", name="add_listing", options={"expose"=true})
  717.      * @Route("/listing/initialize/{id}/{step}", name="edit_listing", options={"expose"=true})
  718.      *
  719.      * @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
  720.      *
  721.      * @throws \Doctrine\ORM\NonUniqueResultException
  722.      */
  723.     public function addListing(): Response
  724.     {
  725.         return $this->render('@AqarmapListing/Listing/add.html.twig', [
  726.             'title' => $this->translator->trans('listing.add_your_listing'),
  727.             'featureToggle' => [
  728.                 'accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),
  729.                 'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),
  730.             ],
  731.         ]);
  732.     }
  733.     /**
  734.      * Add Listing groups.
  735.      *
  736.      * @Route("/listing/add/", name="add_listing_steps", options={"expose"=true})
  737.      * @Route("/listing/{id}/edit/steps", name="edit_listing_steps", options={"expose"=true})
  738.      *
  739.      * @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
  740.      *
  741.      * @throws \Doctrine\ORM\NonUniqueResultException
  742.      */
  743.     public function addListingSteps(): Response
  744.     {
  745.         return $this->render('@AqarmapListing/Listing/addSteps.html.twig', [
  746.             'title' => $this->translator->trans('listing.add_your_listing'),
  747.             'featureToggle' => [
  748.                 'accept_adding_phones' => $this->featureToggleManager->isEnabled('web.addlisting.accept_adding_phones'),
  749.                 'google_maps_location' => $this->featureToggleManager->isEnabled('web.addlisting.google_maps_location'),
  750.             ],
  751.         ]);
  752.     }
  753.     /**
  754.      * Listing Post Action
  755.      * This action manage adding & editing listings.
  756.      *
  757.      * @Route("/listing/{id}/edit/", name="listing_edit", requirements={"id" = "\d+"}, options={"expose"=true})
  758.      *
  759.      * @Security(
  760.      *     "(is_granted('IS_AUTHENTICATED_REMEMBERED') and is_granted('ROLE_OWNER', listing)) or is_granted('ROLE_ADMIN')"
  761.      * )
  762.      */
  763.     public function post(Request $requestListing $listing): Response
  764.     {
  765.         $form $this->createForm(ListingType::class, $listing, [
  766.             'action' => $this->generateUrl('listing_edit', ['id' => $listing->getId()]),
  767.             'method' => 'POST',
  768.             'listingIsLiveFor5Days' => $this->listingManager->checkListingLiveDays($listing),
  769.             'is_admin' => $this->authorizationChecker->isGranted('ROLE_ADMIN'),
  770.             'user_country' => $this->setting->getSetting('general''country'),
  771.             'user_type' => $listing->getUser() ? $listing->getUser()->getUserType() : null,
  772.             'isMortgageOptionsEnabled' => $this->featureToggleManager->isEnabled('web.mortgage.options'),
  773.             'isListingMarketPropertyTypesEnabled' => $this->featureToggleManager->isEnabled('web.listing.market.property.types'),
  774.         ]);
  775.         $form->handleRequest($request);
  776.         if ($request->isMethod('POST')) {
  777.             if ($form->isSubmitted() && $form->isValid()) {
  778.                 $this->updateWhatsAppPhones($listing->getUser()->getId(), (array) $request->request->get('phoneIds', []), (array) $request->request->get('hasWhatsApp', []));
  779.                 $listing $this->handleListingPhones($listing$request->request->all()['listing']['phones']);
  780.                 $this->handleUserPhones($listing->getUser(), $request->request->all()['listing']['phones']);
  781.                 $this->listingManager->saveListing($listing);
  782.                 if ($this->featureToggleManager->isEnabled('web.add.listing.translations')) {
  783.                     if ('en' == $request->getLocale()) {
  784.                         $criteria = [
  785.                             'reversedLocale' => 'ar',
  786.                             'title-ar' => $request->request->get('title-ar'),
  787.                             'description-ar' => $request->request->get('description-ar'),
  788.                         ];
  789.                     } else {
  790.                         $criteria = [
  791.                             'reversedLocale' => 'en',
  792.                             'title-en' => $request->request->get('title-en'),
  793.                             'description-en' => $request->request->get('description-en'),
  794.                         ];
  795.                     }
  796.                     $this->listingManager->updateListingTranslationsFields($listing$criteria);
  797.                 } else {
  798.                     $this->listingManager->updateListingTranslations($listing);
  799.                 }
  800.                 if ($this->featureToggleManager->isEnabled('web.mortgage.options')) {
  801.                     $propertyRegistrationStatus $form->has('propertyRegistrationStatus') ? $form->get('propertyRegistrationStatus')->getData() : null;
  802.                     if (\in_array($propertyRegistrationStatusPropertyRegistrationStatusOption::getValidMorgageOptions())) {
  803.                         $this->mortgageService->addEligibleMortgageTypes($listing);
  804.                     } else {
  805.                         $this->listingManager->setELigibleMortgageToNull($listing);
  806.                     }
  807.                     $listing $this->mortgageService->addMortgageApproval($listing$form);
  808.                 }
  809.                 $listingEvent = new ListingEvent($listing);
  810.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  811.                 if (ListingSource::SCRAPPING == $listing->getSource()
  812.                     || ListingSource::LITE == $listing->getSource()
  813.                 ) {
  814.                     return $this->redirect($this->generateUrl('listing_view', ['id' => $listing->getId()]));
  815.                 }
  816.                 return $this
  817.                     ->redirect(
  818.                         $this->generateUrl(
  819.                             'listing_upload',
  820.                             ['id' => $listing->getId(), '_locale' => $request->get('_locale')]
  821.                         )
  822.                     )
  823.                 ;
  824.             }
  825.             $this->addFlash('danger'$this->translator->trans('static.problem_error_message'));
  826.         }
  827.         $translatedLocale 'en' == $request->getLocale() ? 'ar' 'en';
  828.         return $this->render('@AqarmapListing/Listing/post.html.twig', [
  829.             'form' => $form->createView(),
  830.             'listing' => $listing,
  831.             'title_translation' => $this->listingTitleTranslations($listing$translatedLocale),
  832.             'description_translation' => $this->listingDescriptionTranslations($listing$translatedLocale),
  833.             'brokerChoices' => UserTypes::getBrokerChoices(),
  834.         ]);
  835.     }
  836.     /**
  837.      * @return array|mixed
  838.      */
  839.     private function listingTitleTranslations(Listing $listingstring $locale)
  840.     {
  841.         $this->translatableListener->setTranslatableLocale($locale);
  842.         $listing->setTranslatableLocale($locale);
  843.         $this->entityManager->refresh($listing);
  844.         return $listing->getTitle() ?? $this->listingManager->listingTitleTranslations($listing$locale);
  845.     }
  846.     private function listingDescriptionTranslations(Listing $listingstring $locale)
  847.     {
  848.         $this->translatableListener->setTranslatableLocale($locale);
  849.         $listing->setTranslatableLocale($locale);
  850.         $this->entityManager->refresh($listing);
  851.         return $listing->getDescription() ?? $this->listingManager->listingTitleTranslations($listing$locale);
  852.     }
  853.     private function handleListingPhones(Listing $listing, array $phones): Listing
  854.     {
  855.         $listing->clearPhones();
  856.         foreach ($phones as $phone) {
  857.             $phoneNumber $phone['number'];
  858.             $countryCode $phone['countryCode'];
  859.             $phone = new Phone($countryCode.$phoneNumber$countryCode);
  860.             $listing->addPhone(new ListingPhone($phoneNumber$listing$countryCode$phone));
  861.         }
  862.         return $listing;
  863.     }
  864.     private function handleUserPhones(User $user, array $phones): void
  865.     {
  866.         foreach ($phones as $phone) {
  867.             $originalPhoneNumber $phone['number'];
  868.             $countryCode $phone['countryCode'];
  869.             $phoneNumber $this->phoneManager->trimZero($originalPhoneNumber$countryCode);
  870.             $this->phoneManager->addNewUserPhone($phoneNumber$countryCode$usertruefalsenull$originalPhoneNumber);
  871.         }
  872.     }
  873.     /**
  874.      * Listing Post Action
  875.      * This action manage adding & editing listings.
  876.      *
  877.      * @Route("/listing/{id}/preview/", name="listing_preview", requirements={"id" = "\d+"}, options={"expose"=true})
  878.      *
  879.      * @Security(
  880.      *     "(is_granted('IS_AUTHENTICATED_REMEMBERED') and is_granted('ROLE_OWNER', listing)) or is_granted('ROLE_ADMIN')"
  881.      * )
  882.      *
  883.      * @return array|RedirectResponse
  884.      */
  885.     public function preview(Listing $listing): Response
  886.     {
  887.         return $this->render('@AqarmapListing/Listing/preview.html.twig', [
  888.             'listing' => $listing,
  889.         ]);
  890.     }
  891.     /**
  892.      * Listing Post Action
  893.      * This action manage adding & editing listings.
  894.      *
  895.      * @Route("/listing/lite", name="listing_lite_add",  options={"expose"=true})
  896.      */
  897.     public function postLite(Request $request)
  898.     {
  899.         /** @var $em \Doctrine\ORM\EntityManager */
  900.         $em $this->getDoctrine()->getManager();
  901.         $form $this->createForm(
  902.             LiteListingType::class,
  903.             null,
  904.             ['em' => $em,
  905.                 'action' => $this->generateUrl('listing_lite_add'),
  906.                 'method' => 'post', ]
  907.         );
  908.         if ($request->isMethod('POST')) {
  909.             $form->handleRequest($request);
  910.             if ($form->isSubmitted() && $form->isValid()) {
  911.                 $listing $form->getData();
  912.                 $listing->setSellerRole(ListingSellerRoles::OWNER);
  913.                 $this->listingManager->saveListing($listing);
  914.                 // add listing phone to new phones table ;
  915.                 $this->phoneManager->addListingPhonesList($listing->getPhones(), ''$listing);
  916.                 $this->listingManager->addLiteListingTitleAndDescriptionTranslation($listing);
  917.                 $listingEvent = new ListingEvent($listing);
  918.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  919.                 $this->addFlash(
  920.                     'success',
  921.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  922.                 );
  923.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  924.                     $this->addFlash(
  925.                         'info',
  926.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  927.                     );
  928.                 }
  929.                 return $this->redirect($this->generateUrl('homepage'));
  930.             }
  931.             $this->addFlash('danger'$this->translator->trans('static.problem_error_message'));
  932.         }
  933.         return $this->render('@AqarmapListing/Listing/postLite.html.twig', [
  934.             'form' => $form->createView(),
  935.         ]);
  936.     }
  937.     /**
  938.      * Add Listing First Step Action.
  939.      *
  940.      * @Route("/listing/{id}/edit/photos", name="listing_upload", requirements={"id" = "\d+"}, options={"expose"=true})
  941.      *
  942.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  943.      */
  944.     public function upload(Request $requestListing $listing)
  945.     {
  946.         $form $this->createForm(PhotoType::class, null, [
  947.             'method' => 'POST',
  948.         ]);
  949.         $form->handleRequest($request);
  950.         $listingRules $this->listingRuleMatcher->match($listing);
  951.         if ($form->isSubmitted() && $form->isValid() && $request->isMethod('POST')) {
  952.             $listingPhotos = [];
  953.             try {
  954.                 $listingPhotos $this->listingManager->addListingPhotos($listing$form->get('file')->getData());
  955.                 $listingEvent = new ListingEvent($listing);
  956.                 $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  957.                 $this->listingManager->saveListing($listing);
  958.                 // If not Ajax request
  959.                 if (!$request->isXmlHttpRequest()) {
  960.                     $this->logger->error('Not AJAX');
  961.                     return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  962.                 }
  963.             } catch (\Exception $exception) {
  964.                 $this->logger->error($exception->getMessage());
  965.             }
  966.             return View::create(['files' => $listingPhotos], Response::HTTP_OK);
  967.         }
  968.         return $this->render('@AqarmapListing/Listing/upload.html.twig', [
  969.             'requiredPhotosCount' => $listingRules['required_photos'] ?? 0,
  970.             'listing' => $listing,
  971.             'form' => $form->createView(),
  972.         ]);
  973.     }
  974.     /**
  975.      * Should be called after photos are uploaded.
  976.      *
  977.      * @Route("/listing/{id}/finish", requirements={"id" = "\d+"}, name="listing_finish")
  978.      *
  979.      * @return RedirectResponse|Response
  980.      */
  981.     public function finish(Listing $listingUserPackagesService $userPackagesService)
  982.     {
  983.         $listingEvent = new ListingEvent($listing);
  984.         if (!$userPackagesService->canListInLocation($listing)) {
  985.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  986.             return $this->redirect($this->generateUrl('listing_upload', [
  987.                 'id' => $listing->getId(),
  988.             ]), Response::HTTP_FOUND);
  989.         }
  990.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  991.         $response $listingEvent->getResponse();
  992.         if (null === $response) {
  993.             if (ListingStatus::PENDING === $listing->getStatus()) {
  994.                 $this->addFlash(
  995.                     'success',
  996.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  997.                 );
  998.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  999.                     $this->addFlash(
  1000.                         'info',
  1001.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1002.                     );
  1003.                 }
  1004.             }
  1005.             $response = new RedirectResponse(
  1006.                 $this->generateUrl(
  1007.                     'listing_slug',
  1008.                     ['id' => $listing->getId(), 'slug' => $listing->getSlug()]
  1009.                 )
  1010.             );
  1011.         }
  1012.         return $response;
  1013.     }
  1014.     /**
  1015.      * SWAT special add listing feature page.
  1016.      *
  1017.      * @Route("/listing/{id}/feature", requirements={"id" = "\d+"}, name="special_add_listing_feature")
  1018.      *
  1019.      * @Security("is_granted('ROLE_OWNER', listing)")
  1020.      */
  1021.     public function specialAddListingFeature(Listing $listing): RedirectResponse
  1022.     {
  1023.         return $this->redirectToRoute('listing_finish', ['id' => $listing->getId()]);
  1024.     }
  1025.     /**
  1026.      * @Route("/listing/{id}/make_it_featured",
  1027.      * requirements={"id" = "\d+"}, name="listing_confirm_featured_credit", methods={"GET"})
  1028.      *
  1029.      * @Security("is_granted('ROLE_OWNER', listing)")
  1030.      *
  1031.      * @return RedirectResponse|Response
  1032.      */
  1033.     public function confirmFeaturedPublishing(Listing $listing)
  1034.     {
  1035.         if (!\in_array($listing->getStatus(), [ListingStatus::PENDINGListingStatus::LIVE])) {
  1036.             $this->addFlash(
  1037.                 'danger',
  1038.                 $this->translator->trans('listing.featured_failure_statement.not_live_or_pending')
  1039.             );
  1040.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1041.         }
  1042.         if (UserTypes::INDIVIDUAL == $listing->getUser()->getUserType()) {
  1043.             $listingRules $this->listingFeatureService->getFeaturedListingRules($listing, ['sold_by_owner''sold_by_owner_sponsored']);
  1044.         } else {
  1045.             $listingRules $this->listingFeatureService->getFeaturedListingRules($listing, ['featured''premium''sponsored''spotlight']);
  1046.         }
  1047.         /** @var User $user */
  1048.         $user $this->getUser();
  1049.         return $this->render(
  1050.             '@AqarmapListing/Listing/featuredListingCheckout.html.twig',
  1051.             [
  1052.                 'listingRules' => $listingRules,
  1053.                 'listingId' => $listing->getId(),
  1054.                 'haveFeesToFeature' => $this->listingManager->userHasFeesToFeature($user$listing),
  1055.             ]
  1056.         );
  1057.     }
  1058.     /**
  1059.      * @Route("/listing/{id}/make_it_featured",  options={"expose"=true} ,requirements={"id" = "\d+"},
  1060.      * name="listing_confirm_publish_featured_credit_post", methods={"POST"})
  1061.      *
  1062.      * @Security("is_granted('ROLE_OWNER', listing)")
  1063.      */
  1064.     public function prepareFeaturedListingPayment(Listing $listingRequest $request): RedirectResponse
  1065.     {
  1066.         $listingRules $this->listingManager->getListingRules($listing);
  1067.         $fees $request->query->get('fees'$listingRules['featured_fees']);
  1068.         $duration $request->query->get('duration'$listingRules['featured_duration']);
  1069.         $listingFeaturedType $request->query->get('listingFeaturedType'ListingFeaturedTypes::FEATURED);
  1070.         $listingFeature $request->query->get('listingFeature'ListingFeatures::FEATURED);
  1071.         $listingStatus $listing->getStatus();
  1072.         /** @var User $user */
  1073.         $user $this->getUser();
  1074.         if (!$this->listingManager->isAffordable($user$fees)) {
  1075.             $this->addFlash('danger'$this->translator->trans('credit.not_enough_featuring_credit', [
  1076.                 'link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),
  1077.             ]));
  1078.             return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1079.                 'id' => $listing->getId(),
  1080.             ]), Response::HTTP_FOUND);
  1081.         }
  1082.         $featuredText $this->translator->trans(ListingFeaturedTypes::getFeaturedText($listingFeaturedType));
  1083.         $rules = [
  1084.             'featuredFees' => $fees,
  1085.             'featuredDuration' => $duration,
  1086.             'listingFeaturedType' => $listingFeaturedType,
  1087.             'listingFeature' => $listingFeature,
  1088.             'featuredText' => $featuredText,
  1089.         ];
  1090.         if ($this->listingManager->requiresFeaturingReview($listingFeaturedType)) {
  1091.             try {
  1092.                 $this->listingManager->makeItFeatured($listing$rules);
  1093.                 if (ListingStatus::LIVE == $listingStatus) {
  1094.                     $this->addFlash(
  1095.                         'success',
  1096.                         $this->translator->trans('add_listing_page.success_messages.pending_featuring', [':featured_type:' => $featuredText])
  1097.                     );
  1098.                 } else {
  1099.                     $this->addFlash(
  1100.                         'success',
  1101.                         $this->translator->trans('add_listing_page.success_messages.padding_review')
  1102.                     );
  1103.                     if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1104.                         $this->addFlash(
  1105.                             'info',
  1106.                             $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1107.                         );
  1108.                     }
  1109.                 }
  1110.             } catch (\Exception $exception) {
  1111.                 $this->addFlash('danger'$this->translator->trans($exception->getMessage()));
  1112.             }
  1113.             if (ListingStatus::LIVE == $listingStatus) {
  1114.                 return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1115.             }
  1116.             return $this->redirect($this->generateUrl('listing_finish', [
  1117.                 'id' => $listing->getId(),
  1118.             ]));
  1119.         }
  1120.         try {
  1121.             $this->listingManager->makeItFeatured($listing$rules);
  1122.             if (ListingStatus::LIVE == $listing->getStatus()) {
  1123.                 $this->addFlash(
  1124.                     'success',
  1125.                     $this->translator->trans(
  1126.                         'add_listing_page.success_messages.featured',
  1127.                         [':listing_title:' => $listing->getTitle(), ':featured_type:' => $featuredText]
  1128.                     )
  1129.                 );
  1130.                 $redirectTo $user->hasValidAccessToLiveApp() ?
  1131.                     $this->redirect(sprintf('%s/%s'$this->getParameter('user_dashboard_url'), 'listings')) :
  1132.                     $this->redirectToRoute('aqarmap_listing_default_mylistings');
  1133.                 return $redirectTo;
  1134.             }
  1135.             $this->addFlash(
  1136.                 'success',
  1137.                 $this->translator->trans('add_listing_page.success_messages.padding_review')
  1138.             );
  1139.             if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1140.                 $this->addFlash(
  1141.                     'info',
  1142.                     $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1143.                 );
  1144.             }
  1145.             return $this->redirectToRoute('listing_finish', [
  1146.                 'id' => $listing->getId(),
  1147.             ]);
  1148.         } catch (\Exception $e) {
  1149.             $buyCreditLink $this->generateUrl('page_view', ['slug' => 'buy-credit'], true);
  1150.             if ($this->setting->getSetting('features''payments')) {
  1151.                 $buyCreditLink $this->generateUrl('aqarmap_buy_credit');
  1152.             }
  1153.             $this->addFlash('danger'$this->translator->trans(
  1154.                 $e->getMessage(),
  1155.                 ['%link%' => $buyCreditLink],
  1156.                 'exceptions'
  1157.             ));
  1158.         }
  1159.         return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1160.             'id' => $listing->getId(),
  1161.         ]), Response::HTTP_FOUND);
  1162.     }
  1163.     /**
  1164.      * @Route(
  1165.      *     "/listing/{id}/payment_confirmation",
  1166.      *     requirements={"id" = "\d+"}, name="listing_confirm_publish_credit", methods={"GET"}
  1167.      * )
  1168.      *
  1169.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1170.      *
  1171.      * @return array|RedirectResponse
  1172.      */
  1173.     public function confirmPublishing(Listing $listingUserPackagesService $userPackagesService): Response
  1174.     {
  1175.         $listingRule $this->listingRuleMatcher->match($listing);
  1176.         /** @var $em \Doctrine\ORM\EntityManager */
  1177.         $em $this->getDoctrine()->getManager();
  1178.         // User Balance
  1179.         $userDetails $listing->getUser();
  1180.         $available_balance $this->userPackagesRepository->getTotalCreditsByUser($userDetails);
  1181.         $userId $userDetails->getId();
  1182.         $em->getRepository(User::class)->findOneBy(['id' => $userId]);
  1183.         $listingManger $this->listingManager;
  1184.         if (!$userPackagesService->canListInLocation($listing)) {
  1185.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  1186.             return $this->redirect($this->generateUrl('listing_upload', [
  1187.                 'id' => $listing->getId(),
  1188.             ]), Response::HTTP_FOUND);
  1189.         }
  1190.         $userServiceRepository $em->getRepository(UserServices::class);
  1191.         if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId)
  1192.             && ListingCategories::UNLIMITED != $listing->getCategory()
  1193.             && ListingStatus::DRAFT != $listing->getStatus()
  1194.         ) {
  1195.             if ($userServiceRepository
  1196.                     ->passUnlimitedListing($listing$this->creditManager$listingManger) || $listing->getPublicationCredit()
  1197.             ) {
  1198.                 if ($this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1199.                     return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1200.                         'id' => $listing->getId(),
  1201.                     ]));
  1202.                 }
  1203.                 return $this->redirect($this->generateUrl('listing_finish', [
  1204.                     'id' => $listing->getId(),
  1205.                 ]));
  1206.             }
  1207.         }
  1208.         $isUserInSpecialAddListingGroup $this->specialAddListingService->hasSpecialAddListingGroup($userDetails);
  1209.         $userUnlimitedListings $this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId);
  1210.         $userHasNoFreeListingService = !$userUnlimitedListings;
  1211.         $userHasNoFreeListingQuote = ($userUnlimitedListings && == $userUnlimitedListings['remainingQuota']);
  1212.         if ($isUserInSpecialAddListingGroup) {
  1213.             if ($userHasNoFreeListingService || $userHasNoFreeListingQuote) {
  1214.                 return $this->redirectToRoute('special_add_listing_feature', ['id' => $listing->getId()]);
  1215.             }
  1216.         }
  1217.         $form $this->ConfirmPaymentForm($listing);
  1218.         return $this->render(
  1219.             '@AqarmapListing/Listing/confirmPublishing.html.twig',
  1220.             [
  1221.                 'listing' => $listing,
  1222.                 'fees' => $listingRule['publication_fees'],
  1223.                 'duration' => $listingRule['duration'],
  1224.                 'available_balance' => $available_balance,
  1225.                 'form' => $form->createView(),
  1226.             ]
  1227.         );
  1228.     }
  1229.     /**
  1230.      * @Route(
  1231.      *     "/listing/{id}/list_rejections",
  1232.      *     requirements={"id" = "\d+"},
  1233.      *     name="listing_list_rejections", methods={"GET"}
  1234.      * )
  1235.      *
  1236.      * @Security("is_granted('ROLE_OWNER', listing)")
  1237.      *
  1238.      * @return array
  1239.      */
  1240.     public function listRejections(Listing $listingRequest $request): Response
  1241.     {
  1242.         if ($request->get('notification')) {
  1243.             try {
  1244.                 $this->databaseNotification->markOneAsRead($request->get('notification'));
  1245.             } catch (\Exception $exception) {
  1246.                 $this->logger->log(LogLevel::ERROR$exception->getMessage());
  1247.             }
  1248.         }
  1249.         return $this->render(
  1250.             '@AqarmapListing/Listing/confirmPublishing.html.twig',
  1251.             [
  1252.                 'listing' => $listing,
  1253.             ]
  1254.         );
  1255.     }
  1256.     /**
  1257.      * @Route(
  1258.      *     "/listing/{id}/payment_confirmation",
  1259.      *     requirements={"id" = "\d+"}, name="listing_confirm_publish_credit_post", methods={"POST"}
  1260.      * )
  1261.      *
  1262.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1263.      *
  1264.      * @return array|RedirectResponse
  1265.      */
  1266.     public function prepareListingPayment(Listing $listingRequest $requestUserPackagesService $userPackagesService): RedirectResponse
  1267.     {
  1268.         $listingRule $this->listingRuleMatcher->match($listing);
  1269.         /** @var EntityManager $em */
  1270.         $em $this->getDoctrine()->getManager();
  1271.         // User Balance
  1272.         $available_balance $this->userPackagesRepository->getTotalCreditsByUser($listing->getUser());
  1273.         $userId $listing->getUser()->getId();
  1274.         $listingManger $this->listingManager;
  1275.         if (!$userPackagesService->canListInLocation($listing)) {
  1276.             $this->addFlash('danger'$this->translator->trans('credit.can_not_list_in_location'));
  1277.             return $this->redirect($this->generateUrl('listing_upload', [
  1278.                 'id' => $listing->getId(),
  1279.             ]), Response::HTTP_FOUND);
  1280.         }
  1281.         $userServiceRepository $em->getRepository(UserServices::class);
  1282.         if ($this->userServicesManager->hasActiveService(UserServicesType::UNLIMITED_LISTINGS$userId)) {
  1283.             if ($userServiceRepository->passUnlimitedListing($listing$this->creditManager$listingManger)
  1284.             ) {
  1285.                 if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1286.                     return $this->redirect($this->generateUrl('listing_finish', [
  1287.                         'id' => $listing->getId(),
  1288.                     ]));
  1289.                 }
  1290.                 return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1291.                     'id' => $listing->getId(),
  1292.                 ]));
  1293.             }
  1294.         }
  1295.         $form $this->ConfirmPaymentForm($listing);
  1296.         $form->handleRequest($request);
  1297.         if ($form->isSubmitted() && $form->isValid()) {
  1298.             // Payment Confirmed?
  1299.             // If user cancel payment redirect him to his listing,
  1300.             if (!$form->get('confirm')->isClicked()) {
  1301.                 return $this->redirect($this->generateUrl('listing_view', [
  1302.                     'id' => $listing->getId(),
  1303.                 ]), Response::HTTP_FOUND);
  1304.             }
  1305.             // If user credit expired, complain.
  1306.             $enforceCredit $this->setting->getSetting('features''enforce_credits_expiration');
  1307.             /** @var User $user */
  1308.             $user $this->getUser();
  1309.             if ($enforceCredit && === $user->getAbsoluteCreditExpiryDays()) {
  1310.                 $this->addFlash('danger'$this->translator->trans('credit.credit_can_not_use', [
  1311.                     'link' => $this->generateUrl('aqarmap_buy_credit', ['listing_id' => $listing->getId()]),
  1312.                 ]));
  1313.                 return $this->redirect($this->generateUrl('listing_confirm_publish_credit', [
  1314.                     'id' => $listing->getId(),
  1315.                 ]), Response::HTTP_FOUND);
  1316.             }
  1317.             // User already paid
  1318.             if ($listing->getPublicationCredit()) {
  1319.                 $this->addFlash('info'$this->translator->trans('credit.already_paid'));
  1320.             } else {
  1321.                 // User don't have enough credits
  1322.                 if ($listingRule['publication_fees'] > $available_balance) {
  1323.                     $this->addFlash('danger'$this->translator->trans('credit.not_enough_credits'));
  1324.                 } else {
  1325.                     // Subtract publication fees
  1326.                     $credits $this->creditManager->deduction(
  1327.                         $listing->getUser(),
  1328.                         $listingRule['publication_fees'],
  1329.                         'Listing Fees'
  1330.                     );
  1331.                     foreach ($credits as $credit) {
  1332.                         if ($credit instanceof Credit) {
  1333.                             $credit->setStatus(CreditStatus::SUCCESS);
  1334.                             $this->listingManager->addFeature($listingListingFeatures::PAIDnull$credit);
  1335.                             if (!$this->listingFeatureService->isFeaturedOffersAvailable($listing)) {
  1336.                                 return $this->redirect($this->generateUrl('listing_finish', [
  1337.                                     'id' => $listing->getId(),
  1338.                                 ]));
  1339.                             }
  1340.                         }
  1341.                     }
  1342.                     return $this->redirect($this->generateUrl('listing_confirm_featured_credit', [
  1343.                         'id' => $listing->getId(),
  1344.                         'ref' => 'add_listing',
  1345.                     ]));
  1346.                 }
  1347.             }
  1348.         }
  1349.         $this->addFlash('danger''Unexpected error occurred.');
  1350.         return $this->redirect($this->generateUrl('listing_confirm_publish_credit', [
  1351.             'id' => $listing->getId(),
  1352.         ]));
  1353.     }
  1354.     private function ConfirmPaymentForm(Listing $listing)
  1355.     {
  1356.         return $this->createForm(ConfirmFormType::class, null, [
  1357.             'method' => 'POST',
  1358.             'action' => $this->generateUrl('listing_confirm_publish_credit_post', ['id' => $listing->getId()]),
  1359.         ]);
  1360.     }
  1361.     /**
  1362.      * @return \Symfony\Component\Form\Form
  1363.      */
  1364.     private function confirmFeaturedPaymentForm(Listing $listing)
  1365.     {
  1366.         return $this->createForm(ConfirmFeaturedFormType::class, null, [
  1367.             'method' => 'POST',
  1368.             'action' => $this
  1369.                 ->generateUrl(
  1370.                     'listing_confirm_publish_featured_credit_post',
  1371.                     ['id' => $listing->getId()]
  1372.                 ),
  1373.         ]);
  1374.     }
  1375.     /**
  1376.      * Delete Listing entity.
  1377.      *
  1378.      * @Route("/listing/{id}/delete", requirements={"id" = "\d+"}, name="listing_delete", options={"expose"=true})
  1379.      *
  1380.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1381.      */
  1382.     public function delete(Listing $listingRequest $request): RedirectResponse
  1383.     {
  1384.         if (\in_array('ROLE_PREVENT_DELETE_LISTING'$this->getUser()->getRoles())) {
  1385.             throw new AccessDeniedHttpException("Forbidden, user don't have this permession.");
  1386.         }
  1387.         if (ListingStatus::EXPIRED == $listing->getStatus()) {
  1388.             throw $this->createNotFoundException('Listing is expired.');
  1389.         }
  1390.         $this->listingManager->remove($listingListingStatus::USER_DELETED);
  1391.         $this->addFlash(
  1392.             'success',
  1393.             $this->translator->trans('add_listing_page.success_messages.deleted')
  1394.         );
  1395.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  1396.     }
  1397.     /**
  1398.      * unDelete Listing entity.
  1399.      *
  1400.      * @Route("/listing/{id}/undelete", requirements={"id" = "\d+"}, name="listing_undelete")
  1401.      *
  1402.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1403.      *
  1404.      * @return RedirectResponse|Response|null
  1405.      */
  1406.     public function undelete(Listing $listing)
  1407.     {
  1408.         if (ListingStatus::USER_DELETED != $listing->getStatus()) {
  1409.             throw $this->createNotFoundException('Unable to find this listing.');
  1410.         }
  1411.         $this->getDoctrine()->getManager();
  1412.         $this->listingManager->changeStatus($listingListingStatus::PENDING);
  1413.         $listingEvent = new ListingEvent($listing);
  1414.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.submitted');
  1415.         $response $listingEvent->getResponse();
  1416.         if (null === $response) {
  1417.             if (ListingStatus::PENDING === $listing->getStatus()) {
  1418.                 $this->addFlash(
  1419.                     'success',
  1420.                     $this->translator->trans('add_listing_page.success_messages.padding_review')
  1421.                 );
  1422.                 if ($this->featureToggleManager->isEnabled('web.delayed.review.eid.info.message')) {
  1423.                     $this->addFlash(
  1424.                         'info',
  1425.                         $this->translator->trans('add_listing_page.info_messages.eid_delayed_review')
  1426.                     );
  1427.                 }
  1428.             }
  1429.             $response = new RedirectResponse(
  1430.                 $this->generateUrl(
  1431.                     'listing_slug',
  1432.                     ['id' => $listing->getId(), 'slug' => $listing->getSlug()]
  1433.                 )
  1434.             );
  1435.         }
  1436.         return $response;
  1437.     }
  1438.     /**
  1439.      * Creates "Request a Call" button.
  1440.      *
  1441.      * @return \Symfony\Component\Form\Form
  1442.      */
  1443.     public function callRequestForm(Listing $listing)
  1444.     {
  1445.         return $this->createForm(CallRequestFormType::class, null, [
  1446.             'method' => 'POST',
  1447.             'action' => $this->generateUrl('aqarmap_listing_call_request', ['id' => $listing->getId()]),
  1448.         ]);
  1449.     }
  1450.     /**
  1451.      * Creates contact seller form.
  1452.      *
  1453.      * @param Listing $listing The listing entity
  1454.      *
  1455.      * @return \Symfony\Component\Form\Form The form
  1456.      */
  1457.     public function contactSellerForm(Listing $listing)
  1458.     {
  1459.         return $this->createForm(ContactSellerFormType::class, null, [
  1460.             'method' => 'POST',
  1461.             'action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),
  1462.         ]);
  1463.     }
  1464.     /**
  1465.      * Creates contact seller form.
  1466.      *
  1467.      * @param Listing $listing The listing entity
  1468.      *
  1469.      * @return \Symfony\Component\Form\Form The form
  1470.      */
  1471.     public function contactSellerWideForm(Listing $listing)
  1472.     {
  1473.         return $this->createForm(ContactSellerWideFormType::class, null, [
  1474.             'method' => 'POST',
  1475.             'action' => $this->generateUrl('aqarmap_listing_contact_seller', ['id' => $listing->getId()]),
  1476.         ]);
  1477.     }
  1478.     /**
  1479.      * Creates quick registration form.
  1480.      *
  1481.      * @return \Symfony\Component\Form\Form The form
  1482.      */
  1483.     public function quickRegistrationForm()
  1484.     {
  1485.         return $this->createForm(QuickRegistrationFormType::class, null, [
  1486.             'method' => 'POST',
  1487.             'action' => $this->generateUrl('aqarmap_user_quick_registration'),
  1488.         ]);
  1489.     }
  1490.     /**
  1491.      * Contact Seller Action.
  1492.      *
  1493.      * @Route("/listing/{id}/contact_seller", requirements={"id" = "\d+"}, name="aqarmap_listing_contact_seller", options={"expose"=true}, defaults={"_format": "json"}, methods={"POST"})
  1494.      *
  1495.      * @Rest\View()
  1496.      *
  1497.      * @return array|\Symfony\Component\Form\Form
  1498.      */
  1499.     public function contactSeller(Listing $listingRequest $request)
  1500.     {
  1501.         $form $this->contactSellerForm($listing);
  1502.         if ($request->request->has('contact_seller_wide')) {
  1503.             $form $this->contactSellerWideForm($listing);
  1504.         }
  1505.         $lead $request->get('lead');
  1506.         $originalPhoneNumber $lead['phone'];
  1507.         $phoneNumber $lead $this->phoneManager->trimZero($lead['phone'], $request->get('countryCode')) : null;
  1508.         $message json_decode((string) $request->get('message'), true);
  1509.         $hasEmail = !$request->get('isAutoGeneratedEmail'0);
  1510.         $user $this->getUser();
  1511.         $form->handleRequest($request);
  1512.         if ($lead) {
  1513.             $form $this->createForm(QuickLeadType::class, null, [
  1514.                 'method' => 'POST',
  1515.                 'csrf_protection' => false,
  1516.             ]);
  1517.             /** @var User $user */
  1518.             $user $this->FOSUserManager->findUserByEmail($lead['email']);
  1519.             if (!$user && !$hasEmail) {
  1520.                 $user $this->userManager->findLatestByPhone($phoneNumber$request->get('countryCode'));
  1521.             }
  1522.             if (!$user && $hasEmail) {
  1523.                 $user $this->userManager->findAndReplaceUserAndEmail($phoneNumber$lead['email'], $request->get('countryCode'));
  1524.             }
  1525.             $phone $this->phoneManager->findOrSavePhoneNumber($phoneNumber$request->get('countryCode'), null$originalPhoneNumber);
  1526.             if (!$user) {
  1527.                 $user $this->FOSUserManager->createUser();
  1528.                 $user
  1529.                     ->setFullName($lead['name'])
  1530.                     ->setPhoneNumber($lead['phone'])
  1531.                     ->setTempOriginalPhoneNumber($originalPhoneNumber)
  1532.                     ->setEmail($lead['email'])
  1533.                     ->setHasEmail($hasEmail)
  1534.                     ->setIsQucikRegistered(true)
  1535.                 ;
  1536.                 $this->userManager->quickRegister($user$form$requesttruefalsefalse);
  1537.                 $registerMessage $this->translator->trans('popup_form.success');
  1538.             }
  1539.             $this->phoneManager->addNewUserPhone($phoneNumber$request->get('countryCode'), $usertruefalsenull$originalPhoneNumber);
  1540.         }
  1541.         if ($request->isMethod('POST')) {
  1542.             // Get current logged in user
  1543.             $user ??= $this->getUser();
  1544.             $composer $this->messageComposer;
  1545.             $composer
  1546.                 ->setSender($user)
  1547.                 ->compose($message['content'], $listingnull$message['type'] ?? LeadTypes::SEND_MESSAGE)
  1548.             ;
  1549.             $this->addFlash(
  1550.                 'success',
  1551.                 $this->translator->trans('add_listing_page.success_messages.message_sent')
  1552.             );
  1553.             return [
  1554.                 'status' => 'ok',
  1555.                 'message' => $this->translator->trans('listing.success_message_seller'),
  1556.             ];
  1557.         }
  1558.         return $form;
  1559.     }
  1560.     /**
  1561.      * Contact Seller Action.
  1562.      *
  1563.      * @Route("/listing/{id}/call_request", requirements={"id" = "\d+", "_format" = "json"},
  1564.      *      name="aqarmap_listing_call_request",
  1565.      *      options={"expose"=true},
  1566.      *      defaults={"_format": "json"},
  1567.      *      methods={"POST"}
  1568.      * )
  1569.      *
  1570.      * @Rest\View()
  1571.      */
  1572.     public function callRequest(Request $requestListing $listing)
  1573.     {
  1574.         $lead $request->get('lead');
  1575.         $countryCode $request->get('countryCode'$lead['countryCode'] ?? '+20');
  1576.         $originalPhoneNumber $lead['phone'];
  1577.         $phoneNumber $lead $this->phoneManager->trimZero($lead['phone'], $countryCode) : null;
  1578.         $user $this->getUser();
  1579.         $registerMessage '';
  1580.         $callRequest = new CallRequest();
  1581.         if ($lead) {
  1582.             $form $this->createForm(QuickLeadType::class, null, [
  1583.                 'method' => 'POST',
  1584.                 'csrf_protection' => false,
  1585.             ]);
  1586.             $form->handleRequest($request);
  1587.             $hasEmail = !$request->get('isAutoGeneratedEmail'0);
  1588.             /** @var User $user */
  1589.             $user $this->FOSUserManager->findUserByEmail($lead['email']);
  1590.             if (!$user && !$hasEmail) {
  1591.                 $user $this->userManager->findLatestByPhone($phoneNumber$countryCode);
  1592.             }
  1593.             if (!$user && $hasEmail) {
  1594.                 $user $this->userManager->findAndReplaceUserAndEmail($phoneNumber$lead['email'], $request->get('countryCode'));
  1595.             }
  1596.             $phone $this->phoneManager->findOrSavePhoneNumber($phoneNumber$countryCodenull$originalPhoneNumber);
  1597.             if (!$user) {
  1598.                 $user $this->FOSUserManager->createUser();
  1599.                 $user
  1600.                     ->setFullName($lead['name'])
  1601.                     ->setPhoneNumber($lead['phone'])
  1602.                     ->setTempCountryCode($countryCode)
  1603.                     ->setTempOriginalPhoneNumber($originalPhoneNumber)
  1604.                     ->setEmail($lead['email'])
  1605.                     ->setHasEmail($hasEmail)
  1606.                     ->setIsQucikRegistered(true)
  1607.                 ;
  1608.                 $this->userManager->quickRegister($user$form$requesttruefalsefalse);
  1609.                 $registerMessage $this->translator->trans('popup_form.success');
  1610.             }
  1611.             $callRequest->setPhone($phone);
  1612.             $callRequest->setLeadEmail($lead['email']);
  1613.             $callRequest->setLeadFullName($lead['name']);
  1614.             $this->phoneManager->addNewUserPhone($phoneNumber$countryCode$usertruefalsenull$originalPhoneNumber);
  1615.         }
  1616.         // Create Call Request
  1617.         $callRequest->setUser($user);
  1618.         $callRequest->setListing($listing);
  1619.         $form $this->callRequestForm($listing);
  1620.         $form->handleRequest($request);
  1621.         $isPostRequestAndValidForm $request->isMethod('POST') && ($form->isSubmitted() && $form->isValid());
  1622.         $isNotCheckForm = (false == $request->get('check_form'));
  1623.         if ($isPostRequestAndValidForm || $isNotCheckForm) {
  1624.             try {
  1625.                 $this->callRequestManager->submitCallRequest($callRequestnull$request->query->get('sourceRoute'''));
  1626.                 return [
  1627.                     'status' => 'ok',
  1628.                     'message' => $this->translator->trans('listing.success_call_request'),
  1629.                     'registerMessage' => $registerMessage,
  1630.                 ];
  1631.             } catch (InvalidLeadValidationHttpException $exception) {
  1632.                 return [
  1633.                     'status' => $exception->getStatusCode(),
  1634.                     'message' => $exception->getMessage(),
  1635.                 ];
  1636.             }
  1637.         }
  1638.         return $form;
  1639.     }
  1640.     /**
  1641.      * Show how to add a listing for new users.
  1642.      *
  1643.      * @Route("/add_listing", name="aqarmap_add_listing")
  1644.      */
  1645.     public function addListingRoles(): Response
  1646.     {
  1647.         return $this->render(
  1648.             '@AqarmapListing/Listing/addListingRoles.html.twig',
  1649.             [
  1650.             ]
  1651.         );
  1652.     }
  1653.     /**
  1654.      * @Route("/listing/{id}/relist", requirements={"id" = "\d+"}, name="aqarmap_listing_relist", options={"expose"=true} )
  1655.      *
  1656.      * @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', listing)")
  1657.      *
  1658.      * @return RedirectResponse|Response
  1659.      */
  1660.     public function relist(Listing $listing)
  1661.     {
  1662.         if (!\in_array($listing->getStatus(), [ListingStatus::EXPIREDListingStatus::USER_DELETED])) {
  1663.             throw new LogicHttpException('Whoops! Looks like the listing you are trying to relist in not expired!');
  1664.         }
  1665.         $em $this->getDoctrine()->getManager();
  1666.         $listingRepo $em->getRepository(Listing::class);
  1667.         $relistChild $listingRepo->getRelistChild($listing);
  1668.         if ($relistChild) {
  1669.             $this->addFlash(
  1670.                 'success',
  1671.                 $this->translator->trans('add_listing_page.success_messages.relist')
  1672.             );
  1673.             return new RedirectResponse(
  1674.                 $this
  1675.                     ->generateUrl(
  1676.                         'listing_slug',
  1677.                         ['id' => $relistChild->getId(),
  1678.                             'slug' => $relistChild->getSlug(), ]
  1679.                     )
  1680.             )
  1681.             ;
  1682.         }
  1683.         $listing $this->listingManager->relist($listing);
  1684.         // Check if the listing require more photos or require repayment, and redirection.
  1685.         $listingEvent = new ListingEvent($listing);
  1686.         $this->dispatcher->dispatch($listingEvent'aqarmap.listing.resubmitted');
  1687.         $response $listingEvent->getResponse();
  1688.         if (null === $response) {
  1689.             if (\in_array($listing->getStatus(), [ListingStatus::PENDINGListingStatus::LIVE])) {
  1690.                 $this->addFlash(
  1691.                     'success',
  1692.                     $this->translator->trans('add_listing_page.success_messages.relist')
  1693.                 );
  1694.             }
  1695.             $response = new RedirectResponse(
  1696.                 $this
  1697.                     ->generateUrl(
  1698.                         'listing_slug',
  1699.                         [
  1700.                             'id' => $listing->getId(),
  1701.                             'slug' => $listing->getSlug(),
  1702.                         ]
  1703.                     )
  1704.             );
  1705.         }
  1706.         return $response;
  1707.     }
  1708.     /**
  1709.      * @Route(
  1710.      *     "/listing/transfer/scraped/{id}",
  1711.      *     requirements={"id" = "\d+"},
  1712.      *     name="aqarmap_listing_transfer_ownership",
  1713.      *     options={"expose"=true},
  1714.      *     methods={"POST"},
  1715.      * )
  1716.      */
  1717.     public function transferScrapedListingOwnership(Listing $listing)
  1718.     {
  1719.         /** @var User $user */
  1720.         $user $this->getUser();
  1721.         /** @var EntityManager $em */
  1722.         $em $this->getDoctrine()->getManager();
  1723.         if (!$listing->canChangeScrapedListing()) {
  1724.             throw new LogicHttpException();
  1725.         }
  1726.         $listing->setUser($user);
  1727.         $em->persist($listing);
  1728.         $em->flush($listing);
  1729.         return new JsonResponse();
  1730.     }
  1731.     /**
  1732.      * @Route("/listing/{id}/pump_up",
  1733.      * requirements={"id" = "\d+"}, name="confirm_listing_pump_up", methods={"POST"})
  1734.      *
  1735.      * @Security("is_granted('ROLE_OWNER', listing)")
  1736.      */
  1737.     public function confirmPumpUpListing(Listing $listingRequest $request): RedirectResponse
  1738.     {
  1739.         $pumpUpForm $this->confirmFeaturedPaymentForm($listing);
  1740.         $pumpUpForm->handleRequest($request);
  1741.         if ($request->isMethod('POST') && $pumpUpForm->isValid()) {
  1742.             if (!$pumpUpForm->get('confirm')->isClicked()) {
  1743.                 return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'), Response::HTTP_FOUND);
  1744.             }
  1745.             try {
  1746.                 $this->listingManager->pumpUp($listing);
  1747.                 $this->addFlash(
  1748.                     'success',
  1749.                     $this->translator->trans('credit.pump_up_success', [':listing_title:' => $listing->getTitle()])
  1750.                 );
  1751.             } catch (\Exception $e) {
  1752.                 $this->addFlash('danger'$e->getMessage());
  1753.             }
  1754.         }
  1755.         return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1756.     }
  1757.     /**
  1758.      * @Route("/listing/{id}/pump_up",
  1759.      * requirements={"id" = "\d+"}, name="listing_pump_up", methods={"GET"})
  1760.      *
  1761.      * @Security("is_granted('ROLE_OWNER', listing)")
  1762.      *
  1763.      * @return array|RedirectResponse
  1764.      */
  1765.     public function pumpUpListing(Listing $listing)
  1766.     {
  1767.         $listingRules $this->listingManager->getListingRules($listing);
  1768.         $listingOwner $listing->getUser();
  1769.         $pumpUpFees $listingRules['pump_up_fees'];
  1770.         $pumpUpOccurrence $listingRules['pump_up_occurrence'];
  1771.         $pumpUpDuration $listingRules['pump_up_duration'];
  1772.         if (!$this->listingManager->isPumpUpAvailable($listingRules)) {
  1773.             $this->addFlash(
  1774.                 'danger',
  1775.                 $this->translator->trans('credit.pump_up_not_available')
  1776.             );
  1777.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1778.         }
  1779.         if (!$this->listingManager->isAffordable($listingOwner$pumpUpFees)) {
  1780.             $this->addFlash(
  1781.                 'danger',
  1782.                 $this->translator->trans('credit.pump_up_can_not_use')
  1783.             );
  1784.             return $this->redirect($this->generateUrl('aqarmap_listing_default_mylistings'));
  1785.         }
  1786.         /** @var $em \Doctrine\ORM\EntityManager */
  1787.         $em $this->getDoctrine()->getManager();
  1788.         $em->getRepository(Credit::class);
  1789.         $pumpUpForm $this->createForm(ConfirmFeaturedFormType::class, null, [
  1790.             'method' => 'POST',
  1791.             'action' => $this
  1792.                 ->generateUrl(
  1793.                     'listing_pump_up',
  1794.                     ['id' => $listing->getId()]
  1795.                 ),
  1796.             'confirm_message' => $this->translator->trans('listing.pump_up.confirm'),
  1797.             'cancel_message' => $this->translator->trans('listing.pump_up.cancel'),
  1798.         ]);
  1799.         return $this->render(
  1800.             '@AqarmapListing/Listing/pumpUpListing.html.twig',
  1801.             [
  1802.                 'fees' => $pumpUpFees,
  1803.                 'duration' => $pumpUpDuration,
  1804.                 'occurrence' => $pumpUpOccurrence,
  1805.                 'form' => $pumpUpForm->createView(),
  1806.             ]
  1807.         );
  1808.     }
  1809.     /**
  1810.      * Listing Details Single Page App.
  1811.      *
  1812.      * @Route("/listingApp/{id}", requirements={"id" = "\d+"} , options={"expose" = true} , name="listing_details_app", methods={"GET"})
  1813.      */
  1814.     public function listingDetailsApp(Listing $listing): Response
  1815.     {
  1816.         return $this->render(
  1817.             '@AqarmapListing/Listing/listingDetailsApp.html.twig',
  1818.             [
  1819.                 'listingId' => $listing->getReferenceId(),
  1820.             ]
  1821.         );
  1822.     }
  1823.     /**
  1824.      * Delete Listing Photos.
  1825.      *
  1826.      * @Route("/photos/delete", name="listing_bulk_delete_photo", requirements={"id" = "\d+"})
  1827.      *
  1828.      * @throws \Doctrine\ORM\OptimisticLockException
  1829.      */
  1830.     public function bulkDeletePhoto(Request $requestListingPhotoRepository $listingPhotoRepositoryListingManager $listingManager): RedirectResponse
  1831.     {
  1832.         $photosIds $request->get('photos');
  1833.         try {
  1834.             if ($photosIds) {
  1835.                 $photos $listingPhotoRepository->getPhotos($photosIds);
  1836.                 $listingManager->bulkDeletePhotos($photos);
  1837.             } else {
  1838.                 $this->addFlash('danger''No photos selected for deletion');
  1839.             }
  1840.         } catch (\Exception $e) {
  1841.             $this->addFlash('danger''Something went wrong');
  1842.         }
  1843.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  1844.     }
  1845.     /**
  1846.      * Update WhatsApp Phones.
  1847.      */
  1848.     private function updateWhatsAppPhones(int $userId, array $phones = [], array $whatsApp = []): void
  1849.     {
  1850.         foreach ($phones as $index => $phone) {
  1851.             $whatsApp[$index] = isset($whatsApp[$index]) && 'true' === $whatsApp[$index];
  1852.             $this->phoneManager->updateWhatsApp($userId, (int) $phone$whatsApp[$index], true);
  1853.         }
  1854.     }
  1855. }