src/Aqarmap/Bundle/MainBundle/Controller/DefaultController.php line 371

Open in your IDE?
  1. <?php
  2. namespace Aqarmap\Bundle\MainBundle\Controller;
  3. use Aqarmap\Bundle\BuyerAlertsBundle\Entity\RecentSearches;
  4. use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
  5. use Aqarmap\Bundle\ListingBundle\Entity\Location;
  6. use Aqarmap\Bundle\ListingBundle\Entity\PropertyType;
  7. use Aqarmap\Bundle\ListingBundle\Entity\Section;
  8. use Aqarmap\Bundle\ListingBundle\Form\AdvancedSearchType;
  9. use Aqarmap\Bundle\ListingBundle\Form\FullAdvancedFilterType;
  10. use Aqarmap\Bundle\ListingBundle\Form\MultipleSearchFormType;
  11. use Aqarmap\Bundle\ListingBundle\Repository\SectionRepository;
  12. use Aqarmap\Bundle\ListingBundle\Service\AdvancedFilterFormTypeManager;
  13. use Aqarmap\Bundle\ListingBundle\Service\AdvancedSearchFormTypeManager;
  14. use Aqarmap\Bundle\ListingBundle\Service\CustomFieldService;
  15. use Aqarmap\Bundle\ListingBundle\Service\ListingManager;
  16. use Aqarmap\Bundle\MainBundle\Contract\CacheManagerInterface;
  17. use Aqarmap\Bundle\MainBundle\Service\HomeSubMenuService;
  18. use Aqarmap\Bundle\MainBundle\Service\MobileDetectionService;
  19. use Aqarmap\Bundle\MainBundle\Service\Setting;
  20. use Aqarmap\Bundle\MainBundle\Service\SiteMapService;
  21. use Aqarmap\Bundle\UserBundle\Services\UserActivityService;
  22. use Predis\ClientInterface;
  23. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  24. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  25. use Symfony\Component\Form\FormInterface;
  26. use Symfony\Component\HttpFoundation\Cookie;
  27. use Symfony\Component\HttpFoundation\RedirectResponse;
  28. use Symfony\Component\HttpFoundation\Request;
  29. use Symfony\Component\HttpFoundation\Response;
  30. use Symfony\Component\Routing\Annotation\Route;
  31. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  32. use Symfony\Contracts\Translation\TranslatorInterface;
  33. class DefaultController extends AbstractController
  34. {
  35.     public const LISTING_COUNTER_CACHE_KEY 'listing_counter';
  36.     /**
  37.      * @var UserActivityService
  38.      */
  39.     private $activityService;
  40.     /**
  41.      * @var ClientInterface
  42.      */
  43.     private $redisClient;
  44.     /**
  45.      * @var HomeSubMenuService
  46.      */
  47.     private $homeSubMenuService;
  48.     /**
  49.      * @var CustomFieldService
  50.      */
  51.     private $customFieldService;
  52.     /**
  53.      * @var AdvancedSearchFormTypeManager
  54.      */
  55.     private $advancedSearchFormTypeManager;
  56.     /**
  57.      * @var Setting
  58.      */
  59.     private $setting;
  60.     /**
  61.      * @var AuthorizationCheckerInterface
  62.      */
  63.     private $authorizationChecker;
  64.     /**
  65.      * @var MobileDetectionService
  66.      */
  67.     private $mobileDetectionService;
  68.     /**
  69.      * @var SiteMapService
  70.      */
  71.     private $siteMapService;
  72.     /**
  73.      * @var AdvancedFilterFormTypeManager
  74.      */
  75.     private $advancedFilterFormTypeManager;
  76.     /**
  77.      * @var TranslatorInterface
  78.      */
  79.     private $translator;
  80.     public function __construct(
  81.         FeatureToggleManager $featureToggleManager,
  82.         UserActivityService $activityService,
  83.         ClientInterface $redisClient,
  84.         HomeSubMenuService $homeSubMenuService,
  85.         CustomFieldService $customFieldService,
  86.         AdvancedSearchFormTypeManager $advancedSearchFormTypeManager,
  87.         Setting $setting,
  88.         AuthorizationCheckerInterface $authorizationChecker,
  89.         MobileDetectionService $mobileDetectionService,
  90.         SiteMapService $siteMapService,
  91.         AdvancedFilterFormTypeManager $advancedFilterFormTypeManager,
  92.         TranslatorInterface $translator,
  93.         CacheManagerInterface $cacheManager
  94.     ) {
  95.         $this->activityService $activityService;
  96.         $this->redisClient $redisClient;
  97.         $this->homeSubMenuService $homeSubMenuService;
  98.         $this->customFieldService $customFieldService;
  99.         $this->advancedSearchFormTypeManager $advancedSearchFormTypeManager;
  100.         $this->setting $setting;
  101.         $this->authorizationChecker $authorizationChecker;
  102.         $this->mobileDetectionService $mobileDetectionService;
  103.         $this->siteMapService $siteMapService;
  104.         $this->advancedFilterFormTypeManager $advancedFilterFormTypeManager;
  105.         $this->translator $translator;
  106.     }
  107.     /**
  108.      * Homepage action.
  109.      *
  110.      * @Route("/", name="homepage", methods={"GET"})
  111.      */
  112.     public function home(SectionRepository $sectionRepositoryListingManager $listingManager): Response
  113.     {
  114.         return $this->render('@AqarmapMain/Default/homepage.v2.html.twig', [
  115.             'recent_searches' => $this->getRecentSearch(),
  116.             'searchableSections' => $sectionRepository->getSearchableSection(),
  117.             'listingsCount' => $listingManager->getListingsCount(),
  118.         ]);
  119.     }
  120.     /**
  121.      * Search filters page v2.
  122.      *
  123.      * @Route("/search-page-filters", name="listing_search_page_filters", methods={"GET"})
  124.      */
  125.     public function searchPageFilters(Request $requestSectionRepository $sectionRepository): Response
  126.     {
  127.         $searchForm $this->createAdvancedSearchForm();
  128.         $multipleSearchForm $this->createMultipleSearchForm();
  129.         $mobileDetecton $this->getMobileInfo($request);
  130.         $filterForm $this->setAdvancedFilterFormData($request);
  131.         $context array_merge($mobileDetecton, [
  132.             'section' => null,
  133.             'searchForm' => $searchForm->createView(),
  134.             'advancedFilter' => $filterForm->createView(),
  135.             'customFieldIds' => $this->customFieldService->getCustomFieldIds(),
  136.             'multipleSearchForm' => $multipleSearchForm->createView(),
  137.             'searchableSections' => $sectionRepository->getSearchableSection(),
  138.             'featureToggle' => $this->activityService->getFeatureToggles(),
  139.             'subLocations' => $this->homeSubMenuService->getSubLocations($request->getLocale()),
  140.             'subPropertyTypes' => $this->homeSubMenuService->getSubPropertyTypes($request->getLocale()),
  141.         ]);
  142.         return $this->render('@AqarmapMain/Default/searchPageFilters.html.twig'$context);
  143.     }
  144.     /**
  145.      * Set User Agent In Cookies.
  146.      *
  147.      * @Route ("/set-user-agent", name="desktop_site")
  148.      */
  149.     public function setUserAgent(Request $request): RedirectResponse
  150.     {
  151.         $response = new RedirectResponse($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  152.         $cookie = new Cookie('user-agent''User-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36');
  153.         $response->headers->setCookie($cookie);
  154.         $response->prepare($request);
  155.         $response->send();
  156.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  157.     }
  158.     /**
  159.      * remove User Agent In Cookies.
  160.      *
  161.      * @Route ("/unset-user-agent", name="mobile_site")
  162.      */
  163.     public function unsetUserAgent(Request $request): RedirectResponse
  164.     {
  165.         $response = new RedirectResponse($request->headers->get('referer'));
  166.         $response->headers->clearCookie('user-agent');
  167.         $response->prepare($request);
  168.         $response->send();
  169.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  170.     }
  171.     /**
  172.      *  Add Listing Notifier.
  173.      *
  174.      * @return JsonResponse
  175.      *
  176.      * @Route("/add_listing_notifier", name="add_listing_notifier", options={"expose"=true})
  177.      */
  178.     public function addListingNotifier(Request $request)
  179.     {
  180.         if (!$request->cookies->has('add_listing_notifier')) {
  181.             $response = new Response();
  182.             $time time() + (86400 30);
  183.             $response->headers->setCookie(new Cookie('add_listing_notifier'true$time));
  184.             $response->sendHeaders();
  185.         }
  186.         return new Response();
  187.     }
  188.     /**
  189.      *  Close request a expiry.
  190.      *
  191.      * @return JsonResponse
  192.      *
  193.      * @Route("/close-alert-request", name="close_alert_request", options={"expose"=true})
  194.      */
  195.     public function closeAlertRequest(Request $request)
  196.     {
  197.         if (!$request->cookies->has($request->get('name'))) {
  198.             $response = new Response();
  199.             $time time() + (86400 30);
  200.             $response->headers->setCookie(new Cookie($request->get('name'), true$time));
  201.             $response->sendHeaders();
  202.         }
  203.         return new Response();
  204.     }
  205.     /**
  206.      * Sitemaps flow.
  207.      *
  208.      * @Route ("/sitemap/flow", name="sitemap_flow", methods={"GET"})
  209.      * @Route ("/sitemap/flow/{section}", name="sitemap_section_flow", methods={"GET"})
  210.      * @Route ("/sitemap/flow/{section}/{property_type}", name="sitemap_section_property_type_flow", methods={"GET"})
  211.      * @Route ("/sitemap/flow/{section}/{property_type}/{location}",
  212.      *     name="sitemap_section_property_type_location_flow",
  213.      *     requirements={"location": ".+[^/]"},
  214.      *     methods={"GET"}
  215.      * )
  216.      *
  217.      * @ParamConverter("section", options={"mapping": {"section": "slug"}})
  218.      * @ParamConverter("propertyType", options={"mapping": {"property_type": "slug"}})
  219.      * @ParamConverter("location", options={"mapping": {"location": "slug"}})
  220.      *
  221.      * @return RedirectResponse
  222.      */
  223.     public function sitemapFlow(Request $request, ?Section $section null, ?PropertyType $propertyType null, ?Location $location null)
  224.     {
  225.         $em $this->getDoctrine()->getManager();
  226.         $return = [
  227.             'section' => $section,
  228.             'propertyType' => $propertyType,
  229.             'location' => $location,
  230.         ];
  231.         if (!$section) {
  232.             $return['searchableSections'] = $em
  233.                 ->getRepository(Section::class)
  234.                 ->getSearchableSection();
  235.         } else {
  236.             $return['searchableProperties'] = $this->siteMapService
  237.                 ->getSearchableProperties($section->getId(), $request->getLocale())->getResult();
  238.         }
  239.         $locationsRepository $em->getRepository(Location::class);
  240.         if ($propertyType && !$location) {
  241.             $return['searchableLocations'] = $this->siteMapService
  242.                 ->getSearchableLocations($propertyType->getId(), $request->getLocale())->getResult();
  243.         }
  244.         if ($location) {
  245.             $children $this->siteMapService
  246.                 ->getLocationChildrenFlatResults($location->getId(), $propertyType->getId(), $request->getLocale());
  247.             if (empty($children)) {
  248.                 return $this->redirect($this->generateUrl('search', [
  249.                     'section_slug' => $section->getSlug(),
  250.                     'property_type_slug' => $propertyType->getSlug(),
  251.                     'location_slug' => $location->getSlug(),
  252.                 ]));
  253.             }
  254.             $locationPath $locationsRepository->getLocationPathNodes($location);
  255.             $return['parentLocationBuild'] = $locationsRepository->buildTree($locationPath, [
  256.                 'decorate' => true,
  257.                 'rootOpen' => '',
  258.                 'rootClose' => '',
  259.                 'childOpen' => function ($firstLeafLocation) use ($section$propertyType$location) {
  260.                     $url $this->generateUrl('sitemap_section_property_type_location_flow', [
  261.                         'section' => $section->getSlug(),
  262.                         'property_type' => $propertyType->getSlug(),
  263.                         'location' => $firstLeafLocation['slug'],
  264.                     ]);
  265.                     if ($firstLeafLocation['id'] == $location->getId()) {
  266.                         $url $this->generateUrl('search', [
  267.                             'section_slug' => $section->getSlug(),
  268.                             'property_type_slug' => $propertyType->getSlug(),
  269.                             'location_slug' => $firstLeafLocation['slug'],
  270.                         ]);
  271.                     }
  272.                     return '<li>'.
  273.                         '<a
  274.                         title="'.
  275.                         $this->translator->trans('layout.title.header', [
  276.                             '%section%' => $section->getTitle(),
  277.                             '%property_type%' => $propertyType->getTitle(),
  278.                             '%location%' => $firstLeafLocation['title'],
  279.                         ])
  280.                         .'"
  281.                         href="'.$url.'">';
  282.                 },
  283.                 'childClose' => '</a></li>',
  284.             ]);
  285.             $return['locationBuild'] = $locationsRepository->buildTree($children, [
  286.                 'decorate' => true,
  287.                 'childOpen' => function ($childLocation) use ($section$propertyType$children) {
  288.                     $url $this->generateUrl('sitemap_section_property_type_location_flow', [
  289.                         'section' => $section->getSlug(),
  290.                         'property_type' => $propertyType->getSlug(),
  291.                         'location' => $childLocation['slug'],
  292.                     ]);
  293.                     if (== \count($children)) {
  294.                         $url $this->generateUrl('search', [
  295.                             'section_slug' => $section->getSlug(),
  296.                             'property_type_slug' => $propertyType->getSlug(),
  297.                             'location_slug' => $childLocation['slug'],
  298.                         ]);
  299.                     }
  300.                     return '<li>'.
  301.                         '<a
  302.                         title="'.
  303.                         $this->translator->trans('layout.title.header', [
  304.                             '%section%' => $section->getTitle(),
  305.                             '%property_type%' => $propertyType->getTitle(),
  306.                             '%location%' => $childLocation['title'],
  307.                         ])
  308.                         .'"
  309.                         href="'.$url.'">';
  310.                 },
  311.                 'childClose' => '</a></li>',
  312.             ]);
  313.         }
  314.         return $this->render('@AqarmapMain/Default/sitemapFlow.html.twig'$return);
  315.     }
  316.     /**
  317.      * Sitemaps.
  318.      *
  319.      * @Route ("/sitemap", name="sitemap", methods={"GET"})
  320.      *
  321.      * @throws \Doctrine\ORM\NonUniqueResultException
  322.      */
  323.     public function sitemap(): RedirectResponse
  324.     {
  325.         return $this->redirect($this->generateUrl('sitemap_flow'), Response::HTTP_FOUND);
  326.     }
  327.     /**
  328.      * Expo.
  329.      *
  330.      * @Route("/expo", name="expo_landing", options={"expose"=true})
  331.      */
  332.     public function expo(): Response
  333.     {
  334.         return $this->render('@AqarmapMain/Expo/landingPage.html.twig');
  335.     }
  336.     /**
  337.      * Gets mobile info.
  338.      *
  339.      * @return array
  340.      */
  341.     protected function getMobileInfo(Request $request)
  342.     {
  343.         $userAgent $request->cookies->get('user-agent');
  344.         if (!$userAgent) {
  345.             $userAgent $request->headers->get('user-agent');
  346.         }
  347.         return $this->mobileDetectionService->getInfo($userAgent);
  348.     }
  349.     /**
  350.      * Advanced Search Form.
  351.      */
  352.     protected function createAdvancedSearchForm(): FormInterface
  353.     {
  354.         return $this
  355.             ->advancedSearchFormTypeManager
  356.             ->setAction($this->generateUrl('listing_advanced_search'))
  357.             ->setFormType(AdvancedSearchType::class)
  358.             ->setMethodType('Post')
  359.             ->setSettings($this->setting)
  360.             ->applyOptions()
  361.             ->createForm();
  362.     }
  363.     /**
  364.      * Multiple Search Form.
  365.      */
  366.     protected function createMultipleSearchForm(): FormInterface
  367.     {
  368.         return $this
  369.             ->advancedSearchFormTypeManager
  370.             ->setAction($this->generateUrl('listing_multiple_search'))
  371.             ->setFormType(MultipleSearchFormType::class)
  372.             ->setMethodType('Post')
  373.             ->setSettings($this->setting)
  374.             ->applyOptions()
  375.             ->createForm();
  376.     }
  377.     /**
  378.      * Gets recent user's search.
  379.      */
  380.     protected function getRecentSearch(): array
  381.     {
  382.         $searches = [];
  383.         if ($this->authorizationChecker->isGranted('ROLE_EXPERIMENT')) {
  384.             $searches $this
  385.                 ->getDoctrine()
  386.                 ->getManager()
  387.                 ->getRepository(RecentSearches::class)
  388.                 ->findBy(['user' => $this->getUser()], ['updatedAt' => 'DESC'], 9);
  389.         }
  390.         return $searches;
  391.     }
  392.     /**
  393.      * Advanced Search Form.
  394.      */
  395.     protected function createAdvancedFilterForm(): FormInterface
  396.     {
  397.         $customFields $this->redisClient->get('customFields');
  398.         return $this->advancedFilterFormTypeManager
  399.             ->setAction($this->generateUrl('listing_filter_search'))
  400.             ->setFormType(FullAdvancedFilterType::class)
  401.             ->setMethodType('Post')
  402.             ->setSettings($this->setting)
  403.             ->setCustomFields($customFields unserialize($customFields) : [])
  404.             ->applyOptions()
  405.             ->createForm();
  406.     }
  407.     /**
  408.      * Set Advanced Filters FormData.
  409.      */
  410.     private function setAdvancedFilterFormData(Request $request)
  411.     {
  412.         $filterForm $this->createAdvancedFilterForm();
  413.         $filterForm->get('minPrice')->setData($request->query->get('minPrice'));
  414.         $filterForm->get('maxPrice')->setData($request->query->get('maxPrice'));
  415.         $filterForm->get('minArea')->setData((int) $request->query->get('minArea'));
  416.         $filterForm->get('maxArea')->setData((int) $request->query->get('maxArea'));
  417.         $filterForm->get('section')->setData($request->query->get('section'));
  418.         $filterForm->get('propertyType')->setData($request->query->get('propertyType'));
  419.         $filterForm->get('location')->setData($request->query->get('location'));
  420.         return $filterForm;
  421.     }
  422. }