src/Aqarmap/Bundle/UserBundle/Controller/UserController.php line 255

  1. <?php
  2. namespace Aqarmap\Bundle\UserBundle\Controller;
  3. use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
  4. use Aqarmap\Bundle\ListingBundle\Entity\Location;
  5. use Aqarmap\Bundle\ListingBundle\Entity\PropertyType;
  6. use Aqarmap\Bundle\ListingBundle\Entity\Section;
  7. use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;
  8. use Aqarmap\Bundle\ListingBundle\Service\FavouriteService;
  9. use Aqarmap\Bundle\ListingBundle\Service\LocationManager;
  10. use Aqarmap\Bundle\ListingBundle\Service\TopCustomerService;
  11. use Aqarmap\Bundle\NotifierBundle\Service\V3\NotifierSubscriptionService;
  12. use Aqarmap\Bundle\UserBundle\Constant\UserInterestStatus;
  13. use Aqarmap\Bundle\UserBundle\Entity\User;
  14. use Aqarmap\Bundle\UserBundle\Entity\UserInterest;
  15. use Aqarmap\Bundle\UserBundle\Form\QuickRegistrationFormType;
  16. use Aqarmap\Bundle\UserBundle\Services\GoogleUserManager;
  17. use Aqarmap\Bundle\UserBundle\Services\UserActivityService;
  18. use Aqarmap\Bundle\UserBundle\Services\UserManager;
  19. use Aqarmap\Bundle\UserBundle\Services\V3\UserAuthenticationService as UserAuthenticationServiceV3;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use FOS\RestBundle\Controller\Annotations as Rest;
  22. use FOS\UserBundle\Model\UserManagerInterface;
  23. use Knp\Component\Pager\PaginatorInterface;
  24. use Symfony\Bridge\Doctrine\Attribute\MapEntity;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Symfony\Component\ExpressionLanguage\Expression;
  27. use Symfony\Component\Form\FormInterface;
  28. use Symfony\Component\HttpFoundation\RedirectResponse;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpFoundation\Response;
  31. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  32. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  33. use Symfony\Component\Routing\Attribute\Route;
  34. use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
  35. use Symfony\Component\Security\Http\Attribute\IsGranted;
  36. use Symfony\Contracts\Translation\TranslatorInterface;
  37. #[Route(path: '/user')]
  38. class UserController extends AbstractController
  39. {
  40. public function __construct(
  41. private readonly EntityManagerInterface $entityManager,
  42. private readonly PaginatorInterface $paginator,
  43. TokenStorageInterface $tokenStorage,
  44. private readonly FeatureToggleManager $featureToggleManager,
  45. private readonly TranslatorInterface $translator,
  46. private readonly TopCustomerService $topCustomerService,
  47. private readonly FavouriteService $favouriteService,
  48. private readonly LocationManager $locationManager,
  49. private readonly UserActivityService $userActivityService,
  50. private readonly NotifierSubscriptionService $notifierSubscriptionService,
  51. private readonly UserManagerInterface $fosUserManager,
  52. private readonly UserManager $userManager,
  53. private readonly GoogleUserManager $googleUserManager,
  54. private readonly UserAuthenticationServiceV3 $userAuthenticationServiceV3,
  55. private readonly \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $usageTrackingTokenStorage,
  56. private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
  57. ) {
  58. }
  59. /**
  60. * User listings.
  61. *
  62. * @return array|RedirectResponse|Response
  63. *
  64. * @throws \Exception
  65. */
  66. #[Route(path: '/{id}/{type}/{location}', name: 'aqarmap_user_listings', requirements: ['id' => '\d+', 'type' => 'agent|company|', 'location' => '.+[^/]'])]
  67. #[Route(path: '/{id}/{location}', name: 'aqarmap_user_listings_without_type', requirements: ['id' => '\d+', 'location' => '.+[^/]'])]
  68. public function index(int $id, Request $request, #[MapEntity(mapping: ['location' => 'slug'])] ?Location $location = null, ?string $type = null)
  69. {
  70. $em = $this->entityManager;
  71. $user = $em->getRepository(User::class)->find($id);
  72. if (!$user) {
  73. throw new NotFoundHttpException('User Not Found');
  74. }
  75. $pageNumber = max($request->query->getInt('page', 1), 1);
  76. if (1 == $request->query->getInt('page')) {
  77. return $this->redirectToFirstPage($request, $user, $location);
  78. }
  79. $isAgentProfileToggled = $this->featureToggleManager
  80. ->isEnabled('web.agents.section');
  81. $isTopCustomer = $this->topCustomerService->isTopCustomer($user) && $isAgentProfileToggled;
  82. $users = [$user];
  83. $agents = [];
  84. if ($user->getChildren()->count()) {
  85. $users = array_merge($users, $user->getChildren()->toArray());
  86. $agents = $user->getChildren();
  87. }
  88. $query = $this->userManager->getListingsByLocation($users, $location);
  89. if (empty($query->getQuery()->getScalarResult()) && $location) {
  90. return $this->redirectToRoute('aqarmap_user_listings', [
  91. 'id' => $user->getId(),
  92. 'location' => $location->getParent()?->getSlug(),
  93. ], Response::HTTP_MOVED_PERMANENTLY);
  94. }
  95. if (!\in_array($request->get('sort'), ['l.publishedAt', 'l.price', 'l.area'])) {
  96. $request->query->set('sort', 'l.publishedAt');
  97. }
  98. $paginator = $this->paginator;
  99. $listings = $paginator->paginate(
  100. $query,
  101. $pageNumber,
  102. $isTopCustomer ? 6 : 9
  103. );
  104. if ($pageNumber > 1 && empty($listings->getItems())) {
  105. return $this->redirectToFirstPage($request, $user, $location);
  106. }
  107. $userManager = $this->userManager;
  108. $liveListingsCount = $userManager->countLiveListing($user);
  109. if ($isTopCustomer) {
  110. $locationManager = $this->locationManager;
  111. return $this->render('@AqarmapUser/Profile/agent.html.twig', [
  112. 'results' => $listings,
  113. 'user' => $user,
  114. 'servedLocationsPills' => $this
  115. ->topCustomerService
  116. ->getServedLocations($users, $location, 1),
  117. 'isCompanyProfile' => (bool) $user->getChildrenCount(),
  118. 'companyAgents' => $agents,
  119. 'location' => $location,
  120. 'form' => $this->createQuickLeadForm(),
  121. 'liveListingsCount' => $liveListingsCount,
  122. 'leadsCount' => $user->getClientServedCount(),
  123. 'servedLocations' => $locationManager
  124. ->buildServingLeveledLocationsArray($users, 1, $request->getLocale()),
  125. 'agent' => true,
  126. ]);
  127. }
  128. return $this->render('@AqarmapUser/User/index.html.twig', [
  129. 'liveListingsCount' => $liveListingsCount,
  130. 'entity' => $listings,
  131. 'user' => $user,
  132. 'agent' => $user,
  133. ]);
  134. }
  135. /**
  136. * Unset User Logo.
  137. */
  138. #[Route(path: '/logo/unset', name: 'aqarmap_user_logo_unset')]
  139. #[IsGranted(attribute: 'ROLE_USER')]
  140. public function unsetLogo(): RedirectResponse
  141. {
  142. /** @var User $user */
  143. $user = $this->getUser();
  144. $user->setLogo(null);
  145. $user->setIsValidLogo(false);
  146. $response = new Response();
  147. $response->headers->clearCookie('hide_logo_request');
  148. $response->sendHeaders();
  149. $userManager = $this->fosUserManager;
  150. $userManager->updateUser($user);
  151. $request->getSession()->getFlashBag()->add(
  152. 'success',
  153. $this->translator->trans('profile.flash.user_updated')
  154. );
  155. return new RedirectResponse($this->generateUrl('fos_user_profile_edit'));
  156. }
  157. /**
  158. * Quick Registration Action.
  159. */
  160. #[Route(path: '/', name: 'aqarmap_user_insert', options: ['expose' => true], methods: ['POST'])]
  161. #[Rest\View]
  162. public function post(Request $request)
  163. {
  164. $userManager = $this->fosUserManager;
  165. /** @var User $user */
  166. $user = $userManager->createUser();
  167. $form = $this->createForm(QuickRegistrationFormType::class, $user, [
  168. 'method' => 'POST',
  169. 'action' => $this->generateUrl('aqarmap_user_insert'),
  170. 'validation_groups' => ['simplified'],
  171. 'onlyEmail' => true,
  172. ]);
  173. $form->handleRequest($request);
  174. // Marking the user as a quick registered
  175. $user->setIsQucikRegistered(true);
  176. $usernameFromEmail = explode('@', $user->getEmail());
  177. $user->setFullName($usernameFromEmail[0]);
  178. $registered = $this->userManager->quickRegister($user, $form, $request, true, false, false, $request->get('registerWithPassword', false));
  179. if (true === $registered) {
  180. return [
  181. 'status' => 'ok',
  182. 'message' => $this->translator->trans('popup_form.success'),
  183. ];
  184. }
  185. return $form;
  186. }
  187. #[Route(path: '/interests/', name: 'aqarmap_my_interests')]
  188. #[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]
  189. public function myInterests(Request $request)
  190. {
  191. $user = $this->getUser();
  192. $em = $this->entityManager;
  193. // Creating pagination
  194. $paginator = $this->paginator;
  195. $pagination = $paginator->paginate(
  196. $em->getRepository(UserInterest::class)->getUserInterests($user, 20),
  197. $request->query->getInt('page', 1),
  198. 20
  199. );
  200. return [
  201. 'interests' => $pagination,
  202. ];
  203. }
  204. #[Route(path: '/interests/{id}/pause', name: 'aqarmap_interests_pause', requirements: ['id' => '\d+'], methods: ['GET'])]
  205. #[IsGranted(attribute: new Expression('is_granted("ROLE_ADMIN") or is_granted("ROLE_OWNER", subject["entity"])'), subject: ['entity'])]
  206. public function pauseInterest(Request $request, UserInterest $entity): RedirectResponse
  207. {
  208. if (!$entity) {
  209. throw $this->createNotFoundException('Unable to find this Interest.');
  210. }
  211. $em = $this->entityManager;
  212. $entity->setStatus(UserInterestStatus::PAUSED);
  213. // Save Changes
  214. $em->persist($entity);
  215. $em->flush();
  216. // Set success flash message
  217. $request->getSession()->getFlashBag()->add(
  218. 'info',
  219. $this->translator->trans('interest.paused_successfully')
  220. );
  221. return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  222. }
  223. /**
  224. * User Activity.
  225. */
  226. #[Route(path: '/activity/{step}', name: 'user_activity')]
  227. #[Route(path: '/{userKey}/activity/{step}', name: 'user_activity_share')]
  228. #[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]
  229. public function activity(Request $request): Response
  230. {
  231. $request->query->add([
  232. 'user_key' => $request->attributes->get('userKey'),
  233. 'limit' => 1,
  234. ]);
  235. if ($request->attributes->get('userKey')) {
  236. $favourite = $this->favouriteService->getUserFavourite($request)->getResult();
  237. }
  238. return $this->render('@AqarmapUser/User/activity.html.twig', [
  239. 'favourite' => current($favourite ?? []),
  240. 'featureToggle' => $this->userActivityService->getFeatureToggles(),
  241. ]);
  242. }
  243. /**
  244. * User Inbox.
  245. */
  246. #[Route(path: '/inbox/', name: 'user_inbox')]
  247. #[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]
  248. public function inbox(): Response
  249. {
  250. $entityManager = $this->managerRegistry;
  251. $featureToggleManager = $this->featureToggleManager;
  252. return $this->render('@AqarmapUser/User/inbox.html.twig', [
  253. 'location' => $entityManager->getRepository(Location::class)->getFirstRoot(),
  254. 'propertyType' => $entityManager->getRepository(PropertyType::class)->getFirstRoot(),
  255. 'section' => $entityManager->getRepository(Section::class)->getFirstSection(),
  256. 'featureToggle' => [
  257. 'web.whats.app.chat' => $featureToggleManager->isEnabled('web.whats.app.chat'),
  258. ],
  259. ]);
  260. }
  261. /**
  262. * User Message.
  263. */
  264. #[Route(path: '/messages/{id}', name: 'user_message')]
  265. #[IsGranted(attribute: 'IS_AUTHENTICATED_REMEMBERED')]
  266. public function messages(): Response
  267. {
  268. $featureToggleManager = $this->featureToggleManager;
  269. return $this->render('@AqarmapUser/User/inbox.html.twig', [
  270. 'featureToggle' => [
  271. 'web.whats.app.chat' => $featureToggleManager->isEnabled('web.whats.app.chat'),
  272. ],
  273. ]);
  274. }
  275. public function createQuickLeadForm(): FormInterface
  276. {
  277. return $this->createForm(
  278. QuickLeadType::class,
  279. null,
  280. [
  281. 'action' => $this->generateUrl('add_quick_lead'),
  282. 'method' => 'POST',
  283. ]
  284. );
  285. }
  286. #[Route(path: '/interests/unsubscribe/{locationId}', name: 'aqarmap_poke_notifier_unsubscribe', methods: ['GET'])]
  287. public function unsubscribeLocationNotifier(Request $request, int $locationId): RedirectResponse
  288. {
  289. $token = $request->query->get('token');
  290. $subscriptionService = $this->notifierSubscriptionService;
  291. $subscriptionService->unsubscribeLocation($locationId, $token);
  292. return $this->redirectToRoute('homepage');
  293. }
  294. #[Route(path: '/interests/unsubscribe', name: 'aqarmap_all_poke_notifiers_unsubscribe', methods: ['GET'])]
  295. public function unsubscribeAllNotifiers(Request $request): RedirectResponse
  296. {
  297. $token = $request->query->get('token');
  298. $subscriptionService = $this->notifierSubscriptionService;
  299. $subscriptionService->unsubscribeAll($token);
  300. return $this->redirectToRoute('homepage');
  301. }
  302. /**
  303. * Google login action.
  304. *
  305. * @return RedirectResponse
  306. */
  307. #[Route(path: '/google/login', name: 'user_google_login')]
  308. public function googleLogin(Request $request, SessionInterface $session)
  309. {
  310. $isGoogleToggleEnabled = $this->featureToggleManager->isEnabled('web.google.onetab');
  311. if (!$isGoogleToggleEnabled) {
  312. return $this->redirectToRoute('homepage');
  313. }
  314. $client = $this->googleUserManager->createGoogleClient();
  315. $code = $request->query->get('code');
  316. if (!$code) {
  317. $referer = $request->headers->get('referer');
  318. $session->set('referer_url', $referer);
  319. return $this->redirect($client->createAuthUrl());
  320. }
  321. try {
  322. $refererPage = $session->get('referer_url') ?: $this->generateUrl('homepage');
  323. $userData = $this->googleUserManager->getUserDataFromToken($client, $code);
  324. } catch (\Exception) {
  325. $this->addFlash('danger', $this->translator->trans('user.something_went_wrong'));
  326. return $this->redirect($refererPage);
  327. }
  328. $userHasNoRetrievedData = (!$userData->getId() && !$userData->getName() && !$userData->getEmail());
  329. if ($userHasNoRetrievedData) {
  330. $this->addFlash('danger', $this->translator->trans('user.something_went_wrong'));
  331. return $this->redirect($refererPage);
  332. }
  333. $user = $this->googleUserManager->createOrUpdateUser($userData);
  334. $data = [];
  335. $data['token'] = $this->googleUserManager->createUserAccessToken($request->request->get('aqarmap_teleport_client_id'), $user);
  336. $data['referer'] = $refererPage;
  337. $userToken = $this->userAuthenticationServiceV3->generateToken($user, false);
  338. $this->usageTrackingTokenStorage->setToken($userToken);
  339. $session->set('_security_main', serialize($userToken));
  340. return $this->render('@AqarmapUser/User/google_call_back.html.twig', ['data' => $data]);
  341. }
  342. private function redirectToFirstPage(Request $request, User $user, ?Location $location = null): RedirectResponse
  343. {
  344. $request->query->remove('page');
  345. return $this->redirectToRoute('aqarmap_user_listings', [
  346. 'id' => $user->getId(),
  347. 'location' => $location ? $location->getSlug() : null,
  348. ], Response::HTTP_MOVED_PERMANENTLY);
  349. }
  350. }