<?php
namespace Aqarmap\Bundle\UserBundle\Controller;
use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
use Aqarmap\Bundle\ListingBundle\Entity\Location;
use Aqarmap\Bundle\ListingBundle\Entity\PropertyType;
use Aqarmap\Bundle\ListingBundle\Entity\Section;
use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;
use Aqarmap\Bundle\ListingBundle\Service\FavouriteService;
use Aqarmap\Bundle\ListingBundle\Service\ListingManager;
use Aqarmap\Bundle\ListingBundle\Service\LocationManager;
use Aqarmap\Bundle\ListingBundle\Service\TopCustomerService;
use Aqarmap\Bundle\MainBundle\Contract\ProducerFactoryInterface;
use Aqarmap\Bundle\NotifierBundle\Service\V3\NotifierSubscriptionService;
use Aqarmap\Bundle\UserBundle\Constant\UserInterestStatus;
use Aqarmap\Bundle\UserBundle\Entity\User;
use Aqarmap\Bundle\UserBundle\Entity\UserInterest;
use Aqarmap\Bundle\UserBundle\Form\QuickRegistrationFormType;
use Aqarmap\Bundle\UserBundle\Services\GoogleUserManager;
use Aqarmap\Bundle\UserBundle\Services\UserActivityService;
use Aqarmap\Bundle\UserBundle\Services\UserManager;
use Aqarmap\Bundle\UserBundle\Services\V3\UserAuthenticationService as UserAuthenticationServiceV3;
use Doctrine\ORM\EntityManagerInterface;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\UserBundle\Model\UserManagerInterface;
use JMS\Serializer\SerializerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Predis\ClientInterface as RedisClient;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/user")
*/
class UserController extends AbstractController
{
private UserManager $userManager;
/**
* @var LocationManager
*/
private $locationManager;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var PaginatorInterface
*/
private $paginator;
/**
* @var SessionInterface
*/
private $session;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var FeatureToggleManager
*/
private $featureToggleManager;
/**
* @var TopCustomerService
*/
private $topCustomerService;
/**
* @var FavouriteService
*/
private $favouriteService;
/**
* @var UserActivityService
*/
private $userActivityService;
/**
* @var NotifierSubscriptionService
*/
private $notifierSubscriptionService;
/**
* @var UserManagerInterface
*/
private $fosUserManager;
/**
* @var GoogleUserManager
*/
private $googleUserManager;
/**
* @var UserAuthenticationServiceV3
*/
private $userAuthenticationServiceV3;
private \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $usageTrackingTokenStorage;
public function __construct(
EntityManagerInterface $entityManager,
PaginatorInterface $paginator,
EventDispatcherInterface $eventDispatcher,
TokenStorageInterface $tokenStorage,
FormFactoryInterface $fosFormFactory,
SerializerInterface $jmsSerializer,
RedisClient $redis,
FeatureToggleManager $featureToggleManager,
TranslatorInterface $translator,
ProducerFactoryInterface $producerFactory,
TopCustomerService $topCustomerService,
ListingManager $listingManager,
FavouriteService $favouriteService,
SessionInterface $session,
LocationManager $locationManager,
UserActivityService $userActivityService,
NotifierSubscriptionService $notifierSubscriptionService,
UserManagerInterface $fosUserManager,
UserManager $userManager,
GoogleUserManager $googleUserManager,
UserAuthenticationServiceV3 $userAuthenticationServiceV3,
\Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $usageTrackingTokenStorage
) {
$this->entityManager = $entityManager;
$this->paginator = $paginator;
$this->userManager = $userManager;
$this->tokenStorage = $tokenStorage;
$this->favouriteService = $favouriteService;
$this->topCustomerService = $topCustomerService;
$this->featureToggleManager = $featureToggleManager;
$this->userActivityService = $userActivityService;
$this->locationManager = $locationManager;
$this->translator = $translator;
$this->session = $session;
$this->fosUserManager = $fosUserManager;
$this->notifierSubscriptionService = $notifierSubscriptionService;
$this->googleUserManager = $googleUserManager;
$this->userAuthenticationServiceV3 = $userAuthenticationServiceV3;
$this->usageTrackingTokenStorage = $usageTrackingTokenStorage;
}
/**
* User listings.
*
* @Route("/{id}/{type}/{location}", requirements={"id": "\d+", "type": "agent|company|", "location": ".+[^/]"}, name="aqarmap_user_listings")
* @Route("/{id}/{location}", requirements={"id": "\d+", "location": ".+[^/]"}, name="aqarmap_user_listings_without_type")
*
* @ParamConverter("location", options={"mapping":{"location":"slug"}})
*
* @return array|RedirectResponse|Response
*
* @throws \Exception
*/
public function index(int $id, Request $request, ?Location $location = null, ?string $type = null)
{
$em = $this->entityManager;
$user = $em->getRepository(User::class)->find($id);
if (!$user) {
throw new NotFoundHttpException('User Not Found');
}
$pageNumber = max($request->query->getInt('page', 1), 1);
if (1 == $request->query->getInt('page')) {
return $this->redirectToFirstPage($request, $user, $location);
}
$isAgentProfileToggled = $this->featureToggleManager
->isEnabled('web.agents.section');
$isTopCustomer = $this->topCustomerService->isTopCustomer($user) && $isAgentProfileToggled;
$users = [$user];
$agents = [];
if ($user->getChildren()->count()) {
$users = array_merge($users, $user->getChildren()->toArray());
$agents = $user->getChildren();
}
$query = $this->userManager->getListingsByLocation($users, $location);
if (empty($query->getQuery()->getScalarResult()) && $location) {
return $this->redirect($this->generateUrl('aqarmap_user_listings', [
'id' => $user->getId(),
'location' => $location->getParent() ? $location->getParent()->getSlug() : null,
]), Response::HTTP_MOVED_PERMANENTLY);
}
if (!\in_array($request->get('sort'), ['l.publishedAt', 'l.price', 'l.area'])) {
$request->query->set('sort', 'l.publishedAt');
}
$paginator = $this->paginator;
$listings = $paginator->paginate(
$query,
$pageNumber,
$isTopCustomer ? 6 : 9
);
if ($pageNumber > 1 && empty($listings->getItems())) {
return $this->redirectToFirstPage($request, $user, $location);
}
$userManager = $this->userManager;
$liveListingsCount = $userManager->countLiveListing($user);
if ($isTopCustomer) {
$locationManager = $this->locationManager;
return $this->render('@AqarmapUser/Profile/agent.html.twig', [
'results' => $listings,
'user' => $user,
'servedLocationsPills' => $this
->topCustomerService
->getServedLocations($users, $location, 1),
'isCompanyProfile' => (bool) $user->getChildrenCount(),
'companyAgents' => $agents,
'location' => $location,
'form' => $this->createQuickLeadForm()->createView(),
'liveListingsCount' => $liveListingsCount,
'leadsCount' => $user->getClientServedCount(),
'servedLocations' => $locationManager
->buildServingLeveledLocationsArray($users, 1, $request->getLocale()),
'agent' => true,
]);
}
return $this->render('@AqarmapUser/User/index.html.twig', [
'liveListingsCount' => $liveListingsCount,
'entity' => $listings,
'user' => $user,
'agent' => $user,
]);
}
/**
* Unset User Logo.
*
* @Route("/logo/unset", name="aqarmap_user_logo_unset")
*
* @Security("is_granted('ROLE_USER')")
*/
public function unsetLogo()
{
/** @var User $user */
$user = $this->getUser();
$user->setLogo(null);
$user->setIsValidLogo(false);
$response = new Response();
$response->headers->clearCookie('hide_logo_request');
$response->sendHeaders();
$userManager = $this->fosUserManager;
$userManager->updateUser($user);
$this->session->getFlashBag()->add(
'success',
$this->translator->trans('profile.flash.user_updated')
);
return new RedirectResponse($this->generateUrl('fos_user_profile_edit'));
}
/**
* Quick Registration Action.
*
* @Route("/", name="aqarmap_user_insert", options={"expose"=true}, methods={"POST"})
*
* @Rest\View()
*/
public function post(Request $request)
{
$userManager = $this->fosUserManager;
/** @var User $user */
$user = $userManager->createUser();
$form = $this->createForm(QuickRegistrationFormType::class, $user, [
'method' => 'POST',
'action' => $this->generateUrl('aqarmap_user_insert'),
'validation_groups' => ['simplified'],
'onlyEmail' => true,
]);
$form->handleRequest($request);
// Marking the user as a quick registered
$user->setIsQucikRegistered(true);
$usernameFromEmail = explode('@', $user->getEmail());
$user->setFullName($usernameFromEmail[0]);
$registered = $this->userManager->quickRegister($user, $form, $request, true, false, false, $request->get('registerWithPassword', false));
if (true === $registered) {
return [
'status' => 'ok',
'message' => $this->translator->trans('popup_form.success'),
];
}
return $form;
}
/**
* @Route("/interests/", name="aqarmap_my_interests")
*
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
*/
public function myInterests(Request $request)
{
$user = $this->getUser();
$em = $this->entityManager;
// Creating pagination
$paginator = $this->paginator;
$pagination = $paginator->paginate(
$em->getRepository(UserInterest::class)->getUserInterests($user, 20),
$request->query->get('page', 1),
20
);
return [
'interests' => $pagination,
];
}
/**
* @Route("/interests/{id}/pause", requirements={"id" = "\d+"}, name="aqarmap_interests_pause", methods={"GET"})
*
* @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_OWNER', entity)")
*/
public function pauseInterest(Request $request, UserInterest $entity): RedirectResponse
{
if (!$entity) {
throw $this->createNotFoundException('Unable to find this Interest.');
}
$em = $this->entityManager;
$entity->setStatus(UserInterestStatus::PAUSED);
// Save Changes
$em->persist($entity);
$em->flush();
// Set success flash message
$this->session->getFlashBag()->add(
'info',
$this->translator->trans('interest.paused_successfully')
);
return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
}
/**
* User Activity.
*
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
*
* @Route("/activity/{step}", name="user_activity", options={"expose"=true})
* @Route("/{userKey}/activity/{step}", name="user_activity_share", options={"expose"=true})
*/
public function activity(Request $request): Response
{
$request->query->add([
'user_key' => $request->attributes->get('userKey'),
'limit' => 1,
]);
if ($request->attributes->get('userKey')) {
$favourite = $this->favouriteService->getUserFavourite($request)->getResult();
}
return $this->render('@AqarmapUser/User/activity.html.twig', [
'favourite' => current($favourite ?? []),
'featureToggle' => $this->userActivityService->getFeatureToggles(),
]);
}
/**
* User Inbox.
*
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
*
* @Route("/inbox/", name="user_inbox", options={"expose"=true})
*/
public function inbox(): Response
{
$entityManager = $this->getDoctrine();
$featureToggleManager = $this->featureToggleManager;
return $this->render('@AqarmapUser/User/inbox.html.twig', [
'location' => $entityManager->getRepository(Location::class)->getFirstRoot(),
'propertyType' => $entityManager->getRepository(PropertyType::class)->getFirstRoot(),
'section' => $entityManager->getRepository(Section::class)->getFirstSection(),
'featureToggle' => [
'web.whats.app.chat' => $featureToggleManager->isEnabled('web.whats.app.chat'),
],
]);
}
/**
* User Message.
*
* @Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")
*
* @Route("/messages/{id}", name="user_message", options={"expose"=true})
*/
public function messages(): Response
{
$featureToggleManager = $this->featureToggleManager;
return $this->render('@AqarmapUser/User/inbox.html.twig', [
'featureToggle' => [
'web.whats.app.chat' => $featureToggleManager->isEnabled('web.whats.app.chat'),
],
]);
}
public function createQuickLeadForm(): FormInterface
{
return $this->createForm(
QuickLeadType::class,
null,
[
'action' => $this->generateUrl('add_quick_lead'),
'method' => 'POST',
]
);
}
/**
* @Route("/interests/unsubscribe/{locationId}", name="aqarmap_poke_notifier_unsubscribe", methods={"GET"})
*/
public function unsubscribeLocationNotifier(Request $request, int $locationId): RedirectResponse
{
$token = $request->query->get('token');
$subscriptionService = $this->notifierSubscriptionService;
$subscriptionService->unsubscribeLocation($locationId, $token);
return $this->redirect($this->generateUrl('homepage'));
}
/**
* @Route("/interests/unsubscribe", name="aqarmap_all_poke_notifiers_unsubscribe", methods={"GET"})
*/
public function unsubscribeAllNotifiers(Request $request): RedirectResponse
{
$token = $request->query->get('token');
$subscriptionService = $this->notifierSubscriptionService;
$subscriptionService->unsubscribeAll($token);
return $this->redirect($this->generateUrl('homepage'));
}
/**
* Google login action.
*
* @Route("/google/login", name="user_google_login")
*
* @return RedirectResponse
*/
public function googleLogin(Request $request)
{
$isGoogleToggleEnabled = $this->featureToggleManager->isEnabled('web.google.onetab');
if (!$isGoogleToggleEnabled) {
return $this->redirect($this->generateUrl('homepage'));
}
$client = $this->googleUserManager->createGoogleClient();
$code = $request->query->get('code');
if (!$code) {
$referer = $request->headers->get('referer');
$this->get('session')->set('referer_url', $referer);
return $this->redirect($client->createAuthUrl());
}
try {
$refererPage = $this->get('session')->get('referer_url') ?: $this->generateUrl('homepage');
$userData = $this->googleUserManager->getUserDataFromToken($client, $code);
} catch (\Exception $exception) {
$this->addFlash('danger', $this->translator->trans('user.something_went_wrong'));
return $this->redirect($refererPage);
}
$userHasNoRetrievedData = (!$userData->getId() && !$userData->getName() && !$userData->getEmail());
if ($userHasNoRetrievedData) {
$this->addFlash('danger', $this->translator->trans('user.something_went_wrong'));
return $this->redirect($refererPage);
}
$user = $this->googleUserManager->createOrUpdateUser($userData);
$data = [];
$data['token'] = $this->googleUserManager->createUserAccessToken($request->request->get('aqarmap_teleport_client_id'), $user);
$data['referer'] = $refererPage;
$userToken = $this->userAuthenticationServiceV3->generateToken($user, false);
$this->usageTrackingTokenStorage->setToken($userToken);
$this->get('session')->set('_security_main', serialize($userToken));
return $this->render('@AqarmapUser/User/google_call_back.html.twig', ['data' => $data]);
}
private function redirectToFirstPage(Request $request, User $user, ?Location $location = null): RedirectResponse
{
$request->query->remove('page');
return $this->redirect($this->generateUrl('aqarmap_user_listings', [
'id' => $user->getId(),
'location' => $location ? $location->getSlug() : null,
]), Response::HTTP_MOVED_PERMANENTLY);
}
}