<?php declare(strict_types=1);
namespace Uandi\UandiEfbLoginById\Service;
use Exception;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction;
use Shopware\Core\Content\MailTemplate\Exception\MailEventConfigurationException;
use Shopware\Core\Content\MailTemplate\Exception\SalesChannelNotFoundException;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Event\FlowEvent;
use Shopware\Core\Framework\Event\MailAware;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\Event;
class SendMailActionDecorator extends FlowAction implements EventSubscriberInterface
{
private LoggerInterface $logger;
private EntityRepositoryInterface $customerRepository;
private FlowAction $decoratedService;
/**
* @param LoggerInterface $logger
* @param EntityRepositoryInterface $customerRepository
* @param EventSubscriberInterface $decoratedService
*/
public function __construct(
LoggerInterface $logger,
EntityRepositoryInterface $customerRepository,
FlowAction $decoratedService
) {
$this->logger = $logger;
$this->customerRepository = $customerRepository;
$this->decoratedService = $decoratedService;
}
public function getDecorated(): FlowAction
{
return $this->decoratedService;
}
public static function getName(): string
{
return 'action.mail.send';
}
public static function getSubscribedEvents(): array
{
return [
self::getName() => 'handle',
];
}
/**
* Intercept send mail action to replace recipient if needed
*
* @throws MailEventConfigurationException
* @throws SalesChannelNotFoundException
* @throws InconsistentCriteriaIdsException
*/
public function handle(Event $event): void
{
if (!$event instanceof FlowEvent) {
return;
}
$mailEvent = $event->getEvent();
if ($mailEvent instanceof MailAware) {
//Load default recipients
$recipients = $mailEvent->getMailStruct()->getRecipients();
//Check if there is email in customFields
if ($customEmail = $this->getCustomEmail($event->getEvent(), $recipients)) {
$mailEvent->getMailStruct()->setRecipients($customEmail);
}
}
$this->decoratedService->handle($event);
}
/**
* Get custom email from customFields
*
* @param MailAware $event
* @param array $recipients
* @return array|null
*/
private function getCustomEmail(MailAware $event, array $recipients): ?array
{
try {
$customer = $this->getCustomer($event);
if (isset($customer) && !empty($customer->getCustomFields())) {
$customFields = $customer->getCustomFields() ?? [];
if (isset($customFields['contactEmail']) && !empty($customFields['contactEmail'])
&& $this->isValidEmail($customFields['contactEmail'])
) {
return [$customFields['contactEmail'] => current($recipients)];
}
}
} catch (Exception $exception) {
$this->logger->error('Not possible to find custom email: ' . $exception->getMessage());
}
return null;
}
/**
* Get custom from different objects
*
* @param MailAware $event
* @return CustomerEntity|null
*/
private function getCustomer(MailAware $event) :?CustomerEntity
{
if (true === method_exists($event,'getCustomer')) {
return $event->getCustomer();
}
if (true === method_exists($event,'getOrder')) {
return $event->getOrder()->getOrderCustomer()->getCustomer();
}
if (true === method_exists($event,'getNewsletterRecipient')) {
return $this->getCustomerByEmail($event->getNewsletterRecipient()->getEmail(), $event->getContext());
}
return null;
}
private function getCustomerByEmail(string $email, Context $context): ?CustomerEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('email', $email));
return $this->customerRepository->search($criteria, $context)->first();
}
/**
* @param string $email
* @return bool
*/
private function isValidEmail(string $email): bool
{
//Assume it's valid if we can't validate it
if (!function_exists('filter_var')) {
return true;
}
return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
}
public function requirements(): array
{
return $this->decoratedService->requirements();
}
}