Files
domokits-NEW/domokits/local/modules/Front/Controller/CustomerController.php

596 lines
22 KiB
PHP

<?php
/*
* This file is part of the Thelia package.
* http://www.thelia.net
*
* (c) OpenStudio <info@thelia.net>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Front\Controller;
use Front\Front;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Thelia\Controller\Front\BaseFrontController;
use Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent;
use Thelia\Core\Event\Customer\CustomerLoginEvent;
use Thelia\Core\Event\DefaultActionEvent;
use Thelia\Core\Event\LostPasswordEvent;
use Thelia\Core\Event\Newsletter\NewsletterEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Security\Authentication\CustomerUsernamePasswordFormAuthenticator;
use Thelia\Core\Security\Exception\AuthenticationException;
use Thelia\Core\Security\Exception\CustomerNotConfirmedException;
use Thelia\Core\Security\Exception\UsernameNotFoundException;
use Thelia\Core\Security\Exception\WrongPasswordException;
use Thelia\Form\CustomerLogin;
use Thelia\Form\Definition\FrontForm;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Log\Tlog;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Customer;
use Thelia\Model\CustomerQuery;
use Thelia\Model\Event\CustomerEvent;
use Thelia\Model\Newsletter;
use Thelia\Model\NewsletterQuery;
use Thelia\Tools\RememberMeTrait;
use Thelia\Tools\URL;
/**
* Class CustomerController.
*
* @author Manuel Raynaud <manu@raynaud.io>
*/
class CustomerController extends BaseFrontController
{
use RememberMeTrait;
/**
* Display the register template if no customer logged.
*/
public function viewLoginAction()
{
if ($this->getSecurityContext()->hasCustomerUser()) {
// Redirect to home page
return $this->generateRedirect(URL::getInstance()->getIndexPage());
}
return $this->render('login');
}
/**
* Display the register template if no customer logged.
*/
public function viewRegisterAction()
{
if ($this->getSecurityContext()->hasCustomerUser()) {
// Redirect to home page
return $this->generateRedirect(URL::getInstance()->getIndexPage());
}
return $this->render('register');
}
public function newPasswordAction(EventDispatcherInterface $eventDispatcher)
{
$passwordLost = $this->createForm(FrontForm::CUSTOMER_LOST_PASSWORD);
if (!$this->getSecurityContext()->hasCustomerUser()) {
try {
$form = $this->validateForm($passwordLost);
$event = new LostPasswordEvent($form->get('email')->getData());
$eventDispatcher->dispatch($event, TheliaEvents::LOST_PASSWORD);
return $this->generateSuccessRedirect($passwordLost);
} catch (FormValidationException $e) {
$message = $this->getTranslator()->trans(
'Please check your input: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Sorry, an error occurred: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
}
if ($message !== false) {
Tlog::getInstance()->error(
sprintf(
'Error during customer creation process : %s. Exception was %s',
$message,
$e->getMessage()
)
);
}
} else {
$message = $this->getTranslator()->trans(
"You're currently logged in. Please log out before requesting a new password.",
[],
Front::MESSAGE_DOMAIN
);
}
$passwordLost->setErrorMessage($message);
$this->getParserContext()
->addForm($passwordLost)
->setGeneralError($message)
;
// Redirect to error URL if defined
if ($passwordLost->hasErrorUrl()) {
return $this->generateErrorRedirect($passwordLost);
}
}
public function newPasswordSentAction(): void
{
$this->getParser()->assign('password_sent', true);
}
/**
* Create a new customer.
* On success, redirect to success_url if exists, otherwise, display the same view again.
*/
public function createAction(EventDispatcherInterface $eventDispatcher)
{
if (!$this->getSecurityContext()->hasCustomerUser()) {
$customerCreation = $this->createForm(FrontForm::CUSTOMER_CREATE);
try {
$form = $this->validateForm($customerCreation, 'post');
$customerCreateEvent = $this->createEventInstance($form->getData());
$eventDispatcher->dispatch($customerCreateEvent, TheliaEvents::CUSTOMER_CREATEACCOUNT);
$newCustomer = $customerCreateEvent->getCustomer();
// Newsletter
if (true === $form->get('newsletter')->getData()) {
$newsletterEmail = $newCustomer->getEmail();
$nlEvent = new NewsletterEvent(
$newsletterEmail,
$this->getRequest()->getSession()->getLang()->getLocale()
);
$nlEvent->setFirstname($newCustomer->getFirstname());
$nlEvent->setLastname($newCustomer->getLastname());
// Security : Check if this new Email address already exist
if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterEmail)) {
$nlEvent->setId($newsletter->getId());
$eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_UPDATE);
} else {
$eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_SUBSCRIBE);
}
}
if (ConfigQuery::isCustomerEmailConfirmationEnable() && !$newCustomer->getEnable()) {
$response = $this->generateRedirectFromRoute('customer.login.view');
} else {
$this->processLogin($eventDispatcher, $customerCreateEvent->getCustomer());
$cart = $this->getSession()->getSessionCart($eventDispatcher);
if ($cart->getCartItems()->count() > 0) {
$response = $this->generateRedirectFromRoute('cart.view');
} else {
$response = $this->generateSuccessRedirect($customerCreation);
}
}
return $response;
} catch (FormValidationException $e) {
$message = $this->getTranslator()->trans(
'Please check your input: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Sorry, an error occured: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
}
Tlog::getInstance()->error(
sprintf(
'Error during customer creation process : %s. Exception was %s',
$message,
$e->getMessage()
)
);
$customerCreation->setErrorMessage($message);
$this->getParserContext()
->addForm($customerCreation)
->setGeneralError($message)
;
// Redirect to error URL if defined
if ($customerCreation->hasErrorUrl()) {
return $this->generateErrorRedirect($customerCreation);
}
}
}
/**
* Prepare customer data update.
*/
public function viewAction(): void
{
$this->checkAuth();
/** @var Customer $customer */
$customer = $this->getSecurityContext()->getCustomerUser();
$newsletter = NewsletterQuery::create()->findOneByEmail($customer->getEmail());
$data = [
'id' => $customer->getId(),
'title' => $customer->getTitleId(),
'firstname' => $customer->getFirstName(),
'lastname' => $customer->getLastName(),
'email' => $customer->getEmail(),
'email_confirm' => $customer->getEmail(),
'lang_id' => $customer->getLangId(),
'newsletter' => $newsletter instanceof Newsletter ? !$newsletter->getUnsubscribed() : false,
];
$customerProfileUpdateForm = $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATE, FormType::class, $data);
// Pass it to the parser
$this->getParserContext()->addForm($customerProfileUpdateForm);
}
public function updatePasswordAction(EventDispatcherInterface $eventDispatcher)
{
if ($this->getSecurityContext()->hasCustomerUser()) {
$customerPasswordUpdateForm = $this->createForm(FrontForm::CUSTOMER_PASSWORD_UPDATE);
try {
/** @var Customer $customer */
$customer = $this->getSecurityContext()->getCustomerUser();
$form = $this->validateForm($customerPasswordUpdateForm, 'post');
$customerChangeEvent = $this->createEventInstance($form->getData());
$customerChangeEvent->setCustomer($customer);
$eventDispatcher->dispatch($customerChangeEvent, TheliaEvents::CUSTOMER_UPDATEPROFILE);
return $this->generateSuccessRedirect($customerPasswordUpdateForm);
} catch (FormValidationException $e) {
$message = $this->getTranslator()->trans(
'Please check your input: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Sorry, an error occured: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
}
Tlog::getInstance()->error(
sprintf(
'Error during customer password modification process : %s.',
$message
)
);
$customerPasswordUpdateForm->setErrorMessage($message);
$this->getParserContext()
->addForm($customerPasswordUpdateForm)
->setGeneralError($message)
;
// Redirect to error URL if defined
if ($customerPasswordUpdateForm->hasErrorUrl()) {
return $this->generateErrorRedirect($customerPasswordUpdateForm);
}
}
}
public function updateAction(EventDispatcherInterface $eventDispatcher)
{
if ($this->getSecurityContext()->hasCustomerUser()) {
$customerProfileUpdateForm = $this->createForm(FrontForm::CUSTOMER_PROFILE_UPDATE);
try {
/** @var Customer $customer */
$customer = $this->getSecurityContext()->getCustomerUser();
$newsletterOldEmail = $customer->getEmail();
$form = $this->validateForm($customerProfileUpdateForm, 'post');
$customerChangeEvent = $this->createEventInstance($form->getData());
$customerChangeEvent->setCustomer($customer);
$customerChangeEvent->setEmailUpdateAllowed(
((int) ConfigQuery::read('customer_change_email', 0)) ? true : false
);
$eventDispatcher->dispatch($customerChangeEvent, TheliaEvents::CUSTOMER_UPDATEPROFILE);
$updatedCustomer = $customerChangeEvent->getCustomer();
// Newsletter
if (true === $form->get('newsletter')->getData()) {
$nlEvent = new NewsletterEvent(
$updatedCustomer->getEmail(),
$this->getRequest()->getSession()->getLang()->getLocale()
);
$nlEvent->setFirstname($updatedCustomer->getFirstname());
$nlEvent->setLastname($updatedCustomer->getLastname());
if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) {
$nlEvent->setId($newsletter->getId());
$eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_UPDATE);
} else {
$eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_SUBSCRIBE);
}
} else {
if (null !== $newsletter = NewsletterQuery::create()->findOneByEmail($newsletterOldEmail)) {
$nlEvent = new NewsletterEvent(
$updatedCustomer->getEmail(),
$this->getRequest()->getSession()->getLang()->getLocale()
);
$nlEvent->setId($newsletter->getId());
$eventDispatcher->dispatch($nlEvent, TheliaEvents::NEWSLETTER_UNSUBSCRIBE);
}
}
$this->processLogin($eventDispatcher, $updatedCustomer);
return $this->generateSuccessRedirect($customerProfileUpdateForm);
} catch (FormValidationException $e) {
$message = $this->getTranslator()->trans(
'Please check your input: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Sorry, an error occured: %s',
[
'%s' => $e->getMessage(),
],
Front::MESSAGE_DOMAIN
);
}
Tlog::getInstance()->error(sprintf('Error during customer modification process : %s.', $message));
$customerProfileUpdateForm->setErrorMessage($message);
$this->getParserContext()
->addForm($customerProfileUpdateForm)
->setGeneralError($message)
;
// Redirect to error URL if defined
if ($customerProfileUpdateForm->hasErrorUrl()) {
return $this->generateErrorRedirect($customerProfileUpdateForm);
}
}
}
/**
* Perform user login. On a successful login, the user is redirected to the URL
* found in the success_url form parameter, or / if none was found.
*
* If login is not successfull, the same view is displayed again.
*/
public function loginAction(EventDispatcherInterface $eventDispatcher)
{
if (!$this->getSecurityContext()->hasCustomerUser()) {
$request = $this->getRequest();
$customerLoginForm = $this->createForm(CustomerLogin::class);
try {
$form = $this->validateForm($customerLoginForm, 'post');
// If User is a new customer
if ($form->get('account')->getData() == 0 && $form->get('email')->getErrors()->count() == 0) {
return $this->generateRedirectFromRoute(
'customer.create.process',
['email' => $form->get('email')->getData()]
);
}
try {
$authenticator = new CustomerUsernamePasswordFormAuthenticator($request, $customerLoginForm);
/** @var Customer $customer */
$customer = $authenticator->getAuthentifiedUser();
$this->processLogin($eventDispatcher, $customer);
if ((int) $form->get('remember_me')->getData() > 0) {
// If a remember me field if present and set in the form, create
// the cookie thant store "remember me" information
$this->createRememberMeCookie(
$customer,
$this->getRememberMeCookieName(),
$this->getRememberMeCookieExpiration()
);
}
return $this->generateSuccessRedirect($customerLoginForm);
} catch (UsernameNotFoundException $e) {
$message = $this->getTranslator()->trans(
'Wrong email or password. Please try again',
[],
Front::MESSAGE_DOMAIN
);
} catch (WrongPasswordException $e) {
$message = $this->getTranslator()->trans(
'Wrong email or password. Please try again',
[],
Front::MESSAGE_DOMAIN
);
} catch (CustomerNotConfirmedException $e) {
if ($e->getUser() !== null) {
// Send the confirmation email again
$eventDispatcher->dispatch(
new CustomerEvent($e->getUser()),
TheliaEvents::SEND_ACCOUNT_CONFIRMATION_EMAIL
);
}
$message = $this->getTranslator()->trans(
'Your account is not yet confirmed. A confirmation email has been sent to your email address, please check your mailbox',
[],
Front::MESSAGE_DOMAIN
);
} catch (AuthenticationException $e) {
$message = $this->getTranslator()->trans(
'Wrong email or password. Please try again',
[],
Front::MESSAGE_DOMAIN
);
}
} catch (FormValidationException $e) {
$message = $this->getTranslator()->trans(
'Please check your input: %s',
['%s' => $e->getMessage()],
Front::MESSAGE_DOMAIN
);
} catch (\Exception $e) {
$message = $this->getTranslator()->trans(
'Sorry, an error occured: %s',
['%s' => $e->getMessage()],
Front::MESSAGE_DOMAIN
);
}
Tlog::getInstance()->error(
sprintf(
'Error during customer login process : %s. Exception was %s',
$message,
$e->getMessage()
)
);
$customerLoginForm->setErrorMessage($message);
$this->getParserContext()->addForm($customerLoginForm);
if ($customerLoginForm->hasErrorUrl()) {
return $this->generateErrorRedirect($customerLoginForm);
}
}
}
/**
* Perform customer logout.
*/
public function logoutAction(EventDispatcherInterface $eventDispatcher)
{
if ($this->getSecurityContext()->hasCustomerUser()) {
$eventDispatcher->dispatch(new DefaultActionEvent(), TheliaEvents::CUSTOMER_LOGOUT);
}
$this->clearRememberMeCookie($this->getRememberMeCookieName());
// Redirect to home page
return $this->generateRedirect(URL::getInstance()->getIndexPage());
}
/**
* @throws \Exception
* @throws \Propel\Runtime\Exception\PropelException
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function confirmCustomerAction($token)
{
/** @var Customer $customer */
if (null === $customer = CustomerQuery::create()->findOneByConfirmationToken($token)) {
throw new NotFoundHttpException();
}
$customer
->setEnable(true)
->save()
;
// Clear form error context
return $this->generateRedirectFromRoute('customer.login.view', ['validation_done' => 1]);
}
/**
* Dispatch event for customer login action.
*/
protected function processLogin(EventDispatcherInterface $eventDispatcher, Customer $customer): void
{
$eventDispatcher->dispatch(new CustomerLoginEvent($customer), TheliaEvents::CUSTOMER_LOGIN);
}
/**
* @return \Thelia\Core\Event\Customer\CustomerCreateOrUpdateEvent
*/
private function createEventInstance($data)
{
$customerCreateEvent = new CustomerCreateOrUpdateEvent(
$data['title'] ?? null,
$data['firstname'] ?? null,
$data['lastname'] ?? null,
$data['address1'] ?? null,
$data['address2'] ?? null,
$data['address3'] ?? null,
$data['phone'] ?? null,
$data['cellphone'] ?? null,
$data['zipcode'] ?? null,
$data['city'] ?? null,
$data['country'] ?? null,
$data['email'] ?? null,
$data['password'] ?? null,
$data['lang_id'] ?? $this->getSession()->getLang()->getId(),
$data['reseller'] ?? null,
$data['sponsor'] ?? null,
$data['discount'] ?? null,
$data['company'] ?? null,
null,
$data['state'] ?? null
);
return $customerCreateEvent;
}
protected function getRememberMeCookieName()
{
return ConfigQuery::read('customer_remember_me_cookie_name', 'crmcn');
}
protected function getRememberMeCookieExpiration()
{
return ConfigQuery::read('customer_remember_me_cookie_expiration', 2592000 /* 1 month */);
}
}