vendor/shopware/storefront/Controller/RegisterController.php line 161

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  4. use Shopware\Core\Checkout\Customer\CustomerEntity;
  5. use Shopware\Core\Checkout\Customer\Exception\CustomerAlreadyConfirmedException;
  6. use Shopware\Core\Checkout\Customer\Exception\CustomerNotFoundByHashException;
  7. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractRegisterConfirmRoute;
  8. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractRegisterRoute;
  9. use Shopware\Core\Content\Newsletter\Exception\SalesChannelDomainNotFoundException;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\Feature;
  14. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  15. use Shopware\Core\Framework\Routing\Annotation\Since;
  16. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  17. use Shopware\Core\Framework\Validation\DataBag\DataBag;
  18. use Shopware\Core\Framework\Validation\DataBag\QueryDataBag;
  19. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  20. use Shopware\Core\Framework\Validation\DataValidationDefinition;
  21. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  22. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  23. use Shopware\Core\System\SystemConfig\SystemConfigService;
  24. use Shopware\Storefront\Framework\AffiliateTracking\AffiliateTrackingListener;
  25. use Shopware\Storefront\Framework\Captcha\Annotation\Captcha;
  26. use Shopware\Storefront\Framework\Routing\Annotation\NoStore;
  27. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  28. use Shopware\Storefront\Page\Account\CustomerGroupRegistration\AbstractCustomerGroupRegistrationPageLoader;
  29. use Shopware\Storefront\Page\Account\CustomerGroupRegistration\CustomerGroupRegistrationPageLoadedHook;
  30. use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoader;
  31. use Shopware\Storefront\Page\Account\Register\AccountRegisterPageLoadedHook;
  32. use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedHook;
  33. use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoader;
  34. use Symfony\Component\HttpFoundation\Request;
  35. use Symfony\Component\HttpFoundation\Response;
  36. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  37. use Symfony\Component\Routing\Annotation\Route;
  38. use Symfony\Component\Validator\Constraints\EqualTo;
  39. use Symfony\Component\Validator\Constraints\NotBlank;
  40. /**
  41.  * @Route(defaults={"_routeScope"={"storefront"}})
  42.  *
  43.  * @deprecated tag:v6.5.0 - reason:becomes-internal - Will be internal
  44.  */
  45. class RegisterController extends StorefrontController
  46. {
  47.     private AccountLoginPageLoader $loginPageLoader;
  48.     private CartService $cartService;
  49.     private CheckoutRegisterPageLoader $registerPageLoader;
  50.     private SystemConfigService $systemConfigService;
  51.     private EntityRepositoryInterface $customerRepository;
  52.     private AbstractCustomerGroupRegistrationPageLoader $customerGroupRegistrationPageLoader;
  53.     private AbstractRegisterRoute $registerRoute;
  54.     private AbstractRegisterConfirmRoute $registerConfirmRoute;
  55.     private EntityRepositoryInterface $domainRepository;
  56.     /**
  57.      * @internal
  58.      */
  59.     public function __construct(
  60.         AccountLoginPageLoader $loginPageLoader,
  61.         AbstractRegisterRoute $registerRoute,
  62.         AbstractRegisterConfirmRoute $registerConfirmRoute,
  63.         CartService $cartService,
  64.         CheckoutRegisterPageLoader $registerPageLoader,
  65.         SystemConfigService $systemConfigService,
  66.         EntityRepositoryInterface $customerRepository,
  67.         AbstractCustomerGroupRegistrationPageLoader $customerGroupRegistrationPageLoader,
  68.         EntityRepositoryInterface $domainRepository
  69.     ) {
  70.         $this->loginPageLoader $loginPageLoader;
  71.         $this->cartService $cartService;
  72.         $this->registerPageLoader $registerPageLoader;
  73.         $this->systemConfigService $systemConfigService;
  74.         $this->customerRepository $customerRepository;
  75.         $this->customerGroupRegistrationPageLoader $customerGroupRegistrationPageLoader;
  76.         $this->registerRoute $registerRoute;
  77.         $this->registerConfirmRoute $registerConfirmRoute;
  78.         $this->domainRepository $domainRepository;
  79.     }
  80.     /**
  81.      * @Since("6.0.0.0")
  82.      * @Route("/account/register", name="frontend.account.register.page", methods={"GET"})
  83.      * @NoStore
  84.      */
  85.     public function accountRegisterPage(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  86.     {
  87.         if ($context->getCustomer() && $context->getCustomer()->getGuest()) {
  88.             return $this->redirectToRoute('frontend.account.logout.page');
  89.         }
  90.         if ($context->getCustomer()) {
  91.             return $this->redirectToRoute('frontend.account.home.page');
  92.         }
  93.         $redirect $request->query->get('redirectTo''frontend.account.home.page');
  94.         $page $this->loginPageLoader->load($request$context);
  95.         $this->hook(new AccountRegisterPageLoadedHook($page$context));
  96.         return $this->renderStorefront('@Storefront/storefront/page/account/register/index.html.twig', [
  97.             'redirectTo' => $redirect,
  98.             'redirectParameters' => $request->get('redirectParameters'json_encode([])),
  99.             'page' => $page,
  100.             'data' => $data,
  101.         ]);
  102.     }
  103.     /**
  104.      * @Since("6.3.1.0")
  105.      * @Route("/customer-group-registration/{customerGroupId}", name="frontend.account.customer-group-registration.page", methods={"GET"})
  106.      * @NoStore
  107.      */
  108.     public function customerGroupRegistration(string $customerGroupIdRequest $requestRequestDataBag $dataSalesChannelContext $context): Response
  109.     {
  110.         if ($context->getCustomer() && $context->getCustomer()->getGuest()) {
  111.             return $this->redirectToRoute('frontend.account.logout.page');
  112.         }
  113.         if ($context->getCustomer()) {
  114.             return $this->redirectToRoute('frontend.account.home.page');
  115.         }
  116.         $redirect $request->query->get('redirectTo''frontend.account.home.page');
  117.         $page $this->customerGroupRegistrationPageLoader->load($request$context);
  118.         if ($page->getGroup()->getTranslation('registrationOnlyCompanyRegistration')) {
  119.             $data->set('accountType'CustomerEntity::ACCOUNT_TYPE_BUSINESS);
  120.         }
  121.         $this->hook(new CustomerGroupRegistrationPageLoadedHook($page$context));
  122.         return $this->renderStorefront('@Storefront/storefront/page/account/customer-group-register/index.html.twig', [
  123.             'redirectTo' => $redirect,
  124.             'redirectParameters' => $request->get('redirectParameters'json_encode([])),
  125.             'errorParameters' => json_encode(['customerGroupId' => $customerGroupId]),
  126.             'page' => $page,
  127.             'data' => $data,
  128.         ]);
  129.     }
  130.     /**
  131.      * @Since("6.0.0.0")
  132.      * @Route("/checkout/register", name="frontend.checkout.register.page", options={"seo"="false"}, methods={"GET"})
  133.      * @NoStore
  134.      */
  135.     public function checkoutRegisterPage(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  136.     {
  137.         /** @var string $redirect */
  138.         $redirect $request->get('redirectTo''frontend.checkout.confirm.page');
  139.         if ($context->getCustomer()) {
  140.             return $this->redirectToRoute($redirect);
  141.         }
  142.         if ($this->cartService->getCart($context->getToken(), $context)->getLineItems()->count() === 0) {
  143.             return $this->redirectToRoute('frontend.checkout.cart.page');
  144.         }
  145.         $page $this->registerPageLoader->load($request$context);
  146.         $this->hook(new CheckoutRegisterPageLoadedHook($page$context));
  147.         return $this->renderStorefront(
  148.             '@Storefront/storefront/page/checkout/address/index.html.twig',
  149.             ['redirectTo' => $redirect'page' => $page'data' => $data]
  150.         );
  151.     }
  152.     /**
  153.      * @Since("6.0.0.0")
  154.      * @Route("/account/register", name="frontend.account.register.save", methods={"POST"}, defaults={"_captcha"=true})
  155.      */
  156.     public function register(Request $requestRequestDataBag $dataSalesChannelContext $context): Response
  157.     {
  158.         if ($context->getCustomer()) {
  159.             return $this->redirectToRoute('frontend.account.home.page');
  160.         }
  161.         try {
  162.             if (!$data->has('differentShippingAddress')) {
  163.                 $data->remove('shippingAddress');
  164.             }
  165.             $data->set('storefrontUrl'$this->getConfirmUrl($context$request));
  166.             $data $this->prepareAffiliateTracking($data$request->getSession());
  167.             if (Feature::isActive('FEATURE_NEXT_16236')) {
  168.                 if ($data->getBoolean('createCustomerAccount')) {
  169.                     $data->set('guest'false);
  170.                 } else {
  171.                     $data->set('guest'true);
  172.                 }
  173.             } else {
  174.                 if ($data->has('guest')) {
  175.                     $data->set('guest'$data->has('guest'));
  176.                 }
  177.             }
  178.             $this->registerRoute->register(
  179.                 $data->toRequestDataBag(),
  180.                 $context,
  181.                 false,
  182.                 $this->getAdditionalRegisterValidationDefinitions($data$context)
  183.             );
  184.         } catch (ConstraintViolationException $formViolations) {
  185.             if (!$request->request->has('errorRoute')) {
  186.                 throw new MissingRequestParameterException('errorRoute');
  187.             }
  188.             $params $this->decodeParam($request'errorParameters');
  189.             // this is to show the correct form because we have different usecases (account/register||checkout/register)
  190.             return $this->forwardToRoute($request->get('errorRoute'), ['formViolations' => $formViolations], $params);
  191.         }
  192.         if ($this->isDoubleOptIn($data$context)) {
  193.             return $this->redirectToRoute('frontend.account.register.page');
  194.         }
  195.         return $this->createActionResponse($request);
  196.     }
  197.     /**
  198.      * @Since("6.1.0.0")
  199.      * @Route("/registration/confirm", name="frontend.account.register.mail", methods={"GET"})
  200.      */
  201.     public function confirmRegistration(SalesChannelContext $contextQueryDataBag $queryDataBag): Response
  202.     {
  203.         try {
  204.             $customerId $this->registerConfirmRoute
  205.                 ->confirm($queryDataBag->toRequestDataBag(), $context)
  206.                 ->getCustomer()
  207.                 ->getId();
  208.         } catch (CustomerNotFoundByHashException CustomerAlreadyConfirmedException ConstraintViolationException $exception) {
  209.             $this->addFlash(self::DANGER$this->trans('account.confirmationIsAlreadyDone'));
  210.             return $this->redirectToRoute('frontend.account.register.page');
  211.         }
  212.         /** @var CustomerEntity $customer */
  213.         $customer $this->customerRepository->search(new Criteria([$customerId]), $context->getContext())->first();
  214.         if ($customer->getGuest()) {
  215.             $this->addFlash(self::SUCCESS$this->trans('account.doubleOptInMailConfirmationSuccessfully'));
  216.             return $this->redirectToRoute('frontend.checkout.confirm.page');
  217.         }
  218.         $this->addFlash(self::SUCCESS$this->trans('account.doubleOptInRegistrationSuccessfully'));
  219.         if ($redirectTo $queryDataBag->get('redirectTo')) {
  220.             return $this->redirectToRoute($redirectTo);
  221.         }
  222.         return $this->redirectToRoute('frontend.account.home.page');
  223.     }
  224.     private function isDoubleOptIn(DataBag $dataSalesChannelContext $context): bool
  225.     {
  226.         $creatueCustomerAccount $data->getBoolean('createCustomerAccount');
  227.         if (Feature::isActive('FEATURE_NEXT_16236')) {
  228.             $configKey $creatueCustomerAccount
  229.                 'core.loginRegistration.doubleOptInRegistration'
  230.                 'core.loginRegistration.doubleOptInGuestOrder';
  231.         } else {
  232.             $configKey $data->has('guest')
  233.                 ? 'core.loginRegistration.doubleOptInGuestOrder'
  234.                 'core.loginRegistration.doubleOptInRegistration';
  235.         }
  236.         $doubleOptInRequired $this->systemConfigService
  237.             ->get($configKey$context->getSalesChannel()->getId());
  238.         if (!$doubleOptInRequired) {
  239.             return false;
  240.         }
  241.         if (Feature::isActive('FEATURE_NEXT_16236')) {
  242.             if ($creatueCustomerAccount) {
  243.                 $this->addFlash(self::SUCCESS$this->trans('account.optInRegistrationAlert'));
  244.                 return true;
  245.             }
  246.             $this->addFlash(self::SUCCESS$this->trans('account.optInGuestAlert'));
  247.             return true;
  248.         }
  249.         if ($data->has('guest')) {
  250.             $this->addFlash(self::SUCCESS$this->trans('account.optInGuestAlert'));
  251.             return true;
  252.         }
  253.         $this->addFlash(self::SUCCESS$this->trans('account.optInRegistrationAlert'));
  254.         return true;
  255.     }
  256.     private function getAdditionalRegisterValidationDefinitions(DataBag $dataSalesChannelContext $context): DataValidationDefinition
  257.     {
  258.         $definition = new DataValidationDefinition('storefront.confirmation');
  259.         $definition->add('salutationId', new NotBlank());
  260.         if ($this->systemConfigService->get('core.loginRegistration.requireEmailConfirmation'$context->getSalesChannel()->getId())) {
  261.             $definition->add('emailConfirmation', new NotBlank(), new EqualTo([
  262.                 'value' => $data->get('email'),
  263.             ]));
  264.         }
  265.         if ($data->has('guest')) {
  266.             return $definition;
  267.         }
  268.         if ($this->systemConfigService->get('core.loginRegistration.requirePasswordConfirmation'$context->getSalesChannel()->getId())) {
  269.             $definition->add('passwordConfirmation', new NotBlank(), new EqualTo([
  270.                 'value' => $data->get('password'),
  271.             ]));
  272.         }
  273.         return $definition;
  274.     }
  275.     private function prepareAffiliateTracking(RequestDataBag $dataSessionInterface $session): DataBag
  276.     {
  277.         $affiliateCode $session->get(AffiliateTrackingListener::AFFILIATE_CODE_KEY);
  278.         $campaignCode $session->get(AffiliateTrackingListener::CAMPAIGN_CODE_KEY);
  279.         if ($affiliateCode !== null && $campaignCode !== null) {
  280.             $data->add([
  281.                 AffiliateTrackingListener::AFFILIATE_CODE_KEY => $affiliateCode,
  282.                 AffiliateTrackingListener::CAMPAIGN_CODE_KEY => $campaignCode,
  283.             ]);
  284.         }
  285.         return $data;
  286.     }
  287.     private function getConfirmUrl(SalesChannelContext $contextRequest $request): string
  288.     {
  289.         /** @var string $domainUrl */
  290.         $domainUrl $this->systemConfigService
  291.             ->get('core.loginRegistration.doubleOptInDomain'$context->getSalesChannel()->getId());
  292.         if ($domainUrl) {
  293.             return $domainUrl;
  294.         }
  295.         $domainUrl $request->attributes->get(RequestTransformer::STOREFRONT_URL);
  296.         if ($domainUrl) {
  297.             return $domainUrl;
  298.         }
  299.         $criteria = new Criteria();
  300.         $criteria->addFilter(new EqualsFilter('salesChannelId'$context->getSalesChannel()->getId()));
  301.         $criteria->setLimit(1);
  302.         $domain $this->domainRepository
  303.             ->search($criteria$context->getContext())
  304.             ->first();
  305.         if (!$domain) {
  306.             throw new SalesChannelDomainNotFoundException($context->getSalesChannel());
  307.         }
  308.         return $domain->getUrl();
  309.     }
  310. }