src/Service/ProfileListSpecificationService.php line 366

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Dto\ProfileListSpecification;
  4. use App\Entity\Location\City;
  5. use App\Entity\Location\County;
  6. use App\Entity\Location\District;
  7. use App\Entity\Location\Station;
  8. use App\Entity\Profile\BodyTypes;
  9. use App\Entity\Profile\BreastTypes;
  10. use App\Entity\Profile\Genders;
  11. use App\Entity\Profile\HairColors;
  12. use App\Entity\Profile\Nationalities;
  13. use App\Entity\Profile\PrivateHaircuts;
  14. use App\Entity\Service;
  15. use App\Entity\ServiceGroups;
  16. use App\Entity\TakeOutLocations;
  17. use App\Repository\DistrictRepository;
  18. use App\Repository\ProfileRepository;
  19. use Doctrine\ORM\EntityManagerInterface;
  20. use App\Repository\ServiceRepository;
  21. use App\Specification\ElasticSearch\ISpecification;
  22. use App\Specification\Profile\BdsmProfile;
  23. use App\Specification\Profile\ProfileAdBoardPlacement;
  24. use App\Specification\Profile\ProfileHasApartments;
  25. use App\Specification\Profile\ProfileHasComments;
  26. use App\Specification\Profile\ProfileHasHighPrice;
  27. use App\Specification\Profile\ProfileHasLowPrice;
  28. use App\Specification\Profile\ProfileHasOnCall;
  29. use App\Specification\Profile\ProfileHasOneOfGenders;
  30. use App\Specification\Profile\ProfileHasPriceGreaterThan;
  31. use App\Specification\Profile\ProfileHasSelfie;
  32. use App\Specification\Profile\ProfileHasVideo;
  33. use App\Specification\Profile\ProfileInMoskowDistricts;
  34. use App\Specification\Profile\ProfileIsActive;
  35. use App\Specification\Profile\ProfileIsApproved;
  36. use App\Specification\Profile\ProfileIsElite;
  37. use App\Specification\Profile\ProfileIsForHour;
  38. use App\Specification\Profile\ProfileIsForNight;
  39. use App\Specification\Profile\ProfileIsGirlfriend;
  40. use App\Specification\Profile\ProfileIsLocated;
  41. use App\Specification\Profile\ProfileIsMasseur;
  42. use App\Specification\Profile\ProfileIsMostExpensive;
  43. use App\Specification\Profile\ProfileIsNew;
  44. use App\Specification\Profile\ProfileIsNice;
  45. use App\Specification\Profile\ProfileIsNotExpensive;
  46. use App\Specification\Profile\ProfileIsNotHidden;
  47. use App\Specification\Profile\ProfileIsProvidingOneOfServices;
  48. use App\Specification\Profile\ProfileIsProvidingTakeOut;
  49. use App\Specification\Profile\ProfileIsRealElite;
  50. use App\Specification\Profile\ProfileIsUpdatedWithinAYear;
  51. use App\Specification\Profile\ProfileIsWithoutPrepayment;
  52. use App\Specification\Profile\ProfileHasWhatsapp;
  53. use App\Specification\Profile\ProfileHasTelegram;
  54. use App\Specification\Profile\ProfileIsEighteenYearsOld;
  55. use App\Specification\Profile\ProfileIsVip;
  56. use App\Specification\Profile\ProfileIsVipIndividual;
  57. use App\Specification\Profile\ProfileIsVipMoskow;
  58. use App\Specification\Profile\ProfileNoRetouch;
  59. use App\Specification\Profile\ProfileWithAge;
  60. use App\Specification\Profile\ProfileWithApartmentsOneHourPrice;
  61. use App\Specification\Profile\ProfileWithBodyType;
  62. use App\Specification\Profile\ProfileWithBreastType;
  63. use App\Specification\Profile\ProfileWithHairColor;
  64. use App\Specification\Profile\ProfileWithHeight;
  65. use App\Specification\Profile\ProfileWithNationality;
  66. use App\Specification\Profile\ProfileWithPrivateHaircut;
  67. use App\Specification\QueryModifier\LimitResult;
  68. use App\Specification\QueryModifier\ProfileAvatar;
  69. use App\Specification\QueryModifier\ProfileOrderedByNightPrice;
  70. use App\Specification\QueryModifier\ProfilePlacementHiding;
  71. use Happyr\DoctrineSpecification\Filter\Filter;
  72. use Happyr\DoctrineSpecification\Logic\AndX;
  73. use Happyr\DoctrineSpecification\Spec;
  74. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  75. class ProfileListSpecificationService
  76. {
  77.     public function __construct(
  78.         private CountryCurrencyResolver $countryCurrencyResolver,
  79.         private ServiceRepository $serviceRepository,
  80.         private ParameterBagInterface $parameterBag,
  81.         private ProfileRepository $profileRepository,
  82.         private EntityManagerInterface $entityManager,
  83.         private DistrictRepository $districtRepository,
  84.         private Features $features,
  85.     ) {}
  86.     public function listForMasseur(City $city): ProfileListSpecification
  87.     {
  88.         return new ProfileListSpecification(new ProfileIsMasseur(), \App\Specification\ElasticSearch\ProfileIsLocated::withinCity($city));
  89.     }
  90.     public function listByCity(): ProfileListSpecification
  91.     {
  92.         return new ProfileListSpecification(nullnull);
  93.     }
  94.     public function listByCounty(County $county): ProfileListSpecification
  95.     {
  96.         return new ProfileListSpecification(ProfileIsLocated::withinCounty($county), \App\Specification\ElasticSearch\ProfileIsLocated::withinCounty($county));
  97.     }
  98.     public function listByDistrict(District $district): ProfileListSpecification
  99.     {
  100.         return new ProfileListSpecification(ProfileIsLocated::withinDistrict($district), \App\Specification\ElasticSearch\ProfileIsLocated::withinDistrict($district));
  101.     }
  102.     public function listByStation(Station $station): ProfileListSpecification
  103.     {
  104.         return new ProfileListSpecification(ProfileIsLocated::nearStation($station), \App\Specification\ElasticSearch\ProfileIsLocated::nearStations([$station]));
  105.     }
  106.     public function listByStations(array $stations): ProfileListSpecification
  107.     {
  108.         //        $stationIds = explode(',', $stations);
  109.         //        $stations = $this->stationRepository->findBy(['uriIdentity' => $stationIds]);
  110.         return new ProfileListSpecification(new ProfileIsLocated(nullnullnull$stations), \App\Specification\ElasticSearch\ProfileIsLocated::nearStations($stations));
  111.     }
  112.     public function listApproved(): ProfileListSpecification
  113.     {
  114.         return new ProfileListSpecification(new ProfileIsApproved(), new \App\Specification\ElasticSearch\ProfileIsApproved());
  115.     }
  116.     public function listWithWhatsapp(): ProfileListSpecification
  117.     {
  118.         return new ProfileListSpecification(
  119.             new ProfileHasWhatsapp(),
  120.             new \App\Specification\ElasticSearch\ProfileHasWhatsapp()
  121.         );
  122.     }
  123.     public function listWithTelegram(): ProfileListSpecification
  124.     {
  125.         return new ProfileListSpecification(
  126.             new ProfileHasTelegram(),
  127.             new \App\Specification\ElasticSearch\ProfileHasTelegram()
  128.         );
  129.     }
  130.     public function listEighteenYearsOld(): ProfileListSpecification
  131.     {
  132.         return new ProfileListSpecification(
  133.             new ProfileIsEighteenYearsOld(),
  134.             new \App\Specification\ElasticSearch\ProfileIsEighteenYearsOld()
  135.         );
  136.     }
  137.     public function listRublevskie(City $city): ProfileListSpecification
  138.     {
  139.         $stationRepo $this->entityManager->getRepository(\App\Entity\Location\Station::class);
  140.         $stationUris = require __DIR__ '/../../config/rublevskie_stations.php';
  141.         $stations $stationRepo->createQueryBuilder('s')
  142.             ->andWhere('s.city = :city')
  143.             ->andWhere('s.uriIdentity IN (:uris)')
  144.             ->setParameter('city'$city)
  145.             ->setParameter('uris'$stationUris)
  146.             ->getQuery()->getResult();
  147.         return new ProfileListSpecification(
  148.             new \App\Specification\Profile\ProfileIsRublevskie($city$this->entityManager),
  149.             new \App\Specification\ElasticSearch\ProfileIsRublevskie($city$stations)
  150.         );
  151.     }
  152.     public function listWithTattoo(): ProfileListSpecification
  153.     {
  154.         return new ProfileListSpecification(
  155.             new \App\Specification\Profile\ProfileIsHavingTattoo(true),
  156.             new \App\Specification\ElasticSearch\ProfileIsHavingTattoo(true)
  157.         );
  158.     }
  159.     public function listWithPiercing(): ProfileListSpecification
  160.     {
  161.         return new ProfileListSpecification(
  162.             new \App\Specification\Profile\ProfileIsHavingPiercing(true),
  163.             new \App\Specification\ElasticSearch\ProfileIsHavingPiercing(true)
  164.         );
  165.     }
  166.     public function listRoundTheClock(): ProfileListSpecification
  167.     {
  168.         return new ProfileListSpecification(
  169.             new \App\Specification\Profile\ProfileIsRoundTheClock(),
  170.             new \App\Specification\ElasticSearch\ProfileIsRoundTheClock()
  171.         );
  172.     }
  173.     public function listForTwoHours(): ProfileListSpecification
  174.     {
  175.         return new ProfileListSpecification(
  176.             new \App\Specification\Profile\ProfileIsForTwoHours(),
  177.             new \App\Specification\ElasticSearch\ProfileIsForTwoHours()
  178.         );
  179.     }
  180.     public function listGrandmothers(): ProfileListSpecification
  181.     {
  182.         return new ProfileListSpecification(
  183.             new \App\Specification\Profile\ProfileIsGrandmother(),
  184.             new \App\Specification\ElasticSearch\ProfileIsGrandmother()
  185.         );
  186.     }
  187.     public function listWithComments(): ProfileListSpecification
  188.     {
  189.         return new ProfileListSpecification(new ProfileHasComments(), new \App\Specification\ElasticSearch\ProfileHasComments());
  190.     }
  191.     public function listWithVideo(): ProfileListSpecification
  192.     {
  193.         return new ProfileListSpecification(new ProfileHasVideo(), new \App\Specification\ElasticSearch\ProfileHasVideo());
  194.     }
  195.     public function listWithSelfie(): ProfileListSpecification
  196.     {
  197.         return new ProfileListSpecification(new ProfileHasSelfie(), new \App\Specification\ElasticSearch\ProfileHasSelfie());
  198.     }
  199.     public function listByPrice(City $citystring $priceTypeint $minPrice nullint $maxPrice null): ProfileListSpecification
  200.     {
  201.         $currency $this->countryCurrencyResolver->getCurrencyFor($city->getCountryCode());
  202.         if ($minPrice && $maxPrice) {
  203.             $priceSpec ProfileWithApartmentsOneHourPrice::range($minPrice$maxPrice);
  204.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithApartmentsOneHourPrice::range($minPrice$maxPrice);
  205.         } elseif ($maxPrice) {
  206.             $priceSpec ProfileWithApartmentsOneHourPrice::cheaperThan($maxPrice);
  207.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithApartmentsOneHourPrice::cheaperThan($maxPrice);
  208.         } else {
  209.             switch ($priceType) {
  210.                 case 'not_expensive':
  211.                     $priceSpec = new ProfileIsNotExpensive($city);
  212.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileIsNotExpensive($currency);
  213.                     break;
  214.                 case 'low':
  215.                     $priceSpec = new ProfileHasLowPrice($city$currency);
  216.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasLowPrice($city$currency);
  217.                     break;
  218.                 case 'elite':
  219.                     $priceSpec = new ProfileHasHighPrice($city$currency, [
  220.                         'RUB' => 20000,
  221.                     ], [
  222.                         'RUB' => 20000,
  223.                     ]);
  224.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasHighPrice($city$currency, [], []);
  225.                     break;
  226.                 case 'high':
  227.                 default:
  228.                     $priceSpec = new ProfileHasHighPrice($city$currency);
  229.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasHighPrice($city$currency);
  230.                     break;
  231.             }
  232.         }
  233.         return new ProfileListSpecification($priceSpec$recommendationSpec);
  234.     }
  235.     public function listByAge(string $ageTypeint $minAge nullint $maxAge null): ProfileListSpecification
  236.     {
  237.         if ($minAge && $maxAge) {
  238.             $ageSpec ProfileWithAge::range($minAge$maxAge);
  239.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::range($minAge$maxAge);
  240.         } elseif ($minAge) {
  241.             $ageSpec ProfileWithAge::olderThan($minAge);
  242.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::olderThan($minAge);
  243.         } else {
  244.             switch ($ageType) {
  245.                 case 'old':
  246.                     $ageSpec ProfileWithAge::old();
  247.                     $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::old();
  248.                     break;
  249.                 case 'young':
  250.                 default:
  251.                     $ageSpec ProfileWithAge::young();
  252.                     $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::young();
  253.                     break;
  254.             }
  255.         }
  256.         return new ProfileListSpecification($ageSpec$recommendationSpec);
  257.     }
  258.     public function listByHeight(string $heightType): ProfileListSpecification
  259.     {
  260.         if ('short' === $heightType) {
  261.             $heightSpec ProfileWithHeight::short();
  262.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithHeight::short();
  263.         } else {
  264.             $heightSpec ProfileWithHeight::tall();
  265.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithHeight::tall();
  266.         }
  267.         return new ProfileListSpecification($heightSpec$recommendationSpec);
  268.     }
  269.     public function listByBreastType(string $breastType): ProfileListSpecification
  270.     {
  271.         $breastTypeSpec = new ProfileWithBreastType(BreastTypes::getValueByUriIdentity($breastType));
  272.         return new ProfileListSpecification($breastTypeSpec, new \App\Specification\ElasticSearch\ProfileWithBreastType(BreastTypes::getValueByUriIdentity($breastType)));
  273.     }
  274.     public function listByHairColor(string $hairColor): ProfileListSpecification
  275.     {
  276.         $hairColorSpec = new ProfileWithHairColor(HairColors::getValueByUriIdentity($hairColor));
  277.         return new ProfileListSpecification($hairColorSpec, new \App\Specification\ElasticSearch\ProfileWithHairColor(HairColors::getValueByUriIdentity($hairColor)));
  278.     }
  279.     public function listByBodyType(string $bodyType): ProfileListSpecification
  280.     {
  281.         $bodyTypeSpec = new ProfileWithBodyType(BodyTypes::getValueByUriIdentity($bodyType));
  282.         return new ProfileListSpecification($bodyTypeSpec, new \App\Specification\ElasticSearch\ProfileWithBodyType(BodyTypes::getValueByUriIdentity($bodyType)));
  283.     }
  284.     public function listByPlace(string $placeTypestring $takeOutLocation null): ?ProfileListSpecification
  285.     {
  286.         switch ($placeType) {
  287.             case 'apartments':
  288.                 $placeSpec = new ProfileHasApartments();
  289.                 $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasApartments();
  290.                 break;
  291.             case 'take-out':
  292.                 $takeOutLocation TakeOutLocations::getValueByUriIdentity($takeOutLocation);
  293.                 $placeSpec = new ProfileIsProvidingTakeOut($takeOutLocation);
  294.                 $recommendationSpec = new \App\Specification\ElasticSearch\ProfileIsProvidingTakeOut($takeOutLocation);
  295.                 break;
  296.             case 'on-call':
  297.                 $placeSpec Spec::andX(
  298.                     new ProfileIsProvidingTakeOut(null),
  299.                     Spec::not(new ProfileHasApartments())
  300.                 );
  301.                 $recommendationSpec \App\Specification\ElasticSearch\Spec::andX(
  302.                     (new \App\Specification\ElasticSearch\ProfileIsProvidingTakeOut(null))->getSpec(),
  303.                     \App\Specification\ElasticSearch\Spec::not((new \App\Specification\ElasticSearch\ProfileHasApartments())->getSpec())
  304.                 );
  305.                 break;
  306.             default:
  307.                 return null;
  308.         }
  309.         return new ProfileListSpecification($placeSpec$recommendationSpec);
  310.     }
  311.     public function listByPrivateHaircut(string $privateHaircut): ProfileListSpecification
  312.     {
  313.         $privateHaircutSpec = new ProfileWithPrivateHaircut(PrivateHaircuts::getValueByUriIdentity($privateHaircut));
  314.         return new ProfileListSpecification($privateHaircutSpec, new \App\Specification\ElasticSearch\ProfileWithPrivateHaircut(PrivateHaircuts::getValueByUriIdentity($privateHaircut)));
  315.     }
  316.     public function listByNationality(string $nationality): ProfileListSpecification
  317.     {
  318.         $nationalitySpec = new ProfileWithNationality(Nationalities::getValueByUriIdentity($nationality));
  319.         return new ProfileListSpecification($nationalitySpec, new \App\Specification\ElasticSearch\ProfileWithNationality(Nationalities::getValueByUriIdentity($nationality)));
  320.     }
  321.     public function listByProvidedService(Service $serviceCity $city): ProfileListSpecification
  322.     {
  323.         $sameGroupServices $this->serviceRepository->findBy(['group' => $service->getGroup()]);
  324.         $spec = new AndX(new ProfileIsProvidingOneOfServices([$service]));
  325.         if ('eskort' == $service->getUriIdentity() && true === $this->features->escort_additional_requirements()) {
  326.             $spec->andX(new ProfileIsApproved());
  327.             $spec->andX(new ProfileHasPriceGreaterThan($city'RUB', [
  328.                 'RUB' => 12000,
  329.             ]));
  330.             $spec->andX(new ProfileIsUpdatedWithinAYear());
  331.         }
  332.         return new ProfileListSpecification($spec, new \App\Specification\ElasticSearch\ProfileIsProvidingOneOfServices($sameGroupServices));
  333.     }
  334.     public function listNew(int $weeks 2): ProfileListSpecification
  335.     {
  336.         return new ProfileListSpecification(new ProfileIsNew($weeks), new \App\Specification\ElasticSearch\ProfileIsNew($weeks));
  337.     }
  338.     public function listByNoRetouch(): ProfileListSpecification
  339.     {
  340.         return new ProfileListSpecification(new ProfileNoRetouch(), new \App\Specification\ElasticSearch\ProfileNoRetouch());
  341.     }
  342.     public function listByNice(): ProfileListSpecification
  343.     {
  344.         return new ProfileListSpecification(new ProfileIsNice(), new \App\Specification\ElasticSearch\ProfileIsNice());
  345.     }
  346.     public function listByOnCall(): ProfileListSpecification
  347.     {
  348.         return new ProfileListSpecification(new ProfileHasOnCall(), new \App\Specification\ElasticSearch\ProfileHasOnCall());
  349.     }
  350.     public function listForHour(): ProfileListSpecification
  351.     {
  352.         return new ProfileListSpecification(new ProfileIsForHour(), new \App\Specification\ElasticSearch\ProfileIsForHour());
  353.     }
  354.     public function listForNight(): ProfileListSpecification
  355.     {
  356.         return new ProfileListSpecification(new ProfileIsForNight(), new \App\Specification\ElasticSearch\ProfileIsForNight());
  357.     }
  358.     private function getSpecForEliteGirls(City $city): Filter
  359.     {
  360.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  361.             'RUB' => 5000,
  362.             'UAH' => 1500,
  363.             'USD' => 100,
  364.             'EUR' => 130,
  365.         ]);
  366.         return new ProfileIsElite($minPrice);
  367.     }
  368.     private function getElasticSearchSpecForEliteGirls(City $city): ISpecification
  369.     {
  370.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  371.             'RUB' => 5000,
  372.             'UAH' => 1500,
  373.             'USD' => 100,
  374.             'EUR' => 130,
  375.         ]);
  376.         return new \App\Specification\ElasticSearch\ProfileIsElite($minPrice);
  377.     }
  378.     public function listForEliteGirls(City $city): ProfileListSpecification
  379.     {
  380.         $eliteSpec $this->getSpecForEliteGirls($city);
  381.         return new ProfileListSpecification($eliteSpec$this->getElasticSearchSpecForEliteGirls($city));
  382.     }
  383.     public function listForRealElite(City $city): ProfileListSpecification
  384.     {
  385.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  386.             'RUB' => 5000,
  387.             'UAH' => 1500,
  388.             'USD' => 100,
  389.             'EUR' => 130,
  390.         ]);
  391.         return new ProfileListSpecification(new ProfileIsRealElite($minPrice), new \App\Specification\ElasticSearch\ProfileIsRealElite($minPrice));
  392.     }
  393.     public function listForVipPros(City $city): ProfileListSpecification
  394.     {
  395.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  396.             'RUB' => 4000,
  397.             'UAH' => 1200,
  398.             'USD' => 100,
  399.             'EUR' => 100,
  400.         ]);
  401.         $districts = [];
  402.         foreach (ProfileInMoskowDistricts::$districtsUri as $uri) {
  403.             $districts[] = $this->districtRepository->ofUriIdentityWithinCity($uri$city);
  404.         }
  405.         return new ProfileListSpecification(new ProfileIsVip($city$districts$minPrice), new \App\Specification\ElasticSearch\ProfileIsVip($city$districts$minPrice));
  406.     }
  407.     public function listForVipIndividual(City $city): ProfileListSpecification
  408.     {
  409.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  410.             'RUB' => 30000,
  411.             'UAH' => 10000,
  412.             'USD' => 400,
  413.             'EUR' => 400,
  414.         ]);
  415.         return new ProfileListSpecification(new ProfileIsVipIndividual($minPrice), new \App\Specification\ElasticSearch\ProfileIsVipIndividual($minPrice));
  416.     }
  417.     public function listForVipGirlsCity(City $city): ProfileListSpecification
  418.     {
  419.         return new ProfileListSpecification(new ProfileIsVipMoskow($city), new \App\Specification\ElasticSearch\ProfileIsVipMoskow($city));
  420.     }
  421.     public function listOfGirlfriends(): ProfileListSpecification
  422.     {
  423.         return new ProfileListSpecification(new ProfileIsGirlfriend(), new \App\Specification\ElasticSearch\ProfileIsGirlfriend());
  424.     }
  425.     public function listOfMostExpensive(City $city): ProfileListSpecification
  426.     {
  427.         $count intval($this->profileRepository->match(Spec::countOf(Spec::andX(
  428.             ProfileIsLocated::withinCity($city),
  429.             new ProfileHasOneOfGenders([Genders::FEMALE])
  430.         )))[0][1]);
  431.         $criteria Spec::andX(
  432.             $this->features->free_profiles() ? new ProfileIsNotHidden() : new ProfileIsActive(),
  433.             new ProfileAdBoardPlacement(),
  434.             new ProfilePlacementHiding(),
  435.             new ProfileAvatar(),
  436.             ProfileIsLocated::withinCity($city),
  437.             new LimitResult(round($count 10), 0),
  438.             new ProfileOrderedByNightPrice(),
  439.             new ProfileHasOneOfGenders([Genders::FEMALE])
  440.         );
  441.         $profilesTenPercents $this->profileRepository->match($criteria);
  442.         $criteriaProfile end($profilesTenPercents);
  443.         return new ProfileListSpecification(new ProfileIsMostExpensive($criteriaProfile), new \App\Specification\ElasticSearch\ProfileIsMostExpensive($criteriaProfile));
  444.     }
  445.     public function listBdsm(): ProfileListSpecification
  446.     {
  447.         $bdsmIds $this->serviceRepository->findBy(['group' => ServiceGroups::BDSM]);
  448.         return new ProfileListSpecification(null, new \App\Specification\ElasticSearch\ProfileIsProvidingOneOfServices($bdsmIds), [new BdsmProfile($this->parameterBag->get('profile_list.bdsm_page.min_profile_services'))]);
  449.     }
  450.     public function listByGender(string $gender): ProfileListSpecification
  451.     {
  452.         $gender Genders::getValueByUriIdentity($gender);
  453.         $genders = [$gender];
  454.         return new ProfileListSpecification(nullnullnull$genders);
  455.     }
  456.     public function listBigAss(): ProfileListSpecification
  457.     {
  458.         return new ProfileListSpecification(
  459.             new \App\Specification\Profile\ProfileIsBigAss(),
  460.             new \App\Specification\ElasticSearch\ProfileIsBigAss()
  461.         );
  462.     }
  463.     public function listExpress(): ProfileListSpecification
  464.     {
  465.         return new ProfileListSpecification(
  466.             new \App\Specification\Profile\ProfileIsProvidingExpress(),
  467.             new \App\Specification\ElasticSearch\ProfileIsProvidingExpress()
  468.         );
  469.     }
  470.     public function listBigBreast(): ProfileListSpecification
  471.     {
  472.         return new ProfileListSpecification(
  473.             new \App\Specification\Profile\ProfileHasBigBreast(),
  474.             new \App\Specification\ElasticSearch\ProfileHasBigBreast()
  475.         );
  476.     }
  477.     
  478.     public function listVerySkinny(): ProfileListSpecification
  479.     {
  480.         return new ProfileListSpecification(
  481.             new \App\Specification\Profile\ProfileIsVerySkinny(),
  482.             new \App\Specification\ElasticSearch\ProfileIsVerySkinny()
  483.         );
  484.     }
  485.     public function listSmallAss(): ProfileListSpecification
  486.     {
  487.         return new ProfileListSpecification(
  488.             new \App\Specification\Profile\ProfileIsSmallAss(),
  489.             new \App\Specification\ElasticSearch\ProfileIsSmallAss()
  490.         );
  491.     }
  492.     public function listBeautifulProstitutes(): ProfileListSpecification
  493.     {
  494.         return new ProfileListSpecification(
  495.             new \App\Specification\Profile\ProfileIsBeautifulProstitute(),
  496.             new \App\Specification\ElasticSearch\ProfileIsBeautifulProstitute()
  497.         );
  498.     }
  499.         public function listWithoutIntermediaries(): ProfileListSpecification
  500.     {
  501.         return new ProfileListSpecification(
  502.             new \App\Specification\Profile\ProfileIsWithoutIntermediaries(),
  503.             null 
  504.         );
  505.     }
  506.     public function listByOutcall(): ProfileListSpecification
  507.     {
  508.         return new ProfileListSpecification(new \App\Specification\Profile\ProfileHasOutcall(), new \App\Specification\ElasticSearch\ProfileHasOutcall());
  509.     }
  510.     public function listDwarfs(): ProfileListSpecification
  511.     {
  512.         return new ProfileListSpecification(new \App\Specification\Profile\ProfileIsDwarf(), new \App\Specification\ElasticSearch\ProfileIsDwarf());
  513.     }
  514.     public function listWithoutPrepayment(): ProfileListSpecification
  515.     {
  516.         return new ProfileListSpecification(
  517.             new \App\Specification\Profile\ProfileWithoutPrepayment(),
  518.             new \App\Specification\ElasticSearch\ProfileWithoutPrepayment()
  519.         );
  520.     }
  521. }