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