src/Controller/ProfileListController.php line 212

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