src/Controller/SaloonListController.php line 91

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-04-15
  5.  * Time: 19:51
  6.  */
  7. namespace App\Controller;
  8. use AngelGamez\PorpaginasBundle\Controller\PaginationTrait;
  9. use App\Entity\Location\City;
  10. use App\Repository\DistrictRepository;
  11. use App\Repository\SaloonRepository;
  12. use App\Service\CountryCurrencyResolver;
  13. use App\Service\Features;
  14. use App\Service\GeoCategoryLinkageService;
  15. use App\Service\ProfileListingRecommendationsFiller;
  16. use App\Service\ResponsiveAssetsService;
  17. use App\Service\SaloonListSpecificationService;
  18. use App\Specification\QueryModifier\FreeProfilesFeatureSaloonOrder;
  19. use App\Specification\Saloon\SaloonIsNotHidden;
  20. use App\Specification\QueryModifier\SaloonOrderedByStatus;
  21. use App\Specification\Saloon\SaloonInMoskowDistricts;
  22. use App\Specification\Saloon\SaloonIsActive;
  23. use App\Specification\Saloon\SaloonIsLocated;
  24. use App\Specification\Saloon\SaloonIsVip;
  25. use Flagception\Bundle\FlagceptionBundle\Annotations\Feature;
  26. use Happyr\DoctrineSpecification\Spec;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  29. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\RequestStack;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\Routing\Annotation\Route;
  34. use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
  35. use OpenApi\Attributes as OA;
  36. use Porpaginas\Page;
  37. class SaloonListController extends AbstractController
  38. {
  39.     use PaginationTrait;
  40.     use ResponseTrait;
  41.     const ENTRIES_ON_PAGE = 36;
  42.     private mixed $perPage;
  43.     public function __construct(
  44.         private SaloonRepository $saloonRepository,
  45.         private DistrictRepository $districtRepository,
  46.         private Features $features,
  47.         private RequestStack $requestStack,
  48.         private ResponsiveAssetsService $responsiveAssetsService,
  49.         private ProfileListingRecommendationsFiller $profileListingRecommendationsFiller,
  50.         private SaloonListSpecificationService $saloonListSpecificationService,
  51.         private GeoCategoryLinkageService $geoCategoryLinkageService,
  52.         private NormalizerInterface $normalizer,
  53.         ParameterBagInterface $parameterBag
  54.     )
  55.     {
  56.         $this->perPage = $parameterBag->get('saloon_list.per_page');
  57.     }
  58.     /**
  59.      * @Feature("has_saloons")
  60.      */
  61.     #[ParamConverter('city', converter: 'city_converter')]
  62.     #[Route("/api/saloons/listing/city/{city}", name: "api.saloon_listing.by_city", methods: "GET", format: "json")]
  63.     #[OA\Parameter(name: "page", in: "query", schema: new OA\Schema(type: "integer", default: 1, minimum: 1))]
  64.     #[OA\Tag(name: "SaloonListing")]
  65.     #[OA\Response(
  66.         response: 200,
  67.         description: '',
  68.         content: new OA\JsonContent(ref: "#/components/schemas/SaloonListingPage")
  69.     )]
  70.     public function listByCity(Request $request, City $city): Response
  71.     {
  72.         $criteria = $this->saloonListSpecificationService->listByCity($city);
  73.         return $this->saloonListing($request, $city, $criteria);
  74.     }
  75.     /** @Feature("salons_massage") */
  76.     #[ParamConverter('city', converter: 'city_converter')]
  77.     #[Route("/api/saloons/listing/city/{city}/massage", name: "api.saloon_listing.massage", methods: "GET", format: "json")]
  78.     #[OA\Parameter(name: "page", in: "query", schema: new OA\Schema(type: "integer", default: 1, minimum: 1))]
  79.     #[OA\Tag(name: "SaloonListing")]
  80.     #[OA\Response(response: 200, description: '', content: new OA\JsonContent(ref: "#/components/schemas/SaloonListingPage"))]
  81.     public function listMassage(Request $request, City $city): Response
  82.     {
  83.         return $this->saloonListing($request, $city, $this->saloonListSpecificationService->listMassage($city));
  84.     }
  85.     /** @Feature("salons_brothel") */
  86.     #[ParamConverter('city', converter: 'city_converter')]
  87.     #[Route("/api/saloons/listing/city/{city}/brothels", name: "api.saloon_listing.brothels", methods: "GET", format: "json")]
  88.     #[OA\Parameter(name: "page", in: "query", schema: new OA\Schema(type: "integer", default: 1, minimum: 1))]
  89.     #[OA\Tag(name: "SaloonListing")]
  90.     #[OA\Response(response: 200, description: '', content: new OA\JsonContent(ref: "#/components/schemas/SaloonListingPage"))]
  91.     public function listBrothel(Request $request, City $city): Response
  92.     {
  93.         return $this->saloonListing($request, $city, $this->saloonListSpecificationService->listBrothel($city));
  94.     }
  95.     private function saloonListing(Request $request, City $city, \Happyr\DoctrineSpecification\Filter\Filter $criteria): Response
  96.     {
  97.         $result = $this->saloonRepository->matchingSpec($criteria);
  98.         $saloons = $this->takePage($result, $this->perPage);
  99.         $recommendationsFill = $this->getRecommendationsFill($city, $saloons);
  100.         if ($this->isApiRequest($request)) {
  101.             $data = $this->normalizer->normalize($saloons, 'json', ['groups' => ['listing']]);
  102.             return $this->json(array_merge($data, [
  103.                 'linkage' => $this->geoCategoryLinkageService->links($city) ?? [],
  104.             ]));
  105.         }
  106.         $request->attributes->set('saloons_count', $saloons->totalCount());
  107.         $request->attributes->set('city', $city);
  108.         return $this->render('SaloonList/list.html.twig', [
  109.             'saloons' => $saloons,
  110.             'recommended_profiles' => $recommendationsFill['profiles'],
  111.             'ssr_recommended_profiles' => $recommendationsFill['ssr_profiles'],
  112.             'recommendations_fill_applied' => $recommendationsFill['applied'],
  113.             'recommendations_fill_original_count' => $recommendationsFill['original_count'],
  114.         ]);
  115.     }
  116.     /**
  117.      * @Feature("has_saloons")
  118.      */
  119.     #[ParamConverter('city', converter: 'city_converter')]
  120.     public function listForVipRelax(CountryCurrencyResolver $countryCurrencyResolver, Request $request, City $city): Response
  121.     {
  122.         $minPrice = $countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  123.             'RUB' => 4000,
  124.             'UAH' => 1200,
  125.             'USD' => 100,
  126.             'EUR' => 100,
  127.         ]);
  128.         $districts = [];
  129.         foreach (SaloonInMoskowDistricts::$districtsUri as $uri) {
  130.             if (null !== $district = $this->districtRepository->ofUriIdentityWithinCity($uri, $city)) {
  131.                 $districts[] = $district;
  132.             }
  133.         }
  134.         if (!empty($districts)) {
  135.             $criteria = Spec::andX(
  136.                 $this->features->free_profiles() ? new SaloonIsNotHidden() : new SaloonIsActive(),
  137.                 SaloonIsLocated::withinCity($city),
  138.                 new SaloonIsVip($city, $districts, $minPrice),
  139.                 $this->features->free_profiles() ? new FreeProfilesFeatureSaloonOrder() : new SaloonOrderedByStatus()
  140.             );
  141.             $result = $this->saloonRepository->matchingSpec($criteria);
  142.             $saloons = $this->takePage($result, $this->perPage);
  143.         } else {
  144.             $saloons = $this->emptyPagination();
  145.         }
  146.         $recommendationsFill = $this->getRecommendationsFill($city, $saloons);
  147.         return $this->render('SaloonList/list.html.twig', [
  148.             'saloons' => $saloons,
  149.             'recommended_profiles' => $recommendationsFill['profiles'],
  150.             'ssr_recommended_profiles' => $recommendationsFill['ssr_profiles'],
  151.             'recommendations_fill_applied' => $recommendationsFill['applied'],
  152.             'recommendations_fill_original_count' => $recommendationsFill['original_count'],
  153.         ]);
  154.     }
  155.     private function getRecommendationsFill(City $city, Page $saloons): array
  156.     {
  157.         $fill = $this->profileListingRecommendationsFiller->recommendedProfilesForPage($city, $saloons);
  158.         $fill['ssr_profiles'] = !$fill['applied']
  159.             ? $this->profileListingRecommendationsFiller->popularProfilesForBlock($city, $saloons)
  160.             : [];
  161.         return $fill;
  162.     }
  163.     protected function render(string $view, array $parameters = [], Response $response = null): Response
  164.     {
  165.         if($this->requestStack->getCurrentRequest()->getMethod() == 'POST') {
  166.             $response = parent::render('SaloonList/list.saloons.html.twig', $parameters, $response);
  167.             $content = preg_replace('/\s{2,}/', ' ', $response->getContent());
  168.             $response->setContent($content);
  169.             return $response;
  170.         } else {
  171.             return parent::render($view, $parameters, $response);
  172.         }
  173.     }
  174. }