<?php
namespace Aqarmap\Bundle\SearchBundle\Controller\Api;
use Aqarmap\Bundle\ListingBundle\Builder\BuilderInterface;
use Aqarmap\Bundle\ListingBundle\Entity\Location;
use Aqarmap\Bundle\ListingBundle\Entity\PropertyType;
use Aqarmap\Bundle\ListingBundle\Entity\Section;
use Aqarmap\Bundle\ListingBundle\Repository\LocationRepository;
use Aqarmap\Bundle\ListingBundle\Repository\PropertyTypeRepository;
use Aqarmap\Bundle\ListingBundle\Repository\SectionRepository;
use Aqarmap\Bundle\ListingBundle\Service\ListingManager;
use Aqarmap\Bundle\MainBundle\Constant\CustomParagraphPlaceTypes;
use Aqarmap\Bundle\MainBundle\Controller\Api\BaseController;
use Aqarmap\Bundle\MainBundle\Repository\CustomParagraphRepository;
use Aqarmap\Bundle\MainBundle\Service\MenuBuilderService;
use Aqarmap\Bundle\SearchBundle\Services\SEOListingSearchService;
use FOS\RestBundle\Controller\Annotations as Rest;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
class SearchResultsController extends BaseController
{
/**
* @Rest\Get("/api/v2/search/slug-resolver", options={"i18n" = false}, name="aqarmap_api_search_slug_resolver")
*
* @Rest\View(serializerGroups = {"SlugResolver"})
*
* @Rest\QueryParam(name="section", default=null, description="Section slug")
* @Rest\QueryParam(name="propertyType", default=null, description="Property Type slug")
* @Rest\QueryParam(name="locations", default=null, description="Locations slugs. As array.")
*
* @Cache(expires="+7 days", maxage="+7 days", smaxage="+7 days", public=true, vary={"Accept-Language", "X-Accept-Version", "Accept"})
*/
public function resolveSearchPageSlugs(Request $request, SectionRepository $sectionRepo, PropertyTypeRepository $propertyTypeRepo, LocationRepository $locationRepo): array
{
$locationsSlugs = (array) $request->query->get('locations', []);
$data = [
'section' => $sectionRepo->findOneBy(['slug' => $request->query->get('section')]),
'propertyType' => $propertyTypeRepo->findOneBy(['slug' => $request->query->get('propertyType')]),
'locations' => [],
];
if (!empty($locationsSlugs) && $this->validLocationSlugArray($locationsSlugs)) {
$data['locations'] = $locationRepo->getLocationsBySlugs($locationsSlugs);
}
return $data;
}
/**
* Legazy.
*
* @Rest\Get("/api/v2/search/properties-chips-legazy", options={"i18n" = false}, name="aqarmap_api_properties_chips_legazy")
*
* @Rest\View()
*
* @ParamConverter("location", options={"mapping": {"location": "id"}}, isOptional="true", converter="querystring")
* @ParamConverter("propertyType", options={"mapping": {"propertyType": "id"}}, isOptional="true", converter="querystring")
* @ParamConverter("section", options={"mapping": {"section": "id"}}, isOptional="true", converter="querystring")
*
* @Cache(expires="+1 days", maxage="+1 days", smaxage="+1 days", public=true, vary={"Accept-Language", "X-Accept-Version", "Accept"})
*/
public function getPropertiesChipsLegazy(Request $request, ?Location $location, ?PropertyType $propertyType, ?Section $section, MenuBuilderService $menuBuilderService)
{
$locale = $request->getLocale();
$data = [];
if ($section && $propertyType) {
$criteria = [
'location' => $location,
'propertyType' => $propertyType,
'section' => $section,
'locale' => $locale,
];
$data = $menuBuilderService->getSearchResultPropertyChips($criteria);
}
return $data;
}
/**
* @Rest\Get("/api/v2/search/properties-chips", options={"i18n" = false}, name="aqarmap_api_properties_chips")
*
* @Rest\View()
*
* @Cache(expires="+1 days", maxage="+1 days", smaxage="+1 days", public=true, vary={"Accept-Language", "X-Accept-Version", "Accept"})
*/
public function getPropertiesChips(Request $request, ListingManager $listingManager, PropertyTypeRepository $propertyTypeRepository)
{
$result = [];
$types = $listingManager->getPropertiesChipsElasticResponse($request);
$typesArray = [];
foreach ($types as $id => $doc_count) {
$typesArray[$id] = $doc_count;
}
arsort($typesArray);
$propertyTypes = $propertyTypeRepository->findPropertyTypes(array_keys($typesArray));
foreach ($propertyTypes as $propertyType) {
$id = $propertyType->getId();
$result[] = [
'id' => $id,
'title' => $propertyType->getTitle(),
'slug' => $propertyType->getSlug(),
'searchResultCount' => $typesArray[$id] ?? 0,
'level' => $propertyType->getLevel(),
];
}
return $result;
}
/**
* @Rest\Get("/api/v2/search/{section}/{propertyType}/{location}/page-metadata", options={"i18n"=false}, name="aqarmap_api_search_page_metadata")
*
* @Rest\View(serializerGroups={"Default"})
*/
public function getSeoData(
Section $section,
PropertyType $propertyType,
Location $location,
CustomParagraphRepository $customParagraphRepository,
SEOListingSearchService $seoListingSearchService
) {
$data['customParagraph'] = $customParagraphRepository->get([
'location' => $location->getId(),
'propertyType' => $propertyType->getId(),
'section' => $section->getId(),
'place' => CustomParagraphPlaceTypes::SEARCH_RESULTS,
])->getQuery()->setMaxResults(1)->getOneOrNullResult();
$data['longTail'] = $seoListingSearchService->retrieveLongTail($location, $section, $propertyType);
return [
'data' => $data,
];
}
/**
* @Rest\Get("/api/v2/custom-paragraph", options={"i18n"=false}, name="aqarmap_api_custom_paragraph")
*
* @ParamConverter("location", options={"mapping": {"location": "id"}}, isOptional="true", converter="querystring")
* @ParamConverter("propertyType", options={"mapping": {"propertyType": "id"}}, isOptional="false", converter="querystring")
* @ParamConverter("section", options={"mapping": {"section": "id"}}, isOptional="true", converter="querystring")
*
* @Rest\View(serializerGroups={"Default"})
*/
public function getCustomParagraph(
Request $request,
?Location $location,
Section $section,
?PropertyType $propertyType,
CustomParagraphRepository $customParagraphRepository
) {
return $customParagraphRepository->get([
'location' => $location ? $location->getId() : null,
'propertyType' => $propertyType ? $propertyType->getId() : null,
'section' => $section->getId(),
'place' => $request->query->get('place') ?: CustomParagraphPlaceTypes::SEARCH_RESULTS,
])->getQuery()->setMaxResults(1)->getOneOrNullResult();
}
/**
* @Rest\Get("/api/v2/location/{location}/listing", options={"i18n" = false}, name="aqarmap_api_location_listing_v2")
*
* @Rest\QueryParam(name="id", default=null, description="Location id")
*
* @Rest\View(serializerGroups = {"locationListingV2"})
*/
public function getLocationListing(Location $location)
{
return $location;
}
private function validLocationSlugArray($array): bool
{
return \count($array) > 0 && array_reduce($array, fn ($carry, $item) => $carry && \is_string($item) && '' !== $item, true);
}
/**
* @Rest\Get("/api/v4/search/ssr-data", options={"i18n" = false, "expose" = false}, name="aqarmap_search_results_ssr_data")
*
* @Rest\QueryParam(name="section", default=null, description="Section slug")
* @Rest\QueryParam(name="propertyType", default=null, description="Property Type slug")
* @Rest\QueryParam(name="locations", default=null, description="Array of Locations slugs.")
*
* @Rest\View(serializerGroups = {"SlugResolver"})
*/
public function singlePageSSRData(Request $request, SectionRepository $sectionRepository, PropertyTypeRepository $propertyTypeRepository, LocationRepository $locationRepository, BuilderInterface $searchDescriptionBuilder): array
{
$sectionSlug = $request->get('section');
if (!$sectionSlug) {
throw new \InvalidArgumentException('Section is required');
}
$section = $sectionRepository->findOneBy(['slug' => $sectionSlug]);
$propertyTypeSlug = $request->get('propertyType');
if (!$propertyTypeSlug) {
throw new \InvalidArgumentException('propertyType is required');
}
$propertyType = $propertyTypeRepository->findOneBy(['slug' => $propertyTypeSlug]);
$locationsSlugs = (array) $request->get('locations', []);
if (!$locationsSlugs) {
throw new \InvalidArgumentException('locations is required');
}
$locations = $locationRepository->getLocationsBySlugs($locationsSlugs);
// Page Description
$searchDescriptionBuilder
->setSection($section)
->setPropertyType($propertyType)
->setLocation(reset($locations))
;
return [
'section' => $section,
'propertyType' => $propertyType,
'locations' => $locations,
'pageTitle' => '',
'metaDescription' => $searchDescriptionBuilder->format()->get(),
'metaKeywords' => '',
'canonicalUrl' => '',
'breadcrumbs' => [
[
'title' => '',
'url' => '',
],
],
'propertyTypesChips' => [
[
'title' => '',
'url' => '',
],
],
];
}
}