src/Service/ProfileListSpecificationService.php line 84

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 App\Repository\ServiceRepository;
  20. use App\Specification\ElasticSearch\ISpecification;
  21. use App\Specification\Profile\BdsmProfile;
  22. use App\Specification\Profile\ProfileAdBoardPlacement;
  23. use App\Specification\Profile\ProfileHasApartments;
  24. use App\Specification\Profile\ProfileHasComments;
  25. use App\Specification\Profile\ProfileHasHighPrice;
  26. use App\Specification\Profile\ProfileHasLowPrice;
  27. use App\Specification\Profile\ProfileHasOnCall;
  28. use App\Specification\Profile\ProfileHasOneOfGenders;
  29. use App\Specification\Profile\ProfileHasPriceGreaterThan;
  30. use App\Specification\Profile\ProfileHasSelfie;
  31. use App\Specification\Profile\ProfileHasVideo;
  32. use App\Specification\Profile\ProfileInMoskowDistricts;
  33. use App\Specification\Profile\ProfileIsActive;
  34. use App\Specification\Profile\ProfileIsApproved;
  35. use App\Specification\Profile\ProfileIsElite;
  36. use App\Specification\Profile\ProfileIsForHour;
  37. use App\Specification\Profile\ProfileIsForNight;
  38. use App\Specification\Profile\ProfileIsGirlfriend;
  39. use App\Specification\Profile\ProfileIsLocated;
  40. use App\Specification\Profile\ProfileIsMasseur;
  41. use App\Specification\Profile\ProfileIsMostExpensive;
  42. use App\Specification\Profile\ProfileIsNew;
  43. use App\Specification\Profile\ProfileIsNice;
  44. use App\Specification\Profile\ProfileIsNotExpensive;
  45. use App\Specification\Profile\ProfileIsNotHidden;
  46. use App\Specification\Profile\ProfileIsProvidingOneOfServices;
  47. use App\Specification\Profile\ProfileIsProvidingTakeOut;
  48. use App\Specification\Profile\ProfileIsRealElite;
  49. use App\Specification\Profile\ProfileIsUpdatedWithinAYear;
  50. use App\Specification\Profile\ProfileIsVip;
  51. use App\Specification\Profile\ProfileIsVipIndividual;
  52. use App\Specification\Profile\ProfileIsVipMoskow;
  53. use App\Specification\Profile\ProfileNoRetouch;
  54. use App\Specification\Profile\ProfileWithAge;
  55. use App\Specification\Profile\ProfileWithApartmentsOneHourPrice;
  56. use App\Specification\Profile\ProfileWithBodyType;
  57. use App\Specification\Profile\ProfileWithBreastType;
  58. use App\Specification\Profile\ProfileWithHairColor;
  59. use App\Specification\Profile\ProfileWithHeight;
  60. use App\Specification\Profile\ProfileWithNationality;
  61. use App\Specification\Profile\ProfileWithPrivateHaircut;
  62. use App\Specification\QueryModifier\LimitResult;
  63. use App\Specification\QueryModifier\ProfileAvatar;
  64. use App\Specification\QueryModifier\ProfileOrderedByNightPrice;
  65. use App\Specification\QueryModifier\ProfilePlacementHiding;
  66. use Happyr\DoctrineSpecification\Filter\Filter;
  67. use Happyr\DoctrineSpecification\Logic\AndX;
  68. use Happyr\DoctrineSpecification\Spec;
  69. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  70. class ProfileListSpecificationService
  71. {
  72.     public function __construct(
  73.         private CountryCurrencyResolver $countryCurrencyResolver,
  74.         private ServiceRepository $serviceRepository,
  75.         private ParameterBagInterface $parameterBag,
  76.         private ProfileRepository $profileRepository,
  77.         private DistrictRepository $districtRepository,
  78.         private Features $features,
  79.     ) {}
  80.     public function listForMasseur(City $city): ProfileListSpecification
  81.     {
  82.         return new ProfileListSpecification(new ProfileIsMasseur(), \App\Specification\ElasticSearch\ProfileIsLocated::withinCity($city));
  83.     }
  84.     public function listByCity(): ProfileListSpecification
  85.     {
  86.         return new ProfileListSpecification(nullnull);
  87.     }
  88.     public function listByCounty(County $county): ProfileListSpecification
  89.     {
  90.         return new ProfileListSpecification(ProfileIsLocated::withinCounty($county), \App\Specification\ElasticSearch\ProfileIsLocated::withinCounty($county));
  91.     }
  92.     public function listByDistrict(District $district): ProfileListSpecification
  93.     {
  94.         return new ProfileListSpecification(ProfileIsLocated::withinDistrict($district), \App\Specification\ElasticSearch\ProfileIsLocated::withinDistrict($district));
  95.     }
  96.     public function listByStation(Station $station): ProfileListSpecification
  97.     {
  98.         return new ProfileListSpecification(ProfileIsLocated::nearStation($station), \App\Specification\ElasticSearch\ProfileIsLocated::nearStations([$station]));
  99.     }
  100.     public function listByStations(array $stations): ProfileListSpecification
  101.     {
  102. //        $stationIds = explode(',', $stations);
  103. //        $stations = $this->stationRepository->findBy(['uriIdentity' => $stationIds]);
  104.         return new ProfileListSpecification(new ProfileIsLocated(nullnullnull$stations), \App\Specification\ElasticSearch\ProfileIsLocated::nearStations($stations));
  105.     }
  106.     public function listApproved(): ProfileListSpecification
  107.     {
  108.         return new ProfileListSpecification(new ProfileIsApproved(), new \App\Specification\ElasticSearch\ProfileIsApproved());
  109.     }
  110.     public function listWithComments(): ProfileListSpecification
  111.     {
  112.         return new ProfileListSpecification(new ProfileHasComments(), new \App\Specification\ElasticSearch\ProfileHasComments());
  113.     }
  114.     public function listWithVideo(): ProfileListSpecification
  115.     {
  116.         return new ProfileListSpecification(new ProfileHasVideo(), new \App\Specification\ElasticSearch\ProfileHasVideo());
  117.     }
  118.     public function listWithSelfie(): ProfileListSpecification
  119.     {
  120.         return new ProfileListSpecification(new ProfileHasSelfie(), new \App\Specification\ElasticSearch\ProfileHasSelfie());
  121.     }
  122.     public function listByPrice(City $citystring $priceTypeint $minPrice nullint $maxPrice null): ProfileListSpecification
  123.     {
  124.         $currency $this->countryCurrencyResolver->getCurrencyFor($city->getCountryCode());
  125.         if ($minPrice && $maxPrice) {
  126.             $priceSpec ProfileWithApartmentsOneHourPrice::range($minPrice$maxPrice);
  127.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithApartmentsOneHourPrice::range($minPrice$maxPrice);
  128.         } elseif ($maxPrice) {
  129.             $priceSpec ProfileWithApartmentsOneHourPrice::cheaperThan($maxPrice);
  130.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithApartmentsOneHourPrice::cheaperThan($maxPrice);
  131.         } else {
  132.             switch ($priceType) {
  133.                 case 'not_expensive':
  134.                     $priceSpec = new ProfileIsNotExpensive($city);
  135.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileIsNotExpensive($currency);
  136.                     break;
  137.                 case 'low':
  138.                     $priceSpec = new ProfileHasLowPrice($city$currency);
  139.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasLowPrice($city$currency);
  140.                     break;
  141.                 case 'elite':
  142.                     $priceSpec = new ProfileHasHighPrice($city$currency, [
  143.                         'RUB' => 20000,
  144.                     ], [
  145.                         'RUB' => 20000,
  146.                     ]);
  147.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasHighPrice($city$currency, [], []);
  148.                     break;
  149.                 case 'high':
  150.                 default:
  151.                     $priceSpec = new ProfileHasHighPrice($city$currency);
  152.                     $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasHighPrice($city$currency);
  153.                     break;
  154.             }
  155.         }
  156.         return new ProfileListSpecification($priceSpec$recommendationSpec);
  157.     }
  158.     public function listByAge(string $ageTypeint $minAge nullint $maxAge null): ProfileListSpecification
  159.     {
  160.         if ($minAge && $maxAge) {
  161.             $ageSpec ProfileWithAge::range($minAge$maxAge);
  162.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::range($minAge$maxAge);
  163.         } elseif ($minAge) {
  164.             $ageSpec ProfileWithAge::olderThan($minAge);
  165.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::olderThan($minAge);
  166.         } else {
  167.             switch ($ageType) {
  168.                 case 'old':
  169.                     $ageSpec ProfileWithAge::old();
  170.                     $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::old();
  171.                     break;
  172.                 case 'young':
  173.                 default:
  174.                     $ageSpec ProfileWithAge::young();
  175.                     $recommendationSpec \App\Specification\ElasticSearch\ProfileWithAge::young();
  176.                     break;
  177.             }
  178.         }
  179.         return new ProfileListSpecification($ageSpec$recommendationSpec);
  180.     }
  181.     public function listByHeight(string $heightType): ProfileListSpecification
  182.     {
  183.         if ('short' === $heightType) {
  184.             $heightSpec ProfileWithHeight::short();
  185.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithHeight::short();
  186.         } else {
  187.             $heightSpec ProfileWithHeight::tall();
  188.             $recommendationSpec \App\Specification\ElasticSearch\ProfileWithHeight::tall();
  189.         }
  190.         return new ProfileListSpecification($heightSpec$recommendationSpec);
  191.     }
  192.     public function listByBreastType(string $breastType): ProfileListSpecification
  193.     {
  194.         $breastTypeSpec = new ProfileWithBreastType(BreastTypes::getValueByUriIdentity($breastType));
  195.         return new ProfileListSpecification($breastTypeSpec, new \App\Specification\ElasticSearch\ProfileWithBreastType(BreastTypes::getValueByUriIdentity($breastType)));
  196.     }
  197.     public function listByHairColor(string $hairColor): ProfileListSpecification
  198.     {
  199.         $hairColorSpec = new ProfileWithHairColor(HairColors::getValueByUriIdentity($hairColor));
  200.         return new ProfileListSpecification($hairColorSpec, new \App\Specification\ElasticSearch\ProfileWithHairColor(HairColors::getValueByUriIdentity($hairColor)));
  201.     }
  202.     public function listByBodyType(string $bodyType): ProfileListSpecification
  203.     {
  204.         $bodyTypeSpec = new ProfileWithBodyType(BodyTypes::getValueByUriIdentity($bodyType));
  205.         return new ProfileListSpecification($bodyTypeSpec, new \App\Specification\ElasticSearch\ProfileWithBodyType(BodyTypes::getValueByUriIdentity($bodyType)));
  206.     }
  207.     public function listByPlace(string $placeTypestring $takeOutLocation null): ?ProfileListSpecification
  208.     {
  209.         switch ($placeType) {
  210.             case 'apartments':
  211.                 $placeSpec = new ProfileHasApartments();
  212.                 $recommendationSpec = new \App\Specification\ElasticSearch\ProfileHasApartments();
  213.                 break;
  214.             case 'take-out':
  215.                 $takeOutLocation TakeOutLocations::getValueByUriIdentity($takeOutLocation);
  216.                 $placeSpec = new ProfileIsProvidingTakeOut($takeOutLocation);
  217.                 $recommendationSpec = new \App\Specification\ElasticSearch\ProfileIsProvidingTakeOut($takeOutLocation);
  218.                 break;
  219.             case 'on-call':
  220.                 $placeSpec Spec::andX(
  221.                     new ProfileIsProvidingTakeOut(null),
  222.                     Spec::not(new ProfileHasApartments())
  223.                 );
  224.                 $recommendationSpec \App\Specification\ElasticSearch\Spec::andX(
  225.                     (new \App\Specification\ElasticSearch\ProfileIsProvidingTakeOut(null))->getSpec(),
  226.                     \App\Specification\ElasticSearch\Spec::not((new \App\Specification\ElasticSearch\ProfileHasApartments())->getSpec())
  227.                 );
  228.                 break;
  229.             default:
  230.                 return null;
  231.         }
  232.         return new ProfileListSpecification($placeSpec$recommendationSpec);
  233.     }
  234.     public function listByPrivateHaircut(string $privateHaircut): ProfileListSpecification
  235.     {
  236.         $privateHaircutSpec = new ProfileWithPrivateHaircut(PrivateHaircuts::getValueByUriIdentity($privateHaircut));
  237.         return new ProfileListSpecification($privateHaircutSpec, new \App\Specification\ElasticSearch\ProfileWithPrivateHaircut(PrivateHaircuts::getValueByUriIdentity($privateHaircut)));
  238.     }
  239.     public function listByNationality(string $nationality): ProfileListSpecification
  240.     {
  241.         $nationalitySpec = new ProfileWithNationality(Nationalities::getValueByUriIdentity($nationality));
  242.         return new ProfileListSpecification($nationalitySpec, new \App\Specification\ElasticSearch\ProfileWithNationality(Nationalities::getValueByUriIdentity($nationality)));
  243.     }
  244.     public function listByProvidedService(Service $serviceCity $city): ProfileListSpecification
  245.     {
  246.         $sameGroupServices $this->serviceRepository->findBy(['group' => $service->getGroup()]);
  247.         $spec = new AndX(new ProfileIsProvidingOneOfServices([$service]));
  248.         if('eskort' == $service->getUriIdentity() && true === $this->features->escort_additional_requirements()) {
  249.             $spec->andX(new ProfileIsApproved());
  250.             $spec->andX(new ProfileHasPriceGreaterThan($city'RUB', [
  251.                 'RUB' => 12000,
  252.             ]));
  253.             $spec->andX(new ProfileIsUpdatedWithinAYear());
  254.         }
  255.         return new ProfileListSpecification($spec, new \App\Specification\ElasticSearch\ProfileIsProvidingOneOfServices($sameGroupServices));
  256.     }
  257.     public function listNew(int $weeks 2): ProfileListSpecification
  258.     {
  259.         return new ProfileListSpecification(new ProfileIsNew($weeks), new \App\Specification\ElasticSearch\ProfileIsNew($weeks));
  260.     }
  261.     public function listByNoRetouch(): ProfileListSpecification
  262.     {
  263.         return new ProfileListSpecification(new ProfileNoRetouch(), new \App\Specification\ElasticSearch\ProfileNoRetouch());
  264.     }
  265.     public function listByNice(): ProfileListSpecification
  266.     {
  267.         return new ProfileListSpecification(new ProfileIsNice(), new \App\Specification\ElasticSearch\ProfileIsNice());
  268.     }
  269.     public function listByOnCall(): ProfileListSpecification
  270.     {
  271.         return new ProfileListSpecification(new ProfileHasOnCall(), new \App\Specification\ElasticSearch\ProfileHasOnCall());
  272.     }
  273.     public function listForHour(): ProfileListSpecification
  274.     {
  275.         return new ProfileListSpecification(new ProfileIsForHour(), new \App\Specification\ElasticSearch\ProfileIsForHour());
  276.     }
  277.     public function listForNight(): ProfileListSpecification
  278.     {
  279.         return new ProfileListSpecification(new ProfileIsForNight(), new \App\Specification\ElasticSearch\ProfileIsForNight());
  280.     }
  281.     private function getSpecForEliteGirls(City $city):Filter {
  282.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  283.             'RUB' => 5000,
  284.             'UAH' => 1500,
  285.             'USD' => 100,
  286.             'EUR' => 130,
  287.         ]);
  288.         return new ProfileIsElite($minPrice);
  289.     }
  290.     private function getElasticSearchSpecForEliteGirls(City $city): ISpecification {
  291.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  292.             'RUB' => 5000,
  293.             'UAH' => 1500,
  294.             'USD' => 100,
  295.             'EUR' => 130,
  296.         ]);
  297.         return new \App\Specification\ElasticSearch\ProfileIsElite($minPrice);
  298.     }
  299.     public function listForEliteGirls(City $city): ProfileListSpecification
  300.     {
  301.         $eliteSpec $this->getSpecForEliteGirls($city);
  302.         return new ProfileListSpecification($eliteSpec$this->getElasticSearchSpecForEliteGirls($city));
  303.     }
  304.     public function listForRealElite(City $city): ProfileListSpecification
  305.     {
  306.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  307.             'RUB' => 5000,
  308.             'UAH' => 1500,
  309.             'USD' => 100,
  310.             'EUR' => 130,
  311.         ]);
  312.         return new ProfileListSpecification(new ProfileIsRealElite($minPrice), new \App\Specification\ElasticSearch\ProfileIsRealElite($minPrice));
  313.     }
  314.     public function listForVipPros(City $city): ProfileListSpecification
  315.     {
  316.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  317.             'RUB' => 4000,
  318.             'UAH' => 1200,
  319.             'USD' => 100,
  320.             'EUR' => 100,
  321.         ]);
  322.         $districts = [];
  323.         foreach (ProfileInMoskowDistricts::$districtsUri as $uri) {
  324.             $districts[] = $this->districtRepository->ofUriIdentityWithinCity($uri$city);
  325.         }
  326.         return new ProfileListSpecification(new ProfileIsVip($city$districts$minPrice), new \App\Specification\ElasticSearch\ProfileIsVip($city$districts$minPrice));
  327.     }
  328.     public function listForVipIndividual(City $city): ProfileListSpecification
  329.     {
  330.         $minPrice $this->countryCurrencyResolver->getValueByCountryCode($city->getCountryCode(), [
  331.             'RUB' => 30000,
  332.             'UAH' => 10000,
  333.             'USD' => 400,
  334.             'EUR' => 400,
  335.         ]);
  336.         return new ProfileListSpecification(new ProfileIsVipIndividual($minPrice), new \App\Specification\ElasticSearch\ProfileIsVipIndividual($minPrice));
  337.     }
  338.     public function listForVipGirlsCity(City $city): ProfileListSpecification
  339.     {
  340.         return new ProfileListSpecification(new ProfileIsVipMoskow($city), new \App\Specification\ElasticSearch\ProfileIsVipMoskow($city));
  341.     }
  342.     public function listOfGirlfriends(): ProfileListSpecification
  343.     {
  344.         return new ProfileListSpecification(new ProfileIsGirlfriend(), new \App\Specification\ElasticSearch\ProfileIsGirlfriend());
  345.     }
  346.     public function listOfMostExpensive(City $city): ProfileListSpecification
  347.     {
  348.         $count intval($this->profileRepository->match(Spec::countOf(Spec::andX(
  349.             ProfileIsLocated::withinCity($city),
  350.             new ProfileHasOneOfGenders([Genders::FEMALE])
  351.         )))[0][1]);
  352.         $criteria Spec::andX(
  353.             $this->features->free_profiles() ? new ProfileIsNotHidden() : new ProfileIsActive(),
  354.             new ProfileAdBoardPlacement(),
  355.             new ProfilePlacementHiding(),
  356.             new ProfileAvatar(),
  357.             ProfileIsLocated::withinCity($city),
  358.             new LimitResult(round($count 10), 0),
  359.             new ProfileOrderedByNightPrice(),
  360.             new ProfileHasOneOfGenders([Genders::FEMALE])
  361.         );
  362.         $profilesTenPercents $this->profileRepository->match($criteria);
  363.         $criteriaProfile end($profilesTenPercents);
  364.         return new ProfileListSpecification(new ProfileIsMostExpensive($criteriaProfile), new \App\Specification\ElasticSearch\ProfileIsMostExpensive($criteriaProfile));
  365.     }
  366.     public function listBdsm(): ProfileListSpecification
  367.     {
  368.         $bdsmIds $this->serviceRepository->findBy(['group' => ServiceGroups::BDSM]);
  369.         return new ProfileListSpecification(null, new \App\Specification\ElasticSearch\ProfileIsProvidingOneOfServices($bdsmIds), [new BdsmProfile($this->parameterBag->get('profile_list.bdsm_page.min_profile_services'))]);
  370.     }
  371.     public function listByGender(string $gender): ProfileListSpecification
  372.     {
  373.         $gender Genders::getValueByUriIdentity($gender);
  374.         $genders = [$gender];
  375.         return new ProfileListSpecification(nullnullnull$genders);
  376.     }
  377. }