src/Controller/MapController.php line 63

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Location\City;
  4. use App\Entity\Profile\Genders;
  5. use App\Entity\Saloon\Saloon;
  6. use App\Entity\ServiceGroups;
  7. use App\Event\Profile\ProfilesShownEvent;
  8. use App\Form\FilterMapForm;
  9. use App\Repository\CityRepository;
  10. use App\Repository\ProfileRepository;
  11. use App\Repository\ReadModel\ProfileMapReadModel;
  12. use App\Repository\SaloonRepository;
  13. use App\Repository\ServiceRepository;
  14. use App\Service\Features;
  15. use App\Service\ProfileList;
  16. use App\Specification\Profile\ProfileHasMapCoordinates;
  17. use App\Specification\Profile\ProfileIsSuitableForTheMap;
  18. use App\Specification\Profile\ProfileIdINOrderedByINValues;
  19. use App\Specification\Profile\ProfileIsLocated;
  20. use App\Specification\QueryModifier\PossibleSaloonAdBoardPlacement;
  21. use App\Specification\QueryModifier\PossibleSaloonPlacementHiding;
  22. use App\Specification\Saloon\SaloonIsNotHidden;
  23. use App\Specification\QueryModifier\SaloonThumbnail;
  24. use App\Specification\Saloon\SaloonIsActive;
  25. use App\Specification\Saloon\SaloonIsSuitableForTheMap;
  26. use Happyr\DoctrineSpecification\Spec;
  27. use Psr\Cache\CacheItemPoolInterface;
  28. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  29. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  30. use Symfony\Component\Asset\Packages;
  31. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  32. use Symfony\Component\HttpFoundation\JsonResponse;
  33. use Symfony\Component\HttpFoundation\Request;
  34. use Symfony\Component\HttpFoundation\Response;
  35. use Symfony\Contracts\Cache\ItemInterface;
  36. use Symfony\Contracts\Translation\TranslatorInterface;
  37. class MapController extends AbstractController
  38. {
  39.     use ProfileMinPriceTrait;
  40.     const MAP_PROFILES_CACHE_ITEM_NAME 'map_profiles_';
  41.     public function __construct(
  42.         private ProfileRepository        $profileRepository,
  43.         private CityRepository           $cityRepository,
  44.         private Features                 $features,
  45.         private Packages                 $assetPackage,
  46.         private SaloonRepository         $saloonRepository,
  47.         private ProfileList              $profileList,
  48.         private EventDispatcherInterface $eventDispatcher,
  49.         private ServiceRepository        $serviceRepository,
  50.         private CacheItemPoolInterface   $profilesFilterCache,
  51.     )
  52.     {
  53.     }
  54.     #[ParamConverter("city"converter"city_converter")]
  55.     public function page(City $city): Response
  56.     {
  57.         return $this->render('Map/page.html.twig', [
  58.             'cityUriIdentity' => $city->getUriIdentity(),
  59.             'cityLatitude' => $city->getMapCoordinate()->getLatitude(),
  60.             'cityLongitude' => $city->getMapCoordinate()->getLongitude(),
  61.             'multipleCities' => (int)$this->features->multiple_cities(),
  62.         ]);
  63.     }
  64.     public function form(City $city): Response
  65.     {
  66.         $form $this->createForm(FilterMapForm::class, null, ['data' => ['city_id' => $city->getId()]]);
  67.         return $this->render('Map/form.html.twig', [
  68.             'form' => $form->createView(),
  69.         ]);
  70.     }
  71.     public function filter(Request $requestTranslatorInterface $translator): Response
  72.     {
  73.         $params json_decode($request->request->get('form'), true);
  74.         $form $this->createForm(FilterMapForm::class);
  75.         $form->submit($params);
  76.         $scale $request->request->get('scale') ?? 0;
  77.         if ($scale <= 8) {
  78.             $coordsRoundPrecision 1;
  79.         } else if ($scale <= 14) {
  80.             $coordsRoundPrecision 2;
  81.         } else {
  82.             $coordsRoundPrecision 4;
  83.         }
  84.         $city $this->cityRepository->find($params['city_id']);
  85.         $profiles $this->profileList->listForMap(
  86.             $citynull$form->getData(), [
  87.             new ProfileHasMapCoordinates(),
  88.             new ProfileIsSuitableForTheMap(),
  89.         ], truenull,
  90.             ProfileList::ORDER_NONE, [Genders::FEMALE], $coordsRoundPrecision,
  91.         );
  92.         $specs Spec::andX(
  93.             new SaloonIsSuitableForTheMap(),
  94.             new SaloonThumbnail(),
  95.             ProfileIsLocated::withinCity($city),
  96.             new ProfileHasMapCoordinates(),
  97.         );
  98.         $saloons $this->saloonRepository->listForMapMatchingSpec($specs$coordsRoundPrecision);
  99.         $rowConverter = function ($row) {
  100.             $row array_values($row);
  101.             //id
  102.             $row[0] = array_map('intval'explode(','$row[0]));
  103.             //coords
  104.             $row[3] = array_map('floatval'explode(','$row[$row[2] == 3]));
  105.             //is_masseur
  106.             if (isset($row[4])) {
  107.                 $row[4] = array_map('intval'explode(','$row[4]));
  108.             }
  109.             array_splice($row11);
  110.             return $row;
  111.         };
  112.         $out = [
  113.             'profiles' => array_map($rowConverter$profiles),
  114.             'saloons' => array_map($rowConverter$saloons),
  115.         ];
  116.         return $this->json($out);
  117.     }
  118.     public function detail(Request $requestTranslatorInterface $translator): Response
  119.     {
  120.         $services $this->serviceRepository->allIndexedById();
  121.         $profileIds = ($requestedProfiles $request->request->get('profiles')) ? explode(','$requestedProfiles) : [];
  122.         $saloonIds = ($requestedSaloons $request->request->get('saloons')) ? explode(','$requestedSaloons) : [];
  123.         $result = !empty($profileIds) ? $this->profileRepository->fetchMapProfilesByIds(new ProfileIdINOrderedByINValues($profileIds)) : [];
  124.         $profiles = [];
  125.         foreach ($result as /** @var ProfileMapReadModel $profile */ $profile) {
  126.             if (!$profile->mapLatitude || !$profile->mapLongitude)
  127.                 continue;
  128.             $path $profile->avatar['path'];
  129.             $path str_starts_with($path'/') ? $path substr($path6, -4);
  130.             $hasApartment $profile->apartmentOneHourPrice || $profile->apartmentTwoHoursPrice || $profile->apartmentNightPrice;
  131.             $hasTakeout $profile->takeOutOneHourPrice || $profile->takeOutTwoHoursPrice || $profile->takeOutNightPrice;
  132.             $tags = [];
  133.             if ($hasApartment && !$hasTakeout)
  134.                 $tags[] = 1;
  135.             elseif (!$hasApartment && $hasTakeout)
  136.                 $tags[] = 2;
  137.             elseif ($hasApartment && $hasTakeout)
  138.                 $tags[] = 3;
  139.             foreach ($profile->services as $serviceId) {
  140.                 $service $services[$serviceId];
  141.                 switch ($service->getUriIdentity()) {
  142.                     case 'seks-klassicheskij':
  143.                     case 'sex':
  144.                         $tags[] = 4;
  145.                         break;
  146.                     case 'seks-analnyij':
  147.                     case 'anal-sex':
  148.                         $tags[] = 5;
  149.                         break;
  150.                     case 'minet-bez-rezinki':
  151.                     case 'blowjob-without-condom':
  152.                         $tags[] = 6;
  153.                         break;
  154.                     case 'kunnilingus':
  155.                     case 'cunnilingus-for-me':
  156.                         $tags[] = 7;
  157.                         break;
  158.                     case 'okonchanie-v-rot':
  159.                     case 'cum-in-mouth':
  160.                         $tags[] = 8;
  161.                         break;
  162.                 }
  163.                 if (ServiceGroups::MASSAGE === $service->getGroup() && false === in_array(9$tagstrue)) {
  164.                     $tags[] = 9;
  165.                 }
  166.             }
  167.             $profiles[] = [
  168.                 1,
  169.                 (float)rtrim(substr($profile->mapLatitude07), '0'),
  170.                 (float)rtrim(substr($profile->mapLongitude07), '0'),
  171.                 $profile->uriIdentity,
  172.                 $profile->name,
  173.                 $path//$profile->avatar['path'],
  174.                 //$profile->avatar['type'] ? 'avatar' : 'photo',
  175.                 str_replace(' '''$profile->phoneNumber),
  176.                 $profile->station ?? 0,
  177.                 $profile->apartmentOneHourPrice ?? $profile->takeOutOneHourPrice ?? 0,
  178.                 $profile->apartmentTwoHoursPrice ?? $profile->takeOutTwoHoursPrice ?? 0,
  179.                 $profile->apartmentNightPrice ?? $profile->takeOutNightPrice ?? 0,
  180.                 (int)$profile->isApproved,
  181.                 (int)$profile->isMasseur,
  182.                 (int)$profile->hasComments,
  183.                 (int)$profile->hasSelfies,
  184.                 (int)$profile->hasVideos,
  185.                 $profile->age ?? 0,
  186.                 $profile->breastSize ?? 0,
  187.                 $profile->height ?? 0,
  188.                 $profile->weight ?? 0,
  189.                 $tags,
  190.                 $profile->id,
  191.                 (int)$profile->isPaid ?? 0,
  192.             ];
  193.         }
  194.         $result = !empty($saloonIds) ? $this->saloonRepository->matchingSpecRaw(new ProfileIdINOrderedByINValues($saloonIds), nullfalse) : [];
  195.         $saloons = [];
  196.         foreach ($result as /** @var Saloon $saloon */ $saloon) {
  197.             $photoPath null !== ($mainPhoto $saloon->getThumbnail()) ? $mainPhoto->getPath() : '';
  198.             $photoPath str_starts_with($photoPath'/') ? $photoPath str_replace(".jpg"""substr($photoPath6));
  199.             $saloons[] = [
  200.                 2,
  201.                 (float)rtrim(substr($saloon->getMapCoordinate()->getLatitude(), 07), '0'),
  202.                 (float)rtrim(substr($saloon->getMapCoordinate()->getLongitude(), 07), '0'),
  203.                 $saloon->getUriIdentity(),
  204.                 $translator->trans($saloon->getName()),
  205.                 $photoPath,
  206.                 //'thumb',
  207.                 str_replace(' '''$saloon->getPhoneNumber()),
  208.                 $saloon->getPrimaryStation()?->getId() ?? 0,
  209.                 $saloon->getApartmentsPricing()->getOneHourPrice() ?? $saloon->getTakeOutPricing()->getOneHourPrice() ?? 0,
  210.                 $saloon->getApartmentsPricing()->getTwoHoursPrice() ?? $saloon->getTakeOutPricing()->getTwoHoursPrice() ?? 0,
  211.                 $saloon->getApartmentsPricing()->getNightPrice() ?? $saloon->getTakeOutPricing()->getNightPrice() ?? 0,
  212.                 //$saloon->getExpressPricing()->isProvided() ? $saloon->getExpressPricing()->getPrice() ?? 0 : 0,
  213.                 (int)($saloon?->getAdBoardPlacement() !== null),
  214.                 $saloon->getId(),
  215.             ];
  216.         }
  217.         return new JsonResponse([
  218.             'profiles' => $profiles,
  219.             'saloons' => $saloons,
  220.         ]);
  221.     }
  222.     public function processProfileShows(Request $requestProfileRepository $profileRepository): JsonResponse
  223.     {
  224.         $id $request->query->get('id');
  225.         $profile $profileRepository->find($id);
  226.         if ($profile) {
  227.             $this->eventDispatcher->dispatch(new ProfilesShownEvent([$profile->getId()], 'map'), ProfilesShownEvent::NAME);
  228.         }
  229.         return $this->json([]);
  230.     }
  231.     public function cachedMapProfilesResultByIds(ProfileIdINOrderedByINValues $specification)
  232.     {
  233.         $key sha1(self::MAP_PROFILES_CACHE_ITEM_NAME implode(','$specification->getIds()));
  234.         return $this->profilesFilterCache->get($key, function (ItemInterface $item) use ($specification) {
  235.             return $this->profileRepository->fetchMapProfilesByIds($specification);
  236.         });
  237.     }
  238. }