src/Controller/AccountB2CController.php line 459

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace App\Controller;
  15. use App\EventListener\AuthenticationLoginListener;
  16. use App\Form\LoginFormType;
  17. use App\Form\RegistrationFormHandler;
  18. use App\Form\RegistrationFormType;
  19. use App\Model\Customer;
  20. use App\Services\NewsletterDoubleOptInService;
  21. use App\Services\PasswordRecoveryService;
  22. use CustomerManagementFrameworkBundle\CustomerProvider\CustomerProviderInterface;
  23. use CustomerManagementFrameworkBundle\CustomerSaveValidator\Exception\DuplicateCustomerException;
  24. use CustomerManagementFrameworkBundle\Model\CustomerInterface;
  25. use CustomerManagementFrameworkBundle\Security\Authentication\LoginManagerInterface;
  26. use CustomerManagementFrameworkBundle\Security\OAuth\Exception\AccountNotLinkedException;
  27. use CustomerManagementFrameworkBundle\Security\OAuth\OAuthRegistrationHandler;
  28. use CustomerManagementFrameworkBundle\Security\SsoIdentity\SsoIdentityServiceInterface;
  29. use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
  30. use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
  31. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  32. use Pimcore\Bundle\EcommerceFrameworkBundle\OrderManager\Order\Listing\Filter\CustomerObject;
  33. use Pimcore\DataObject\Consent\Service;
  34. use Pimcore\Translation\Translator;
  35. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  36. use Symfony\Component\HttpFoundation\RedirectResponse;
  37. use Symfony\Component\HttpFoundation\Request;
  38. use Symfony\Component\HttpFoundation\Response;
  39. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  40. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  41. use Symfony\Component\Routing\Annotation\Route;
  42. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  43. use Symfony\Component\Security\Core\User\UserInterface;
  44. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  45. use Symfony\Component\Uid\Uuid;
  46. use App\Model\Order;
  47. use App\Model\QuoteModel;
  48. use Knp\Component\Pager\Pagination\SlidingPagination;
  49. use Knp\Component\Pager\PaginatorInterface;
  50. use Pimcore\Model\DataObject;
  51. use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
  52. use Box\Spout\Common\Entity\Row;
  53. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  54. use FrontendPermissionToolkitBundle\Service as FrontenKitService;
  55. use Pimcore\Db;
  56. use App\Controller\CartB2CController;
  57. /**
  58.  * Class AccountController
  59.  *
  60.  * Controller that handles all account functionality, including register, login and connect to SSO profiles
  61.  */
  62. class AccountB2CController extends BaseB2CController
  63. {
  64.     const LIMIT_PER_PAGE 10;
  65.     protected $service;
  66.     public function __construct(EventDispatcherInterface $eventDispatcher)
  67.     {
  68.         $this->service = new FrontenKitService($eventDispatcher);
  69.     }
  70.     /**
  71.      * @Route("/b2c/account/login", name="b2c-account-login")
  72.      *
  73.      * @param AuthenticationUtils $authenticationUtils
  74.      * @param OAuthRegistrationHandler $oAuthHandler
  75.      * @param SessionInterface $session
  76.      * @param Request $request
  77.      * @param UserInterface|null $user
  78.      *
  79.      * @return Response|RedirectResponse
  80.      */
  81.     public function loginAction(
  82.         AuthenticationUtils $authenticationUtils,
  83.         OAuthRegistrationHandler $oAuthHandler,
  84.         SessionInterface $session,
  85.         Request $request,
  86.         UserInterface $user null
  87.     ) {
  88.         // //redirect user to index page if logged in
  89.         if ($user && $this->isGranted('ROLE_USER')) {
  90.             return $this->redirectToRoute('b2c-account-index');
  91.         }
  92.         // get the login error if there is one
  93.         $error $authenticationUtils->getLastAuthenticationError();
  94.         // OAuth handling - the OAuth authenticator is configured to return to the login page on errors
  95.         // (see failure_path configuration) - therefore we can fetch the last authentication error
  96.         // here. If the error is an AccountNotLinkedException (as thrown by our user provider) save the
  97.         // OAuth token to the session and redirect to registration with a special key which can be used
  98.         // to load the token to prepopulate the registration form with account data.
  99.         if ($error instanceof AccountNotLinkedException) {
  100.             // this can be anything - for simplicity we just use an UUID as it is unique and random
  101.             $registrationKey = (string) Uuid::v4()->toRfc4122();
  102.             $oAuthHandler->saveToken($registrationKey$error->getToken());
  103.             return $this->redirectToRoute('b2c-account-register', [
  104.                 'registrationKey' => $registrationKey
  105.             ]);
  106.         }
  107.         // last username entered by the user
  108.         $lastUsername $authenticationUtils->getLastUsername();
  109.         $formData = [
  110.             '_username' => $lastUsername
  111.         ];
  112.         $form $this->createForm(LoginFormType::class, $formData, [
  113.             'action' => $this->generateUrl('b2c-account-login'),
  114.         ]);
  115.         //store referer in session to get redirected after login
  116.         if (!$request->get('no-referer-redirect')) {
  117.             $session->set('_security.demo_frontend_b2c.target_path'$request->headers->get('referer'));
  118.         }
  119.         return $this->render('account/login.html.twig', [
  120.             'form' => $form->createView(),
  121.             'error' => $error,
  122.             'hideBreadcrumbs' => true
  123.         ]);
  124.     }
  125.     /**
  126.      * If registration is called with a registration key, the key will be used to look for an existing OAuth token in
  127.      * the session. This OAuth token will be used to fetch user info which can be used to pre-populate the form and to
  128.      * link a SSO identity to the created customer object.
  129.      *
  130.      * This could be further separated into services, but was kept as single method for demonstration purposes as the
  131.      * registration process is different on every project.
  132.      *
  133.      * @Route("/b2c/account/register", name="b2c-account-register")
  134.      *
  135.      * @param Request $request
  136.      * @param CustomerProviderInterface $customerProvider
  137.      * @param OAuthRegistrationHandler $oAuthHandler
  138.      * @param LoginManagerInterface $loginManager
  139.      * @param RegistrationFormHandler $registrationFormHandler
  140.      * @param SessionInterface $session
  141.      * @param AuthenticationLoginListener $authenticationLoginListener
  142.      * @param Translator $translator
  143.      * @param Service $consentService
  144.      * @param UrlGeneratorInterface $urlGenerator
  145.      * @param NewsletterDoubleOptInService $newsletterDoubleOptInService
  146.      * @param UserInterface|null $user
  147.      *
  148.      * @return Response|RedirectResponse
  149.      */
  150.     public function registerAction(
  151.         Request $request,
  152.         CustomerProviderInterface $customerProvider,
  153.         OAuthRegistrationHandler $oAuthHandler,
  154.         LoginManagerInterface $loginManager,
  155.         RegistrationFormHandler $registrationFormHandler,
  156.         SessionInterface $session,
  157.         AuthenticationLoginListener $authenticationLoginListener,
  158.         Translator $translator,
  159.         Service $consentService,
  160.         UrlGeneratorInterface $urlGenerator,
  161.         NewsletterDoubleOptInService $newsletterDoubleOptInService,
  162.         UserInterface $user null,
  163.         Factory $factory
  164.     ) {
  165.         if ($user && $this->isGranted('ROLE_USER')) {
  166.             return $this->redirectToRoute('b2c-account-index');
  167.         }
  168.         $form $this->createForm(RegistrationFormType::class,[],[]);
  169.         $form->handleRequest($request);
  170.         $customer $customerProvider->create();
  171.         $errors = [];
  172.         if ($form->isSubmitted()) {
  173.             $registrationFormHandler->setData($form,$request,$customer);
  174.             $customer->setCustomerLanguage($request->getLocale());
  175.             $customer->setActive(true);
  176.             try {
  177.                 $customer->save();
  178.                 $response $this->redirectToRoute('b2c-account-index');
  179.                 // log user in manually
  180.                 // pass response to login manager as it adds potential remember me cookies
  181.                 $loginManager->login($customer$request$response);
  182.                 //do ecommerce framework login
  183.                 $authenticationLoginListener->doEcommerceFrameworkLogin($customer);
  184.                 if($customer->getUserRoles() == 'Customer'){
  185.                     $cartManager $factory->getCartManager();
  186.                     $oldCart $cartManager->getCartByName(CartB2CController::DEFAULT_CART_NAME);
  187.                     if($oldCart){
  188.                         if($oldCart->getItems()){
  189.                             return new RedirectResponse('/b2c/cart');
  190.                         }
  191.                     }
  192.                 }
  193.                 return $response;
  194.             } catch (DuplicateCustomerException $e) {
  195.                 $errors[] = $translator->trans(
  196.                     'account.customer-already-exists',
  197.                     [
  198.                         $customer->getEmail(),
  199.                         $urlGenerator->generate('account-password-send-recovery', ['email' => $customer->getEmail()])
  200.                     ]
  201.                 );
  202.             } catch (\Exception $e) {
  203.                 $errors[] = $e->getMessage();
  204.             }
  205.         }
  206.         if ($form->isSubmitted() && !$form->isValid()) {
  207.             p_r($form->getErrors());
  208.             p_r(get_Class_methods($form));
  209.             p_r($errors);exit;
  210.             $this->addFlash("error","La password deve essere identica e contenere almeno 10 caratteri.");
  211.         }
  212.         return $this->render('account/b2c_customer_registration.html.twig', [
  213.             'form' => $form->createView(),
  214.             'errors' => $errors,
  215.             'hideBreadcrumbs' => true
  216.         ]);
  217.     }
  218.     /**
  219.      *
  220.      * @param array $formData
  221.      * @param UserResponseInterface $userInformation
  222.      *
  223.      * @return array
  224.      */
  225.     private function mergeOAuthFormData(
  226.         array $formData,
  227.         UserResponseInterface $userInformation
  228.     ): array {
  229.         return array_replace([
  230.             'firstname' => $userInformation->getFirstName(),
  231.             'lastname' => $userInformation->getLastName(),
  232.             'email' => $userInformation->getEmail()
  233.         ], $formData);
  234.     }
  235.     /**
  236.      * Index page for account - it is restricted to ROLE_USER via security annotation
  237.      *
  238.      * @Route("/b2c/account/index", name="b2c-account-index")
  239.      * @Route("/en/b2c/account/index", name="b2c-account-index-en")
  240.      * @Security("is_granted('ROLE_USER')")
  241.      *
  242.      * @param SsoIdentityServiceInterface $identityService
  243.      * @param UserInterface|null $user
  244.      *
  245.      * @return Response
  246.      */
  247.     public function indexAction(Request $requestUserInterface $user null,PaginatorInterface $paginatorSessionInterface $session)
  248.     {
  249.         if(!$user){
  250.             return $this->redirectToRoute('account-login');
  251.         }
  252.         $limit $request->get('limit',20);
  253.         $orderColumn $request->get('column','oo_id');
  254.         $orderBy $request->get('order','desc');
  255.         $quoteListing = new DataObject\Quote\Listing();
  256.         $quoteListing->filterByUser($user);
  257.         $quoteListing->setOrderKey($orderColumn);
  258.         $quoteListing->setOrder($orderBy);
  259.         $paginator $paginator->paginate(
  260.             $quoteListing,
  261.             $request->get('page'1),
  262.             $limit
  263.         );
  264.         return $this->render('account/b2c_quotation_list.html.twig', [
  265.             'paginator' => $paginator,
  266.             'column'=>$orderColumn,
  267.             'order'=>$orderBy,
  268.             'paginationVariables' => $paginator->getPaginationData(),
  269.             'limit'=>$limit
  270.         ]);
  271.     }
  272.     /**
  273.      * Index page for account - it is restricted to ROLE_USER via security annotation
  274.      *
  275.      * @Route("/b2c/account/profile", name="b2c-account-profile")
  276.      * @Security("is_granted('ROLE_USER')")
  277.      *
  278.      * @param RegistrationFormHandler $registrationFormHandler
  279.      * @param UserInterface|null $user
  280.      *
  281.      * @return Response
  282.      */
  283.     public function profileAction(Request $request,RegistrationFormHandler $registrationFormHandlerUserInterface $user null,PaginatorInterface $paginatorSessionInterface $session)
  284.     {
  285.          //redirect user to index page if logged in
  286.         if (!$user) {
  287.             return $this->redirectToRoute('b2c-account-login');
  288.         }
  289.         $customer $user;
  290.         $formData $registrationFormHandler->buildFormData($customer);
  291.         $form $this->createForm(RegistrationFormType::class,$formData);
  292.         $form->remove('password');
  293.         $form->remove('consent');
  294.         $form->handleRequest($request);
  295.         $errors = [];
  296.         if ($form->isSubmitted() && $form->isValid()) {
  297.             $registrationFormHandler->setData($form,$request,$customer,true);
  298.             $customer->setCustomerLanguage($request->getLocale());
  299.             $customer->setActive(true);
  300.             try {
  301.                 $customer->save();
  302.                 $response $this->redirectToRoute('b2c-account-index');
  303.                 return $response;
  304.             } catch (DuplicateCustomerException $e) {
  305.                 $errors[] = $translator->trans(
  306.                     'account.customer-already-exists',
  307.                     [
  308.                         $customer->getEmail(),
  309.                         $urlGenerator->generate('account-password-send-recovery', ['email' => $customer->getEmail()])
  310.                     ]
  311.                 );
  312.             } catch (\Exception $e) {
  313.                 $errors[] = $e->getMessage();
  314.             }
  315.         }
  316.         $customerAddress = new DataObject\CustomerAddressB2C\Listing();
  317.         $customerAddress->filterByUser($user);
  318.         return $this->render('account/b2c_customer_profile.html.twig', [
  319.             'form' => $form->createView(),
  320.             'errors' => $errors,
  321.             'addresses'=>$customerAddress,
  322.             'hideBreadcrumbs' => true
  323.         ]);
  324.     }
  325.     /**
  326.      * @Route("/account/send-password-recovery", name="account-password-send-recovery")
  327.      *
  328.      * @param Request $request
  329.      * @param PasswordRecoveryService $service
  330.      * @param Translator $translator
  331.      *
  332.      * @return Response
  333.      *
  334.      * @throws \Exception
  335.      */
  336.     public function sendPasswordRecoveryMailAction(Request $requestPasswordRecoveryService $serviceTranslator $translator)
  337.     {
  338.         if ($request->isMethod(Request::METHOD_POST)) {
  339.             try {
  340.                 $customer $service->sendRecoveryMail($request->get('email'''), $this->document->getProperty('password_reset_mail'));
  341.                 if (!$customer instanceof CustomerInterface) {
  342.                     throw new \Exception('Invalid Customer');
  343.                 }
  344.                 $this->addFlash('success'$translator->trans('account.reset-mail-sent-when-possible'));
  345.             } catch (\Exception $e) {
  346.                 $this->addFlash('danger'$e->getMessage());
  347.             }
  348.             return $this->redirectToRoute('b2c-account-login', ['no-referer-redirect' => true]);
  349.         }
  350.         return $this->render('account/send_password_recovery_mail.html.twig', [
  351.             'hideBreadcrumbs' => true,
  352.             'emailPrefill' => $request->get('email')
  353.         ]);
  354.     }
  355.     /**
  356.      * @Route("/b2c/account/reset-password", name="b2c-account-reset-password")
  357.      *
  358.      * @param Request $request
  359.      * @param PasswordRecoveryService $service
  360.      * @param Translator $translator
  361.      *
  362.      * @return Response|RedirectResponse
  363.      */
  364.     public function resetPasswordAction(Request $requestPasswordRecoveryService $serviceTranslator $translator)
  365.     {
  366.         $token $request->get('token');
  367.         $customer $service->getCustomerByToken($token);
  368.         if (!$customer) {
  369.             //TODO render error page
  370.             throw new NotFoundHttpException('Invalid token');
  371.         }
  372.         if ($request->isMethod(Request::METHOD_POST)) {
  373.             $newPassword $request->get('password');
  374.             $service->setPassword($token$newPassword);
  375.             $this->addFlash('success'$translator->trans('account.password-reset-successful'));
  376.             return $this->redirectToRoute('b2c-account-login', ['no-referer-redirect' => true]);
  377.         }
  378.         return $this->render('account/reset_password.html.twig', [
  379.             'hideBreadcrumbs' => true,
  380.             'token' => $token,
  381.             'email' => $customer->getEmail()
  382.         ]);
  383.     }
  384.     private function checkPermission(){
  385.         $allow false;
  386.         $userObject \Pimcore::getContainer()->get('security.token_storage')->getToken()->getUser();
  387.         if($this->service->isAllowed($userObject"draft_create") || $this->service->isAllowed($userObject"booking_create") || $this->service->isAllowed($userObject"order_create") || $this->service->isAllowed($userObject"order_view")) {
  388.             $allow true;
  389.         }
  390.         return $allow;
  391.     }
  392.     /**
  393.      * @Route("/account/b2c/wish-list/index", name="b2c-wishlist-index")
  394.      * @Security("is_granted('ROLE_USER')")
  395.      * @param Request $request
  396.      * @return Response
  397.      *
  398.      * @throws \Exception
  399.      */
  400.     public function wishListIndexAction(Request $request,UserInterface $user null)
  401.     {
  402.         if (!$user) {
  403.             return $this->redirectToRoute('b2c-account-login');
  404.         }
  405.         $result = [];
  406.         $products = [];
  407.         $productId $request->get('id',0);
  408.         $params array_merge($request->query->all(), $request->attributes->all());
  409.         if($user){
  410.             $db Db::get();
  411.             $orderBy " ow.oo_id DESC";
  412.             if(isset($params['orderby'])){
  413.                 if($params['orderby'] == "price")
  414.                 {
  415.                     $orderBy 'CONSORZ ASC';
  416.                 }else if($params['orderby'] == "price-desc"){
  417.                     $orderBy =  'CONSORZ DESC';
  418.                 }else if($params['orderby'] == "date"){
  419.                     $orderBy 'oo_id DESC';
  420.                 }else if($params['orderby'] == "popularity"){
  421.                     $orderBy 'oo_id DESC';
  422.                 }
  423.             }else{
  424.                 $orderBy  "ow.o_modificationDate DESC";
  425.             }
  426.             $lists = [];
  427.             $sql 'SELECT ow.oo_id FROM `object_wishlist` ow LEFT JOIN object_prod op ON ow.item__id = op.oo_id WHERE user__id = '.$user->getId().' ORDER BY '.$orderBy;
  428.             $products $db->fetchAll($sql);
  429.             if($products)
  430.             {
  431.                 foreach($products as $prod){
  432.                     $lists[] = \Pimcore\Model\DataObject::getById($prod['oo_id']);
  433.                 }
  434.             }
  435.             $params['products'] = $lists;
  436.             $params['orderby'] = $orderBy;
  437.             $params['isMecstoreUser'] =  false;
  438.             $partner $user->getPartner();
  439.             if($partner->getisMecstoreHQ()){
  440.                 $params['isMecstoreUser'] =  true;
  441.             }
  442.         }
  443.         return $this->render('product_b2c/wishlist.html.twig'$params);
  444.     }
  445.     /**
  446.      * @Route("/account/get_branch_by_province", name="account-get-branch-by-province")
  447.      * @return Response|RedirectResponse
  448.      */
  449.     public function getBranchByRegion(Request $request){
  450.         $result = [];
  451.         $branches = [];
  452.         $user null;
  453.         $id $request->get('id',null);
  454.         if($id){
  455.             $db \Pimcore\Db::get();
  456.             $provinces $db->fetchAll("SELECT * FROM province WHERE code='$id' limit 1");
  457.             if($provinces){
  458.                 $partnerBranches = new DataObject\Partners\Listing();
  459.                 $partnerBranches->setCondition("Region = ? AND isMecstoreHQ != 1",[$provinces[0]['region']]);
  460.                 $partnerBranches $partnerBranches->load();
  461.                 if($partnerBranches)
  462.                 {
  463.                     foreach($partnerBranches as $branch){
  464.                         $branches[$branch->getId()] = $branch->getCompany().'-'.$branch->getCity().', '.$branch->getRegion().' - '.$branch->getZip();
  465.                     }
  466.                     $result = ['success'=>true,'data'=>$branches];
  467.                     return $this->json($result);
  468.                 }
  469.             }
  470.         }
  471.         return $this->json(['success'=>false]);
  472.     }
  473. }