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

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