src/Controller/SearchController.php line 57

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Elastica\AdvertisementSearch;
  4. use App\Elastica\ReviewSearch;
  5. use App\Elastica\ReviewMapSearch;
  6. use App\Entity\Review;
  7. use App\Entity\Search;
  8. use App\Service\GeocodingService;
  9. use App\Form\SearchAdvertisementForm;
  10. use Knp\Component\Pager\Pagination\AbstractPagination;
  11. use Liip\ImagineBundle\Imagine\Cache\CacheManager;
  12. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
  13. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  14. use Cocur\Slugify\SlugifyInterface;
  15. use Symfony\Component\HttpFoundation\JsonResponse;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\Translation\TranslatorInterface;
  19. use Symfony\Component\HttpKernel\KernelInterface;
  20. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  21. class SearchController extends AbstractController
  22. {
  23.     private $slugify;
  24.     /**
  25.      * @var TranslatorInterface
  26.      */
  27.     private $translator;
  28.     private $cacheManager;
  29.     private $kernel;
  30.     private $parameterBag;
  31.     public function __construct(SlugifyInterface $slugifyTranslatorInterface $translatorKernelInterface $kernel,CacheManager $cacheManager,ParameterBagInterface $parameterBag)
  32.     {
  33.         $this->translator $translator;
  34.         $this->slugify $slugify;
  35.         $this->kernel $kernel;
  36.         $this->cacheManager $cacheManager;
  37.         $this->parameterBag $parameterBag;
  38.     }
  39.     /**
  40.      * Show search results
  41.      * @param Request $request
  42.      * @param AdvertisementSearch $advertisementSearch
  43.      * @param ReviewMapSearch $reviewSearch
  44.      * @return Response
  45.      * @Route("/search", options={"expose"=true}, name="advertisement_search")
  46.      */
  47.     public function showSearchAction(Request $requestAdvertisementSearch $advertisementSearch,ReviewMapSearch $reviewSearch)
  48.     {
  49.         $form $this->createForm(SearchAdvertisementForm::class, null, [
  50.             'action' => $this->generateUrl('advertisement_search'),
  51.             'method' => 'GET',
  52.         ]);
  53.         $form->handleRequest($request);
  54.         $searchTerms $request->query->all();
  55.         /*if(!property_exists($searchTerms, 'sort')){
  56.             $searchTerms['sort'] = 'updatedAt';
  57.             $searchTerms['direction'] = 'desc';
  58.         }*/
  59.         $em $this->getDoctrine()->getManager();
  60.         if(isset($searchTerms['advantages'])){
  61.             $list = [];
  62.             foreach($searchTerms['advantages'] as $ad){
  63.                 $advantage $em->getRepository("App\Entity\Advantage")->find($ad);
  64.                 if($advantage!=null){
  65.                     $list[]= $advantage->getName();
  66.                 }
  67.             }
  68.             $searchTerms['advantages'] = implode(",",$list);
  69.         }
  70.         $departmentName null ;
  71.         if(array_key_exists('department',$searchTerms) && isset($searchTerms['department'])){
  72.             $departmentName $searchTerms['department'];
  73.         }
  74.         $userSearchTerms $searchTerms;
  75.         $userSearchTerms['publisherType'] = Review::PUBLISHER_TYPE_RESIDENT;
  76.         $advertisementSearchResults $advertisementSearch->searchPaginated($searchTerms,$departmentName,25);
  77.         $userReviewDataList $reviewSearch->getStat($userSearchTerms);
  78.         $adValues $this->getAdValues($advertisementSearchResults);
  79.         if ($request->isXmlHttpRequest()) {
  80.             return new JsonResponse([
  81.                     'html' => $this->renderView('ajax/search.html.twig', [
  82.                         'advertisements' => $advertisementSearchResults,
  83.                         'sortValue' => $request->query->get('sort'),
  84.                         'directionValue' => $request->query->get('direction'),
  85.                     ]),
  86.                     'markers' => $adValues
  87.                 ]
  88.             );
  89.         }
  90.         $advertisementsFromRenter array_filter($advertisementSearchResults->getItems(), function ($result) {
  91.             return !$result->getOwner() && !in_array($result->getUser()->getRoles(), ['ROLE_PRO']);
  92.         });
  93.         $sortValue $request->query->get('sort');
  94.         $directionValue $request->query->get('direction');
  95.         return $this->render('advertisement/search.html.twig', [
  96.             'advertisements' => $advertisementSearchResults,
  97.             'noAdvertisementFromRenter' => sizeof($advertisementsFromRenter) == 0,
  98.             'sortValue' => isset($sortValue) ? $sortValue 'updatedAt',
  99.             'directionValue' => isset($directionValue) ? $directionValue 'desc',
  100.             'form' => $form->createView(),
  101.             'searchTerm' => '',
  102.             'js_vars' => [
  103.                 'adData' => [
  104.                     'advertisements' => $adValues,
  105.                     'reviews' => [
  106.                         'user' => $userReviewDataList,
  107.                     ],
  108.                     'flux' => $this->getFlux($searchTerms),
  109.         
  110.                 ]
  111.             ]
  112.         ]);
  113.     }
  114.     /**
  115.      * Show search results
  116.      * @param Request $request
  117.      * @return Response
  118.      * @Route("/search/autocomplete", options={"expose"=true}, name="autocomplete_search")
  119.      */
  120.     public function autoCompleteAction(Request $request)
  121.     {
  122.         $searchTerm $request->query->get('keyword');
  123.         $data = [];
  124.         if(isset($searchTerm)){
  125.             $searchTerm trim($searchTerm);
  126.             $data =  $this->searchPlace($searchTerm);
  127.         }
  128.         return new JsonResponse([
  129.             'error' => false,
  130.             'data' => $data
  131.         ]);
  132.     }
  133.     
  134.     /**
  135.      * Register a search request
  136.      * @param Request $request
  137.      * @return Response
  138.      * @Route("/search/register", methods={"POST"}, name="register_search")
  139.      */
  140.     public function registerSearchAction(Request $request)
  141.     {
  142.         $query $request->query->all();
  143.         $agencyContactAllowed filter_var($request->request->get('agencyContactAllowed'), FILTER_VALIDATE_BOOLEAN);
  144.         $search = new Search();
  145.         $search->setUser($this->getUser());
  146.         $search->setQuery($query);
  147.         $search->setAgencyContactAllowed($agencyContactAllowed);
  148.         if (empty($search->getQuery())) {
  149.             return new JsonResponse(['error' => 'No valid query params'], 400);
  150.         }
  151.         $em $this->getDoctrine()->getManager();
  152.         $em->persist($search);
  153.         $em->flush();
  154.         return new JsonResponse(["success" => true], 200);
  155.     }
  156.     /**
  157.      * @Route("/advertisement/search/{id}/remove", methods={"POST"},name="remove_search")
  158.      * @param Search $search
  159.      * @return JsonResponse
  160.      */
  161.     public function removeSearchAction(Search $search)
  162.     {
  163.         $error false;
  164.         if ($this->getUser()->getId() !== $search->getUser()->getId()) {
  165.             $error true;
  166.         }
  167.         $em $this->getDoctrine()->getManager();
  168.         $em->remove($search);
  169.         $em->flush();
  170.         return new JsonResponse(["error" => $error]);
  171.     }
  172.     /**
  173.      * @param AbstractPagination $advertisements
  174.      * @return array
  175.      */
  176.     public function getAdValues(AbstractPagination $advertisements)
  177.     {
  178.         $adValues = [];
  179.         foreach ($advertisements->getItems() as $advertisement) {
  180.             $image null;
  181.             foreach($advertisement->getFiles() as $file){
  182.                 if(file_exists(realpath($this->kernel->getRootDir() . '/../public/uploads/pictures/'.$file->getPath()))){
  183.                     $image $file;
  184.                     break;
  185.                 }
  186.             }
  187.             $surfacePrice "";
  188.             if ($advertisement->getSale() == 1) {
  189.                 $surfacePrice $advertisement->getSurface() !== 0
  190.                     ? (int)$advertisement->getPrice() / $advertisement->getSurface()
  191.                     : 0;
  192.             }
  193.             if ($advertisement->getCreatorType() == 'agency') {
  194.                 $role "agence";
  195.             } elseif ($advertisement->getCreatorType() == 'owner') {
  196.                 $role "proprietaire";
  197.             } else {
  198.                 $role "locataire";
  199.             }
  200.             $slug $this->translator->transchoice('label.advertisement.title',$advertisement->getRoomNumber(), ['%category%'=>$this->translator->trans($advertisement->getCategory()),'%type%'=>$this->translator->trans($advertisement->getTypeLabel()), '%roomNumber%'=> $this->translator->trans($advertisement->getRoomNumber()), '%surface%'=>$this->translator->trans($advertisement->getSurface())]);
  201.             $adValues[] = [
  202.                 "id" => $advertisement->getId(),
  203.                 "slug" => $this->slugify->slugify($slug),
  204.                 "latitude" => $advertisement->getLatitude(),
  205.                 "longitude" => $advertisement->getLongitude(),
  206.                 "hasImage" => true,
  207.                 "image" => ($image $this->cacheManager->getBrowserPath('/uploads/pictures/' $image->getPath(), 'thumb') : '/images/default-picture.png'),
  208.                 "type" => $advertisement->getType(),
  209.                 "typeLabel" => $this->translator->trans($advertisement->getTypeLabel()),
  210.                 "saleLabel" => $advertisement->getSaleLabel(),
  211.                 "roomnumber" => $advertisement->getRoomNumber(),
  212.                 "surface" => $advertisement->getSurface(),
  213.                 "price" => $advertisement->getPrice(),
  214.                 "city" => $advertisement->getCity(),
  215.                 "surfacePrice" => $surfacePrice,
  216.                 "role" => $role,
  217.             ];
  218.         }
  219.         return $adValues;
  220.     }
  221.     private function getFlux($searchTerms){
  222.         $city null;
  223.         $em $this->getDoctrine()->getManager();
  224.         $results = [];
  225.         $qb $em->getRepository('App\Entity\FluxRss')->createQueryBuilder('flux')
  226.             ->select("flux.longitude,flux.latitude,flux.city,flux.region,flux.department")
  227.             ->where('flux.type=:type')
  228.             ->setParameter('type''city')
  229.             ->groupBy('flux.longitude')
  230.             ->addGroupBy('flux.latitude')
  231.             ->addGroupBy('flux.city')
  232.             ->addGroupBy('flux.region')
  233.             ->addGroupBy('flux.department');
  234.         $query $qb->getQuery();
  235.         $cities $query->getResult();
  236.         foreach ($cities as $cityItem) {
  237.             $qb $em->getRepository('App\Entity\FluxRss')->createQueryBuilder('flux')
  238.                 ->addSelect("flux.title,flux.link,flux.city,flux.department,flux.region,flux.postalCode")
  239.                 ->where('flux.type=:type')
  240.                 ->andWhere('flux.city=:city')
  241.                 ->andWhere('flux.longitude=:longitude')
  242.                 ->andWhere('flux.latitude=:latitude')
  243.                 ->setParameter('type''city')
  244.                 ->setParameter('city'$cityItem['city'])
  245.                 ->setParameter('longitude'$cityItem['longitude'])
  246.                 ->setParameter('latitude'$cityItem['latitude'])
  247.                 ->orderBy('flux.title''ASC');
  248.             $query $qb->getQuery();
  249.             $result $query->getResult();
  250.             $results[] = [
  251.                 'specific' => false,
  252.                 'longitude' => $cityItem['longitude'],
  253.                 'latitude' => $cityItem['latitude'],
  254.                 'city_id' => 1,
  255.                 'city_name' => $cityItem['city'],
  256.                 'selected' =>  $this->isFocused($searchTerms,null,$cityItem['city'],$cityItem['department'],$cityItem['region']) ,
  257.                 'data' => $result
  258.             ];
  259.         }
  260.         $qb $em->getRepository('App\Entity\FluxRss')->createQueryBuilder('flux')
  261.             ->addSelect("flux.id,flux.title,flux.link,flux.longitude,flux.latitude,flux.city,flux.department,flux.region,flux.postalCode,flux.pinColor")
  262.             ->where('flux.type=:type')
  263.             ->setParameter('type''address')
  264.             ->orderBy('flux.title''ASC');
  265.         if(array_key_exists("postalCode",$searchTerms) && $searchTerms['postalCode']!=""){
  266.             $qb $qb->andWhere("flux.postalCode=:postalCode  OR flux.postalCode is null OR flux.postalCode='' ")->setParameter('postalCode'$searchTerms['postalCode']);
  267.         }
  268.         if(array_key_exists("city",$searchTerms) && $searchTerms['city']!=""){
  269.             $qb $qb->andWhere('flux.city=:city')->setParameter('city'$searchTerms['city']);
  270.         }
  271.         if(array_key_exists("department",$searchTerms) && $searchTerms['department']!=""){
  272.             $qb $qb->andWhere('flux.department=:department')->setParameter('department'$searchTerms['department']);
  273.         }
  274.         $query $qb->getQuery();
  275.         $specificFlux $query->getResult();
  276.         foreach ($specificFlux as $flux) {
  277.             $results[] = [
  278.                 'longitude' => $flux['longitude'],
  279.                 'latitude' => $flux['latitude'],
  280.                 'flux_name' => $flux['title'],
  281.                 'flux_link' => $flux['link'],
  282.                 'pin_color' => $flux['pinColor'],
  283.                 'selected' => $this->isFocused($searchTerms,$flux['postalCode'],$flux['city'],$flux['department'],$flux['region']) ,
  284.                 'specific' => true,
  285.                 'flux_id' => $flux['id'],
  286.             ];
  287.         }
  288.         return $results;
  289.     }
  290.     private function isFocused($searchTerms,$postalCode,$city,$department,$region){
  291.         $isFocused false;
  292.         if(array_key_exists("region",$searchTerms) && $searchTerms['region']!="" && $searchTerms['region']==$region){
  293.             $isFocused true;
  294.         }else if(array_key_exists("department",$searchTerms) && $searchTerms['department']!="" && $searchTerms['department']==$department){
  295.             $isFocused true;
  296.         }else if(array_key_exists("city",$searchTerms) && $searchTerms['city']!="" && $searchTerms['city']==$city){
  297.             $isFocused true;
  298.         }else if($postalCode!=null &&  array_key_exists("postalCode",$searchTerms) && $searchTerms['postalCode']!="" && $searchTerms['postalCode']==$postalCode){
  299.             $isFocused true;
  300.         }else{
  301.             $isFocused false;
  302.         }
  303.         return $isFocused;
  304.     }
  305.     private function searchPlace($initialSearchTerm): array
  306.     {
  307.         $em $this->getDoctrine()->getManager();
  308.         //$searchTerm = iconv('UTF-8', 'ASCII//TRANSLIT', $searchTerm);
  309.         $searchTerm "%".$initialSearchTerm "%";
  310.     
  311.         $RAW_QUERY "SELECT * ,MATCH(full_text_search) AGAINST(:initialSearchTerm IN BOOLEAN MODE) as relevance  FROM `place` WHERE full_text_search like :searchTerm AND ( department IN ( 'Guadeloupe','Guyane','Réunion','Martinique','Mayotte','Nouvelle-Calédonie','Polynésie française','Saint-pierre-et-Miquelon','Wallis-et-Futuna')) ORDER BY relevance desc,postal_code,label LIMIT 10";
  312.         $statement $em->getConnection()->prepare($RAW_QUERY);
  313.         $statement->bindValue("searchTerm"$searchTerm);
  314.         $statement->bindValue("initialSearchTerm"$initialSearchTerm);
  315.         $result =$statement->execute();
  316.         return $result->fetchAllAssociative(); 
  317.     }
  318. }