<?php
declare(strict_types=1);
namespace NetInventors\NetiNextAccessManager\Subscriber;
use NetInventors\NetiNextAccessManager\Constants\BusinessEventsConstants;
use NetInventors\NetiNextAccessManager\Events\BusinessEvent\CustomerRegisteredEvent;
use NetInventors\NetiNextAccessManager\Events\BusinessEvent\CustomerRegisteredOperatorEvent;
use NetInventors\NetiNextAccessManager\Extension\Content\Customer\Aggregate\CustomerAttribute\CustomerAttributeEntity;
use NetInventors\NetiNextAccessManager\Service\CustomerService;
use NetInventors\NetiNextAccessManager\Service\PluginConfig;
use NetInventors\NetiNextAccessManager\Service\Repository\CustomerMediaRepository;
use NetInventors\NetiNextAccessManager\Service\UploadFileService;
use NetInventors\NetiNextAccessManager\Validation\AccountType\AccountType;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\BaseConstraint;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\CustomerType;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\FileSize;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\MaxAmount;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\MimeType;
use NetInventors\NetiNextAccessManager\Validation\CustomerFileUpload\Required;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Customer\Event\CustomerDoubleOptInRegistrationEvent;
use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
use Shopware\Core\Content\Media\Event\MediaFileExtensionWhitelistEvent;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\Framework\Validation\BuildValidationEvent;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Account\Login\AccountLoginPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class RegisterSubscriber implements EventSubscriberInterface
{
public const REGISTRATION_CUSTOMER_GROUPS = 'netiAccessManagerRegistrationCustomerGroups';
private $isNotCustomerRegistration = true;
/** @var RequestStack */
protected $requestStack;
/** @var PluginConfig */
protected $pluginConfig;
/** @var UploadFileService */
protected $uploadFileService;
/** @var CustomerMediaRepository */
protected $customerUploadFilesRepository;
/** @var CustomerService */
protected $customerService;
/** @var EventDispatcherInterface */
protected $eventDispatcher;
/** @var SystemConfigService */
protected $systemConfigService;
protected EntityRepositoryInterface $customerGroupRepository;
/**
* Register constructor.
*
* @param RequestStack $requestStack
* @param PluginConfig $pluginConfig
* @param UploadFileService $uploadFileService
* @param CustomerMediaRepository $customerUploadFilesRepository
* @param CustomerService $customerService
* @param EventDispatcherInterface $eventDispatcher
* @param SystemConfigService $systemConfigService
* @param EntityRepositoryInterface $customerGroupRepository
*/
public function __construct(
RequestStack $requestStack,
PluginConfig $pluginConfig,
UploadFileService $uploadFileService,
CustomerMediaRepository $customerUploadFilesRepository,
CustomerService $customerService,
EventDispatcherInterface $eventDispatcher,
SystemConfigService $systemConfigService,
EntityRepositoryInterface $customerGroupRepository
) {
$this->requestStack = $requestStack;
$this->pluginConfig = $pluginConfig;
$this->uploadFileService = $uploadFileService;
$this->customerUploadFilesRepository = $customerUploadFilesRepository;
$this->customerService = $customerService;
$this->eventDispatcher = $eventDispatcher;
$this->systemConfigService = $systemConfigService;
$this->customerGroupRepository = $customerGroupRepository;
}
/**
* @return array|string[]
*/
public static function getSubscribedEvents(): array
{
return [
CustomerRegisterEvent::class => 'onCustomerRegister',
CustomerDoubleOptInRegistrationEvent::class => 'onCustomerDoubleOptInRegistration',
'framework.validation.customer.create' => 'onCreateCustomer',
MediaFileExtensionWhitelistEvent::class => 'onWhiteListEvent',
AccountLoginPageLoadedEvent::class => 'onAccountLoginPageLoaded',
];
}
public function onAccountLoginPageLoaded(AccountLoginPageLoadedEvent $event):void
{
if (
!$this->pluginConfig->isActive()
|| !$this->pluginConfig->isActivateCustomerGroupSelection()
|| 0 === \count($this->pluginConfig->getRegistrationCustomerGroups())
) {
return;
}
$criteria = new Criteria($this->pluginConfig->getRegistrationCustomerGroups());
$customerGroups = $this->customerGroupRepository->search($criteria, $event->getContext());
$event->getPage()->addExtension(self::REGISTRATION_CUSTOMER_GROUPS, $customerGroups);
}
public function onCustomerDoubleOptInRegistration(CustomerDoubleOptInRegistrationEvent $event): void
{
if (!$this->pluginConfig->isActive()) {
return;
}
$currentRequest = $this->requestStack->getCurrentRequest();
if (!$currentRequest instanceof Request) {
return;
}
$context = $event->getContext();
$customer = $event->getCustomer();
$accountType = $this->getAccountType($currentRequest);
$this->changeCustomerGroup($customer, $accountType, $context);
$this->customerService->setActiveAttribute(
$customer->getId(),
!$this->isPrivateLogin($accountType),
$context,
null,
CustomerAttributeEntity::ACTIVATED_BY_SYSTEM
);
$this->uploadFiles($accountType, $currentRequest, $context, $customer);
}
public function onCreateCustomer(BuildValidationEvent $event): void
{
if (!$this->pluginConfig->isActive()) {
return;
}
$event->getDefinition()->add(BaseConstraint::REQUEST_KEY, new Required());
$event->getDefinition()->add(BaseConstraint::REQUEST_KEY, new MaxAmount());
$event->getDefinition()->add(BaseConstraint::REQUEST_KEY, new MimeType());
$event->getDefinition()->add(BaseConstraint::REQUEST_KEY, new FileSize());
$event->getDefinition()->add(BaseConstraint::REQUEST_KEY, new CustomerType());
$event->getDefinition()->add(AccountType::REQUEST_KEY, new AccountType());
}
protected function uploadFiles(string $accountType, Request $currentRequest, Context $context, CustomerEntity $customer): array
{
$files = [];
if (
\in_array($accountType, $this->pluginConfig->getUploadFile(), true)
|| (
$this->pluginConfig->isActivateCustomerGroupSelection()
&& \in_array($accountType, $this->pluginConfig->getUploadFileCustomerGroups(), true)
)
) {
$files = $currentRequest->files->get(BaseConstraint::REQUEST_KEY);
if (!\is_array($files)) {
return [];
}
$this->isNotCustomerRegistration = false;
$files = $this->uploadFileService->uploadFiles($files, $context);
$this->isNotCustomerRegistration = true;
$this->customerUploadFilesRepository->addUploadFiles(array_keys($files), $customer->getId(), $context);
}
return $files;
}
/**
* @param CustomerRegisterEvent $event
*/
public function onCustomerRegister(CustomerRegisterEvent $event): void
{
$customer = $event->getCustomer();
$context = $event->getContext();
if (!$this->pluginConfig->isActive()) {
$this->customerService->setActiveAttribute($customer->getId(), true, $context);
return;
}
$currentRequest = $this->requestStack->getCurrentRequest();
if (!$currentRequest instanceof Request || null === $currentRequest->get('accountType')) {
return;
}
/*
* Overwrite the account type with the customer group ID if the double opt-in registration is active
* and the customer group selections is active
*/
$accountType = $this->getAccountType($currentRequest);
if ($customer->getDoubleOptInRegistration() && $this->pluginConfig->isActivateCustomerGroupSelection()) {
$accountType = $customer->getGroupId();
}
$files = $this->uploadFiles($accountType, $currentRequest, $context, $customer);
$this->customerService->setActiveAttribute(
$customer->getId(),
!$this->isPrivateLogin($accountType),
$context,
null,
CustomerAttributeEntity::ACTIVATED_BY_SYSTEM
);
$this->changeCustomerGroup($customer, $accountType, $context);
if (CustomerEntity::ACCOUNT_TYPE_PRIVATE === $accountType) {
$this->customerService->setPrivateCustomerGroup($customer->getId(), $context);
} elseif (CustomerEntity::ACCOUNT_TYPE_BUSINESS === $accountType) {
$this->customerService->setBusinessCustomerGroup($customer->getId(), $context);
}
if (!$this->isPrivateLogin($accountType)) {
return;
}
$customerExtended = $this->customerService->getCustomerWithSalutationAndBillingAddress($customer->getId(), $context);
if ([] === $files) {
$files = $this->customerUploadFilesRepository->getUploadFilesIdsFromCustomer($customer->getId(), $context);
}
$this->eventDispatcher->dispatch(new CustomerRegisteredEvent($event->getSalesChannelContext(), $customerExtended));
$this->eventDispatcher->dispatch(
new CustomerRegisteredOperatorEvent(
$event->getSalesChannelContext(),
$customerExtended,
array_keys($files),
$this->systemConfigService,
$this->getLink(BusinessEventsConstants::ACTIVATION_PATH, $customerExtended->getId()),
$this->getLink(BusinessEventsConstants::DEACTIVATION_PATH, $customerExtended->getId())
)
);
}
protected function changeCustomerGroup(CustomerEntity $customer, string $customerGroupId, Context $context): void
{
if (
!$this->pluginConfig->isActivateCustomerGroupSelection()
|| $customer->getGroupId() === $customerGroupId
) {
return;
}
$this->customerService->changeCustomerGroup($customer->getId(), $customerGroupId, $context);
}
protected function getAccountType(Request $request): string
{
$accountType = $request->request->get('accountType', CustomerEntity::ACCOUNT_TYPE_PRIVATE);
if ('' === $accountType) {
$accountType = CustomerEntity::ACCOUNT_TYPE_PRIVATE;
}
return $accountType;
}
protected function isPrivateLogin(string $accountType): bool
{
if ($this->pluginConfig->isActivateCustomerGroupSelection()) {
return \in_array($accountType, $this->pluginConfig->getPrivateLoginCustomerGroups(), true);
}
return \in_array($accountType, $this->pluginConfig->getPrivateLoginAccountTypes(), true);
}
protected function getLink(string $path, string $customerId): string
{
$link = '';
if ($this->pluginConfig->isAcceptPrivateLoginByMail()) {
$currentRequest = $this->requestStack->getCurrentRequest();
if (!$currentRequest instanceof Request) {
return '';
}
$baseUrl = $currentRequest->get('sw-sales-channel-absolute-base-url');
$link = $baseUrl . $path . $customerId;
}
return $link;
}
public function onWhiteListEvent(MediaFileExtensionWhitelistEvent $event): void
{
if ($this->isNotCustomerRegistration || !$this->pluginConfig->isActive()) {
return;
}
$whiteList = $event->getWhitelist();
foreach ($this->pluginConfig->getUploadFileFormats() as $mimeType) {
$extension = explode('/', $mimeType)[1];
if (!\in_array($extension, $whiteList, true)) {
$whiteList[] = $extension;
}
}
$event->setWhitelist($whiteList);
}
}