src/Controller/Account/AccountController.php line 194

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Account;
  3. use AngelGamez\PorpaginasBundle\Controller\PaginationTrait;
  4. use App\Entity\Account\Customer;
  5. use App\Entity\User;
  6. use App\Form\BulkActionForm;
  7. use App\Form\ChangeAccountPasswordForm;
  8. use App\Form\ChangeAccountInformationForm;
  9. use App\Repository\ProfileRepository;
  10. use App\Repository\ModerationRequestsRepository;
  11. use App\Repository\SaloonRepository;
  12. use App\Service\AccountChargesDurationEstimator;
  13. use App\Service\AccountChargesDurationPresenter;
  14. use App\Service\AccountPaidServicesPricesProvider;
  15. use App\Service\BulkQueueService;
  16. use App\Service\Features;
  17. use App\Service\ProfilePlanPlacementService;
  18. use App\Service\ProfileCtrService;
  19. use App\Service\UserService;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  22. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  23. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  24. use Symfony\Component\HttpFoundation\JsonResponse;
  25. use Symfony\Component\HttpFoundation\RedirectResponse;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\RequestStack;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  30. use Symfony\Component\HttpKernel\KernelInterface;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  33. class AccountController extends AbstractController
  34. {
  35.     use PaginationTrait;
  36.     use AccountListFilterTrait;
  37.     private const STEP_TURN_ON_PROFILE = 0;
  38.     private const STEP_ENTER_PHONE = 1;
  39.     private const STEP_SEND_CODE = 2;
  40.     private const STEP_CONNECT_PROFILES = 3;
  41.     private const STEP_REPEAT_CALL = 4;
  42.     public const ACTION_ACTIVATE = 1;
  43.     public const ACTION_DEACTIVATE = 2;
  44.     const LEGACY_MASSEUR_LIST_PARAM = 'massagers';
  45.     const AVAILABLE_CTR_PERIODS = ['today', 'yesterday', 'week', 'month', 'all_time'];
  46.     const AVAILABLE_PROFILE_PLACEMENT_TYPES = ['all', 'paid', 'free', 'ultra-vip', 'vip', 'standard', 'hidden'];
  47.     private KernelInterface $kernel;
  48.     private Features $features;
  49.     function __construct(
  50.         RequestStack $requestStack, SessionInterface $session, ParameterBagInterface $parameterBag,
  51.         KernelInterface $kernel, Features $features, ProfileRepository $profileRepository,
  52.         private ModerationRequestsRepository $moderationRequestsRepository
  53.     )
  54.     {
  55.         $this->request = $requestStack->getCurrentRequest();
  56.         $this->session = $session;
  57.         $this->parameterBag = $parameterBag;
  58.         $this->availablePlacementTypeFilters = self::AVAILABLE_PROFILE_PLACEMENT_TYPES;
  59.         $this->kernel = $kernel;
  60.         $this->profileRepository = $profileRepository;
  61.         $this->features = $features;
  62.     }
  63.     /**
  64.      * @throws \Doctrine\ORM\NoResultException
  65.      * @throws \Doctrine\ORM\NonUniqueResultException
  66.      */
  67.     #[Route(path: '/', name: 'account', options: ['expose' => true])]
  68.     #[Route(path: '/page{page<\d+>}/', name: 'account._pagination', options: ['expose' => true])]
  69.     #[Security("is_granted('ROLE_ADVERTISER') or is_granted('ROLE_CUSTOMER')")]
  70.     public function homepage(ProfileRepository $profileRepository, SaloonRepository $saloonRepository,
  71.         Request $request, ParameterBagInterface $parameterBag, SessionInterface $session, ProfileCtrService $profileCtrService,
  72.         BulkQueueService $bulkQueueService, ProfilePlanPlacementService $planPlacementService): Response
  73.     {
  74.         $user = $this->getUser();
  75.         if($user instanceof Customer) {
  76.             return $this->redirectToRoute('account.preferred_profiles.list');
  77.         }
  78.         if($this->features->account_main_is_profiles()) {
  79.             return $this->redirectToRoute('account_girls');
  80.         }
  81.         list(
  82.             'per_page' => $perPage, 'placement_type_filter' => $placementTypeFilter, 'name_filter' =>  $nameFilter,
  83.             'sort' =>  $sort, 'sort_direction' =>  $sortDirection, 'ctr_period' => $ctrPeriod,
  84.             ) = $this->processListRequestData($request, true);
  85.         $profilesCtr = $profileCtrService->getCtrByOwner($user, $ctrPeriod);
  86.         $profileIdsWaitingAction = $bulkQueueService->getProfilesWaitingAction($user);
  87.         $isMasseur = $this->features->non_masseur_on_account_profile_list() ? false : null;
  88.         $profiles = $this->getFilteredAndSortedProfiles(
  89.             $user, $perPage, $sort, $sortDirection, $placementTypeFilter, $nameFilter, $profilesCtr, $isMasseur
  90.         );
  91.         $profileIds = [];
  92.         foreach ($profiles as $profile) {
  93.             $profileIds[] = $profile->getId();
  94.         }
  95.         $templateParameters = [
  96.             'is_masseur_list' => null,
  97.             'profiles' => $profiles,
  98.             'all_profiles_ids' => $this->showDebugData() ? $this->getProfileIdsByFilter($user, $placementTypeFilter, $nameFilter, null) : [],
  99.             'profiles_ctr' => $profilesCtr,
  100.             'ctr_period' => $ctrPeriod,
  101.             'per_page' => $perPage == 99999 ? -1 : $perPage,
  102.             'placement_type_filter' => $placementTypeFilter,
  103.             'name_filter' => $nameFilter,
  104.             'sort' => $sort,
  105.             'sort_direction' => $sortDirection,
  106.             'profiles_waiting_action' => $profileIdsWaitingAction,
  107.             'plan_placement_enabled' => $planPlacementService->isEnabled(),
  108.             'profile_plan_badges' => $planPlacementService->buildBadgesByProfiles($profiles),
  109.             'profile_moderation_states' => $this->moderationRequestsRepository->getLatestStatesByOwner($user, $profileIds),
  110.         ];
  111.         if($request->isXmlHttpRequest()) {
  112.             return $this->render('account/advertiser/account.profiles.html.twig', $templateParameters);
  113.         } else {
  114.             if(null !== ($redirectResponse = $this->redirectToRouteWithoutPaginationIfNeeded($profiles)))
  115.                 return $redirectResponse;
  116.             $bulkAction = $this->createForm(BulkActionForm::class, null, [
  117.                 'action' => $this->generateUrl('account.profile_management.bulk_action'),
  118.                 'method' => 'post',
  119.                 'data' => [
  120.                     'entity_repository' => $profileRepository,
  121.                 ],
  122.             ]);
  123.             return $this->render('account/advertiser/account.html.twig', array_merge($templateParameters, [
  124.                 'user' => $user,
  125.                 'profiles_active_count' => $profileRepository->countActiveOfOwner($user, $this->features->non_masseur_on_account_profile_list() ? false : null),
  126.                 'profiles_all_count' => $profileRepository->countAllOfOwnerNotDeleted($user, $this->features->non_masseur_on_account_profile_list() ? false : null),
  127.                 'masseurs_active_count' => $profileRepository->countActiveOfOwner($user, true),
  128.                 'masseurs_all_count' => $profileRepository->countAllOfOwnerNotDeleted($user, true),
  129.                 'saloons_active_count' => $saloonRepository->countActiveOfOwner($user),
  130.                 'saloons_all_count' => $saloonRepository->countAllOfOwner($user),
  131.                 'bulk_form' => $bulkAction->createView(),
  132.                 'per_page_variants' => explode(',', $parameterBag->get('account.setting.advertiser_profile_list_per_page.variants')),
  133.                 'ctr_periods' => AccountController::AVAILABLE_CTR_PERIODS,
  134.                 'placement_type_filter_variants' => self::AVAILABLE_PROFILE_PLACEMENT_TYPES,
  135.             ]));
  136.         }
  137.     }
  138.     #[Route(path: '/profile/', name: 'account.settings')]
  139.     #[Security("is_granted('ROLE_ADVERTISER') or is_granted('ROLE_CUSTOMER')")]
  140.     public function accountProfileEdit(Request $request, UserService $userService, ParameterBagInterface $parameterBag): RedirectResponse|Response
  141.     {
  142.         /** @var User $user */
  143.         $user = $this->getUser();
  144.         $form = $this->createForm(ChangeAccountInformationForm::class, $user);
  145.         $form->handleRequest($request);
  146.         $passwordForm = $this->createForm(ChangeAccountPasswordForm::class);
  147.         $passwordForm->handleRequest($request);
  148.         if ($form->isSubmitted() && $form->isValid()) {
  149.             $userService->edit($form->getData());
  150.             $this->addFlash('success', 'Profile settings updated.');
  151.             return $this->redirectToRoute('account.settings');
  152.         } elseif ($passwordForm->isSubmitted() && $passwordForm->isValid()) {
  153.             $newPassword = $passwordForm->get('new_password')->getData();
  154.             $userService->changePassword($user, $newPassword);
  155.             $this->addFlash('success', 'Profile password updated.');
  156.             return $this->redirectToRoute('account.settings');
  157.         }
  158.         return $this->render('account/profile.html.twig', [
  159.             'user' => $user,
  160.             'form' => $form->createView(),
  161.             'password_form' => $passwordForm->createView(),
  162.             'approval_media_upload_domain' => $parameterBag->get('app.approval_media_upload_domain'),
  163.         ]);
  164.     }
  165.     #[Route(path: '/top/', name: 'account.profile.top_placement')]
  166.     #[Route(path: '/top/page{page<\d+>}/', name: 'account.profile.top_placement._pagination', options: ['expose' => true])]
  167.     #[IsGranted('ROLE_ADVERTISER')]
  168.     public function topPlacement(
  169.          ProfileRepository $profileRepository,
  170.          AccountPaidServicesPricesProvider $accountPaidServicesPricesProvider,
  171.          Request $request, ParameterBagInterface $parameterBag): Response
  172.     {
  173.         /** @var User $user */
  174.         $user = $this->getUser();
  175.         $result = $profileRepository->ofOwnerPaged($user);
  176.         $profiles = $this->takePage($result, $parameterBag->get('advertiser.profiles.per_page'));
  177.         $city = $user->getCity();
  178.         $topPlacementHourlyPrice = $accountPaidServicesPricesProvider
  179.             ->getPricesForAccount($user)
  180.             ->getTopPlacementHourlyPrice();
  181.         if($request->isXmlHttpRequest()) {
  182.             return $this->render('account/profile_top/top_placement.profiles.html.twig', [
  183.                 'profiles' => $profiles,
  184.             ]);
  185.         } else {
  186.             return $this->render('account/profile_top/top_placement.html.twig', [
  187.                 'profiles' => $profiles,
  188.                 'city' => $city,
  189.                 'profile_top_placement_hourly_price' => $topPlacementHourlyPrice,
  190.                 'top_price_tables' => $accountPaidServicesPricesProvider->getTopPriceTablesForAccount($user),
  191.             ]);
  192.         }
  193.     }
  194.     /**
  195.      * @deprecated ?
  196.      */
  197.     #[Route(path: '/settings/profile-list/per-page/{count}/', name: 'account.settings.advertiser_profile_list_per_page')]
  198.     #[Route(path: '/settings/saloon-list/per-page/{count}/', name: 'account.settings.advertiser_saloon_list_per_page')]
  199.     #[IsGranted('ROLE_ADVERTISER')]
  200.     public function settingsPerPage(int $count, SessionInterface $session, Request $request, ParameterBagInterface $parameterBag): Response
  201.     {
  202.         $route = $request->attributes->get('_route');
  203.         $isProfileSetting = ("account.settings.advertiser_profile_list_per_page" == $route);
  204.         $variants = $isProfileSetting
  205.             ? $parameterBag->get('account.setting.advertiser_profile_list_per_page.variants')
  206.             : $parameterBag->get('account.setting.advertiser_saloon_list_per_page.variants');
  207.         $variants = explode(',', $variants);
  208.         if(false === array_search($count, $variants)) {
  209.             throw new \LogicException(sprintf('Count must be one of %s', implode(',', $variants)));
  210.         }
  211.         $isProfileSetting
  212.            ? $session->set($parameterBag->get('account.setting.advertiser_profile_list_per_page.name'), $count)
  213.            : $session->set($parameterBag->get('account.setting.advertiser_saloon_list_per_page.name'), $count);
  214.         $referer = $request->headers->get('referer');
  215.         return $referer ? $this->redirect($request->headers->get('referer')) : $this->redirectToRoute('account');
  216.     }
  217.     #[Route(path: '/settings/profile-list/ctr-period/{period}/', name: 'account.settings.advertiser_profile_list_ctr_period')]
  218.     #[IsGranted('ROLE_ADVERTISER')]
  219.     public function settingsCtrPeriod(string $period, SessionInterface $session, Request $request, ParameterBagInterface $parameterBag, ProfileCtrService $profileCtrService): Response
  220.     {
  221.         if(false === array_search($period, self::AVAILABLE_CTR_PERIODS)) {
  222.             throw new \LogicException(sprintf('Ctr period must be one of %s', implode(',', self::AVAILABLE_CTR_PERIODS)));
  223.         }
  224.         $session->set($parameterBag->get('account.setting.advertiser_profile_list_ctr_period.name'), $period);
  225.         if($request->isXmlHttpRequest()) {
  226.             return $this->json([
  227.                 'success' => true,
  228.                 'profiles_ctr' => $profileCtrService->getCtrByOwner($this->getUser(), $period),
  229.                 'period' => $period,
  230.             ]);
  231.         } else {
  232.             $referer = $request->headers->get('referer');
  233.             return $referer ? $this->redirect($request->headers->get('referer')) : $this->redirectToRoute('account');
  234.         }
  235.     }
  236.     
  237.     #[Route(path: '/rules/', name: 'account.rules')]
  238.     public function rules(): Response
  239.     {
  240.         return $this->render('account/static/rules.html.twig');
  241.     }
  242.     #[Route(path: '/charges/duration/', name: 'account.charges_duration', options: ['expose' => true])]
  243.     #[Security("is_granted('ROLE_ADVERTISER') or is_granted('ROLE_CUSTOMER')")]
  244.     public function chargesDuration(
  245.         Request $request,
  246.         AccountChargesDurationEstimator $accountChargesDurationEstimator,
  247.         AccountChargesDurationPresenter $accountChargesDurationPresenter
  248.     ): JsonResponse
  249.     {
  250.         $user = $this->getUser();
  251.         if (!$user instanceof User) {
  252.             return $this->json(['success' => false, 'duration' => null], 401);
  253.         }
  254.         $referenceAt = null;
  255.         $referenceAtRaw = $request->query->get('at');
  256.         if (is_scalar($referenceAtRaw) && ctype_digit((string)$referenceAtRaw)) {
  257.             $referenceAt = (new \DateTimeImmutable('@'.(string)$referenceAtRaw))
  258.                 ->setTimezone(new \DateTimeZone('UTC'));
  259.         }
  260.         $estimate = $accountChargesDurationEstimator->estimate($user, $referenceAt);
  261.         $durationKey = $accountChargesDurationPresenter->messageKey($estimate);
  262.         $durationParameters = $accountChargesDurationPresenter->messageParameters($estimate);
  263.         return $this->json([
  264.             'success' => true,
  265.             'duration' => $accountChargesDurationPresenter->present($estimate),
  266.             'duration_key' => $durationKey,
  267.             'duration_parameters' => $durationParameters,
  268.             'hours' => $estimate->getHours(),
  269.             'has_paid_placements' => $estimate->hasPaidPlacements(),
  270.             'unlimited' => $estimate->isUnlimited(),
  271.         ]);
  272.     }
  273.     #[Route(path: '/hide-offer-bar/', name: 'account.offer_bar.hide')]
  274.     public function hideOfferBar(EntityManagerInterface $entityManager): Response
  275.     {
  276.         /** @var User $user */
  277.         $user = $this->getUser();
  278.         $user->setOfferBarHidden();
  279.         $entityManager->flush();
  280.         return $this->json(['status' => 1]);
  281.     }
  282.     private function showDebugData(): bool
  283.     {
  284.         return $this->kernel->getEnvironment() == 'dev' || $this->kernel->getEnvironment() == 'review';
  285.     }
  286. }