local/modules/Front/Controller/CustomerController.php line 56

  1. <?php
  2. /*
  3.  * This file is part of the Thelia package.
  4.  * http://www.thelia.net
  5.  *
  6.  * (c) OpenStudio <info@thelia.net>
  7.  *
  8.  * For the full copyright and license information, please view the LICENSE
  9.  * file that was distributed with this source code.
  10.  */
  11. namespace Front\Controller;
  12. use Front\Front;
  13. use Symfony\Component\Form\Extension\Core\Type\FormType;
  14. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  15. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  16. use Thelia\Controller\Front\BaseFrontController;
  17. use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
  18. use Thelia\Core\Event\Customer\CustomerEvent;
  19. use Thelia\Core\Event\Customer\CustomerLoginEvent;
  20. use Thelia\Core\Event\DefaultActionEvent;
  21. use Thelia\Core\Event\LostPasswordEvent;
  22. use Thelia\Core\Event\Newsletter\NewsletterEvent;
  23. use Thelia\Core\Event\TheliaEvents;
  24. use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator;
  25. use Thelia\Core\Security\Exception\AuthenticationException;
  26. use Thelia\Core\Security\Exception\CustomerNotConfirmedException;
  27. use Thelia\Core\Security\Exception\UsernameNotFoundException;
  28. use Thelia\Core\Security\Exception\WrongPasswordException;
  29. use Thelia\Form\CustomerLogin;
  30. use Thelia\Form\Definition\FrontForm;
  31. use Thelia\Form\Exception\FormValidationException;
  32. use Thelia\Log\Tlog;
  33. use Thelia\Model\ConfigQuery;
  34. use Thelia\Model\Customer;
  35. use Thelia\Model\CustomerQuery;
  36. use Thelia\Model\Newsletter;
  37. use Thelia\Model\NewsletterQuery;
  38. use Thelia\Tools\RememberMeTrait;
  39. use Thelia\Tools\URL;
  40. /**
  41.  * Class CustomerController.
  42.  *
  43.  * @author Manuel Raynaud <manu@raynaud.io>
  44.  */
  45. class CustomerController extends BaseFrontController
  46. {
  47.     use RememberMeTrait;
  48.     /**
  49.      * Display the register template if no customer logged.
  50.      */
  51.     public function viewLoginAction()
  52.     {
  53.         if ($this->getSecurityContext()->hasCustomerUser()) {
  54.             // Redirect to home page
  55.             return $this->generateRedirect(URL::getInstance()->getIndexPage());
  56.         }
  57.         return $this->render('login');
  58.     }
  59.     /**
  60.      * Display the register template if no customer logged.
  61.      */
  62.     public function viewRegisterAction()
  63.     {
  64.         if ($this->getSecurityContext()->hasCustomerUser()) {
  65.             // Redirect to home page
  66.             return $this->generateRedirect(URL::getInstance()->getIndexPage());
  67.         }
  68.         return $this->render('register');
  69.     }
  70.     public function newPasswordAction(EventDispatcherInterface $eventDispatcher)
  71.     {
  72.         $passwordLost $this->createForm(FrontForm::CUSTOMER_LOST_PASSWORD);
  73.         if (!$this->getSecurityContext()->hasCustomerUser()) {
  74.             try {
  75.                 $form $this->validateForm($passwordLost);
  76.                 $event = new LostPasswordEvent($form->get('email')->getData());
  77.                 $eventDispatcher->dispatch($eventTheliaEvents::LOST_PASSWORD);
  78.                 return $this->generateSuccessRedirect($passwordLost);
  79.             } catch (FormValidationException $e) {
  80.                 $message $this->getTranslator()->trans(
  81.                     'Please check your input: %s',
  82.                     [
  83.                         '%s' => $e->getMessage(),
  84.                     ],
  85.                     Front::MESSAGE_DOMAIN
  86.                 );
  87.             } catch (\Exception $e) {
  88.                 $message $this->getTranslator()->trans(
  89.                     'Sorry, an error occurred: %s',
  90.                     [
  91.                         '%s' => $e->getMessage(),
  92.                     ],
  93.                     Front::MESSAGE_DOMAIN
  94.                 );
  95.             }
  96.             if ($message !== false) {
  97.                 Tlog::getInstance()->error(
  98.                     sprintf(
  99.                         'Error during customer creation process : %s. Exception was %s',
  100.                         $message,
  101.                         $e->getMessage()
  102.                     )
  103.                 );
  104.             }
  105.         } else {
  106.             $message $this->getTranslator()->trans(
  107.                 "You're currently logged in. Please log out before requesting a new password.",
  108.                 [],
  109.                 Front::MESSAGE_DOMAIN
  110.             );
  111.         }
  112.         $passwordLost->setErrorMessage($message);
  113.         $this->getParserContext()
  114.             ->addForm($passwordLost)
  115.             ->setGeneralError($message)
  116.         ;
  117.         // Redirect to error URL if defined
  118.         if ($passwordLost->hasErrorUrl()) {
  119.             return $this->generateErrorRedirect($passwordLost);
  120.         }
  121.     }
  122.     public function newPasswordSentAction(): void
  123.     {
  124.         $this->getParser()->assign('password_sent'true);
  125.     }
  126.     /**
  127.      * Create a new customer.
  128.      * On success, redirect to success_url if exists, otherwise, display the same view again.
  129.      */
  130.     public function createAction(EventDispatcherInterface $eventDispatcher)
  131.     {
  132.         if (!$this->getSecurityContext()->hasCustomerUser()) {
  133.             $customerCreation $this->createForm(FrontForm::CUSTOMER_CREATE);
  134.             try {
  135.                 $form $this->validateForm($customerCreation'post');
  136.                 $customerCreateEvent $this->createEventInstance($form->getData());
  137.                 $eventDispatcher->dispatch($customerCreateEventTheliaEvents::CUSTOMER_CREATEACCOUNT);
  138.                 $newCustomer $customerCreateEvent->getCustomer();
  139.                 // Newsletter
  140.                 if (true === $form->get('newsletter')->getData()) {
  141.                     $newsletterEmail $newCustomer->getEmail();
  142.                     $nlEvent = new NewsletterEvent(
  143.                         $newsletterEmail,
  144.                         $this->getRequest()->getSession()->getLang()->getLocale()
  145.                     );
  146.                     $nlEvent->setFirstname($newCustomer->getFirstname());
  147.                     $nlEvent->setLastname($newCustomer->getLastname());
  148.                     // Security : Check if this new Email address already exist
  149.                     if (null !== $newsletter NewsletterQuery::create()->findOneByEmail($newsletterEmail)) {
  150.                         $nlEvent->setId($newsletter->getId());
  151.                         $eventDispatcher->dispatch($nlEventTheliaEvents::NEWSLETTER_UPDATE);
  152.                     } else {
  153.                         $eventDispatcher->dispatch($nlEventTheliaEvents::NEWSLETTER_SUBSCRIBE);
  154.                     }
  155.                 }
  156.                 if (ConfigQuery::isCustomerEmailConfirmationEnable() && !$newCustomer->getEnable()) {
  157.                     $response $this->generateRedirectFromRoute('customer.login.view');
  158.                 } else {
  159.                     $this->processLogin($eventDispatcher$customerCreateEvent->getCustomer());
  160.                     $cart $this->getSession()->getSessionCart($eventDispatcher);
  161.                     if ($cart->getCartItems()->count() > 0) {
  162.                         $response $this->generateRedirectFromRoute('cart.view');
  163.                     } else {
  164.                         $response $this->generateSuccessRedirect($customerCreation);
  165.                     }
  166.                 }
  167.                 return $response;
  168.             } catch (FormValidationException $e) {
  169.                 $message $this->getTranslator()->trans(
  170.                     'Please check your input: %s',
  171.                     [
  172.                         '%s' => $e->getMessage(),
  173.                     ],
  174.                     Front::MESSAGE_DOMAIN
  175.                 );
  176.             } catch (\Exception $e) {
  177.                 $message $this->getTranslator()->trans(
  178.                     'Sorry, an error occured: %s',
  179.                     [
  180.                         '%s' => $e->getMessage(),
  181.                     ],
  182.                     Front::MESSAGE_DOMAIN
  183.                 );
  184.             }
  185.             Tlog::getInstance()->error(
  186.                 sprintf(
  187.                     'Error during customer creation process : %s. Exception was %s',
  188.                     $message,
  189.                     $e->getMessage()
  190.                 )
  191.             );
  192.             $customerCreation->setErrorMessage($message);
  193.             $this->getParserContext()
  194.                 ->addForm($customerCreation)
  195.                 ->setGeneralError($message)
  196.             ;
  197.             // Redirect to error URL if defined
  198.             if ($customerCreation->hasErrorUrl()) {
  199.                 return $this->generateErrorRedirect($customerCreation);
  200.             }
  201.         }
  202.     }
  203.     /**
  204.      * Prepare customer data update.
  205.      */
  206.     public function viewAction(): void
  207.     {
  208.         $this->checkAuth();
  209.         /** @var Customer $customer */
  210.         $customer $this->getSecurityContext()->getCustomerUser();
  211.         $newsletter NewsletterQuery::create()->findOneByEmail($customer->getEmail());
  212.         $data = [
  213.             'id' => $customer->getId(),
  214.             'title' => $customer->getTitleId(),
  215.             'firstname' => $customer->getFirstName(),
  216.             'lastname' => $customer->getLastName(),
  217.             'email' => $customer->getEmail(),
  218.             'email_confirm' => $customer->getEmail(),
  219.             'lang_id' => $customer->getLangId(),
  220.             'newsletter' => $newsletter instanceof Newsletter ? !$newsletter->getUnsubscribed() : false,
  221.         ];
  222.         $customerProfileUpdateForm $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATEFormType::class, $data);
  223.         // Pass it to the parser
  224.         $this->getParserContext()->addForm($customerProfileUpdateForm);
  225.     }
  226.     public function updatePasswordAction(EventDispatcherInterface $eventDispatcher)
  227.     {
  228.         if ($this->getSecurityContext()->hasCustomerUser()) {
  229.             $customerPasswordUpdateForm $this->createForm(FrontForm::CUSTOMER_PASSWORD_UPDATE);
  230.             try {
  231.                 /** @var Customer $customer */
  232.                 $customer $this->getSecurityContext()->getCustomerUser();
  233.                 $form $this->validateForm($customerPasswordUpdateForm'post');
  234.                 $customerChangeEvent $this->createEventInstance($form->getData());
  235.                 $customerChangeEvent->setCustomer($customer);
  236.                 $eventDispatcher->dispatch($customerChangeEventTheliaEvents::CUSTOMER_UPDATEPROFILE);
  237.                 return $this->generateSuccessRedirect($customerPasswordUpdateForm);
  238.             } catch (FormValidationException $e) {
  239.                 $message $this->getTranslator()->trans(
  240.                     'Please check your input: %s',
  241.                     [
  242.                         '%s' => $e->getMessage(),
  243.                     ],
  244.                     Front::MESSAGE_DOMAIN
  245.                 );
  246.             } catch (\Exception $e) {
  247.                 $message $this->getTranslator()->trans(
  248.                     'Sorry, an error occured: %s',
  249.                     [
  250.                         '%s' => $e->getMessage(),
  251.                     ],
  252.                     Front::MESSAGE_DOMAIN
  253.                 );
  254.             }
  255.             Tlog::getInstance()->error(
  256.                 sprintf(
  257.                     'Error during customer password modification process : %s.',
  258.                     $message
  259.                 )
  260.             );
  261.             $customerPasswordUpdateForm->setErrorMessage($message);
  262.             $this->getParserContext()
  263.                 ->addForm($customerPasswordUpdateForm)
  264.                 ->setGeneralError($message)
  265.             ;
  266.             // Redirect to error URL if defined
  267.             if ($customerPasswordUpdateForm->hasErrorUrl()) {
  268.                 return $this->generateErrorRedirect($customerPasswordUpdateForm);
  269.             }
  270.         }
  271.     }
  272.     public function updateAction(EventDispatcherInterface $eventDispatcher)
  273.     {
  274.         if ($this->getSecurityContext()->hasCustomerUser()) {
  275.             $customerProfileUpdateForm $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATE);
  276.             try {
  277.                 /** @var Customer $customer */
  278.                 $customer $this->getSecurityContext()->getCustomerUser();
  279.                 $newsletterOldEmail $customer->getEmail();
  280.                 $form $this->validateForm($customerProfileUpdateForm'post');
  281.                 $customerChangeEvent $this->createEventInstance($form->getData());
  282.                 $customerChangeEvent->setCustomer($customer);
  283.                 $customerChangeEvent->setEmailUpdateAllowed(
  284.                     ((int) ConfigQuery::read('customer_change_email'0)) ? true false
  285.                 );
  286.                 $eventDispatcher->dispatch($customerChangeEventTheliaEvents::CUSTOMER_UPDATEPROFILE);
  287.                 $updatedCustomer $customerChangeEvent->getCustomer();
  288.                 // Newsletter
  289.                 if (true === $form->get('newsletter')->getData()) {
  290.                     $nlEvent = new NewsletterEvent(
  291.                         $updatedCustomer->getEmail(),
  292.                         $this->getRequest()->getSession()->getLang()->getLocale()
  293.                     );
  294.                     $nlEvent->setFirstname($updatedCustomer->getFirstname());
  295.                     $nlEvent->setLastname($updatedCustomer->getLastname());
  296.                     if (null !== $newsletter NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) {
  297.                         $nlEvent->setId($newsletter->getId());
  298.                         $eventDispatcher->dispatch($nlEventTheliaEvents::NEWSLETTER_UPDATE);
  299.                     } else {
  300.                         $eventDispatcher->dispatch($nlEventTheliaEvents::NEWSLETTER_SUBSCRIBE);
  301.                     }
  302.                 } else {
  303.                     if (null !== $newsletter NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) {
  304.                         $nlEvent = new NewsletterEvent(
  305.                             $updatedCustomer->getEmail(),
  306.                             $this->getRequest()->getSession()->getLang()->getLocale()
  307.                         );
  308.                         $nlEvent->setId($newsletter->getId());
  309.                         $eventDispatcher->dispatch($nlEventTheliaEvents::NEWSLETTER_UNSUBSCRIBE);
  310.                     }
  311.                 }
  312.                 $this->processLogin($eventDispatcher$updatedCustomer);
  313.                 return $this->generateSuccessRedirect($customerProfileUpdateForm);
  314.             } catch (FormValidationException $e) {
  315.                 $message $this->getTranslator()->trans(
  316.                     'Please check your input: %s',
  317.                     [
  318.                         '%s' => $e->getMessage(),
  319.                     ],
  320.                     Front::MESSAGE_DOMAIN
  321.                 );
  322.             } catch (\Exception $e) {
  323.                 $message $this->getTranslator()->trans(
  324.                     'Sorry, an error occured: %s',
  325.                     [
  326.                         '%s' => $e->getMessage(),
  327.                     ],
  328.                     Front::MESSAGE_DOMAIN
  329.                 );
  330.             }
  331.             Tlog::getInstance()->error(sprintf('Error during customer modification process : %s.'$message));
  332.             $customerProfileUpdateForm->setErrorMessage($message);
  333.             $this->getParserContext()
  334.                 ->addForm($customerProfileUpdateForm)
  335.                 ->setGeneralError($message)
  336.             ;
  337.             // Redirect to error URL if defined
  338.             if ($customerProfileUpdateForm->hasErrorUrl()) {
  339.                 return $this->generateErrorRedirect($customerProfileUpdateForm);
  340.             }
  341.         }
  342.     }
  343.     /**
  344.      * Perform user login. On a successful login, the user is redirected to the URL
  345.      * found in the success_url form parameter, or / if none was found.
  346.      *
  347.      * If login is not successfull, the same view is displayed again.
  348.      */
  349.     public function loginAction(EventDispatcherInterface $eventDispatcher)
  350.     {
  351.         if (!$this->getSecurityContext()->hasCustomerUser()) {
  352.             $request $this->getRequest();
  353.             $customerLoginForm $this->createForm(CustomerLogin::class);
  354.             try {
  355.                 $form $this->validateForm($customerLoginForm'post');
  356.                 // If User is a new customer
  357.                 if ($form->get('account')->getData() == && $form->get('email')->getErrors()->count() == 0) {
  358.                     return $this->generateRedirectFromRoute(
  359.                         'customer.create.process',
  360.                         ['email' => $form->get('email')->getData()]
  361.                     );
  362.                 }
  363.                 try {
  364.                     $authenticator = new CustomerUsernamePasswordFormAuthenticator($request$customerLoginForm);
  365.                     /** @var Customer $customer */
  366.                     $customer $authenticator->getAuthentifiedUser();
  367.                     $this->processLogin($eventDispatcher$customer);
  368.                     if ((int) $form->get('remember_me')->getData() > 0) {
  369.                         // If a remember me field if present and set in the form, create
  370.                         // the cookie thant store "remember me" information
  371.                         $this->createRememberMeCookie(
  372.                             $customer,
  373.                             $this->getRememberMeCookieName(),
  374.                             $this->getRememberMeCookieExpiration()
  375.                         );
  376.                     }
  377.                     return $this->generateSuccessRedirect($customerLoginForm);
  378.                 } catch (UsernameNotFoundException $e) {
  379.                     $message $this->getTranslator()->trans(
  380.                         'Wrong email or password. Please try again',
  381.                         [],
  382.                         Front::MESSAGE_DOMAIN
  383.                     );
  384.                 } catch (WrongPasswordException $e) {
  385.                     $message $this->getTranslator()->trans(
  386.                         'Wrong email or password. Please try again',
  387.                         [],
  388.                         Front::MESSAGE_DOMAIN
  389.                     );
  390.                 } catch (CustomerNotConfirmedException $e) {
  391.                     if ($e->getUser() !== null) {
  392.                         // Send the confirmation email again
  393.                         $eventDispatcher->dispatch(
  394.                             new CustomerEvent($e->getUser()),
  395.                             TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL
  396.                         );
  397.                     }
  398.                     $message $this->getTranslator()->trans(
  399.                         'Your account is not yet confirmed. A confirmation email has been sent to your email address, please check your mailbox',
  400.                         [],
  401.                         Front::MESSAGE_DOMAIN
  402.                     );
  403.                 } catch (AuthenticationException $e) {
  404.                     $message $this->getTranslator()->trans(
  405.                         'Wrong email or password. Please try again',
  406.                         [],
  407.                         Front::MESSAGE_DOMAIN
  408.                     );
  409.                 }
  410.             } catch (FormValidationException $e) {
  411.                 $message $this->getTranslator()->trans(
  412.                     'Please check your input: %s',
  413.                     ['%s' => $e->getMessage()],
  414.                     Front::MESSAGE_DOMAIN
  415.                 );
  416.             } catch (\Exception $e) {
  417.                 $message $this->getTranslator()->trans(
  418.                     'Sorry, an error occured: %s',
  419.                     ['%s' => $e->getMessage()],
  420.                     Front::MESSAGE_DOMAIN
  421.                 );
  422.             }
  423.             Tlog::getInstance()->error(
  424.                 sprintf(
  425.                     'Error during customer login process : %s. Exception was %s',
  426.                     $message,
  427.                     $e->getMessage()
  428.                 )
  429.             );
  430.             $customerLoginForm->setErrorMessage($message);
  431.             $this->getParserContext()->addForm($customerLoginForm);
  432.             if ($customerLoginForm->hasErrorUrl()) {
  433.                 return $this->generateErrorRedirect($customerLoginForm);
  434.             }
  435.         }
  436.     }
  437.     /**
  438.      * Perform customer logout.
  439.      */
  440.     public function logoutAction(EventDispatcherInterface $eventDispatcher)
  441.     {
  442.         if ($this->getSecurityContext()->hasCustomerUser()) {
  443.             $eventDispatcher->dispatch(new DefaultActionEvent(), TheliaEvents::CUSTOMER_LOGOUT);
  444.         }
  445.         $this->clearRememberMeCookie($this->getRememberMeCookieName());
  446.         // Redirect to home page
  447.         return $this->generateRedirect(URL::getInstance()->getIndexPage());
  448.     }
  449.     /**
  450.      * @throws \Exception
  451.      * @throws \Propel\Runtime\Exception\PropelException
  452.      *
  453.      * @return \Symfony\Component\HttpFoundation\Response
  454.      */
  455.     public function confirmCustomerAction($token)
  456.     {
  457.         /** @var Customer $customer */
  458.         if (null === $customer CustomerQuery::create()->findOneByConfirmationToken($token)) {
  459.             throw new NotFoundHttpException();
  460.         }
  461.         $customer
  462.             ->setEnable(true)
  463.             ->save()
  464.         ;
  465.         // Clear form error context
  466.         return $this->generateRedirectFromRoute('customer.login.view', ['validation_done' => 1]);
  467.     }
  468.     /**
  469.      * Dispatch event for customer login action.
  470.      */
  471.     protected function processLogin(EventDispatcherInterface $eventDispatcherCustomer $customer): void
  472.     {
  473.         $eventDispatcher->dispatch(new CustomerLoginEvent($customer), TheliaEvents::CUSTOMER_LOGIN);
  474.     }
  475.     /**
  476.      * @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent
  477.      */
  478.     private function createEventInstance($data)
  479.     {
  480.         $customerCreateEvent = new CustomerCreateOrUpdateEvent(
  481.             $data['title'] ?? null,
  482.             $data['firstname'] ?? null,
  483.             $data['lastname'] ?? null,
  484.             $data['address1'] ?? null,
  485.             $data['address2'] ?? null,
  486.             $data['address3'] ?? null,
  487.             $data['phone'] ?? null,
  488.             $data['cellphone'] ?? null,
  489.             $data['zipcode'] ?? null,
  490.             $data['city'] ?? null,
  491.             $data['country'] ?? null,
  492.             $data['email'] ?? null,
  493.             $data['password'] ?? null,
  494.             $data['lang_id'] ?? $this->getSession()->getLang()->getId(),
  495.             $data['reseller'] ?? null,
  496.             $data['sponsor'] ?? null,
  497.             $data['discount'] ?? null,
  498.             $data['company'] ?? null,
  499.             null,
  500.             $data['state'] ?? null
  501.         );
  502.         return $customerCreateEvent;
  503.     }
  504.     protected function getRememberMeCookieName()
  505.     {
  506.         return ConfigQuery::read('customer_remember_me_cookie_name''crmcn');
  507.     }
  508.     protected function getRememberMeCookieExpiration()
  509.     {
  510.         return ConfigQuery::read('customer_remember_me_cookie_expiration'2592000 /* 1 month */);
  511.     }
  512. }