<?php
namespace App\Ecommerce\Controller;
use App\Form\Type\RegistrationType;
use App\Security\OAuth\OAuthRegistrationHandler;
use CoreShop\Bundle\CoreBundle\Event\CustomerRegistrationEvent;
use CoreShop\Bundle\CoreBundle\Form\DataMapper\CustomerDataMapper;
use CoreShop\Bundle\UserBundle\Event\RequestPasswordChangeEvent;
use CoreShop\Bundle\UserBundle\Form\Type\RequestResetPasswordType;
use CoreShop\Bundle\UserBundle\Form\Type\ResetPasswordType;
use CoreShop\Component\Core\Model\CustomerInterface;
use CoreShop\Component\Core\Model\UserInterface;
use Exception;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
use HWI\Bundle\OAuthBundle\Security\Core\Exception\AccountNotLinkedException;
use Pimcore\Model\DataObject\CoreShopCustomer;
use RuntimeException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Pimcore\Twig\Extension\Templating\Placeholder;
use Symfony\Component\Uid\Uuid;
use CoreShop\Bundle\FrontendBundle\Controller\RegisterController as BaseRegisterController;
class RegisterController extends BaseRegisterController
{
public function __construct(
private readonly OAuthRegistrationHandler $oAuthHandler,
private readonly EventDispatcherInterface $eventDispatcher,
private readonly AuthenticationUtils $authenticationUtils,
private readonly Placeholder $placeholder
)
{
}
/**
* @param Request $request
* @return Response
* @throws Exception
*/
public function registerAction(Request $request): Response
{
if (($customer = $this->getCustomer()) instanceof CustomerInterface && null !== $customer->getUser()) {
return $this->redirectToRoute('coreshop_customer_profile');
}
$token = null;
$lastError = $this->authenticationUtils->getLastAuthenticationError(false);
if ($lastError instanceof AccountNotLinkedException) {
$token = $lastError->getToken();
}
if ($lastError && $lastError->getPrevious() instanceof AccountNotLinkedException) {
$token = $lastError->getPrevious()->getToken();
}
$registrationKey = null;
$oAuthToken = null;
$oAuthUserInfo = null;
if ($token instanceof OAuthToken) {
$registrationKey = Uuid::v4()->toRfc4122();
$this->oAuthHandler->saveToken($registrationKey, $token);
}
if (null !== $registrationKey) {
$oAuthToken = $this->oAuthHandler->loadToken($registrationKey);
$oAuthUserInfo = $this->oAuthHandler->loadUserInformation($oAuthToken);
}
if ($oAuthUserInfo instanceof UserResponseInterface) {
if ($this->oAuthHandler->getCustomerFromUserResponse($oAuthUserInfo)) {
throw new RuntimeException('Customer is already registered');
}
}
$redirect = $this->getParameterFromRequest($request, '_redirect', $this->generateUrl('profil'));
if ($oAuthToken instanceof OAuthToken) {
$form = $this->container->get('form.factory')->createNamed('customer', RegistrationType::class, $this->container->get('coreshop.factory.customer')->createNew());
$array = $this->mergeOAuthFormData([], $oAuthUserInfo);
if (!$array['firstname']) {
$array['firstname'] = sprintf('N/A (%s login)', $oAuthToken->getResourceOwnerName());
}
if (!$array['lastname']) {
$array['lastname'] = sprintf('N/A (%s login)', $oAuthToken->getResourceOwnerName());
}
$form->submit($array);
$mapper = new CustomerDataMapper();
$customer = $form->getData();
$mapper->mapFormsToData($form, $customer);
$checkCustomer = CoreShopCustomer::getByEmail($customer->getEmail(), ['limit' => 1, 'unpublished' => true]);
if (!$checkCustomer) {
$this->container->get('coreshop.customer.manager')->persistCustomer($customer);
} else {
$customer = $checkCustomer;
if (!$customer->getPublished()) {
$customer->setPublished(true);
$customer->save();
}
}
$this->oAuthHandler->connectSsoIdentity($customer->getUser(), $oAuthUserInfo);
// todo login and fire events after oauth registration
$this->eventDispatcher->dispatch(new CustomerRegistrationEvent($customer, ['type' => 'oAuthRegister']), 'coreshop.customer.register');
return $this->redirect($redirect);
}
/** @var Form $form */
$form = $this->container->get('form.factory')->createNamed('customer', RegistrationType::class, $this->container->get('coreshop.factory.customer')->createNew());
if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true)) {
$form = $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$customer = $form->getData();
$customer->setLocaleCode($this->container->get('coreshop.context.locale')->getLocaleCode());
try {
$this->container->get('coreshop.customer.manager')->persistCustomer($customer);
$this->eventDispatcher->dispatch(new CustomerRegistrationEvent($customer, ['type' => 'formRegister']), 'coreshop.customer.register');
$this->addFlash('success', 'Sikeres regisztráció!<br>A regisztráció véglegesítéséhez szükséges információkat elküldtük a regisztrációkor megadott e-mail címre!');
return $this->redirect($redirect);
} catch (Exception $e) {
$form->get('email')->addError(new FormError($e->getMessage()));
}
}
}
$layout = $this->templateConfigurator->findTemplate('Register/register.html');
$bc = [
['title' => 'Főoldal', 'path' => '/'],
['title' => 'Profil', 'path' => null],
];
$pl = $this->placeholder;
$pl('breadcrumbNews')->set($bc);
return $this->render($layout, [
'lastError' => $lastError,
'form' => $form->createView(),
]);
}
public function passwordResetRequestAction(Request $request): Response
{
$resetIdentifier = $this->container->getParameter('coreshop.customer.security.login_identifier');
$form = $this->container->get('form.factory')->createNamed('coreshop', RequestResetPasswordType::class, null, ['reset_identifier' => $resetIdentifier]);
if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true)) {
$handledForm = $form->handleRequest($request);
if ($handledForm->isSubmitted() && $handledForm->isValid()) {
$passwordResetData = $handledForm->getData();
$user = $this->container->get('coreshop.repository.user')->findByLoginIdentifier($passwordResetData['email']);
if (!$user instanceof UserInterface) {
return $this->redirectToRoute('profil');
}
$user->setPasswordResetHash($this->generateResetPasswordHash($user));
$user->save();
$resetLink = $this->generateUrl('coreshop_customer_password_reset', ['token' => $user->getPasswordResetHash()], UrlGeneratorInterface::ABSOLUTE_URL);
$dispatcher = $this->container->get('event_dispatcher');
$dispatcher->dispatch(new RequestPasswordChangeEvent($user, $resetLink), 'coreshop.user.request_password_reset');
$this->addFlash('success', $this->container->get('translator')->trans('coreshop.ui.password_reset_request_success'));
return $this->redirectToRoute('profil');
}
}
$bc = [
[
'title' => 'Főoldal',
'path' => '/'
],
[
'title' => 'Profil',
'path' => $this->generateUrl('profil')
],
[
'title' => 'Elfelejtett jelszó',
'path' => null
],
];
$pl = $this->placeholder;
$pl('breadcrumbNews')->set($bc);
return $this->render($this->templateConfigurator->findTemplate('Register/password-reset-request.html'), [
'form' => $form->createView(),
]);
}
public function passwordResetAction(Request $request): Response
{
$resetToken = $this->getParameterFromRequest($request, 'token');
if ($resetToken) {
/**
* @var UserInterface $user
*/
$user = $this->container->get('coreshop.repository.user')->findByResetToken($resetToken);
if (!$user instanceof UserInterface) {
return $this->redirectToRoute('profil');
}
$form = $this->container->get('form.factory')->createNamed('coreshop', ResetPasswordType::class);
if (in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true)) {
$handledForm = $form->handleRequest($request);
if ($handledForm->isSubmitted() && $handledForm->isValid()) {
$resetPassword = $handledForm->getData();
$user->setPasswordResetHash(null);
$user->setPassword($resetPassword['password']);
$user->save();
$this->addFlash('success', $this->container->get('translator')->trans('coreshop.ui.password_reset_success'));
$dispatcher = $this->container->get('event_dispatcher');
$dispatcher->dispatch(new GenericEvent($user), 'coreshop.user.password_reset');
return $this->redirectToRoute('profil');
}
}
$bc = [
[
'title' => 'Főoldal',
'path' => '/'
],
[
'title' => 'Profil',
'path' => $this->generateUrl('profil')
],
[
'title' => 'Jelszó visszaállítás',
'path' => null
],
];
$pl = $this->placeholder;
$pl('breadcrumbNews')->set($bc);
return $this->render($this->templateConfigurator->findTemplate('Register/password-reset.html'), [
'form' => $form->createView(),
]);
}
return $this->redirectToRoute('profil');
}
/**
*
* @param array $formData
* @param UserResponseInterface $userInformation
*
* @return array
*/
private function mergeOAuthFormData(
array $formData,
UserResponseInterface $userInformation
): array
{
return array_replace([
'firstname' => $userInformation->getFirstName(),
'lastname' => $userInformation->getLastName(),
'email' => $userInformation->getEmail()
], $formData);
}
}