<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Entity\Channel\Channel;
use Doctrine\Persistence\ObjectManager;
use Sylius\Bundle\CoreBundle\Mailer\Emails;
use Sylius\Bundle\UserBundle\Security\UserLoginInterface;
use Sylius\Bundle\UserBundle\UserEvents;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\ShopUserInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Mailer\Sender\SenderInterface;
use Sylius\Component\User\Model\UserInterface;
use Sylius\Component\User\Security\Generator\GeneratorInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Webmozart\Assert\Assert;
final class UserRegistrationListener
{
/** @var ObjectManager */
private $userManager;
/** @var GeneratorInterface */
private $tokenGenerator;
/** @var EventDispatcherInterface */
private $eventDispatcher;
/** @var ChannelContextInterface */
private $channelContext;
/** @var LocaleContextInterface */
private $localeContext;
/** @var UserLoginInterface */
private $userLogin;
/** @var string */
private $firewallContextName;
private RequestStack $requestStack;
private SenderInterface $emailSender;
public function __construct(ObjectManager $userManager, GeneratorInterface $tokenGenerator, EventDispatcherInterface $eventDispatcher, ChannelContextInterface $channelContext, LocaleContextInterface $localeContext, UserLoginInterface $userLogin, string $firewallContextName, RequestStack $requestStack, SenderInterface $emailSender)
{
$this->userManager = $userManager;
$this->tokenGenerator = $tokenGenerator;
$this->eventDispatcher = $eventDispatcher;
$this->channelContext = $channelContext;
$this->localeContext = $localeContext;
$this->userLogin = $userLogin;
$this->firewallContextName = $firewallContextName;
$this->requestStack = $requestStack;
$this->emailSender = $emailSender;
}
public function handleUserVerification(GenericEvent $event): void
{
$customer = $event->getSubject();
Assert::isInstanceOf($customer, CustomerInterface::class);
$user = $customer->getUser();
Assert::notNull($user);
/** @var ChannelInterface $channel */
$channel = $this->channelContext->getChannel();
if (!$channel->isAccountVerificationRequired()) {
$this->enableAndLogin($user);
$session = $this->requestStack->getSession();
$session->getFlashBag()->clear();
$session->getFlashBag()->add('success', 'app.customer.register_without_verification');
return;
}
$this->sendVerificationEmail($user);
}
private function sendVerificationEmail(ShopUserInterface $user): void
{
$token = $this->tokenGenerator->generate();
$user->setEmailVerificationToken($token);
$this->userManager->persist($user);
$this->userManager->flush();
$this->eventDispatcher->dispatch(new GenericEvent($user), UserEvents::REQUEST_VERIFICATION_TOKEN);
}
private function enableAndLogin(ShopUserInterface $user): void
{
$user->setEnabled(true);
$this->userManager->persist($user);
$this->userManager->flush();
$this->userLogin->login($user, $this->firewallContextName);
}
public function sendUserVerifiedEmail(GenericEvent $event): void
{
/** @var CustomerInterface $newCustomer */
$user = $event->getSubject();
Assert::isInstanceOf($user, ShopUserInterface::class);
/** @var Channel $channel */
$channel = $this->channelContext->getChannel();
if ($channel->isAccountVerificationRequired()) {
$this->sendEmail($user, Emails::USER_REGISTRATION);
}
}
private function sendEmail(UserInterface $user, string $emailCode): void
{
$this->emailSender->send(
$emailCode,
[$user->getEmail()],
[
'user' => $user,
'channel' => $this->channelContext->getChannel(),
'localeCode' => $this->localeContext->getLocaleCode(),
]
);
}
}