<?php
declare (strict_types=1);
namespace Frosh\TemplateMail\DependencyInjection;
use \Shopware\Core\Content\MailTemplate\Subscriber\MailSendSubscriberConfig;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Document\DocumentService;
use Shopware\Core\Content\Mail\Service\AbstractMailService;
use Shopware\Core\Content\MailTemplate\Event\MailSendSubscriberBridgeEvent;
use Shopware\Core\Content\MailTemplate\Exception\MailEventConfigurationException;
use Shopware\Core\Content\MailTemplate\Exception\SalesChannelNotFoundException;
use Shopware\Core\Content\MailTemplate\MailTemplateActions;
use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
use Shopware\Core\Content\Media\MediaService;
use Shopware\Core\Framework\Adapter\Translation\Translator;
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\Event\BusinessEvent;
use Shopware\Core\Framework\Event\MailActionInterface;
use Shopware\Core\Framework\Feature;
use Shopware\Core\Framework\Validation\DataBag\DataBag;
use Shopware\Core\System\Locale\LanguageLocaleCodeProvider;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\Event;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* @deprecated tag:v6.5.0 - reason:remove-subscriber - Will be removed in v6.5.0 Use SendMailAction instead
*/
class MailSendSubscriber extends \Shopware\Core\Content\MailTemplate\Subscriber\MailSendSubscriber implements EventSubscriberInterface
{
public $froshEventDispatcher;
public const ACTION_NAME = MailTemplateActions::MAIL_TEMPLATE_MAIL_SEND_ACTION;
public const MAIL_CONFIG_EXTENSION = 'mail-attachments';
private EntityRepositoryInterface $mailTemplateRepository;
private MediaService $mediaService;
private EntityRepositoryInterface $mediaRepository;
private DocumentService $documentService;
private EntityRepositoryInterface $documentRepository;
private LoggerInterface $logger;
private AbstractMailService $emailService;
private EventDispatcherInterface $eventDispatcher;
private EntityRepositoryInterface $mailTemplateTypeRepository;
private Translator $translator;
private LanguageLocaleCodeProvider $languageLocaleProvider;
/**
* @internal
*/
public function __construct(AbstractMailService $emailService, EntityRepositoryInterface $mailTemplateRepository, MediaService $mediaService, EntityRepositoryInterface $mediaRepository, EntityRepositoryInterface $documentRepository, DocumentService $documentService, LoggerInterface $logger, EventDispatcherInterface $eventDispatcher, EntityRepositoryInterface $mailTemplateTypeRepository, Translator $translator, LanguageLocaleCodeProvider $languageLocaleProvider, $froshEventDispatcher)
{
$this->mailTemplateRepository = $mailTemplateRepository;
$this->mediaService = $mediaService;
$this->mediaRepository = $mediaRepository;
$this->documentRepository = $documentRepository;
$this->documentService = $documentService;
$this->logger = $logger;
$this->emailService = $emailService;
$this->eventDispatcher = $eventDispatcher;
$this->mailTemplateTypeRepository = $mailTemplateTypeRepository;
$this->translator = $translator;
$this->languageLocaleProvider = $languageLocaleProvider;
$this->froshEventDispatcher = $froshEventDispatcher;
}
public static function getSubscribedEvents() : array
{
return [self::ACTION_NAME => 'sendMail'];
}
/**
* @throws MailEventConfigurationException
* @throws SalesChannelNotFoundException
* @throws InconsistentCriteriaIdsException
*/
public function sendMail(Event $event) : void
{
if (Feature::isActive('FEATURE_NEXT_17858')) {
return;
}
if (!$event instanceof BusinessEvent) {
return;
}
$mailEvent = $event->getEvent();
$extension = $event->getContext()->getExtension(self::MAIL_CONFIG_EXTENSION);
if (!$extension instanceof MailSendSubscriberConfig) {
$extension = new MailSendSubscriberConfig(false, [], []);
}
if ($extension->skip()) {
return;
}
if (!$mailEvent instanceof MailActionInterface) {
throw new MailEventConfigurationException('Not a instance of MailActionInterface', \get_class($mailEvent));
}
$config = $event->getConfig();
if (!isset($config['mail_template_id'])) {
return;
}
$mailTemplate = $this->getMailTemplate($config['mail_template_id'], $event->getContext());
if ($mailTemplate === null) {
return;
}
$injectedTranslator = $this->injectTranslator($mailEvent);
$data = new DataBag();
$recipients = $mailEvent->getMailStruct()->getRecipients();
if (isset($config['recipients']) && !empty($config['recipients'])) {
$recipients = $config['recipients'];
}
$data->set('recipients', $recipients);
$data->set('senderName', $mailTemplate->getTranslation('senderName'));
$data->set('salesChannelId', $mailEvent->getSalesChannelId());
$data->set('templateId', $mailTemplate->getId());
$data->set('customFields', $mailTemplate->getCustomFields());
$data->set('contentHtml', $mailTemplate->getTranslation('contentHtml'));
$data->set('contentPlain', $mailTemplate->getTranslation('contentPlain'));
$data->set('subject', $mailTemplate->getTranslation('subject'));
$this->froshEventDispatcher->dispatch(new \Frosh\TemplateMail\Event\MailDataBagFilter($data, $mailTemplate, $event->getContext()));
$data->set('mediaIds', []);
$attachments = $this->buildAttachments($event, $mailTemplate, $extension);
if (!empty($attachments)) {
$data->set('binAttachments', $attachments);
}
$this->eventDispatcher->dispatch(new MailSendSubscriberBridgeEvent($data, $mailTemplate, $event));
if ($data->has('templateId')) {
try {
$this->mailTemplateTypeRepository->update([['id' => $mailTemplate->getMailTemplateTypeId(), 'templateData' => $this->getTemplateData($mailEvent)]], $mailEvent->getContext());
} catch (\Throwable $e) {
// Dont throw errors if this fails // Fix with NEXT-15475
}
}
try {
$this->emailService->send($data->all(), $event->getContext(), $this->getTemplateData($mailEvent));
$writes = array_map(static function ($id) {
return ['id' => $id, 'sent' => true];
}, $extension->getDocumentIds());
if (!empty($writes)) {
$this->documentRepository->update($writes, $event->getContext());
}
} catch (\Exception $e) {
$this->logger->error("Could not send mail:\n" . $e->getMessage() . "\n" . 'Error Code:' . $e->getCode() . "\n" . "Template data: \n" . json_encode($data->all()) . "\n");
}
if ($injectedTranslator) {
$this->translator->resetInjection();
}
}
private function getMailTemplate(string $id, Context $context) : ?MailTemplateEntity
{
$criteria = new Criteria([$id]);
$criteria->addAssociation('media.media');
$criteria->setLimit(1);
return $this->mailTemplateRepository->search($criteria, $context)->first();
}
/**
* @throws MailEventConfigurationException
*/
private function getTemplateData(MailActionInterface $event) : array
{
$data = [];
foreach (array_keys($event::getAvailableData()->toArray()) as $key) {
$getter = 'get' . ucfirst($key);
if (method_exists($event, $getter)) {
$data[$key] = $event->{$getter}();
} else {
throw new MailEventConfigurationException('Data for ' . $key . ' not available.', \get_class($event));
}
}
return $data;
}
private function buildAttachments(BusinessEvent $event, MailTemplateEntity $mailTemplate, MailSendSubscriberConfig $config) : array
{
$attachments = [];
if ($mailTemplate->getMedia() !== null) {
foreach ($mailTemplate->getMedia() as $mailTemplateMedia) {
if ($mailTemplateMedia->getMedia() === null) {
continue;
}
if ($mailTemplateMedia->getLanguageId() !== null && $mailTemplateMedia->getLanguageId() !== $event->getContext()->getLanguageId()) {
continue;
}
$attachments[] = $this->mediaService->getAttachment($mailTemplateMedia->getMedia(), $event->getContext());
}
}
if (!empty($config->getMediaIds())) {
$entities = $this->mediaRepository->search(new Criteria($config->getMediaIds()), $event->getContext());
foreach ($entities as $media) {
$attachments[] = $this->mediaService->getAttachment($media, $event->getContext());
}
}
if (!empty($config->getDocumentIds())) {
$criteria = new Criteria($config->getDocumentIds());
$criteria->addAssociation('documentMediaFile');
$criteria->addAssociation('documentType');
$entities = $this->documentRepository->search($criteria, $event->getContext());
foreach ($entities as $document) {
$document = $this->documentService->getDocument($document, $event->getContext());
$attachments[] = ['content' => $document->getFileBlob(), 'fileName' => $document->getFilename(), 'mimeType' => $document->getContentType()];
}
}
return $attachments;
}
private function injectTranslator(MailActionInterface $event) : bool
{
if ($event->getSalesChannelId() === null) {
return false;
}
if ($this->translator->getSnippetSetId() !== null) {
return false;
}
$this->translator->injectSettings($event->getSalesChannelId(), $event->getContext()->getLanguageId(), $this->languageLocaleProvider->getLocaleForLanguageId($event->getContext()->getLanguageId()), $event->getContext());
return true;
}
}