<?php
namespace App\EventSubscriber\Order;
use App\Ecommerce\Model\Order;
use App\Model\Customer;
use App\Repository\OrderRepository;
use Factory\CartBundle\Classes\DataMapper\CartDataMapper;
use Factory\CheckoutBundle\Model\AbstractOrder;
use Factory\OrderManagementBundle\Classes\CsrEvents;
use Factory\OrderManagementBundle\Repository\OrderRepository as FactoryOrderRepository;
use Factory\SupportBundle\Contract\AbstractEvent;
use Pimcore;
use Pimcore\Bundle\EcommerceFrameworkBundle\EnvironmentInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Event\Ecommerce\CommitOrderProcessorEvents;
use Pimcore\Event\Model\Ecommerce\SendConfirmationMailEvent;
use Pimcore\HttpKernel\BundleLocator\NotFoundException;
use App\Classes\DataMapper\Invoice\InvoiceDataMapper;
use App\Classes\StoeltingEvents;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment as TwigEnv;
use function PHPUnit\Framework\throwException;
class SendEmailsSubscriber implements EventSubscriberInterface
{
/**
* @var RequestStack
*/
protected $requestStack;
/**
* @var EnvironmentInterface
*/
protected $environment;
/**
* @var OrderRepository
*/
protected $orderRepository;
/**
* @var TwigEnv
*/
protected $twig;
/**
* @var ParameterBagInterface
*/
protected $parametarBag;
/**
* @var RouterInterface
*/
protected $router;
/**
* @var TranslatorInterface
*/
protected $translator;
protected $session;
protected $availableEmails = [
'emails.order-placed' => '/emails/order/order-placed',
'emails.order-placed-admin' => '/emails/order/order-placed-admin',
'emails.quote-save' => '/emails/quote/quote-saved',
'emails.quote-request' => '/emails/quote/quote-requested',
'emails.quote-request-admin' => '/emails/quote/quote-requested-admin',
];
protected $factoryOrderRepository;
public static function getSubscribedEvents()
{
return [
StoeltingEvents::ORDER_PAID => [
['sendOrderPaidEmail', 10]
],
CsrEvents::ORDER_PAID => [
['sendOrderPaidEmail', 10]
],
StoeltingEvents::QUOTE_ORDER_PAID => [
['sendOrderPaidEmail', 10]
],
CommitOrderProcessorEvents::SEND_CONFIRMATION_MAILS => [
['sendOrderPlacedEmail', 10],
['sendQuoteSavedEmail', 10],
['sendQuoteRequestedEmail', 10]
],
CsrEvents::QUOTE_SEND_INVOICE_MANUAL => [
['simpleSendQuoteEmail', 10]
]
];
}
public function __construct(
RequestStack $requestStack,
OrderRepository $orderRepository,
EnvironmentInterface $environment,
TwigEnv $twig,
FactoryOrderRepository $factoryOrderRepository,
TranslatorInterface $translator,
ParameterBagInterface $parameterBag,
RouterInterface $router,
SessionInterface $session
) {
$this->requestStack = $requestStack;
$this->environment = $environment;
$this->orderRepository = $orderRepository;
$this->twig = $twig;
$this->factoryOrderRepository = $factoryOrderRepository;
$this->translator = $translator;
$this->parametarBag = $parameterBag;
$this->router = $router;
$this->session = $session;
}
protected function getRequest(): Request
{
return $this->requestStack->getMasterRequest();
}
protected function getCurrentCustomer(): Customer
{
if (!$this->customer) {
$env = Factory::getInstance()->getEnvironment();
$this->customer = Customer::getById($env->getCurrentUserId());
}
return $this->customer;
}
protected function getCustomerAddress(string $addressId)
{
$customer = $this->getCurrentCustomer();
return $customer->getAddress($addressId);
}
public function sendOrderPlacedEmail(SendConfirmationMailEvent $event)
{
if ($event->getOrder()->getOrderType() != Order::ORDER_TYPE_ORDER) {
return;
}
$event->setSkipDefaultBehaviour(true);
$path = $this->getPath('emails.order-placed');
$customer = $event->getOrder()->getCustomer();
$order = $event->getOrder();
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($event->getOrder()),
'order' => $event->getOrder()
];
$mail = $this->sendEmail($path, $params, function (\Pimcore\Mail $mail) use ($params, $order, $customer) {
$name = $order->getCustomerFirstname().' '.$order->getCustomerLastname();
$mail->addTo($order->getCustomerEmail(), $name);
});
}
public function sendOrderPaidEmail(AbstractEvent $event)
{
try {
$order = $event->getSubject();
if (!$order instanceof AbstractOrder || $order->getOrderType() != Order::ORDER_TYPE_ORDER) {
return;
}
$event->stopPropagation(true);
$path = $this->getPath('emails.order-placed');
$ccEmail = $this->getAdditionalEmail($order);
$customer = $order->getCustomer();
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($order),
'order' => $order
];
$mail = $this->sendEmail($path, $params, function (\Pimcore\Mail $mail) use ($params, $order, $customer, $ccEmail) {
$name = $order->getCustomerFirstname().' '.$order->getCustomerLastname();
$mail->addTo($order->getCustomerEmail(), $name);
if ($ccEmail) {
$mail->addCc($ccEmail);
}
});
$adminPath = $this->getPath('emails.order-placed-admin');
$mail = $this->sendEmail($adminPath, $params, function (\Pimcore\Mail $mail) {
});
} catch (\Exception $e) {
// Log exception
\Pimcore\Log\Simple::log('stoelting', 'CHECKOUT [email]: '.$e->getMessage());
if (empty($event->hasArgument('xhr'))) {
$this->session
->getFlashBag()
->add('error', $this->translator->trans('stoelting.payment.email.error'));
return;
}
throw new \Exception($this->translator->trans('stoelting.payment.email.error'), 0, $e);
}
}
public function sendQuoteSavedEmail(SendConfirmationMailEvent $event)
{
if ($event->getOrder()->getOrderType() != Order::ORDER_TYPE_QUOUTE_SAVED) {
return;
}
$event->setSkipDefaultBehaviour(true);
$path = $this->getPath('emails.quote-save');
$customer = $event->getOrder()->getCustomer();
$order = $event->getOrder();
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($event->getOrder()),
'order' => $event->getOrder()
];
$this->sendEmail($path, $params, function (\Pimcore\Mail $mail) use ($params, $order, $customer) {
$name = $order->getCustomerFirstname().' '.$order->getCustomerLastname();
$mail->addTo($order->getCustomerEmail(), $name);
});
}
public function sendQuoteReminderEmail($documentPath, $quoteReminders, $quoteReminderLinks)
{
$document = \Pimcore\Model\Document::getByPath($documentPath);
if (!$document) {
throw new \Exception('Unable to find email template!');
}
$request = new Request();
$request->setLocale($this->getEmailLocale());
$request->setDefaultLocale($this->getEmailLocale());
foreach ($quoteReminders as $key => $quoteReminder) {
$this->translator->setLocale($this->getEmailLocale());
$params = [
'invoiceHtml' => $this->getInvoiceContent($quoteReminder, $request),
'link' => $quoteReminderLinks[$key]
];
//sending the email
$mail = new \Pimcore\Mail();
$mail->setDocument($document);
$mail->setParams($params);
// This fixed sentry issue but caused sending of the broken emails to customers so this needs to be handled
// in the future
//$mail->addTo($quoteReminder->getCustomerEmail());
$mail->send();
}
}
public function sendPricesImportEmail($documentPath)
{
$document = \Pimcore\Model\Document::getByPath($documentPath);
if (!$document) {
throw new \Exception('Unable to find email template!');
}
//sending the email
$mail = new \Pimcore\Mail();
$mail->setDocument($document);
$mail->send();
}
public function getEmailLocale() {
return 'en';
}
public function sendQuoteRequestedEmail(SendConfirmationMailEvent $event)
{
if ($event->getOrder()->getOrderType() != Order::ORDER_TYPE_QUOUTE_REQUEST) {
return;
}
$event->setSkipDefaultBehaviour(true);
$this->__sendEmail($event->getOrder(), $this->getPath('emails.quote-request'));
$order = $event->getOrder();
$customer = $order->getCustomer();
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($order),
'order' => $order
];
$adminPath = $this->getPath('emails.quote-request-admin');
$this->sendEmail($adminPath, $params, function (\Pimcore\Mail $mail) {
});
}
public function simpleSendQuoteEmail (AbstractEvent $event)
{
$order = $event->getSubject();
$path = $this->getPath('emails.quote-request');
$customer = $order->getCustomer();
$toName = $order->getCustomerFirstname().' '.$order->getCustomerLastname();
$toEmail = $order->getCustomerEmail();
$ccEmail = $this->getAdditionalEmail($order);
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($order),
'order' => $order
];
$this->sendEmail($path, $params, function (\Pimcore\Mail $mail) use ($toName, $toEmail, $ccEmail) {
$mail->addTo($toEmail, $toName);
if ($ccEmail) {
$mail->addCc($ccEmail, $ccEmail);
}
});
$adminPath = $this->getPath('emails.quote-request-admin');
$this->sendEmail($adminPath, $params, function (\Pimcore\Mail $mail) {
});
}
/**
* @param AbstractOrder $order
*
* @return null|string
*/
private function getAdditionalEmail($order)
{
$customized = $order->getCustomized();
if (!in_array('getOrderAditionalEmailAddress', $customized->getBrickGetters())) {
return null;
}
$additionalAddress = $customized->getOrderAditionalEmailAddress();
if (!$additionalAddress) {
return null;
}
return $additionalAddress->getEmail();
}
private function __sendEmail($order, $path)
{
$customer = $order->getCustomer();
$params = [
'orderId' => $order->getId(),
'customerId' => $customer ? $customer->getId() : null,
'invoiceHtml' => $this->getInvoiceContent($order),
'order' => $order
];
$this->sendEmail($path, $params, function (\Pimcore\Mail $mail) use ($order) {
$name = $order->getCustomerFirstname().' '.$order->getCustomerLastname();
$mail->addTo($order->getCustomerEmail(), $name);
});
}
protected function getPath($name)
{
$path = $this->availableEmails[$name] ?? null;
if (Pimcore::getContainer()->hasParameter($name)) {
$path = Pimcore::getContainer()->getParameter($name);
}
return $path;
}
protected function sendEmail($documentPath, array $params = [], $callable = null)
{
$document = \Pimcore\Model\Document::getByPath($documentPath);
if (!$document) {
throw new \Exception(sprintf('Unable to find email template %s.', $documentPath));
}
//sending the email
$mail = new \Pimcore\Mail();
$mail->setDocument($document);
$mail->setParams($params);
if ($callable && is_callable($callable)) {
$callable($mail, $params, $document);
}
try {
return $mail->send();
} catch (\Throwable $e) {
\Pimcore\Log\Simple::log('stoelting-email', $e->getMessage() . $e->getTraceAsString());
throw $e;
}
}
protected function getInvoiceContent($order, $request = null)
{
$order = $this->factoryOrderRepository->findOrFail($order->getId());
if (!$order || $order->getOrderState() != AbstractOrder::ORDER_STATE_COMMITTED) {
throw new NotFoundException($this->translator->trans('stoelting.not-found.order'));
}
if (!$request) {
$request = $this->getRequest();
}
return $this->twig->render('email/invoice.html.twig', [
'data' => (new InvoiceDataMapper($order))->toArray($request),
'summary' => (new CartDataMapper($order))->toArray($request)
]);
}
}