src/Controller/ProfileListController.php line 202

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-03-19
  5.  * Time: 22:28
  6.  */
  7. namespace App\Controller;
  8. use App\Attribute\SplitFirstPagePagination;
  9. use App\Bridge\Porpaginas\Doctrine\ORM\FakeORMQueryPage;
  10. use App\Entity\Location\City;
  11. use App\Entity\Location\County;
  12. use App\Entity\Location\District;
  13. use App\Entity\Location\Station;
  14. use App\Entity\Profile\BodyTypes;
  15. use App\Entity\Profile\BreastTypes;
  16. use App\Entity\Profile\Genders;
  17. use App\Entity\Profile\HairColors;
  18. use App\Entity\Profile\Nationalities;
  19. use App\Entity\Profile\PrivateHaircuts;
  20. use App\Entity\Service;
  21. use App\Entity\ServiceGroups;
  22. use App\Entity\TakeOutLocations;
  23. use App\Repository\ServiceRepository;
  24. use App\Repository\StationRepository;
  25. use App\Service\CountryCurrencyResolver;
  26. use App\Service\DefaultCityProvider;
  27. use App\Service\Features;
  28. use App\Service\HomepageCityListingsBlockProvider;
  29. use App\Service\ListingRotationApi;
  30. use App\Service\ListingService;
  31. use App\Service\ProfileList;
  32. use App\Service\ProfileListingRecommendationsFiller;
  33. use App\Service\ProfileListingDataCreator;
  34. use App\Service\ProfileListSpecificationService;
  35. use App\Service\ProfileFilterService;
  36. use App\Service\ProfileTopBoard;
  37. use App\Service\Top100ProfilesService;
  38. use App\Specification\ElasticSearch\ISpecification;
  39. use App\Specification\Profile\ProfileHasApartments;
  40. use App\Specification\Profile\ProfileIdINOrderedByINValues;
  41. use App\Specification\Profile\ProfileIsElite;
  42. use App\Specification\Profile\ProfileIsLocated;
  43. use App\Specification\Profile\ProfileIsProvidingOneOfServices;
  44. use App\Specification\Profile\ProfileIsProvidingTakeOut;
  45. use App\Specification\Profile\ProfileWithBodyType;
  46. use App\Specification\Profile\ProfileWithBreastType;
  47. use App\Specification\Profile\ProfileWithHairColor;
  48. use App\Specification\Profile\ProfileWithNationality;
  49. use App\Specification\Profile\ProfileWithPrivateHaircut;
  50. use Flagception\Bundle\FlagceptionBundle\Annotations\Feature;
  51. use Happyr\DoctrineSpecification\Filter\Filter;
  52. use Happyr\DoctrineSpecification\Logic\OrX;
  53. use OpenApi\Attributes as OA;
  54. use Porpaginas\Doctrine\ORM\ORMQueryResult;
  55. use Porpaginas\Page;
  56. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
  57. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
  58. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  59. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  60. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  61. use Symfony\Component\HttpFoundation\Request;
  62. use Happyr\DoctrineSpecification\Spec;
  63. use Symfony\Component\HttpFoundation\RequestStack;
  64. use Symfony\Component\HttpFoundation\Response;
  65. use Symfony\Component\Routing\Annotation\Route;
  66. /**
  67.  * @see \App\Console\Export\ExportRotationListingsConfigCommand for listing API endpoints
  68.  */
  69. #[Cache(maxage60, public: true)]
  70. class ProfileListController extends AbstractController
  71. {
  72.     use ExtendedPaginationTrait;
  73.     use SpecTrait;
  74.     use ProfileMinPriceTrait;
  75.     use ResponseTrait;
  76.     const ENTRIES_ON_PAGE 36;
  77.     const RESULT_SOURCE_COUNTY 'county';
  78.     const RESULT_SOURCE_DISTRICT 'district';
  79.     const RESULT_SOURCE_STATION 'station';
  80.     const RESULT_SOURCE_APPROVED 'approved';
  81.     const RESULT_SOURCE_WITH_COMMENTS 'with_comments';
  82.     const RESULT_SOURCE_WITH_VIDEO 'with_video';
  83.     const RESULT_SOURCE_WITH_SELFIE 'with_selfie';
  84.     const RESULT_SOURCE_TOP_100 'top_100';
  85.     const RESULT_SOURCE_ELITE 'elite';
  86.     const RESULT_SOURCE_MASSEURS 'masseurs';
  87.     const RESULT_SOURCE_MASSAGE_SERVICE 'massage_service';
  88.     const RESULT_SOURCE_BY_PARAMS 'by_params';
  89.     const RESULT_SOURCE_SERVICE 'service';
  90.     const RESULT_SOURCE_CITY 'city';
  91.     const RESULT_SOURCE_COUNTRY 'country';
  92.     const RESULT_SOURCE_WITH_WHATSAPP 'with_whatsapp';
  93.     const RESULT_SOURCE_WITH_TELEGRAM 'with_telegram';
  94.     const RESULT_SOURCE_EIGHTEEN_YEARS_OLD 'eighteen_years_old';
  95.     const RESULT_SOURCE_BIG_ASS 'big_ass';
  96.     const RESULT_SOURCE_WITH_TATTOO 'with_tattoo';
  97.     const RESULT_SOURCE_WITH_PIERCING 'with_piercing';
  98.     const RESULT_SOURCE_ROUND_THE_CLOCK 'round_the_clock';
  99.     const RESULT_SOURCE_FOR_TWO_HOURS 'for_two_hours';
  100.     const RESULT_SOURCE_FOR_HOUR 'for_hour';
  101.     const RESULT_SOURCE_EXPRESS_PROGRAM 'express_program';
  102.     const RESULT_SOURCE_EROMASSAGE 'eromassage';
  103.     const RESULT_SOURCE_VERIFIED 'verified';
  104.     const RESULT_SOURCE_CHEAP 'cheap';
  105.     const RESULT_SOURCE_MATURE 'mature';
  106.     const RESULT_SOURCE_UZBEK 'uzbek';
  107.     private ?string $source null;
  108.     public function __construct(
  109.         private RequestStack $requestStack,
  110.         private ProfileList                     $profileList,
  111.         private CountryCurrencyResolver         $countryCurrencyResolver,
  112.         private ServiceRepository               $serviceRepository,
  113.         private ListingService                  $listingService,
  114.         private Features                        $features,
  115.         private ProfileFilterService            $profilesFilterService,
  116.         private ProfileListSpecificationService $profileListSpecificationService,
  117.         private ProfileListingDataCreator       $profileListingDataCreator,
  118.         private Top100ProfilesService           $top100ProfilesService,
  119.         private ParameterBagInterface           $parameterBag,
  120.         private ListingRotationApi              $listingRotationApi,
  121.         private ProfileTopBoard                 $profileTopBoard,
  122.         private HomepageCityListingsBlockProvider $homepageCityListingsBlockProvider,
  123.         private ProfileListingRecommendationsFiller $profileListingRecommendationsFiller,
  124.     ) {}
  125.     /**
  126.      * @Feature("has_masseurs")
  127.      */
  128.     #[ParamConverter("city"converter"city_converter")]
  129.     #[Route("/api/profiles/listing/city/{city}/masseur"name"api.profile_listing.masseur"methods"GET"format"json")]
  130.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  131.     #[OA\Tag(name"ProfileListing")]
  132.     #[OA\Response(
  133.         response200,
  134.         description'',
  135.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  136.     )]
  137.     public function listForMasseur(Request $requestCity $cityServiceRepository $serviceRepository): Response
  138.     {
  139.         $specs $this->profileListSpecificationService->listForMasseur($city);
  140.         $response = new Response();
  141.         $massageGroupServices $serviceRepository->findBy(['group' => ServiceGroups::MASSAGE]);
  142.         $alternativeSpec $this->getORSpecForItemsArray([$massageGroupServices], function($item): ProfileIsProvidingOneOfServices {
  143.             return new ProfileIsProvidingOneOfServices($item);
  144.         });
  145.         $result $this->paginatedListing($city'/city/{city}/masseur', ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_MASSAGE_SERVICE$response);
  146.         if ($this->isApiRequest($request)) {
  147.             return $this->json($result);
  148.         }
  149.         return $this->render('ProfileList/list.html.twig', [
  150.             'profiles' => $result,
  151.             'source' => $this->source,
  152.             'source_default' => self::RESULT_SOURCE_MASSEURS,
  153.             'recommendationSpec' => $specs->recommendationSpec(),
  154.         ], response$response);
  155.     }
  156.     /**
  157.      * @Feature("extra_category_big_ass")
  158.      */
  159.     #[ParamConverter("city"converter"city_converter")]
  160.     #[Route("/api/profiles/listing/city/{city}/category/big_ass"name"api.profile_listing.category.big_ass"methods"GET"format"json")]
  161.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  162.     #[OA\Tag(name"ProfileListing")]
  163.     #[OA\Response(
  164.         response200,
  165.         description'',
  166.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  167.     )]
  168.     public function listBigAss(Request $requestCity $city): Response
  169.     {
  170.         $specs $this->profileListSpecificationService->listBigAss();
  171.         $response = new Response();
  172.         $result $this->paginatedListing($city'/city/{city}/category/big_ass', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  173.         if ($this->isApiRequest($request)) {
  174.             return $this->json($result);
  175.         }
  176.         return $this->render('ProfileList/list.html.twig', [
  177.             'profiles' => $result,
  178.             'source' => $this->source,
  179.             'source_default' => self::RESULT_SOURCE_BIG_ASS,
  180.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  181.                 'city' => $city->getUriIdentity(),
  182.                 'page' => $this->getCurrentPageNumber(),
  183.             ]),
  184.             'recommendationSpec' => $specs->recommendationSpec(),
  185.         ], response$response);
  186.     }
  187.     public function listByDefaultCity(ParameterBagInterface $parameterBagRequest $request): Response
  188.     {
  189.         $controller get_class($this).'::listByCity';
  190.         $path = [
  191.             'city' => $parameterBag->get('default_city'),
  192.             'subRequest' => true,
  193.         ];
  194.         //чтобы в обработчике можно было понять, по какому роуту зашли
  195.         $request->request->set('_route''profile_list.list_by_city');
  196.         return $this->forward($controller$path);
  197.     }
  198.     private function paginatedListing(City $city, ?string $apiEndpoint, array $apiParams, ?Filter $listingSpec null, ?OrX $alternativeSpec null, ?string $alternativeSource null, ?Response $response null): Page
  199.     {
  200.         $topPlacement $this->profileTopBoard->topPlacementSatisfiedBy($city$listingSpec);
  201.         $topPlacement?->setTopCard(); // mark as top card for UI
  202.         $page $this->getCurrentPageNumber();
  203.         $apiParams['city'] = $city->getId();
  204.         try {
  205.             if (null === $apiEndpoint) {
  206.                 throw new \RuntimeException('Empty API endpoint to switch to legacy listing query.');
  207.             }
  208.             $result $this->listingRotationApi->paginate($apiEndpoint$apiParams$page$topPlacement);
  209.             $response?->setMaxAge(10);
  210.         } catch (\Exception) {
  211.             $avoidOrTopPlacement = (null !== $topPlacement && $page 2) ? $topPlacement null;
  212.             $result $this->profileList->list($citynull$listingSpec, [], truenullProfileList::ORDER_BY_STATUS,
  213.                 nulltruenull, [Genders::FEMALE], $avoidOrTopPlacement);
  214.         }
  215.         return $result;
  216.     }
  217.     #[SplitFirstPagePagination]
  218.     #[ParamConverter("city"converter"city_converter")]
  219.     #[Route("/api/profiles/listing/city/{city}"name"api.profile_listing.by_city"methods"GET"format"json")]
  220.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  221.     #[OA\Tag(name"ProfileListing")]
  222.     #[OA\Response(
  223.         response200,
  224.         description'Листинг анкет по городу',
  225.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  226.     )]
  227.     public function listByCity(ParameterBagInterface $parameterBagRequest $requestCity $citybool $subRequest false): Response
  228.     {
  229.         $page $this->getCurrentPageNumber();
  230.         if ($this->features->redirect_default_city_to_homepage() && false === $subRequest && $city->equals($parameterBag->get('default_city')) && $page 2) {
  231.             return $this->redirectToRoute('homepage', [], 301);
  232.         }
  233.         $specs $this->profileListSpecificationService->listByCity();
  234.         $response = new Response();
  235.         $result $this->paginatedListing($city'/city/{city}', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  236.         if ($this->isApiRequest($request)) {
  237.             return $this->json($result);
  238.         }
  239.         $homepageCityListingsBlock null;
  240.         if ($this->shouldShowHomepageCityListingsBlock($city$page$subRequest)) {
  241.             $homepageCityListingsBlock $this->homepageCityListingsBlockProvider->getForCity($city);
  242.         }
  243.         return $this->render('ProfileList/list.html.twig', [
  244.             'profiles' => $result,
  245.             'homepage_city_listings_block' => $homepageCityListingsBlock,
  246.             'recommendationSpec' => $specs->recommendationSpec(),
  247.         ], response$response);
  248.     }
  249.     /**
  250.      * @Feature("intim_moscow_listing")
  251.      */
  252.     #[Cache(maxage3600, public: true)]
  253.     #[Route("/api/profiles/listing/city/{city}/intim"name"api.profile_listing.intim"methods"GET"format"json")]
  254.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  255.     #[OA\Tag(name"ProfileListing")]
  256.     #[OA\Response(
  257.         response200,
  258.         description'',
  259.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  260.     )]
  261.     public function listIntim(Request $requestDefaultCityProvider $defaultCityProvider): Response
  262.     {
  263.         $city $defaultCityProvider->getDefaultCity();
  264.         $request->attributes->set('city'$city);
  265.         $specs $this->profileListSpecificationService->listByCity();
  266.         $response = new Response();
  267.         $result $this->paginatedListing($city'/city/{city}/intim', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  268.         $result $this->shuffleProfilesOnPage($result);
  269.         $response->setMaxAge(3600);
  270.         if ($this->isApiRequest($request)) {
  271.             return $this->json($result);
  272.         }
  273.         return $this->render('ProfileList/list.html.twig', [
  274.             'profiles' => $result,
  275.             'city' => $city,
  276.             'recommendationSpec' => $specs->recommendationSpec(),
  277.         ], response$response);
  278.     }
  279.     #[ParamConverter("city"converter"city_converter")]
  280.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  281.     #[Route("/api/profiles/listing/city/{city}/county/{county}"name"api.profile_listing.by_county"methods"GET"format"json")]
  282.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  283.     #[OA\Tag(name"ProfileListing")]
  284.     #[OA\Response(
  285.         response200,
  286.         description'',
  287.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  288.     )]
  289.     public function listByCounty(Request $requestCity $cityCounty $county): Response
  290.     {
  291.         if (!$city->hasCounty($county)) {
  292.             throw $this->createNotFoundException();
  293.         }
  294.         $specs $this->profileListSpecificationService->listByCounty($county);
  295.         $response = new Response();
  296.         $alternativeSpec Spec::orX(ProfileIsLocated::withinCounties($city$city->getCounties()->toArray()));
  297.         $result $this->paginatedListing($city'/city/{city}/county/{county}', ['city' => $city->getId(), 'county' => $county->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_COUNTY$response);
  298.         if ($this->isApiRequest($request)) {
  299.             return $this->json($result);
  300.         }
  301.         return $this->render('ProfileList/list.html.twig', [
  302.             'profiles' => $result,
  303.             'source' => $this->source,
  304.             'source_default' => self::RESULT_SOURCE_COUNTY,
  305.             'county' => $county,
  306.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  307.                 'city' => $city->getUriIdentity(),
  308.                 'county' => $county->getUriIdentity(),
  309.                 'page' => $this->getCurrentPageNumber()
  310.             ]),
  311.             'recommendationSpec' => $specs->recommendationSpec(),
  312.         ], response$response);
  313.     }
  314.     #[ParamConverter("city"converter"city_converter")]
  315.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  316.     #[Route("/api/profiles/listing/city/{city}/district/{district}"name"api.profile_listing.by_district"methods"GET"format"json")]
  317.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  318.     #[OA\Tag(name"ProfileListing")]
  319.     #[OA\Response(
  320.         response200,
  321.         description'',
  322.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  323.     )]
  324.     public function listByDistrict(Request $requestCity $cityDistrict $district): Response
  325.     {
  326.         if (!$city->hasDistrict($district)) {
  327.             throw $this->createNotFoundException();
  328.         }
  329.         $specs $this->profileListSpecificationService->listByDistrict($district);
  330.         $response = new Response();
  331.         $alternativeSpec Spec::orX(ProfileIsLocated::withinDistricts($city$city->getDistricts()->toArray()));
  332.         $result $this->paginatedListing($city'/city/{city}/district/{district}', ['city' => $city->getId(), 'district' => $district->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_DISTRICT$response);
  333.         if ($this->isApiRequest($request)) {
  334.             return $this->json($result);
  335.         }
  336.         return $this->render('ProfileList/list.html.twig', [
  337.             'profiles' => $result,
  338.             'source' => $this->source,
  339.             'source_default' => self::RESULT_SOURCE_DISTRICT,
  340.             'district' => $district,
  341.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  342.                 'city' => $city->getUriIdentity(),
  343.                 'district' => $district->getUriIdentity(),
  344.                 'page' => $this->getCurrentPageNumber()
  345.             ]),
  346.             'recommendationSpec' => $specs->recommendationSpec(),
  347.         ], response$response);
  348.     }
  349.     /**
  350.      * @Feature("extra_category_without_prepayment")
  351.      */
  352.     #[ParamConverter("city"converter"city_converter")]
  353.     #[Route("/api/profiles/listing/city/{city}/category/without_prepayment"name"api.profile_listing.category.without_prepayment"methods"GET"format"json")]
  354.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  355.     #[OA\Tag(name"ProfileListing")]
  356.     #[OA\Response(
  357.         response200,
  358.         description'',
  359.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  360.     )]
  361.     public function listWithoutPrepayment(Request $requestCity $city): Response
  362.     {
  363.         $listingData $this->profileListingDataCreator->getListingDataForFilter('listWithoutPrepayment', [], $city);
  364.         $specs $listingData['specs'];
  365.         $listingTypeName $listingData['listingTypeName'];
  366.         $response = new Response();
  367.         $result $this->paginatedListing($city'/city/{city}/category/without_prepayment', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  368.         if ($this->isApiRequest($request)) {
  369.             return $this->json($result);
  370.         }
  371.         $request->attributes->set('profiles_count'$result->totalCount());
  372.         $request->attributes->set('listingTypeName'$listingTypeName);
  373.         $request->attributes->set('city'$city);
  374.         return $this->render('ProfileList/list.html.twig', [
  375.             'profiles' => $result,
  376.             'source' => $this->source,
  377.             'source_default' => 'without_prepayment',
  378.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  379.                 'city' => $city->getUriIdentity(),
  380.                 'page' => $this->getCurrentPageNumber(),
  381.             ]),
  382.             'recommendationSpec' => $specs->recommendationSpec(),
  383.         ], response$response);
  384.     }
  385.     #[ParamConverter("city"converter"city_converter")]
  386.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  387.     #[Route("/api/profiles/listing/city/{city}/station/{station}"name"api.profile_listing.by_station"methods"GET"format"json")]
  388.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  389.     #[OA\Tag(name"ProfileListing")]
  390.     #[OA\Response(
  391.         response200,
  392.         description'',
  393.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  394.     )]
  395.     public function listByStation(Request $requestCity $cityStation $station): Response
  396.     {
  397.         if (!$city->hasStation($station)) {
  398.             throw $this->createNotFoundException();
  399.         }
  400.         $specs $this->profileListSpecificationService->listByStation($station);
  401.         $response = new Response();
  402.         $result $this->paginatedListing($city'/city/{city}/station/{station}', ['city' => $city->getId(), 'station' => $station->getId()], $specs->spec(), nullnull$response);
  403.         if ($this->isApiRequest($request)) {
  404.             return $this->json($result);
  405.         }
  406.         return $this->render('ProfileList/list.html.twig', [
  407.             'profiles' => $result,
  408.             'source' => $this->source,
  409.             'source_default' => self::RESULT_SOURCE_STATION,
  410.             'station' => $station,
  411.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  412.                 'city' => $city->getUriIdentity(),
  413.                 'station' => $station->getUriIdentity(),
  414.                 'page' => $this->getCurrentPageNumber()
  415.             ]),
  416.             'recommendationSpec' => $specs->recommendationSpec(),
  417.         ], response$response);
  418.     }
  419.     #[ParamConverter("city"converter"city_converter")]
  420.     public function listByStations(City $citystring $stationsStationRepository $stationRepository): Response
  421.     {
  422.         $stationIds explode(','$stations);
  423.         $stations $stationRepository->findBy(['uriIdentity' => $stationIds]);
  424.         $specs $this->profileListSpecificationService->listByStations($stations);
  425.         $response = new Response();
  426.         $result $this->paginatedListing($citynull, [], $specs->spec(), nullnull$response);
  427.         return $this->render('ProfileList/list.html.twig', [
  428.             'profiles' => $result,
  429.             'recommendationSpec' => $specs->recommendationSpec(),
  430.         ]);
  431.     }
  432.     #[ParamConverter("city"converter"city_converter")]
  433.     #[Route("/api/profiles/listing/city/{city}/approved"name"api.profile_listing.approved"methods"GET"format"json")]
  434.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  435.     #[OA\Tag(name"ProfileListing")]
  436.     #[OA\Response(
  437.         response200,
  438.         description'',
  439.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  440.     )]
  441.     public function listApproved(Request $requestCity $city): Response
  442.     {
  443.         $specs $this->profileListSpecificationService->listApproved();
  444.         $response = new Response();
  445.         $result $this->paginatedListing($city'/city/{city}/approved', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  446.         if ($this->isApiRequest($request)) {
  447.             return $this->json($result);
  448.         }
  449.         return $this->render('ProfileList/list.html.twig', [
  450.             'profiles' => $result,
  451.             'source' => $this->source,
  452.             'source_default' => self::RESULT_SOURCE_APPROVED,
  453.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  454.                 'city' => $city->getUriIdentity(),
  455.                 'page' => $this->getCurrentPageNumber()
  456.             ]),
  457.             'recommendationSpec' => $specs->recommendationSpec(),
  458.         ], response$response);
  459.     }
  460.     /**
  461.      * @Feature("extra_category_with_whatsapp")
  462.      */
  463.     #[ParamConverter("city"converter"city_converter")]
  464.     #[Route("/api/profiles/listing/city/{city}/category/whatsapp"name"api.profile_listing.category.whatsapp"methods"GET"format"json")]
  465.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  466.     #[OA\Tag(name"ProfileListing")]
  467.     #[OA\Response(
  468.         response200,
  469.         description'',
  470.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  471.     )]
  472.     public function listWithWhatsapp(Request $requestCity $city): Response
  473.     {
  474.         $specs $this->profileListSpecificationService->listWithWhatsapp();
  475.         $response = new Response();
  476.         $result $this->paginatedListing($city'/city/{city}/category/whatsapp', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  477.         if ($this->isApiRequest($request)) {
  478.             return $this->json($result);
  479.         }
  480.         return $this->render('ProfileList/list.html.twig', [
  481.             'profiles' => $result,
  482.             'source' => $this->source,
  483.             'source_default' => self::RESULT_SOURCE_WITH_WHATSAPP,
  484.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  485.                 'city' => $city->getUriIdentity(),
  486.                 'page' => $this->getCurrentPageNumber(),
  487.             ]),
  488.             'recommendationSpec' => $specs->recommendationSpec(),
  489.         ], response$response);
  490.     }
  491.     /**
  492.      * @Feature("extra_category_with_telegram")
  493.      */
  494.     #[ParamConverter("city"converter"city_converter")]
  495.     #[Route("/api/profiles/listing/city/{city}/category/telegram"name"api.profile_listing.category.telegram"methods"GET"format"json")]
  496.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  497.     #[OA\Tag(name"ProfileListing")]
  498.     #[OA\Response(
  499.         response200,
  500.         description'',
  501.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  502.     )]
  503.     public function listWithTelegram(Request $requestCity $city): Response
  504.     {
  505.         $specs $this->profileListSpecificationService->listWithTelegram();
  506.         $response = new Response();
  507.         $result $this->paginatedListing($city'/city/{city}/category/telegram', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  508.         if ($this->isApiRequest($request)) {
  509.             return $this->json($result);
  510.         }
  511.         return $this->render('ProfileList/list.html.twig', [
  512.             'profiles' => $result,
  513.             'source' => $this->source,
  514.             'source_default' => self::RESULT_SOURCE_WITH_TELEGRAM,
  515.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  516.                 'city' => $city->getUriIdentity(),
  517.                 'page' => $this->getCurrentPageNumber(),
  518.             ]),
  519.             'recommendationSpec' => $specs->recommendationSpec(),
  520.         ], response$response);
  521.     }
  522.     /**
  523.      * @Feature("extra_category_eighteen_years_old")
  524.      */
  525.     #[ParamConverter("city"converter"city_converter")]
  526.     #[Route("/api/profiles/listing/city/{city}/category/eighteen_years_old"name"api.profile_listing.category.eighteen_years_old"methods"GET"format"json")]
  527.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  528.     #[OA\Tag(name"ProfileListing")]
  529.     #[OA\Response(
  530.         response200,
  531.         description'',
  532.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  533.     )]
  534.     public function listEighteenYearsOld(Request $requestCity $city): Response
  535.     {
  536.         $specs $this->profileListSpecificationService->listEighteenYearsOld();
  537.         $response = new Response();
  538.         $result $this->paginatedListing($city'/city/{city}/category/eighteen_years_old', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  539.         if ($this->isApiRequest($request)) {
  540.             return $this->json($result);
  541.         }
  542.         return $this->render('ProfileList/list.html.twig', [
  543.             'profiles' => $result,
  544.             'source' => $this->source,
  545.             'source_default' => self::RESULT_SOURCE_EIGHTEEN_YEARS_OLD,
  546.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  547.                 'city' => $city->getUriIdentity(),
  548.                 'page' => $this->getCurrentPageNumber(),
  549.             ]),
  550.             'recommendationSpec' => $specs->recommendationSpec(),
  551.         ], response$response);
  552.     }
  553.     /**
  554.      * @Feature("extra_category_rublevskie")
  555.      */
  556.     #[ParamConverter("city"converter"city_converter")]
  557.     #[Route("/api/profiles/listing/city/{city}/category/rublevskie"name"api.profile_listing.category.rublevskie"methods"GET"format"json")]
  558.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  559.     #[OA\Tag(name"ProfileListing")]
  560.     #[OA\Response(
  561.         response200,
  562.         description'',
  563.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  564.     )]
  565.     public function listRublevskie(Request $requestCity $city): Response
  566.     {
  567.         if ($city->getUriIdentity() !== 'moscow') {
  568.             throw $this->createNotFoundException();
  569.         }
  570.         $specs $this->profileListSpecificationService->listRublevskie($city);
  571.         $response = new Response();
  572.         $result $this->paginatedListing($city'/city/{city}/category/rublevskie', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  573.         if ($this->isApiRequest($request)) {
  574.             return $this->json($result);
  575.         }
  576.         return $this->render('ProfileList/list.html.twig', [
  577.             'profiles' => $result,
  578.             'source' => $this->source,
  579.             'source_default' => 'rublevskie',
  580.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  581.                 'city' => $city->getUriIdentity(),
  582.                 'page' => $this->getCurrentPageNumber(),
  583.             ]),
  584.             'recommendationSpec' => $specs->recommendationSpec(),
  585.         ], response$response);
  586.     }
  587.     /**
  588.      * @Feature("extra_category_with_tattoo")
  589.      */
  590.     #[ParamConverter("city"converter"city_converter")]
  591.     #[Route("/api/profiles/listing/city/{city}/category/with_tattoo"name"api.profile_listing.category.with_tattoo"methods"GET"format"json")]
  592.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  593.     #[OA\Tag(name"ProfileListing")]
  594.     #[OA\Response(
  595.         response200,
  596.         description'',
  597.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  598.     )]
  599.     public function listWithTattoo(Request $requestCity $city): Response
  600.     {
  601.         $specs $this->profileListSpecificationService->listWithTattoo();
  602.         $response = new Response();
  603.         $result $this->paginatedListing($city'/city/{city}/category/with_tattoo', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  604.         if ($this->isApiRequest($request)) {
  605.             return $this->json($result);
  606.         }
  607.         return $this->render('ProfileList/list.html.twig', [
  608.             'profiles' => $result,
  609.             'source' => $this->source,
  610.             'source_default' => self::RESULT_SOURCE_WITH_TATTOO,
  611.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  612.                 'city' => $city->getUriIdentity(),
  613.                 'page' => $this->getCurrentPageNumber(),
  614.             ]),
  615.             'recommendationSpec' => $specs->recommendationSpec(),
  616.         ], response$response);
  617.     }
  618.     #[ParamConverter("city"converter"city_converter")]
  619.     #[Route("/api/profiles/listing/city/{city}/with_comments"name"api.profile_listing.with_comments"methods"GET"format"json")]
  620.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  621.     #[OA\Tag(name"ProfileListing")]
  622.     #[OA\Response(
  623.         response200,
  624.         description'',
  625.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  626.     )]
  627.     public function listWithComments(Request $requestCity $city): Response
  628.     {
  629.         $specs $this->profileListSpecificationService->listWithComments();
  630.         $response = new Response();
  631.         $result $this->paginatedListing($city'/city/{city}/with_comments', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  632.         if ($this->isApiRequest($request)) {
  633.             return $this->json($result);
  634.         }
  635.         return $this->render('ProfileList/list.html.twig', [
  636.             'profiles' => $result,
  637.             'source' => $this->source,
  638.             'source_default' => self::RESULT_SOURCE_WITH_COMMENTS,
  639.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  640.                 'city' => $city->getUriIdentity(),
  641.                 'page' => $this->getCurrentPageNumber()
  642.             ]),
  643.             'recommendationSpec' => $specs->recommendationSpec(),
  644.         ], response$response);
  645.     }
  646.     /**
  647.      * @Feature("extra_category_with_piercing")
  648.      */
  649.     #[ParamConverter("city"converter"city_converter")]
  650.     #[Route("/api/profiles/listing/city/{city}/category/with_piercing"name"api.profile_listing.category.with_piercing"methods"GET"format"json")]
  651.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  652.     #[OA\Tag(name"ProfileListing")]
  653.     #[OA\Response(
  654.         response200,
  655.         description'',
  656.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  657.     )]
  658.     public function listWithPiercing(Request $requestCity $city): Response
  659.     {
  660.         $specs $this->profileListSpecificationService->listWithPiercing();
  661.         $response = new Response();
  662.         $result $this->paginatedListing($city'/city/{city}/category/with_piercing', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  663.         if ($this->isApiRequest($request)) {
  664.             return $this->json($result);
  665.         }
  666.         return $this->render('ProfileList/list.html.twig', [
  667.             'profiles' => $result,
  668.             'source' => $this->source,
  669.             'source_default' => self::RESULT_SOURCE_WITH_PIERCING,
  670.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  671.                 'city' => $city->getUriIdentity(),
  672.                 'page' => $this->getCurrentPageNumber(),
  673.             ]),
  674.             'recommendationSpec' => $specs->recommendationSpec(),
  675.         ], response$response);
  676.     }
  677.     #[ParamConverter("city"converter"city_converter")]
  678.     #[Route("/api/profiles/listing/city/{city}/with_video"name"api.profile_listing.with_video"methods"GET"format"json")]
  679.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  680.     #[OA\Tag(name"ProfileListing")]
  681.     #[OA\Response(
  682.         response200,
  683.         description'',
  684.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  685.     )]
  686.     public function listWithVideo(Request $requestCity $city): Response
  687.     {
  688.         $specs $this->profileListSpecificationService->listWithVideo();
  689.         $response = new Response();
  690.         $result $this->paginatedListing($city'/city/{city}/with_video', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  691.         if ($this->isApiRequest($request)) {
  692.             return $this->json($result);
  693.         }
  694.         return $this->render('ProfileList/list.html.twig', [
  695.             'profiles' => $result,
  696.             'source' => $this->source,
  697.             'source_default' => self::RESULT_SOURCE_WITH_VIDEO,
  698.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  699.                 'city' => $city->getUriIdentity(),
  700.                 'page' => $this->getCurrentPageNumber()
  701.             ]),
  702.             'recommendationSpec' => $specs->recommendationSpec(),
  703.         ], response$response);
  704.     }
  705.      /**
  706.      * @Feature("extra_category_round_the_clock")
  707.      */
  708.     #[ParamConverter("city"converter"city_converter")]
  709.     #[Route("/api/profiles/listing/city/{city}/category/round_the_clock"name"api.profile_listing.category.round_the_clock"methods"GET"format"json")]
  710.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  711.     #[OA\Tag(name"ProfileListing")]
  712.     #[OA\Response(
  713.         response200,
  714.         description'',
  715.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  716.     )]
  717.     public function listRoundTheClock(Request $requestCity $city): Response
  718.     {
  719.         $specs $this->profileListSpecificationService->listRoundTheClock();
  720.         $response = new Response();
  721.         $result $this->paginatedListing($city'/city/{city}/category/round_the_clock', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  722.         if ($this->isApiRequest($request)) {
  723.             return $this->json($result);
  724.         }
  725.         return $this->render('ProfileList/list.html.twig', [
  726.             'profiles' => $result,
  727.             'source' => $this->source,
  728.             'source_default' => self::RESULT_SOURCE_ROUND_THE_CLOCK,
  729.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  730.                 'city' => $city->getUriIdentity(),
  731.                 'page' => $this->getCurrentPageNumber(),
  732.             ]),
  733.             'recommendationSpec' => $specs->recommendationSpec(),
  734.         ], response$response);
  735.     }
  736.     /**
  737.      * @Feature("extra_category_for_two_hours")
  738.      */
  739.     #[ParamConverter("city"converter"city_converter")]
  740.     #[Route("/api/profiles/listing/city/{city}/category/for_two_hours"name"api.profile_listing.category.for_two_hours"methods"GET"format"json")]
  741.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  742.     #[OA\Tag(name"ProfileListing")]
  743.     #[OA\Response(
  744.         response200,
  745.         description'',
  746.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  747.     )]
  748.     public function listForTwoHours(Request $requestCity $city): Response
  749.     {
  750.         $specs $this->profileListSpecificationService->listForTwoHours();
  751.         $response = new Response();
  752.         $result $this->paginatedListing($city'/city/{city}/category/for_two_hours', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  753.         if ($this->isApiRequest($request)) {
  754.             return $this->json($result);
  755.         }
  756.         return $this->render('ProfileList/list.html.twig', [
  757.             'profiles' => $result,
  758.             'source' => $this->source,
  759.             'source_default' => self::RESULT_SOURCE_FOR_TWO_HOURS,
  760.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  761.                 'city' => $city->getUriIdentity(),
  762.                 'page' => $this->getCurrentPageNumber(),
  763.             ]),
  764.             'recommendationSpec' => $specs->recommendationSpec(),
  765.         ], response$response);
  766.     }
  767.     /**
  768.      * @Feature("extra_category_for_hour")
  769.      */
  770.     #[ParamConverter("city"converter"city_converter")]
  771.     #[Route("/api/profiles/listing/city/{city}/category/for_hour"name"api.profile_listing.category.for_hour"methods"GET"format"json")]
  772.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  773.     #[OA\Tag(name"ProfileListing")]
  774.     #[OA\Response(
  775.         response200,
  776.         description'',
  777.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  778.     )]
  779.     public function listForHour(Request $requestCity $city): Response
  780.     {
  781.         $specs $this->profileListSpecificationService->listForHour();
  782.         $response = new Response();
  783.         $result $this->paginatedListing($city'/city/{city}/category/for_hour', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  784.         if ($this->isApiRequest($request)) {
  785.             return $this->json($result);
  786.         }
  787.         return $this->render('ProfileList/list.html.twig', [
  788.             'profiles' => $result,
  789.             'source' => $this->source,
  790.             'source_default' => self::RESULT_SOURCE_FOR_HOUR,
  791.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  792.                 'city' => $city->getUriIdentity(),
  793.                 'page' => $this->getCurrentPageNumber(),
  794.             ]),
  795.             'recommendationSpec' => $specs->recommendationSpec(),
  796.         ], response$response);
  797.     }
  798.     /**
  799.      * @Feature("extra_category_express_program")
  800.      */
  801.     #[ParamConverter("city"converter"city_converter")]
  802.     #[Route("/api/profiles/listing/city/{city}/category/express"name"api.profile_listing.category.express"methods"GET"format"json")]
  803.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  804.     #[OA\Tag(name"ProfileListing")]
  805.     #[OA\Response(
  806.         response200,
  807.         description'',
  808.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  809.     )]
  810.     public function listExpress(Request $requestCity $city): Response
  811.     {
  812.         $specs $this->profileListSpecificationService->listExpress();
  813.         $response = new Response();
  814.         $result $this->paginatedListing($city'/city/{city}/category/express', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  815.         if ($this->isApiRequest($request)) {
  816.             return $this->json($result);
  817.         }
  818.         return $this->render('ProfileList/list.html.twig', [
  819.             'profiles' => $result,
  820.             'source' => $this->source,
  821.             'source_default' => self::RESULT_SOURCE_EXPRESS_PROGRAM,
  822.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  823.                 'city' => $city->getUriIdentity(),
  824.                 'page' => $this->getCurrentPageNumber(),
  825.             ]),
  826.             'recommendationSpec' => $specs->recommendationSpec(),
  827.         ], response$response);
  828.     }
  829.     /**
  830.      * @Feature("extra_category_grandmothers")
  831.      */
  832.     #[ParamConverter("city"converter"city_converter")]
  833.     #[Route("/api/profiles/listing/city/{city}/category/grandmothers"name"api.profile_listing.category.grandmothers"methods"GET"format"json")]
  834.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  835.     #[OA\Tag(name"ProfileListing")]
  836.     #[OA\Response(
  837.         response200,
  838.         description'',
  839.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  840.     )]
  841.     public function listGrandmothers(Request $requestCity $city): Response
  842.     {
  843.         $specs $this->profileListSpecificationService->listGrandmothers();
  844.         $response = new Response();
  845.         $result $this->paginatedListing($city'/city/{city}/category/grandmothers', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  846.         if ($this->isApiRequest($request)) {
  847.             return $this->json($result);
  848.         }
  849.         return $this->render('ProfileList/list.html.twig', [
  850.             'profiles' => $result,
  851.             'source' => $this->source,
  852.             'source_default' => 'grandmothers',
  853.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  854.                 'city' => $city->getUriIdentity(),
  855.                 'page' => $this->getCurrentPageNumber(),
  856.             ]),
  857.             'recommendationSpec' => $specs->recommendationSpec(),
  858.         ], response$response);
  859.     }
  860.         /**
  861.      * @Feature("extra_category_big_breast")
  862.      */
  863.     #[ParamConverter("city"converter"city_converter")]
  864.     #[Route("/api/profiles/listing/city/{city}/category/big_breast"name"api.profile_listing.category.big_breast"methods"GET"format"json")]
  865.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  866.     #[OA\Tag(name"ProfileListing")]
  867.     #[OA\Response(
  868.         response200,
  869.         description'',
  870.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  871.     )]
  872.     public function listBigBreast(Request $requestCity $city): Response
  873.     {
  874.         $specs $this->profileListSpecificationService->listBigBreast();
  875.         $response = new Response();
  876.         $result $this->paginatedListing($city'/city/{city}/category/big_breast', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  877.         if ($this->isApiRequest($request)) {
  878.             return $this->json($result);
  879.         }
  880.         return $this->render('ProfileList/list.html.twig', [
  881.             'profiles' => $result,
  882.             'source' => $this->source,
  883.             'source_default' => 'big_breast',
  884.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  885.                 'city' => $city->getUriIdentity(),
  886.                 'page' => $this->getCurrentPageNumber(),
  887.             ]),
  888.             'recommendationSpec' => $specs->recommendationSpec(),
  889.         ], response$response);
  890.     }
  891.     /**
  892.      * @Feature("extra_category_very_skinny")
  893.      */
  894.     #[ParamConverter("city"converter"city_converter")]
  895.     #[Route("/api/profiles/listing/city/{city}/category/very_skinny"name"api.profile_listing.category.very_skinny"methods"GET"format"json")]
  896.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  897.     #[OA\Tag(name"ProfileListing")]
  898.     #[OA\Response(
  899.         response200,
  900.         description'',
  901.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  902.     )]
  903.     public function listVerySkinny(Request $requestCity $city): Response
  904.     {
  905.         $specs $this->profileListSpecificationService->listVerySkinny();
  906.         $response = new Response();
  907.         $result $this->paginatedListing($city'/city/{city}/category/very_skinny', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  908.         if ($this->isApiRequest($request)) {
  909.             return $this->json($result);
  910.         }
  911.         return $this->render('ProfileList/list.html.twig', [
  912.             'profiles' => $result,
  913.             'source' => $this->source,
  914.             'source_default' => 'very_skinny',
  915.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  916.                 'city' => $city->getUriIdentity(),
  917.                 'page' => $this->getCurrentPageNumber(),
  918.             ]),
  919.             'recommendationSpec' => $specs->recommendationSpec(),
  920.         ], response$response);
  921.     }
  922.     /**
  923.      * @Feature("extra_category_small_ass")
  924.      */
  925.     #[ParamConverter("city"converter"city_converter")]
  926.     #[Route("/api/profiles/listing/city/{city}/category/small_ass"name"api.profile_listing.category.small_ass"methods"GET"format"json")]
  927.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  928.     #[OA\Tag(name"ProfileListing")]
  929.     #[OA\Response(
  930.         response200,
  931.         description'',
  932.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  933.     )]
  934.     public function listSmallAss(Request $requestCity $city): Response
  935.     {
  936.         $specs $this->profileListSpecificationService->listSmallAss();
  937.         $response = new Response();
  938.         $result $this->paginatedListing($city'/city/{city}/category/small_ass', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  939.         if ($this->isApiRequest($request)) {
  940.             return $this->json($result);
  941.         }
  942.         return $this->render('ProfileList/list.html.twig', [
  943.             'profiles' => $result,
  944.             'source' => $this->source,
  945.             'source_default' => 'small_ass',
  946.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  947.                 'city' => $city->getUriIdentity(),
  948.                 'page' => $this->getCurrentPageNumber(),
  949.             ]),
  950.             'recommendationSpec' => $specs->recommendationSpec(),
  951.         ], response$response);
  952.     }
  953.     /**
  954.      * @Feature("extra_category_beautiful_prostitutes")
  955.      */
  956.     #[ParamConverter("city"converter"city_converter")]
  957.     #[Route("/api/profiles/listing/city/{city}/category/beautiful_prostitutes"name"api.profile_listing.category.beautiful_prostitutes"methods"GET"format"json")]
  958.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  959.     #[OA\Tag(name"ProfileListing")]
  960.     #[OA\Response(
  961.         response200,
  962.         description'',
  963.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  964.     )]
  965.     public function listBeautifulProstitutes(Request $requestCity $city): Response
  966.     {
  967.         $specs $this->profileListSpecificationService->listBeautifulProstitutes();
  968.         $response = new Response();
  969.         $result $this->paginatedListing($city'/city/{city}/category/beautiful_prostitutes', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  970.         if ($this->isApiRequest($request)) {
  971.             return $this->json($result);
  972.         }
  973.         return $this->render('ProfileList/list.html.twig', [
  974.             'profiles' => $result,
  975.             'source' => $this->source,
  976.             'source_default' => 'beautiful_prostitutes',
  977.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  978.                 'city' => $city->getUriIdentity(),
  979.                 'page' => $this->getCurrentPageNumber(),
  980.             ]),
  981.             'recommendationSpec' => $specs->recommendationSpec(),
  982.         ], response$response);
  983.     }
  984.     /**
  985.      * @Feature("extra_category_without_intermediaries")
  986.      */
  987.     #[ParamConverter("city"converter"city_converter")]
  988.     #[Route("/api/profiles/listing/city/{city}/category/without_intermediaries"name"api.profile_listing.category.without_intermediaries"methods"GET"format"json")]
  989.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  990.     #[OA\Tag(name"ProfileListing")]
  991.     #[OA\Response(
  992.         response200,
  993.         description'',
  994.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  995.     )]
  996.     public function listWithoutIntermediaries(Request $requestCity $city): Response
  997.     {
  998.         $specs $this->profileListSpecificationService->listWithoutIntermediaries();
  999.         $response = new Response();
  1000.         $result $this->paginatedListing($city'/city/{city}/category/without_intermediaries', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1001.         if ($this->isApiRequest($request)) {
  1002.             return $this->json($result);
  1003.         }
  1004.         return $this->render('ProfileList/list.html.twig', [
  1005.             'profiles' => $result,
  1006.             'source' => $this->source,
  1007.             'source_default' => 'without_intermediaries',
  1008.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1009.                 'city' => $city->getUriIdentity(),
  1010.                 'page' => $this->getCurrentPageNumber(),
  1011.             ]),
  1012.             'recommendationSpec' => $specs->recommendationSpec(),
  1013.         ], response$response);
  1014.     }
  1015.     /**
  1016.      * @Feature("extra_category_intim_services")
  1017.      */
  1018.     #[ParamConverter("city"converter"city_converter")]
  1019.     public function intimServices(Request $requestCity $city): Response
  1020.     {
  1021.         $servicesByGroup $this->serviceRepository->allIndexedByGroup();
  1022.         return $this->render('ProfileList/intim_services.html.twig', [
  1023.             'city' => $city,
  1024.             'servicesByGroup' => $servicesByGroup,
  1025.             'skipSetCurrentListingPage' => true,
  1026.         ]);
  1027.     }
  1028.     /**
  1029.      * @Feature("extra_category_outcall")
  1030.      */
  1031.     #[ParamConverter("city"converter"city_converter")]
  1032.     #[Route("/api/profiles/listing/city/{city}/category/outcall"name"api.profile_listing.category.outcall"methods"GET"format"json")]
  1033.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1034.     #[OA\Tag(name"ProfileListing")]
  1035.     #[OA\Response(
  1036.         response200,
  1037.         description'',
  1038.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1039.     )]
  1040.     public function listOutcall(Request $requestCity $city): Response
  1041.     {
  1042.         $specs $this->profileListSpecificationService->listByOutcall();
  1043.         $response = new Response();
  1044.         $result $this->paginatedListing($city'/city/{city}/category/outcall', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1045.         if ($this->isApiRequest($request)) {
  1046.             return $this->json($result);
  1047.         }
  1048.         return $this->render('ProfileList/list.html.twig', [
  1049.             'profiles' => $result,
  1050.             'source' => $this->source,
  1051.             'source_default' => 'outcall',
  1052.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1053.                 'city' => $city->getUriIdentity(),
  1054.                 'page' => $this->getCurrentPageNumber(),
  1055.             ]),
  1056.             'recommendationSpec' => $specs->recommendationSpec(),
  1057.         ], response$response);
  1058.     }
  1059.     /**
  1060.      * @Feature("extra_category_dwarfs")
  1061.      */
  1062.     #[ParamConverter("city"converter"city_converter")]
  1063.     #[Route("/api/profiles/listing/city/{city}/category/dwarfs"name"api.profile_listing.category.dwarfs"methods"GET"format"json")]
  1064.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1065.     #[OA\Tag(name"ProfileListing")]
  1066.     #[OA\Response(
  1067.         response200,
  1068.         description'',
  1069.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1070.     )]
  1071.     public function listDwarfs(Request $requestCity $city): Response
  1072.     {
  1073.         $specs $this->profileListSpecificationService->listDwarfs();
  1074.         $response = new Response();
  1075.         $result $this->paginatedListing($city'/city/{city}/category/dwarfs', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1076.         if ($this->isApiRequest($request)) {
  1077.             return $this->json($result);
  1078.         }
  1079.         return $this->render('ProfileList/list.html.twig', [
  1080.             'profiles' => $result,
  1081.             'source' => $this->source,
  1082.             'source_default' => 'dwarfs',
  1083.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1084.                 'city' => $city->getUriIdentity(),
  1085.                 'page' => $this->getCurrentPageNumber(),
  1086.             ]),
  1087.             'recommendationSpec' => $specs->recommendationSpec(),
  1088.         ], response$response);
  1089.     }
  1090.     #[ParamConverter("city"converter"city_converter")]
  1091.     #[Route("/api/profiles/listing/city/{city}/with_selfie"name"api.profile_listing.with_selfie"methods"GET"format"json")]
  1092.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1093.     #[OA\Tag(name"ProfileListing")]
  1094.     #[OA\Response(
  1095.         response200,
  1096.         description'',
  1097.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1098.     )]
  1099.     public function listWithSelfie(Request $requestCity $city): Response
  1100.     {
  1101.         $specs $this->profileListSpecificationService->listWithSelfie();
  1102.         $response = new Response();
  1103.         $result $this->paginatedListing($city'/city/{city}/with_selfie', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1104.         if ($this->isApiRequest($request)) {
  1105.             return $this->json($result);
  1106.         }
  1107.         return $this->render('ProfileList/list.html.twig', [
  1108.             'profiles' => $result,
  1109.             'source' => $this->source,
  1110.             'source_default' => self::RESULT_SOURCE_WITH_SELFIE,
  1111.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1112.                 'city' => $city->getUriIdentity(),
  1113.                 'page' => $this->getCurrentPageNumber()
  1114.             ]),
  1115.             'recommendationSpec' => $specs->recommendationSpec(),
  1116.         ], response$response);
  1117.     }
  1118.     /**
  1119.      * @Feature("extra_category_top_100")
  1120.      */
  1121.     #[ParamConverter("city"converter"city_converter")]
  1122.     #[Route("/api/profiles/listing/city/{city}/category/top_100"name"api.profile_listing.category.top_100"methods"GET"format"json")]
  1123.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1124.     #[OA\Tag(name"ProfileListing")]
  1125.     #[OA\Response(
  1126.         response200,
  1127.         description'',
  1128.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1129.     )]
  1130.     public function listTop100(Request $requestCity $city): Response
  1131.     {
  1132.         $specs $this->profileListSpecificationService->listApproved();
  1133.         $result $this->top100ProfilesService->getSortedProfilesByVisits($city);
  1134.         if ($this->isApiRequest($request)) {
  1135.             return $this->json($result);
  1136.         }
  1137.         return $this->render('ProfileList/list.html.twig', [
  1138.             'profiles' => $result,
  1139.             'source' => self::RESULT_SOURCE_TOP_100,
  1140.             'source_default' => self::RESULT_SOURCE_TOP_100,
  1141.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1142.                 'city' => $city->getUriIdentity(),
  1143.                 'page' => $this->getCurrentPageNumber(),
  1144.             ]),
  1145.             'recommendationSpec' => $specs->recommendationSpec(),
  1146.         ]);
  1147.     }
  1148.     /**
  1149.      * @Feature("extra_category_eromassage")
  1150.      */
  1151.     #[ParamConverter("city"converter"city_converter")]
  1152.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  1153.     public function listByCountyEromassage(Request $requestCity $cityCounty $county): Response
  1154.     {
  1155.         if (!$city->hasCounty($county)) {
  1156.             throw $this->createNotFoundException();
  1157.         }
  1158.         $specs $this->profileListSpecificationService->listByCountyEromassage($county);
  1159.         $response = new Response();
  1160.         $result $this->paginatedListing(
  1161.             $city,
  1162.             '/city/{city}/county/{county}/eromassage',
  1163.             ['city' => $city->getId(), 'county' => $county->getId()],
  1164.             $specs->spec(),
  1165.             null,
  1166.             null,
  1167.             $response
  1168.         );
  1169.         $request->attributes->set('profiles_count'$result->totalCount());
  1170.         return $this->render('ProfileList/list.html.twig', [
  1171.             'profiles' => $result,
  1172.             'source' => $this->source,
  1173.             'source_default' => self::RESULT_SOURCE_EROMASSAGE,
  1174.             'county' => $county,
  1175.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1176.                 'city' => $city->getUriIdentity(),
  1177.                 'county' => $county->getUriIdentity(),
  1178.                 'page' => $this->getCurrentPageNumber(),
  1179.             ]),
  1180.             'recommendationSpec' => $specs->recommendationSpec(),
  1181.         ], response$response);
  1182.     }
  1183.     /**
  1184.      * @Feature("extra_category_eromassage")
  1185.      */
  1186.     #[ParamConverter("city"converter"city_converter")]
  1187.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  1188.     public function listByDistrictEromassage(Request $requestCity $cityDistrict $district): Response
  1189.     {
  1190.         if (!$city->hasDistrict($district)) {
  1191.             throw $this->createNotFoundException();
  1192.         }
  1193.         $specs $this->profileListSpecificationService->listByDistrictEromassage($district);
  1194.         $response = new Response();
  1195.         $result $this->paginatedListing(
  1196.             $city,
  1197.             '/city/{city}/district/{district}/eromassage',
  1198.             ['city' => $city->getId(), 'district' => $district->getId()],
  1199.             $specs->spec(),
  1200.             null,
  1201.             null,
  1202.             $response
  1203.         );
  1204.         $request->attributes->set('profiles_count'$result->totalCount());
  1205.         return $this->render('ProfileList/list.html.twig', [
  1206.             'profiles' => $result,
  1207.             'source' => $this->source,
  1208.             'source_default' => self::RESULT_SOURCE_EROMASSAGE,
  1209.             'district' => $district,
  1210.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1211.                 'city' => $city->getUriIdentity(),
  1212.                 'district' => $district->getUriIdentity(),
  1213.                 'page' => $this->getCurrentPageNumber(),
  1214.             ]),
  1215.             'recommendationSpec' => $specs->recommendationSpec(),
  1216.         ], response$response);
  1217.     }
  1218.     /**
  1219.      * @Feature("extra_category_eromassage")
  1220.      */
  1221.     #[ParamConverter("city"converter"city_converter")]
  1222.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  1223.     public function listByStationEromassage(Request $requestCity $cityStation $station): Response
  1224.     {
  1225.         if (!$city->hasStation($station)) {
  1226.             throw $this->createNotFoundException();
  1227.         }
  1228.         $specs $this->profileListSpecificationService->listByStationEromassage($station);
  1229.         $response = new Response();
  1230.         $result $this->paginatedListing(
  1231.             $city,
  1232.             '/city/{city}/station/{station}/eromassage',
  1233.             ['city' => $city->getId(), 'station' => $station->getId()],
  1234.             $specs->spec(),
  1235.             null,
  1236.             null,
  1237.             $response
  1238.         );
  1239.         $request->attributes->set('profiles_count'$result->totalCount());
  1240.         return $this->render('ProfileList/list.html.twig', [
  1241.             'profiles' => $result,
  1242.             'source' => $this->source,
  1243.             'source_default' => self::RESULT_SOURCE_EROMASSAGE,
  1244.             'station' => $station,
  1245.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1246.                 'city' => $city->getUriIdentity(),
  1247.                 'station' => $station->getUriIdentity(),
  1248.                 'page' => $this->getCurrentPageNumber(),
  1249.             ]),
  1250.             'recommendationSpec' => $specs->recommendationSpec(),
  1251.         ], response$response);
  1252.     }
  1253.     /**
  1254.      * @Feature("extra_category_verified")
  1255.      */
  1256.     #[ParamConverter("city"converter"city_converter")]
  1257.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  1258.     public function listByCountyVerified(Request $requestCity $cityCounty $county): Response
  1259.     {
  1260.         if (!$city->hasCounty($county)) {
  1261.             throw $this->createNotFoundException();
  1262.         }
  1263.         $specs $this->profileListSpecificationService->listByCountyVerified($county);
  1264.         $response = new Response();
  1265.         $result $this->paginatedListing(
  1266.             $city,
  1267.             '/city/{city}/county/{county}/proverennye',
  1268.             ['city' => $city->getId(), 'county' => $county->getId()],
  1269.             $specs->spec(),
  1270.             null,
  1271.             null,
  1272.             $response
  1273.         );
  1274.         $request->attributes->set('profiles_count'$result->totalCount());
  1275.         return $this->render('ProfileList/list.html.twig', [
  1276.             'profiles' => $result,
  1277.             'source' => $this->source,
  1278.             'source_default' => self::RESULT_SOURCE_VERIFIED,
  1279.             'county' => $county,
  1280.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1281.                 'city' => $city->getUriIdentity(),
  1282.                 'county' => $county->getUriIdentity(),
  1283.                 'page' => $this->getCurrentPageNumber(),
  1284.             ]),
  1285.             'recommendationSpec' => $specs->recommendationSpec(),
  1286.         ], response$response);
  1287.     }
  1288.     /**
  1289.      * @Feature("extra_category_verified")
  1290.      */
  1291.     #[ParamConverter("city"converter"city_converter")]
  1292.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  1293.     public function listByDistrictVerified(Request $requestCity $cityDistrict $district): Response
  1294.     {
  1295.         if (!$city->hasDistrict($district)) {
  1296.             throw $this->createNotFoundException();
  1297.         }
  1298.         $specs $this->profileListSpecificationService->listByDistrictVerified($district);
  1299.         $response = new Response();
  1300.         $result $this->paginatedListing(
  1301.             $city,
  1302.             '/city/{city}/district/{district}/proverennye',
  1303.             ['city' => $city->getId(), 'district' => $district->getId()],
  1304.             $specs->spec(),
  1305.             null,
  1306.             null,
  1307.             $response
  1308.         );
  1309.         $request->attributes->set('profiles_count'$result->totalCount());
  1310.         return $this->render('ProfileList/list.html.twig', [
  1311.             'profiles' => $result,
  1312.             'source' => $this->source,
  1313.             'source_default' => self::RESULT_SOURCE_VERIFIED,
  1314.             'district' => $district,
  1315.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1316.                 'city' => $city->getUriIdentity(),
  1317.                 'district' => $district->getUriIdentity(),
  1318.                 'page' => $this->getCurrentPageNumber(),
  1319.             ]),
  1320.             'recommendationSpec' => $specs->recommendationSpec(),
  1321.         ], response$response);
  1322.     }
  1323.     /**
  1324.      * @Feature("extra_category_verified")
  1325.      */
  1326.     #[ParamConverter("city"converter"city_converter")]
  1327.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  1328.     public function listByStationVerified(Request $requestCity $cityStation $station): Response
  1329.     {
  1330.         if (!$city->hasStation($station)) {
  1331.             throw $this->createNotFoundException();
  1332.         }
  1333.         $specs $this->profileListSpecificationService->listByStationVerified($station);
  1334.         $response = new Response();
  1335.         $result $this->paginatedListing(
  1336.             $city,
  1337.             '/city/{city}/station/{station}/proverennye',
  1338.             ['city' => $city->getId(), 'station' => $station->getId()],
  1339.             $specs->spec(),
  1340.             null,
  1341.             null,
  1342.             $response
  1343.         );
  1344.         $request->attributes->set('profiles_count'$result->totalCount());
  1345.         return $this->render('ProfileList/list.html.twig', [
  1346.             'profiles' => $result,
  1347.             'source' => $this->source,
  1348.             'source_default' => self::RESULT_SOURCE_VERIFIED,
  1349.             'station' => $station,
  1350.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1351.                 'city' => $city->getUriIdentity(),
  1352.                 'station' => $station->getUriIdentity(),
  1353.                 'page' => $this->getCurrentPageNumber(),
  1354.             ]),
  1355.             'recommendationSpec' => $specs->recommendationSpec(),
  1356.         ], response$response);
  1357.     }
  1358.     /**
  1359.      * @Feature("extra_category_cheap")
  1360.      */
  1361.     #[ParamConverter("city"converter"city_converter")]
  1362.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  1363.     public function listByCountyCheap(Request $requestCity $cityCounty $county): Response
  1364.     {
  1365.         if (!$city->hasCounty($county)) {
  1366.             throw $this->createNotFoundException();
  1367.         }
  1368.         $specs $this->profileListSpecificationService->listByCountyCheap($county);
  1369.         $response = new Response();
  1370.         $result $this->paginatedListing(
  1371.             $city,
  1372.             null,
  1373.             [],
  1374.             $specs->spec(),
  1375.             null,
  1376.             null,
  1377.             $response
  1378.         );
  1379.         $request->attributes->set('profiles_count'$result->totalCount());
  1380.         return $this->render('ProfileList/list.html.twig', [
  1381.             'profiles' => $result,
  1382.             'source' => $this->source,
  1383.             'source_default' => self::RESULT_SOURCE_CHEAP,
  1384.             'county' => $county,
  1385.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1386.                 'city' => $city->getUriIdentity(),
  1387.                 'county' => $county->getUriIdentity(),
  1388.                 'page' => $this->getCurrentPageNumber(),
  1389.             ]),
  1390.             'recommendationSpec' => $specs->recommendationSpec(),
  1391.         ], response$response);
  1392.     }
  1393.     /**
  1394.      * @Feature("extra_category_cheap")
  1395.      */
  1396.     #[ParamConverter("city"converter"city_converter")]
  1397.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  1398.     public function listByDistrictCheap(Request $requestCity $cityDistrict $district): Response
  1399.     {
  1400.         if (!$city->hasDistrict($district)) {
  1401.             throw $this->createNotFoundException();
  1402.         }
  1403.         $specs $this->profileListSpecificationService->listByDistrictCheap($district);
  1404.         $response = new Response();
  1405.         $result $this->paginatedListing(
  1406.             $city,
  1407.             null,
  1408.             [],
  1409.             $specs->spec(),
  1410.             null,
  1411.             null,
  1412.             $response
  1413.         );
  1414.         $request->attributes->set('profiles_count'$result->totalCount());
  1415.         return $this->render('ProfileList/list.html.twig', [
  1416.             'profiles' => $result,
  1417.             'source' => $this->source,
  1418.             'source_default' => self::RESULT_SOURCE_CHEAP,
  1419.             'district' => $district,
  1420.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1421.                 'city' => $city->getUriIdentity(),
  1422.                 'district' => $district->getUriIdentity(),
  1423.                 'page' => $this->getCurrentPageNumber(),
  1424.             ]),
  1425.             'recommendationSpec' => $specs->recommendationSpec(),
  1426.         ], response$response);
  1427.     }
  1428.     /**
  1429.      * @Feature("extra_category_cheap")
  1430.      */
  1431.     #[ParamConverter("city"converter"city_converter")]
  1432.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  1433.     public function listByStationCheap(Request $requestCity $cityStation $station): Response
  1434.     {
  1435.         if (!$city->hasStation($station)) {
  1436.             throw $this->createNotFoundException();
  1437.         }
  1438.         $specs $this->profileListSpecificationService->listByStationCheap($station);
  1439.         $response = new Response();
  1440.         $result $this->paginatedListing(
  1441.             $city,
  1442.             null,
  1443.             [],
  1444.             $specs->spec(),
  1445.             null,
  1446.             null,
  1447.             $response
  1448.         );
  1449.         $request->attributes->set('profiles_count'$result->totalCount());
  1450.         return $this->render('ProfileList/list.html.twig', [
  1451.             'profiles' => $result,
  1452.             'source' => $this->source,
  1453.             'source_default' => self::RESULT_SOURCE_CHEAP,
  1454.             'station' => $station,
  1455.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1456.                 'city' => $city->getUriIdentity(),
  1457.                 'station' => $station->getUriIdentity(),
  1458.                 'page' => $this->getCurrentPageNumber(),
  1459.             ]),
  1460.             'recommendationSpec' => $specs->recommendationSpec(),
  1461.         ], response$response);
  1462.     }
  1463.     /**
  1464.      * @Feature("extra_category_mature")
  1465.      */
  1466.     #[ParamConverter("city"converter"city_converter")]
  1467.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  1468.     public function listByCountyMature(Request $requestCity $cityCounty $county): Response
  1469.     {
  1470.         if (!$city->hasCounty($county)) {
  1471.             throw $this->createNotFoundException();
  1472.         }
  1473.         $specs $this->profileListSpecificationService->listByCountyMature($county);
  1474.         $response = new Response();
  1475.         $result $this->paginatedListing(
  1476.             $city,
  1477.             null,
  1478.             [],
  1479.             $specs->spec(),
  1480.             null,
  1481.             null,
  1482.             $response
  1483.         );
  1484.         $request->attributes->set('profiles_count'$result->totalCount());
  1485.         return $this->render('ProfileList/list.html.twig', [
  1486.             'profiles' => $result,
  1487.             'source' => $this->source,
  1488.             'source_default' => self::RESULT_SOURCE_MATURE,
  1489.             'county' => $county,
  1490.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1491.                 'city' => $city->getUriIdentity(),
  1492.                 'county' => $county->getUriIdentity(),
  1493.                 'page' => $this->getCurrentPageNumber(),
  1494.             ]),
  1495.             'recommendationSpec' => $specs->recommendationSpec(),
  1496.         ], response$response);
  1497.     }
  1498.     /**
  1499.      * @Feature("extra_category_mature")
  1500.      */
  1501.     #[ParamConverter("city"converter"city_converter")]
  1502.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  1503.     public function listByDistrictMature(Request $requestCity $cityDistrict $district): Response
  1504.     {
  1505.         if (!$city->hasDistrict($district)) {
  1506.             throw $this->createNotFoundException();
  1507.         }
  1508.         $specs $this->profileListSpecificationService->listByDistrictMature($district);
  1509.         $response = new Response();
  1510.         $result $this->paginatedListing(
  1511.             $city,
  1512.             null,
  1513.             [],
  1514.             $specs->spec(),
  1515.             null,
  1516.             null,
  1517.             $response
  1518.         );
  1519.         $request->attributes->set('profiles_count'$result->totalCount());
  1520.         return $this->render('ProfileList/list.html.twig', [
  1521.             'profiles' => $result,
  1522.             'source' => $this->source,
  1523.             'source_default' => self::RESULT_SOURCE_MATURE,
  1524.             'district' => $district,
  1525.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1526.                 'city' => $city->getUriIdentity(),
  1527.                 'district' => $district->getUriIdentity(),
  1528.                 'page' => $this->getCurrentPageNumber(),
  1529.             ]),
  1530.             'recommendationSpec' => $specs->recommendationSpec(),
  1531.         ], response$response);
  1532.     }
  1533.     /**
  1534.      * @Feature("extra_category_mature")
  1535.      */
  1536.     #[ParamConverter("city"converter"city_converter")]
  1537.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  1538.     public function listByStationMature(Request $requestCity $cityStation $station): Response
  1539.     {
  1540.         if (!$city->hasStation($station)) {
  1541.             throw $this->createNotFoundException();
  1542.         }
  1543.         $specs $this->profileListSpecificationService->listByStationMature($station);
  1544.         $response = new Response();
  1545.         $result $this->paginatedListing(
  1546.             $city,
  1547.             null,
  1548.             [],
  1549.             $specs->spec(),
  1550.             null,
  1551.             null,
  1552.             $response
  1553.         );
  1554.         $request->attributes->set('profiles_count'$result->totalCount());
  1555.         return $this->render('ProfileList/list.html.twig', [
  1556.             'profiles' => $result,
  1557.             'source' => $this->source,
  1558.             'source_default' => self::RESULT_SOURCE_MATURE,
  1559.             'station' => $station,
  1560.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1561.                 'city' => $city->getUriIdentity(),
  1562.                 'station' => $station->getUriIdentity(),
  1563.                 'page' => $this->getCurrentPageNumber(),
  1564.             ]),
  1565.             'recommendationSpec' => $specs->recommendationSpec(),
  1566.         ], response$response);
  1567.     }
  1568.     /**
  1569.      * @Feature("extra_category_uzbek")
  1570.      */
  1571.     #[ParamConverter("city"converter"city_converter")]
  1572.     #[Entity("county"expr"repository.ofUriIdentityWithinCity(county, city)")]
  1573.     public function listByCountyUzbek(Request $requestCity $cityCounty $county): Response
  1574.     {
  1575.         if (!$city->hasCounty($county)) {
  1576.             throw $this->createNotFoundException();
  1577.         }
  1578.         $specs $this->profileListSpecificationService->listByCountyUzbek($county);
  1579.         $response = new Response();
  1580.         $result $this->paginatedListing(
  1581.             $city,
  1582.             '/city/{city}/county/{county}/uzbechki',
  1583.             ['city' => $city->getId(), 'county' => $county->getId()],
  1584.             $specs->spec(),
  1585.             null,
  1586.             null,
  1587.             $response
  1588.         );
  1589.         $request->attributes->set('profiles_count'$result->totalCount());
  1590.         return $this->render('ProfileList/list.html.twig', [
  1591.             'profiles' => $result,
  1592.             'source' => $this->source,
  1593.             'source_default' => self::RESULT_SOURCE_UZBEK,
  1594.             'county' => $county,
  1595.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1596.                 'city' => $city->getUriIdentity(),
  1597.                 'county' => $county->getUriIdentity(),
  1598.                 'page' => $this->getCurrentPageNumber(),
  1599.             ]),
  1600.             'recommendationSpec' => $specs->recommendationSpec(),
  1601.         ], response$response);
  1602.     }
  1603.     /**
  1604.      * @Feature("extra_category_uzbek")
  1605.      */
  1606.     #[ParamConverter("city"converter"city_converter")]
  1607.     #[Entity("district"expr"repository.ofUriIdentityWithinCity(district, city)")]
  1608.     public function listByDistrictUzbek(Request $requestCity $cityDistrict $district): Response
  1609.     {
  1610.         if (!$city->hasDistrict($district)) {
  1611.             throw $this->createNotFoundException();
  1612.         }
  1613.         $specs $this->profileListSpecificationService->listByDistrictUzbek($district);
  1614.         $response = new Response();
  1615.         $result $this->paginatedListing(
  1616.             $city,
  1617.             '/city/{city}/district/{district}/uzbechki',
  1618.             ['city' => $city->getId(), 'district' => $district->getId()],
  1619.             $specs->spec(),
  1620.             null,
  1621.             null,
  1622.             $response
  1623.         );
  1624.         $request->attributes->set('profiles_count'$result->totalCount());
  1625.         return $this->render('ProfileList/list.html.twig', [
  1626.             'profiles' => $result,
  1627.             'source' => $this->source,
  1628.             'source_default' => self::RESULT_SOURCE_UZBEK,
  1629.             'district' => $district,
  1630.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1631.                 'city' => $city->getUriIdentity(),
  1632.                 'district' => $district->getUriIdentity(),
  1633.                 'page' => $this->getCurrentPageNumber(),
  1634.             ]),
  1635.             'recommendationSpec' => $specs->recommendationSpec(),
  1636.         ], response$response);
  1637.     }
  1638.     /**
  1639.      * @Feature("extra_category_uzbek")
  1640.      */
  1641.     #[ParamConverter("city"converter"city_converter")]
  1642.     #[Entity("station"expr"repository.ofUriIdentityWithinCity(station, city)")]
  1643.     public function listByStationUzbek(Request $requestCity $cityStation $station): Response
  1644.     {
  1645.         if (!$city->hasStation($station)) {
  1646.             throw $this->createNotFoundException();
  1647.         }
  1648.         $specs $this->profileListSpecificationService->listByStationUzbek($station);
  1649.         $response = new Response();
  1650.         $result $this->paginatedListing(
  1651.             $city,
  1652.             '/city/{city}/station/{station}/uzbechki',
  1653.             ['city' => $city->getId(), 'station' => $station->getId()],
  1654.             $specs->spec(),
  1655.             null,
  1656.             null,
  1657.             $response
  1658.         );
  1659.         $request->attributes->set('profiles_count'$result->totalCount());
  1660.         return $this->render('ProfileList/list.html.twig', [
  1661.             'profiles' => $result,
  1662.             'source' => $this->source,
  1663.             'source_default' => self::RESULT_SOURCE_UZBEK,
  1664.             'station' => $station,
  1665.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1666.                 'city' => $city->getUriIdentity(),
  1667.                 'station' => $station->getUriIdentity(),
  1668.                 'page' => $this->getCurrentPageNumber(),
  1669.             ]),
  1670.             'recommendationSpec' => $specs->recommendationSpec(),
  1671.         ], response$response);
  1672.     }
  1673.     #[ParamConverter("city"converter"city_converter")]
  1674.     #[Route("/api/profiles/listing/city/{city}/price/{priceType}"name"api.profile_listing.by_price"methods"GET"format"json")]
  1675.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1676.     #[OA\Tag(name"ProfileListing")]
  1677.     #[OA\Response(
  1678.         response200,
  1679.         description'',
  1680.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1681.     )]
  1682.     public function listByPrice(Request $requestCountryCurrencyResolver $countryCurrencyResolverCity $citystring $priceTypeint $minPrice nullint $maxPrice null): Response
  1683.     {
  1684.         $specs $this->profileListSpecificationService->listByPrice($city$priceType$minPrice$maxPrice);
  1685.         $response = new Response();
  1686.         $apiEndpoint in_array($priceType, ['low''high''elite']) ? '/city/{city}/price/'.$priceType null;
  1687.         $result $this->paginatedListing($city$apiEndpoint, ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1688.         if ($this->isApiRequest($request)) {
  1689.             return $this->json($result);
  1690.         }
  1691.         return $this->render('ProfileList/list.html.twig', [
  1692.             'profiles' => $result,
  1693.             'source' => $this->source,
  1694.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1695.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1696.                 'city' => $city->getUriIdentity(),
  1697.                 'priceType' => $priceType,
  1698.                 'minPrice' => $minPrice,
  1699.                 'maxPrice' => $maxPrice,
  1700.                 'page' => $this->getCurrentPageNumber()
  1701.             ]),
  1702.             'recommendationSpec' => $specs->recommendationSpec(),
  1703.         ], response$response);
  1704.     }
  1705.     #[ParamConverter("city"converter"city_converter")]
  1706.     #[Route("/api/profiles/listing/city/{city}/age/{ageType}"name"api.profile_listing.by_age"methods"GET"format"json")]
  1707.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1708.     #[OA\Tag(name"ProfileListing")]
  1709.     #[OA\Response(
  1710.         response200,
  1711.         description'',
  1712.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1713.     )]
  1714.     public function listByAge(Request $requestCity $citystring $ageTypeint $minAge nullint $maxAge null): Response
  1715.     {
  1716.         $specs $this->profileListSpecificationService->listByAge($ageType$minAge$maxAge);
  1717.         $response = new Response();
  1718.         $apiEndpoint in_array($ageType, ['young''old']) ? '/city/{city}/age/'.$ageType null;
  1719.         $result $this->paginatedListing($city$apiEndpoint, ['city' => $city->getId()], $specs->spec(), nullnull$response);
  1720.         if ($this->isApiRequest($request)) {
  1721.             return $this->json($result);
  1722.         }
  1723.         return $this->render('ProfileList/list.html.twig', [
  1724.             'profiles' => $result,
  1725.             'source' => $this->source,
  1726.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1727.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1728.                 'city' => $city->getUriIdentity(),
  1729.                 'ageType' => $ageType,
  1730.                 'minAge' => $minAge,
  1731.                 'maxAge' => $maxAge,
  1732.                 'page' => $this->getCurrentPageNumber()
  1733.             ]),
  1734.             'recommendationSpec' => $specs->recommendationSpec(),
  1735.         ], response$response);
  1736.     }
  1737.     #[ParamConverter("city"converter"city_converter")]
  1738.     #[Route("/api/profiles/listing/city/{city}/height/{heightType}"name"api.profile_listing.by_height"methods"GET"format"json")]
  1739.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1740.     #[OA\Tag(name"ProfileListing")]
  1741.     #[OA\Response(
  1742.         response200,
  1743.         description'',
  1744.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1745.     )]
  1746.     public function listByHeight(Request $requestCity $citystring $heightType): Response
  1747.     {
  1748.         $specs $this->profileListSpecificationService->listByHeight($heightType);
  1749.         $response = new Response();
  1750.         $result $this->paginatedListing($city'/city/{city}/height/'.$heightType, ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  1751.         if ($this->isApiRequest($request)) {
  1752.             return $this->json($result);
  1753.         }
  1754.         return $this->render('ProfileList/list.html.twig', [
  1755.             'profiles' => $result,
  1756.             'source' => $this->source,
  1757.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1758.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1759.                 'city' => $city->getUriIdentity(),
  1760.                 'heightType' => $heightType,
  1761.                 'page' => $this->getCurrentPageNumber()
  1762.             ]),
  1763.             'recommendationSpec' => $specs->recommendationSpec(),
  1764.         ], response$response);
  1765.     }
  1766.     #[ParamConverter("city"converter"city_converter")]
  1767.     #[Route("/api/profiles/listing/city/{city}/breasttype/{breastType}"name"api.profile_listing.by_breast_type"methods"GET"format"json")]
  1768.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1769.     #[OA\Tag(name"ProfileListing")]
  1770.     #[OA\Response(
  1771.         response200,
  1772.         description'',
  1773.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1774.     )]
  1775.     public function listByBreastType(Request $requestCity $citystring $breastType): Response
  1776.     {
  1777.         if (null === $type BreastTypes::getValueByUriIdentity($breastType)) {
  1778.             throw $this->createNotFoundException();
  1779.         }
  1780.         $specs $this->profileListSpecificationService->listByBreastType($breastType);
  1781.         $response = new Response();
  1782.         $alternativeSpec $this->getORSpecForItemsArray(BreastTypes::getList(), function($item): ProfileWithBreastType {
  1783.             return new ProfileWithBreastType($item);
  1784.         });
  1785.         $result $this->paginatedListing($city'/city/{city}/breasttype/'.$type, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1786.         if ($this->isApiRequest($request)) {
  1787.             return $this->json($result);
  1788.         }
  1789.         return $this->render('ProfileList/list.html.twig', [
  1790.             'profiles' => $result,
  1791.             'source' => $this->source,
  1792.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1793.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1794.                 'city' => $city->getUriIdentity(),
  1795.                 'breastType' => $breastType,
  1796.                 'page' => $this->getCurrentPageNumber()
  1797.             ]),
  1798.             'recommendationSpec' => $specs->recommendationSpec(),
  1799.         ], response$response);
  1800.     }
  1801.     #[ParamConverter("city"converter"city_converter")]
  1802.     #[Route("/api/profiles/listing/city/{city}/haircolor/{hairColor}"name"api.profile_listing.by_haircolor"methods"GET"format"json")]
  1803.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1804.     #[OA\Tag(name"ProfileListing")]
  1805.     #[OA\Response(
  1806.         response200,
  1807.         description'',
  1808.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1809.     )]
  1810.     public function listByHairColor(Request $requestCity $citystring $hairColor): Response
  1811.     {
  1812.         if (null === $color HairColors::getValueByUriIdentity($hairColor)) {
  1813.             throw $this->createNotFoundException();
  1814.         }
  1815.         $specs $this->profileListSpecificationService->listByHairColor($hairColor);
  1816.         $response = new Response();
  1817.         $alternativeSpec $this->getORSpecForItemsArray(HairColors::getList(), function($item): ProfileWithHairColor {
  1818.             return new ProfileWithHairColor($item);
  1819.         });
  1820.         $result $this->paginatedListing($city'/city/{city}/haircolor/'.$color, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1821.         if ($this->isApiRequest($request)) {
  1822.             return $this->json($result);
  1823.         }
  1824.         return $this->render('ProfileList/list.html.twig', [
  1825.             'profiles' => $result,
  1826.             'source' => $this->source,
  1827.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1828.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1829.                 'city' => $city->getUriIdentity(),
  1830.                 'hairColor' => $hairColor,
  1831.                 'page' => $this->getCurrentPageNumber()
  1832.             ]),
  1833.             'recommendationSpec' => $specs->recommendationSpec(),
  1834.         ], response$response);
  1835.     }
  1836.     #[ParamConverter("city"converter"city_converter")]
  1837.     #[Route("/api/profiles/listing/city/{city}/bodytype/{bodyType}"name"api.profile_listing.by_bodytype"methods"GET"format"json")]
  1838.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1839.     #[OA\Tag(name"ProfileListing")]
  1840.     #[OA\Response(
  1841.         response200,
  1842.         description'',
  1843.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1844.     )]
  1845.     public function listByBodyType(Request $requestCity $citystring $bodyType): Response
  1846.     {
  1847.         if (null === $type BodyTypes::getValueByUriIdentity($bodyType)) {
  1848.             throw $this->createNotFoundException();
  1849.         }
  1850.         $specs $this->profileListSpecificationService->listByBodyType($bodyType);
  1851.         $response = new Response();
  1852.         $alternativeSpec $this->getORSpecForItemsArray(BodyTypes::getList(), function($item): ProfileWithBodyType {
  1853.             return new ProfileWithBodyType($item);
  1854.         });
  1855.         $result $this->paginatedListing($city'/city/{city}/bodytype/'.$type, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1856.         if ($this->isApiRequest($request)) {
  1857.             return $this->json($result);
  1858.         }
  1859.         return $this->render('ProfileList/list.html.twig', [
  1860.             'profiles' => $result,
  1861.             'source' => $this->source,
  1862.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1863.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1864.                 'city' => $city->getUriIdentity(),
  1865.                 'bodyType' => $bodyType,
  1866.                 'page' => $this->getCurrentPageNumber()
  1867.             ]),
  1868.             'recommendationSpec' => $specs->recommendationSpec(),
  1869.         ], response$response);
  1870.     }
  1871.     #[ParamConverter("city"converter"city_converter")]
  1872.     #[Route("/api/profiles/listing/city/{city}/place/{placeType}"name"api.profile_listing.by_place"methods"GET"format"json")]
  1873.     #[Route("/api/profiles/listing/city/{city}/place/{placeType}/{takeOutLocation}"name"api.profile_listing.by_place.take_out_location"methods"GET"format"json")]
  1874.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1875.     #[OA\Tag(name"ProfileListing")]
  1876.     #[OA\Response(
  1877.         response200,
  1878.         description'',
  1879.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1880.     )]
  1881.     public function listByPlace(Request $requestCity $citystring $placeTypestring $takeOutLocation null): Response
  1882.     {
  1883.         if ('take-out' === $placeType && null !== $takeOutLocation && null === TakeOutLocations::getValueByUriIdentity($takeOutLocation)) {
  1884.             throw $this->createNotFoundException();
  1885.         }
  1886.         $specs $this->profileListSpecificationService->listByPlace($placeType$takeOutLocation);
  1887.         if (null === $specs) {
  1888.             throw $this->createNotFoundException();
  1889.         }
  1890.         $response = new Response();
  1891.         $alternativeSpec $this->getORSpecForItemsArray(TakeOutLocations::getList(), function($item): ProfileIsProvidingTakeOut {
  1892.             return new ProfileIsProvidingTakeOut($item);
  1893.         });
  1894.         if ($placeType === 'take-out') {
  1895.             $alternativeSpec->orX(new ProfileHasApartments());
  1896.         }
  1897.         $apiEndpoint '/city/{city}/place/'.$placeType;
  1898.         if (null !== $takeOutLocation) {
  1899.             $apiEndpoint .= '/'.$takeOutLocation;
  1900.         }
  1901.         $result $this->paginatedListing($city$apiEndpoint, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1902.         if ($this->isApiRequest($request)) {
  1903.             return $this->json($result);
  1904.         }
  1905.         return $this->render('ProfileList/list.html.twig', [
  1906.             'profiles' => $result,
  1907.             'source' => $this->source,
  1908.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1909.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1910.                 'city' => $city->getUriIdentity(),
  1911.                 'placeType' => $placeType,
  1912.                 'takeOutLocation' => TakeOutLocations::getUriIdentity(TakeOutLocations::getValueByUriIdentity($takeOutLocation)),
  1913.                 'page' => $this->getCurrentPageNumber()
  1914.             ]),
  1915.             'recommendationSpec' => $specs->recommendationSpec(),
  1916.         ], response$response);
  1917.     }
  1918.     #[ParamConverter("city"converter"city_converter")]
  1919.     #[Route("/api/profiles/listing/city/{city}/privatehaircut/{privateHaircut}"name"api.profile_listing.by_privatehaircut"methods"GET"format"json")]
  1920.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1921.     #[OA\Tag(name"ProfileListing")]
  1922.     #[OA\Response(
  1923.         response200,
  1924.         description'',
  1925.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1926.     )]
  1927.     public function listByPrivateHaircut(Request $requestCity $citystring $privateHaircut): Response
  1928.     {
  1929.         if(null === $type PrivateHaircuts::getValueByUriIdentity($privateHaircut))
  1930.             throw $this->createNotFoundException();
  1931.         $specs $this->profileListSpecificationService->listByPrivateHaircut($privateHaircut);
  1932.         $response = new Response();
  1933.         $apiEndpoint '/city/{city}/privatehaircut/'.$type;
  1934.         $alternativeSpec $this->getORSpecForItemsArray(PrivateHaircuts::getList(), function($item): ProfileWithPrivateHaircut {
  1935.             return new ProfileWithPrivateHaircut($item);
  1936.         });
  1937.         $result $this->paginatedListing($city$apiEndpoint, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1938.         if ($this->isApiRequest($request)) {
  1939.             return $this->json($result);
  1940.         }
  1941.         return $this->render('ProfileList/list.html.twig', [
  1942.             'profiles' => $result,
  1943.             'source' => $this->source,
  1944.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1945.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1946.                 'city' => $city->getUriIdentity(),
  1947.                 'privateHaircut' => $privateHaircut,
  1948.                 'page' => $this->getCurrentPageNumber()
  1949.             ]),
  1950.             'recommendationSpec' => $specs->recommendationSpec(),
  1951.         ], response$response);
  1952.     }
  1953.     #[ParamConverter("city"converter"city_converter")]
  1954.     #[Route("/api/profiles/listing/city/{city}/nationality/{nationality}"name"api.profile_listing.by_nationality"methods"GET"format"json")]
  1955.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1956.     #[OA\Tag(name"ProfileListing")]
  1957.     #[OA\Response(
  1958.         response200,
  1959.         description'',
  1960.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1961.     )]
  1962.     public function listByNationality(Request $requestCity $citystring $nationality): Response
  1963.     {
  1964.         if (null === $type Nationalities::getValueByUriIdentity($nationality))
  1965.             throw $this->createNotFoundException();
  1966.         $specs $this->profileListSpecificationService->listByNationality($nationality);
  1967.         $response = new Response();
  1968.         $alternativeSpec $this->getORSpecForItemsArray(Nationalities::getList(), function($item): ProfileWithNationality {
  1969.             return new ProfileWithNationality($item);
  1970.         });
  1971.         $apiEndpoint '/city/{city}/nationality/'.$type;
  1972.         $result $this->paginatedListing($city$apiEndpoint, ['city' => $city->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_BY_PARAMS$response);
  1973.         if ($this->isApiRequest($request)) {
  1974.             return $this->json($result);
  1975.         }
  1976.         return $this->render('ProfileList/list.html.twig', [
  1977.             'profiles' => $result,
  1978.             'source' => $this->source,
  1979.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  1980.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  1981.                 'city' => $city->getUriIdentity(),
  1982.                 'nationality' => $nationality,
  1983.                 'page' => $this->getCurrentPageNumber()
  1984.             ]),
  1985.             'recommendationSpec' => $specs->recommendationSpec(),
  1986.         ], response$response);
  1987.     }
  1988.     #[ParamConverter("city"converter"city_converter")]
  1989.     #[ParamConverter("service"options: ['mapping' => ['service' => 'uriIdentity']])]
  1990.     #[Route("/api/profiles/listing/city/{city}/service/{service}"name"api.profile_listing.by_service"methods"GET"format"json")]
  1991.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  1992.     #[OA\Tag(name"ProfileListing")]
  1993.     #[OA\Response(
  1994.         response200,
  1995.         description'',
  1996.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  1997.     )]
  1998.     public function listByProvidedService(Request $requestCity $cityService $service): Response
  1999.     {
  2000.         $specs $this->profileListSpecificationService->listByProvidedService($service$city);
  2001.         $response = new Response();
  2002.         $sameGroupServices $this->serviceRepository->findBy(['group' => $service->getGroup()]);
  2003.         $alternativeSpec $this->getORSpecForItemsArray([$sameGroupServices], function($item): ProfileIsProvidingOneOfServices {
  2004.             return new ProfileIsProvidingOneOfServices($item);
  2005.         });
  2006.         $result $this->paginatedListing($city'/city/{city}/service/{service}', ['city' => $city->getId(), 'service' => $service->getId()], $specs->spec(), $alternativeSpecself::RESULT_SOURCE_SERVICE$response);
  2007.         if ($this->isApiRequest($request)) {
  2008.             return $this->json($result);
  2009.         }
  2010.         return $this->render('ProfileList/list.html.twig', [
  2011.             'profiles' => $result,
  2012.             'source' => $this->source,
  2013.             'source_default' => self::RESULT_SOURCE_SERVICE,
  2014.             'service' => $service,
  2015.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  2016.                 'city' => $city->getUriIdentity(),
  2017.                 'service' => $service->getUriIdentity(),
  2018.                 'page' => $this->getCurrentPageNumber()
  2019.             ]),
  2020.             'recommendationSpec' => $specs->recommendationSpec(),
  2021.         ], response$response);
  2022.     }
  2023.     /**
  2024.      * @Feature("has_archive_page")
  2025.      */
  2026.     #[ParamConverter("city"converter"city_converter")]
  2027.     #[Route("/api/profiles/listing/city/{city}/archive"name"api.profile_listing.archive"methods"GET"format"json")]
  2028.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2029.     #[OA\Tag(name"ProfileListing")]
  2030.     #[OA\Response(
  2031.         response200,
  2032.         description'',
  2033.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2034.     )]
  2035.     public function listArchived(Request $requestCity $city): Response
  2036.     {
  2037.         $result $this->profileList->list($citynullnullnullfalsenullProfileList::ORDER_BY_UPDATED);
  2038.         if ($this->isApiRequest($request)) {
  2039.             return $this->json($result);
  2040.         }
  2041.         return $this->render('ProfileList/list.html.twig', [
  2042.             'profiles' => $result,
  2043.             'recommendationSpec' => new \App\Specification\ElasticSearch\ProfileIsNotArchived(), //ProfileIsArchived, согласно https://redminez.net/issues/28305 в реках выводятся неарзивные
  2044.         ]);
  2045.     }
  2046.     #[ParamConverter("city"converter"city_converter")]
  2047.     #[Route("/api/profiles/listing/city/{city}/recent"name"api.profile_listing.recent"methods"GET"format"json")]
  2048.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2049.     #[OA\Tag(name"ProfileListing")]
  2050.     #[OA\Response(
  2051.         response200,
  2052.         description'',
  2053.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2054.     )]
  2055.     public function listNew(Request $requestCity $cityint $weeks 2): Response
  2056.     {
  2057.         $specs $this->profileListSpecificationService->listNew($weeks);
  2058.         $response = new Response();
  2059.         $result $this->paginatedListing($city'/city/{city}/recent', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  2060.         if ($this->isApiRequest($request)) {
  2061.             return $this->json($result);
  2062.         }
  2063.         return $this->render('ProfileList/list.html.twig', [
  2064.             'profiles' => $result,
  2065.             'recommendationSpec' => $specs->recommendationSpec(),
  2066.         ], response$response);
  2067.     }
  2068.     #[ParamConverter("city"converter"city_converter")]
  2069.     #[Route("/api/profiles/listing/city/{city}/noretouch"name"api.profile_listing.noretouch"methods"GET"format"json")]
  2070.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2071.     #[OA\Tag(name"ProfileListing")]
  2072.     #[OA\Response(
  2073.         response200,
  2074.         description'',
  2075.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2076.     )]
  2077.     public function listByNoRetouch(Request $requestCity $city): Response
  2078.     {
  2079.         $specs $this->profileListSpecificationService->listByNoRetouch();
  2080.         $response = new Response();
  2081.         $result $this->paginatedListing($city'/city/{city}/noretouch', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2082.         if ($this->isApiRequest($request)) {
  2083.             return $this->json($result);
  2084.         }
  2085.         return $this->render('ProfileList/list.html.twig', [
  2086.             'profiles' => $result,
  2087.             'profiles_count' => $result->count(),
  2088.             'source' => $this->source,
  2089.             'recommendationSpec' => $specs->recommendationSpec(),
  2090.         ], response$response);
  2091.     }
  2092.     #[ParamConverter("city"converter"city_converter")]
  2093.     #[Route("/api/profiles/listing/city/{city}/nice"name"api.profile_listing.nice"methods"GET"format"json")]
  2094.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2095.     #[OA\Tag(name"ProfileListing")]
  2096.     #[OA\Response(
  2097.         response200,
  2098.         description'',
  2099.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2100.     )]
  2101.     public function listByNice(Request $requestCity $city): Response
  2102.     {
  2103.         $specs $this->profileListSpecificationService->listByNice();
  2104.         $response = new Response();
  2105.         $result $this->paginatedListing($city'/city/{city}/nice', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2106.         if ($this->isApiRequest($request)) {
  2107.             return $this->json($result);
  2108.         }
  2109.         return $this->render('ProfileList/list.html.twig', [
  2110.             'profiles' => $result,
  2111.             'source' => $this->source,
  2112.             'recommendationSpec' => $specs->recommendationSpec(),
  2113.         ], response$response);
  2114.     }
  2115.     #[ParamConverter("city"converter"city_converter")]
  2116.     #[Route("/api/profiles/listing/city/{city}/oncall"name"api.profile_listing.oncall"methods"GET"format"json")]
  2117.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2118.     #[OA\Tag(name"ProfileListing")]
  2119.     #[OA\Response(
  2120.         response200,
  2121.         description'',
  2122.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2123.     )]
  2124.     public function listByOnCall(Request $requestCity $city): Response
  2125.     {
  2126.         $specs $this->profileListSpecificationService->listByOnCall();
  2127.         $response = new Response();
  2128.         $result $this->paginatedListing($city'/city/{city}/oncall', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2129.         if ($this->isApiRequest($request)) {
  2130.             return $this->json($result);
  2131.         }
  2132.         return $this->render('ProfileList/list.html.twig', [
  2133.             'profiles' => $result,
  2134.             'source' => $this->source,
  2135.             'recommendationSpec' => $specs->recommendationSpec(),
  2136.         ], response$response);
  2137.     }
  2138.     #[ParamConverter("city"converter"city_converter")]
  2139.     #[Route("/api/profiles/listing/city/{city}/fornight"name"api.profile_listing.fornight"methods"GET"format"json")]
  2140.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2141.     #[OA\Tag(name"ProfileListing")]
  2142.     #[OA\Response(
  2143.         response200,
  2144.         description'',
  2145.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2146.     )]
  2147.     public function listForNight(Request $requestCity $city): Response
  2148.     {
  2149.         $specs $this->profileListSpecificationService->listForNight();
  2150.         $response = new Response();
  2151.         $result $this->paginatedListing($city'/city/{city}/fornight', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2152.         if ($this->isApiRequest($request)) {
  2153.             return $this->json($result);
  2154.         }
  2155.         return $this->render('ProfileList/list.html.twig', [
  2156.             'profiles' => $result,
  2157.             'source' => $this->source,
  2158.             'recommendationSpec' => $specs->recommendationSpec(),
  2159.         ], response$response);
  2160.     }
  2161.     private function getSpecForEliteGirls(City $city): Filter
  2162.     {
  2163.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  2164.             'RUB' => 5000,
  2165.             'UAH' => 1500,
  2166.             'USD' => 100,
  2167.             'EUR' => 130,
  2168.         ]);
  2169.         return new ProfileIsElite($minPrice);
  2170.     }
  2171.     private function getElasticSearchSpecForEliteGirls(City $city): ISpecification
  2172.     {
  2173.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  2174.             'RUB' => 5000,
  2175.             'UAH' => 1500,
  2176.             'USD' => 100,
  2177.             'EUR' => 130,
  2178.         ]);
  2179.         return new \App\Specification\ElasticSearch\ProfileIsElite($minPrice);
  2180.     }
  2181.     #[ParamConverter("city"converter"city_converter")]
  2182.     #[Route("/api/profiles/listing/city/{city}/elite"name"api.profile_listing.elite"methods"GET"format"json")]
  2183.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2184.     #[OA\Tag(name"ProfileListing")]
  2185.     #[OA\Response(
  2186.         response200,
  2187.         description'',
  2188.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2189.     )]
  2190.     public function listForEliteGirls(CountryCurrencyResolver $countryCurrencyResolverRequest $requestCity $city): Response
  2191.     {
  2192.         $specs $this->profileListSpecificationService->listForEliteGirls($city);
  2193.         $response = new Response();
  2194.         $result $this->paginatedListing($city'/city/{city}/elite', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  2195.         if ($this->isApiRequest($request)) {
  2196.             return $this->json($result);
  2197.         }
  2198.         return $this->render('ProfileList/list.html.twig', [
  2199.             'profiles' => $result,
  2200.             'source' => $this->source,
  2201.             'source_default' => self::RESULT_SOURCE_BY_PARAMS,
  2202.             'category_url' => $this->generateUrl($request->attributes->get('_route'), [
  2203.                 'city' => $city->getUriIdentity(),
  2204.                 'page' => $this->getCurrentPageNumber()
  2205.             ]),
  2206.             'recommendationSpec' => $specs->recommendationSpec(),
  2207.         ], response$response);
  2208.     }
  2209.     #[ParamConverter("city"converter"city_converter")]
  2210.     #[Route("/api/profiles/listing/city/{city}/realelite"name"api.profile_listing.real_elite"methods"GET"format"json")]
  2211.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2212.     #[OA\Tag(name"ProfileListing")]
  2213.     #[OA\Response(
  2214.         response200,
  2215.         description'',
  2216.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2217.     )]
  2218.     public function listForRealElite(Request $requestCountryCurrencyResolver $countryCurrencyResolverCity $city): Response
  2219.     {
  2220.         $specs $this->profileListSpecificationService->listForRealElite($city);
  2221.         $response = new Response();
  2222.         $result $this->paginatedListing($city'/city/{city}/realelite', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2223.         if ($this->isApiRequest($request)) {
  2224.             return $this->json($result);
  2225.         }
  2226.         return $this->render('ProfileList/list.html.twig', [
  2227.             'profiles' => $result,
  2228.             'source' => $this->source,
  2229.             'recommendationSpec' => $specs->recommendationSpec(),
  2230.         ], response$response);
  2231.     }
  2232.     #[ParamConverter("city"converter"city_converter")]
  2233.     #[Route("/api/profiles/listing/city/{city}/vip"name"api.profile_listing.vip"methods"GET"format"json")]
  2234.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2235.     #[OA\Tag(name"ProfileListing")]
  2236.     #[OA\Response(
  2237.         response200,
  2238.         description'',
  2239.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2240.     )]
  2241.     public function listForVipPros(Request $requestCountryCurrencyResolver $countryCurrencyResolverCity $city): Response
  2242.     {
  2243.         $specs $this->profileListSpecificationService->listForVipPros($city);
  2244.         $response = new Response();
  2245.         $result $this->paginatedListing($city'/city/{city}/vip', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2246.         if ($this->isApiRequest($request)) {
  2247.             return $this->json($result);
  2248.         }
  2249.         return $this->render('ProfileList/list.html.twig', [
  2250.             'profiles' => $result,
  2251.             'source' => $this->source,
  2252.             'recommendationSpec' => $specs->recommendationSpec(),
  2253.         ], response$response);
  2254.     }
  2255.     #[ParamConverter("city"converter"city_converter")]
  2256.     #[Route("/api/profiles/listing/city/{city}/vipindi"name"api.profile_listing.vipindi"methods"GET"format"json")]
  2257.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2258.     #[OA\Tag(name"ProfileListing")]
  2259.     #[OA\Response(
  2260.         response200,
  2261.         description'',
  2262.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2263.     )]
  2264.     public function listForVipIndividual(Request $requestCountryCurrencyResolver $countryCurrencyResolverCity $city): Response
  2265.     {
  2266.         $specs $this->profileListSpecificationService->listForVipIndividual($city);
  2267.         $response = new Response();
  2268.         $result $this->paginatedListing($city'/city/{city}/vipindi', ['city' => $city->getId()], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2269.         if ($this->isApiRequest($request)) {
  2270.             return $this->json($result);
  2271.         }
  2272.         return $this->render('ProfileList/list.html.twig', [
  2273.             'profiles' => $result,
  2274.             'source' => $this->source,
  2275.             'recommendationSpec' => $specs->recommendationSpec(),
  2276.         ], response$response);
  2277.     }
  2278.     #[ParamConverter("city"converter"city_converter")]
  2279.     #[Route("/api/profiles/listing/city/{city}/vipgirls"name"api.profile_listing.vipgirls"methods"GET"format"json")]
  2280.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2281.     #[OA\Tag(name"ProfileListing")]
  2282.     #[OA\Response(
  2283.         response200,
  2284.         description'',
  2285.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2286.     )]
  2287.     public function listForVipGirlsCity(Request $requestCity $city): Response
  2288.     {
  2289.         $specs $this->profileListSpecificationService->listForVipGirlsCity($city);
  2290.         $response = new Response();
  2291.         $result $this->paginatedListing($citynull, [], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2292.         if ($this->isApiRequest($request)) {
  2293.             return $this->json($result);
  2294.         }
  2295.         return $this->render('ProfileList/list.html.twig', [
  2296.             'profiles' => $result,
  2297.             'source' => $this->source,
  2298.             'recommendationSpec' => $specs->recommendationSpec(),
  2299.         ], response$response);
  2300.     }
  2301.     #[ParamConverter("city"converter"city_converter")]
  2302.     #[Route("/api/profiles/listing/city/{city}/girlfriends"name"api.profile_listing.girlfriends"methods"GET"format"json")]
  2303.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2304.     #[OA\Tag(name"ProfileListing")]
  2305.     #[OA\Response(
  2306.         response200,
  2307.         description'',
  2308.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2309.     )]
  2310.     public function listOfGirlfriends(Request $requestCity $city): Response
  2311.     {
  2312.         $specs $this->profileListSpecificationService->listOfGirlfriends();
  2313.         $response = new Response();
  2314.         $result $this->paginatedListing($citynull, [], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2315.         if ($this->isApiRequest($request)) {
  2316.             return $this->json($result);
  2317.         }
  2318.         return $this->render('ProfileList/list.html.twig', [
  2319.             'profiles' => $result,
  2320.             'source' => $this->source,
  2321.             'recommendationSpec' => $specs->recommendationSpec(),
  2322.         ]);
  2323.     }
  2324.     #[ParamConverter("city"converter"city_converter")]
  2325.     #[Route("/api/profiles/listing/city/{city}/most_expensive"name"api.profile_listing.most_expensive"methods"GET"format"json")]
  2326.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2327.     #[OA\Tag(name"ProfileListing")]
  2328.     #[OA\Response(
  2329.         response200,
  2330.         description'',
  2331.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2332.     )]
  2333.     public function listOfMostExpensive(Request $requestCity $city): Response
  2334.     {
  2335.         $specs $this->profileListSpecificationService->listOfMostExpensive($city);
  2336.         $response = new Response();
  2337.         $result $this->paginatedListing($citynull, [], $specs->spec(), nullself::RESULT_SOURCE_CITY$response);
  2338.         if ($this->isApiRequest($request)) {
  2339.             return $this->json($result);
  2340.         }
  2341.         return $this->render('ProfileList/list.html.twig', [
  2342.             'profiles' => $result,
  2343.             'source' => $this->source,
  2344.             'recommendationSpec' => $specs->recommendationSpec(),
  2345.         ]);
  2346.     }
  2347.     #[ParamConverter("city"converter"city_converter")]
  2348.     #[Route("/api/profiles/listing/city/{city}/bdsm"name"api.profile_listing.bdsm"methods"GET"format"json")]
  2349.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2350.     #[OA\Tag(name"ProfileListing")]
  2351.     #[OA\Response(
  2352.         response200,
  2353.         description'',
  2354.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2355.     )]
  2356.     public function listBdsm(Request $requestCity $cityServiceRepository $serviceRepositoryParameterBagInterface $parameterBag): Response
  2357.     {
  2358.         $specs $this->profileListSpecificationService->listBdsm();
  2359.         $response = new Response();
  2360.         $result $this->paginatedListing($city'/city/{city}/bdsm', ['city' => $city->getId()], $specs->spec(), nullnull$response);
  2361.         if ($this->isApiRequest($request)) {
  2362.             return $this->json($result);
  2363.         }
  2364.         return $this->render('ProfileList/list.html.twig', [
  2365.             'profiles' => $result,
  2366.             'recommendationSpec' => $specs->recommendationSpec(),
  2367.         ], response$response);
  2368.     }
  2369.     #[ParamConverter("city"converter"city_converter")]
  2370.     #[Route("/api/profiles/listing/city/{city}/gender/{gender}"name"api.profile_listing.by_gender"methods"GET"format"json")]
  2371.     #[OA\Parameter(name"page"in"query"schema: new OA\Schema(type"integer", default: 1minimum1))]
  2372.     #[OA\Tag(name"ProfileListing")]
  2373.     #[OA\Response(
  2374.         response200,
  2375.         description'',
  2376.         content: new OA\JsonContent(ref"#/components/schemas/ProfileListingPage")
  2377.     )]
  2378.     public function listByGender(Request $requestCity $citystring $genderDefaultCityProvider $defaultCityProvider): Response
  2379.     {
  2380.         if ($city->getId() != $defaultCityProvider->getDefaultCity()->getId()) {
  2381.             throw $this->createNotFoundException();
  2382.         }
  2383.         if (null === Genders::getValueByUriIdentity($gender))
  2384.             throw $this->createNotFoundException();
  2385.         $specs $this->profileListSpecificationService->listByGender($gender);
  2386.         $response = new Response();
  2387.         $result $this->paginatedListing($citynull, [], $specs->spec(), nullnull$response);
  2388.         if ($this->isApiRequest($request)) {
  2389.             return $this->json($result);
  2390.         }
  2391.         return $this->render('ProfileList/list.html.twig', [
  2392.             'profiles' => $result,
  2393.             'recommendationSpec' => $specs->recommendationSpec(),
  2394.         ]);
  2395.     }
  2396.     /**
  2397.      * Сейчас не используется, решили доставать их всех соседних подкатегорий разом.
  2398.      * Пока оставил, вдруг передумают.
  2399.      * @deprecated
  2400.      */
  2401.     public function listByNextSimilarCategories(callable $listMethod$requestCategory, array $similarItems): ORMQueryResult
  2402.     {
  2403.         $similarItems array_filter($similarItems, function ($item) use ($requestCategory): bool {
  2404.             return $item != $requestCategory;
  2405.         });
  2406.         //shuffle($similarItems);
  2407.         $item null;
  2408.         $result null;
  2409.         do {
  2410.             $item $item == null current($similarItems) : next($similarItems);
  2411.             if (false === $item)
  2412.                 return $result;
  2413.             $result $listMethod($item);
  2414.         } while ($result->count() == 0);
  2415.         return $result;
  2416.     }
  2417.     private function shouldShowHomepageCityListingsBlock(City $cityint $pagebool $subRequest): bool
  2418.     {
  2419.         if ($page !== 1) {
  2420.             return false;
  2421.         }
  2422.         if ($subRequest) {
  2423.             return true;
  2424.         }
  2425.         return !$city->equals($this->parameterBag->get('default_city'));
  2426.     }
  2427.     protected function getCurrentPageNumber(): int
  2428.     {
  2429.         $page = (int) $this->requestStack->getCurrentRequest()?->get($this->pageParameter1);
  2430.         if ($page 1) {
  2431.             $page 1;
  2432.         }
  2433.         return $page;
  2434.     }
  2435.     protected function render(string $view, array $parameters = [], Response $response null): Response
  2436.     {
  2437.         $parameters $this->fillListingWithRecommendations($parameters);
  2438.         $this->listingService->setCurrentListingPage($parameters['profiles']);
  2439.         $requestAttrs $this->requestStack->getCurrentRequest();
  2440.         if (isset($parameters['profiles']) && is_object($parameters['profiles']) && method_exists($parameters['profiles'], 'totalCount')) {
  2441.             $requestAttrs->attributes->set('profiles_count'$parameters['profiles']->totalCount());
  2442.         }
  2443.         $listing $requestAttrs->get('_controller');
  2444.         $listing is_array($listing) ? $listing[count($listing) - 1] : $listing;
  2445.         $listing preg_replace('/[^:]+::/'''$listing);
  2446.         $listingParameters $requestAttrs->get('_route_params');
  2447.         $listingParameters is_array($listingParameters) ? $listingParameters : [];
  2448.         $mainRequestHasPageParam = isset(($this->requestStack->getMainRequest()->get('_route_params') ?? [])['page']);
  2449.         if ($this->requestStack->getCurrentRequest()->isXmlHttpRequest()) {
  2450.             $view = (
  2451.                 str_starts_with($listing'list')
  2452.                 && 'ProfileList/list.html.twig' === $view
  2453.                 && $mainRequestHasPageParam //isset($listingParameters['page'])
  2454.             )
  2455.                 ? 'ProfileList/list.profiles.html.twig'
  2456.                 $view;
  2457.             return $this->prepareForXhr(parent::render($view$parameters$response));
  2458.             //return $this->getJSONResponse($parameters);
  2459.         } else {
  2460.             $parameters $this->prepareSsrRecommendedProfiles($parameters);
  2461.             $parameters array_merge($parameters, [
  2462.                 'listing' => $listing,
  2463.                 'listing_parameters' => $listingParameters,
  2464.             ]);
  2465.             return parent::render($view$parameters$response);
  2466.         }
  2467.     }
  2468.     private function fillListingWithRecommendations(array $parameters): array
  2469.     {
  2470.         $parameters['recommendations_fill_applied'] = $parameters['recommendations_fill_applied'] ?? false;
  2471.         if (!($parameters['profiles'] ?? null) instanceof Page) {
  2472.             return $parameters;
  2473.         }
  2474.         $city $this->requestStack->getCurrentRequest()?->attributes->get('city');
  2475.         if (!$city instanceof City) {
  2476.             return $parameters;
  2477.         }
  2478.         $filled $this->profileListingRecommendationsFiller->fill(
  2479.             $city,
  2480.             $parameters['profiles'],
  2481.             $this->resolveRecommendationGenders(),
  2482.         );
  2483.         $parameters['profiles'] = $filled['profiles'];
  2484.         $parameters['recommendations_fill_applied'] = $filled['applied'];
  2485.         $parameters['recommendations_fill_original_count'] = $filled['original_count'];
  2486.         $parameters['excludeRecommendationProfileIds'] = array_values(array_unique(array_merge(
  2487.             $parameters['excludeRecommendationProfileIds'] ?? [],
  2488.             $filled['visible_profile_ids'] ?? [],
  2489.         )));
  2490.         return $parameters;
  2491.     }
  2492.     private function prepareSsrRecommendedProfiles(array $parameters): array
  2493.     {
  2494.         if (!empty($parameters['recommendations_fill_applied'])) {
  2495.             return $parameters;
  2496.         }
  2497.         if (isset($parameters['ssr_recommended_profiles']) || !($parameters['profiles'] ?? null) instanceof Page) {
  2498.             return $parameters;
  2499.         }
  2500.         $city $this->requestStack->getCurrentRequest()?->attributes->get('city');
  2501.         if (!$city instanceof City) {
  2502.             return $parameters;
  2503.         }
  2504.         $parameters['ssr_recommended_profiles'] = $this->profileListingRecommendationsFiller->popularProfilesForBlock(
  2505.             $city,
  2506.             $parameters['profiles'],
  2507.             $this->resolveRecommendationGenders(),
  2508.             5,
  2509.             $parameters['excludeRecommendationProfileIds'] ?? [],
  2510.         );
  2511.         return $parameters;
  2512.     }
  2513.     private function resolveRecommendationGenders(): array
  2514.     {
  2515.         $gender $this->requestStack->getCurrentRequest()?->attributes->get('gender');
  2516.         if (is_string($gender) && null !== Genders::getValueByUriIdentity($gender)) {
  2517.             return [Genders::getValueByUriIdentity($gender)];
  2518.         }
  2519.         return [Genders::FEMALE];
  2520.     }
  2521.     private function listActiveWithinCityOrderedByStatusWithSpecAvoidingTopPlacementLimited(
  2522.         City $city,
  2523.         ?Filter $spec,
  2524.         array $additionalSpecs null,
  2525.         array $genders = [Genders::FEMALE],
  2526.         int $limit 0,
  2527.     ): array|Page {
  2528.         return $this->profileList->listActiveWithinCityOrderedByStatusWithSpecLimited($city$spec$additionalSpecs$genderstrue$limit);
  2529.     }
  2530.     private function listRandomSinglePage(
  2531.         City $city,
  2532.         ?string $country,
  2533.         ?Filter $spec,
  2534.         ?array $additionalSpecs,
  2535.         bool $active,
  2536.         ?bool $masseur false,
  2537.         array $genders = [Genders::FEMALE]
  2538.     ): Page {
  2539.         return $this->profileList->listRandom($city$country$spec$additionalSpecs$active$masseur$genderstrue);
  2540.     }
  2541.     private function shuffleProfilesOnPage(Page $result): Page
  2542.     {
  2543.         $profiles iterator_to_array($result->getIterator());
  2544.         if(count($profiles) > 1) {
  2545.             shuffle($profiles);
  2546.         }
  2547.         return new FakeORMQueryPage(
  2548.             $result->getCurrentOffset(),
  2549.             $result->getCurrentPage(),
  2550.             $result->getCurrentLimit(),
  2551.             $result->totalCount(),
  2552.             $profiles
  2553.         );
  2554.     }
  2555.     /**
  2556.      * Достает из списка анкет их id с учетом совместимости разных форматов данных
  2557.      */
  2558.     private function extractProfileIds(array $profiles): array
  2559.     {
  2560.         $ids array_map(static function ($item) {
  2561.             /**
  2562.              * - array - данные из микросервиса ротации через API
  2563.              * - Profile::getId() - полноценная сущность анкеты
  2564.              * - ProfileListingReadModel::$id - read-model анкеты
  2565.              */
  2566.             return is_array($item) ? $item['id'] : ($item?->id ?? $item?->getId());
  2567.         }, $profiles);
  2568.         return array_filter($ids); // remove null values
  2569.     }
  2570. //    protected function getJSONResponse(array $parameters)
  2571. //    {
  2572. //        $request = $this->request;
  2573. //        $data = json_decode($request->getContent(), true);
  2574. //
  2575. //        $imageSize = !empty($data['imageSize']) ? $data['imageSize'] : "357x500";
  2576. //
  2577. //        /** @var FakeORMQueryPage $queryPage */
  2578. //        $queryPage = $parameters['profiles'];
  2579. //
  2580. //        $profiles = array_map(function(ProfileListingReadModel $profile) use ($imageSize) {
  2581. //            $profile->stations = array_values($profile->stations);
  2582. //            $profile->avatar['path'] = $this->responsiveAssetsService->getResponsiveImageUrl($profile->avatar['path'], 'profile_media', $imageSize, 'jpg');
  2583. //            $profile->uri = $this->generateUrl('profile_preview.page', ['city' => $profile->city->uriIdentity, 'profile' => $profile->uriIdentity]);
  2584. //            return $profile;
  2585. //        }, $queryPage->getArray());
  2586. //
  2587. //        return new JsonResponse([
  2588. //            'profiles' => $profiles,
  2589. //            'currentPage' => $queryPage->getCurrentPage(),
  2590. //        ], Response::HTTP_OK);
  2591. //    }
  2592. }