151 lines
8.5 KiB
PHP
151 lines
8.5 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\EmailPreview\Model;
|
|
|
|
use Magento\Email\Model\TemplateFactory;
|
|
use Magento\Framework\App\Area;
|
|
use Magento\Framework\App\Config\ScopeConfigInterface;
|
|
use Magento\Framework\DataObject;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Mail\Template\TransportBuilder;
|
|
use Magento\Payment\Helper\Data as PaymentHelper;
|
|
use Magento\Sales\Model\Order;
|
|
use Magento\Sales\Model\Order\Address\Renderer as AddressRenderer;
|
|
use Magento\Sales\Model\OrderFactory;
|
|
use Magento\Sales\Model\ResourceModel\Order\Creditmemo\CollectionFactory as CreditmemoCollectionFactory;
|
|
use Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory as InvoiceCollectionFactory;
|
|
use Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory as ShipmentCollectionFactory;
|
|
use Magento\Store\Model\ScopeInterface;
|
|
use Magento\Store\Model\StoreManagerInterface;
|
|
|
|
class PreviewService
|
|
{
|
|
public function __construct(
|
|
private readonly StoreManagerInterface $storeManager,
|
|
private readonly ScopeConfigInterface $scopeConfig,
|
|
private readonly TemplateFactory $templateFactory,
|
|
private readonly TransportBuilder $transportBuilder,
|
|
private readonly OrderFactory $orderFactory,
|
|
private readonly ShipmentCollectionFactory $shipments,
|
|
private readonly CreditmemoCollectionFactory $creditmemos,
|
|
private readonly InvoiceCollectionFactory $invoices,
|
|
private readonly AddressRenderer $addressRenderer,
|
|
private readonly PaymentHelper $paymentHelper
|
|
) {}
|
|
|
|
public function render(array $request): array
|
|
{
|
|
[$identifier, $variables, $storeId] = $this->prepare($request);
|
|
$template = $this->templateFactory->create();
|
|
$template->setDesignConfig(['area' => Area::AREA_FRONTEND, 'store' => $storeId]);
|
|
$template->setId($identifier);
|
|
$template->setVars($variables);
|
|
$html = $template->processTemplate();
|
|
return ['html' => $html, 'subject' => $template->getProcessedTemplateSubject($variables)];
|
|
}
|
|
|
|
public function send(array $request, string $recipient): void
|
|
{
|
|
if (!filter_var($recipient, FILTER_VALIDATE_EMAIL)) {
|
|
throw new LocalizedException(__('Enter a valid test recipient email address.'));
|
|
}
|
|
[$identifier, $variables, $storeId] = $this->prepare($request);
|
|
$this->transportBuilder
|
|
->setTemplateIdentifier($identifier)
|
|
->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
|
|
->setTemplateVars($variables)
|
|
->setFromByScope('general', $storeId)
|
|
->addTo($recipient)
|
|
->getTransport()->sendMessage();
|
|
}
|
|
|
|
private function prepare(array $request): array
|
|
{
|
|
$type = (string)($request['type'] ?? '');
|
|
if (!isset(TemplateTypes::TYPES[$type])) {
|
|
throw new LocalizedException(__('Select a supported email type.'));
|
|
}
|
|
$storeId = (int)($request['store_id'] ?? 0);
|
|
$store = $this->storeManager->getStore($storeId);
|
|
$definition = TemplateTypes::TYPES[$type];
|
|
$identifier = '';
|
|
$variables = [];
|
|
|
|
if (in_array($type, ['order', 'order_update', 'invoice', 'invoice_update', 'shipment', 'shipment_update', 'creditmemo', 'creditmemo_update'], true)) {
|
|
$order = $this->loadOrder((string)($request['increment_id'] ?? ''), $storeId);
|
|
if ($identifier === '') {
|
|
$default = $order->getCustomerIsGuest() && isset($definition['guest']) ? $definition['guest'] : $definition['template'];
|
|
$configPath = $order->getCustomerIsGuest() ? str_replace('/template', '/guest_template', $definition['config']) : $definition['config'];
|
|
$identifier = (string)($this->scopeConfig->getValue($configPath, ScopeInterface::SCOPE_STORE, $storeId) ?: $default);
|
|
}
|
|
$variables = $this->orderVariables($order);
|
|
$variables['comment'] = 'This is a preview of the latest customer notification.';
|
|
if (in_array($type, ['invoice', 'invoice_update'], true)) {
|
|
$entity = $this->invoices->create()->setOrderFilter($order)->setOrder('entity_id', 'DESC');
|
|
$number = trim((string)($request['entity_id'] ?? ''));
|
|
if ($number !== '') { $entity->addFieldToFilter('increment_id', $number); }
|
|
$invoice = $entity->getFirstItem();
|
|
if (!$invoice->getId()) { throw new LocalizedException(__('No invoice was found for this order.')); }
|
|
$variables += ['invoice' => $invoice, 'invoice_id' => $invoice->getId()];
|
|
} elseif (in_array($type, ['shipment', 'shipment_update'], true)) {
|
|
$entity = $this->shipments->create()->setOrderFilter($order)->setOrder('entity_id', 'DESC');
|
|
$number = trim((string)($request['entity_id'] ?? ''));
|
|
if ($number !== '') { $entity->addFieldToFilter('increment_id', $number); }
|
|
$shipment = $entity->getFirstItem();
|
|
if (!$shipment->getId()) { throw new LocalizedException(__('No shipment was found for this order.')); }
|
|
$variables += ['shipment' => $shipment, 'shipment_id' => $shipment->getId(), 'comment' => ''];
|
|
} elseif (in_array($type, ['creditmemo', 'creditmemo_update'], true)) {
|
|
$entity = $this->creditmemos->create()->setOrderFilter($order)->setOrder('entity_id', 'DESC');
|
|
$number = trim((string)($request['entity_id'] ?? ''));
|
|
if ($number !== '') { $entity->addFieldToFilter('increment_id', $number); }
|
|
$creditmemo = $entity->getFirstItem();
|
|
if (!$creditmemo->getId()) { throw new LocalizedException(__('No credit memo was found for this order.')); }
|
|
$variables += ['creditmemo' => $creditmemo, 'creditmemo_id' => $creditmemo->getId(), 'comment' => ''];
|
|
}
|
|
} else {
|
|
if ($identifier === '') {
|
|
$identifier = (string)($this->scopeConfig->getValue($definition['config'], ScopeInterface::SCOPE_STORE, $storeId) ?: $definition['template']);
|
|
}
|
|
$customer = new DataObject([
|
|
'id' => 0, 'firstname' => 'Preview', 'lastname' => 'Customer',
|
|
'name' => 'Preview Customer', 'email' => 'customer@example.com',
|
|
'rp_token' => 'preview-only-token'
|
|
]);
|
|
$customer->setData('confirmation', 'preview-confirmation-key');
|
|
$variables = ['store' => $store, 'customer' => $customer, 'back_url' => ''];
|
|
}
|
|
return [$identifier, $variables + $this->storeVariables($storeId), $storeId];
|
|
}
|
|
|
|
private function loadOrder(string $incrementId, int $storeId): Order
|
|
{
|
|
if (trim($incrementId) === '') { throw new LocalizedException(__('Enter an order number for this email type.')); }
|
|
$order = $this->orderFactory->create()->loadByIncrementId(trim($incrementId));
|
|
if (!$order->getId() || (int)$order->getStoreId() !== $storeId) { throw new LocalizedException(__('The order was not found in the selected Store View.')); }
|
|
return $order;
|
|
}
|
|
|
|
private function orderVariables(Order $order): array
|
|
{
|
|
return [
|
|
'order' => $order, 'order_id' => $order->getId(), 'billing' => $order->getBillingAddress(),
|
|
'payment_html' => $this->paymentHelper->getInfoBlockHtml($order->getPayment(), (int)$order->getStoreId()),
|
|
'store' => $order->getStore(),
|
|
'formattedShippingAddress' => $order->getIsVirtual() ? '' : $this->addressRenderer->format($order->getShippingAddress(), 'html'),
|
|
'formattedBillingAddress' => $this->addressRenderer->format($order->getBillingAddress(), 'html'),
|
|
'created_at_formatted' => $order->getCreatedAtFormatted(2),
|
|
'order_data' => new DataObject(['customer_name' => $order->getCustomerName(), 'is_not_virtual' => $order->getIsNotVirtual(), 'email_customer_note' => $order->getEmailCustomerNote(), 'frontend_status_label' => $order->getFrontendStatusLabel()])
|
|
];
|
|
}
|
|
|
|
private function storeVariables(int $storeId): array
|
|
{
|
|
return [
|
|
'store_email' => (string)$this->scopeConfig->getValue('trans_email/ident_general/email', ScopeInterface::SCOPE_STORE, $storeId),
|
|
'store_phone' => (string)$this->scopeConfig->getValue('general/store_information/phone', ScopeInterface::SCOPE_STORE, $storeId),
|
|
'store_hours' => (string)$this->scopeConfig->getValue('general/store_information/hours', ScopeInterface::SCOPE_STORE, $storeId),
|
|
];
|
|
}
|
|
}
|