<?php
namespace Boldr\Shop\ReceiptPrinterBundle\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Boldr\Shop\ShopBundle\Event\OrderStateUpdatedEvent;
use Boldr\Shop\ReceiptPrinterBundle\Printer\PrintJobManager;
use Boldr\Shop\ReceiptPrinterBundle\Event\QueueReceiptEvent;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Psr\Log\LoggerInterface;
class EventSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly PrintJobManager $printJobManager,
private readonly array $receiptOrderStates,
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger
) {}
public static function getSubscribedEvents()
{
return [
OrderStateUpdatedEvent::class => [
['onOrderStateChanged', 10]
],
QueueReceiptEvent::class => [
['onQueueReceipt', 10]
]
];
}
public function onQueueReceipt(QueueReceiptEvent $event)
{
$printer = $event->getPrinter();
$orders = $event->getOrders();
// Filter out printers that don't print this category
if ($printer->getRestrictItemsByCategory())
{
$foundItemsInCategory = false;
$printerCategoryIds = [];
foreach ($printer->getRestrictCategories() as $category)
{
$printerCategoryIds[$category->getId()] = true;
}
foreach ($orders as $order)
{
foreach ($order->getItems() as $item)
{
foreach ($item->getProductVariant()->getProduct()->getCategories() as $category)
{
if (isset($printerCategoryIds[$category->getId()]))
{
$foundItemsInCategory = true;
break 2;
}
}
}
}
if (!$foundItemsInCategory)
{
$event->stopPropagation();
return;
}
}
if ($printer->getRestrictItemsByCategory() && count($printer->onlyContainingCategories) > 0)
{
// Stop propagation, if the order contains a product that does not as one of its categories have any of the categories in the printer's onlyContainingCategories
foreach ($orders as $order)
{
foreach ($order->getItems() as $item)
{
$productCategories = $item->getProductVariant()->getProduct()->getCategories();
$productCategoryIds = array_map(fn($category) => $category->getId(), $productCategories->toArray());
$found = false;
foreach ($printer->onlyContainingCategories as $category)
{
if (in_array($category->getId(), $productCategoryIds))
{
$found = true;
break;
}
}
if (!$found)
{
$event->stopPropagation();
return;
}
}
}
}
}
public function onOrderStateChanged(OrderStateUpdatedEvent $event)
{
if (in_array($event->getNewState(), $this->receiptOrderStates))
{
// Execute transaction to prevent double receipts
$sql = 'INSERT INTO shop_receipt_printer_initial_receipt (`order_id`) VALUES (:id)';
$stmt = $this->entityManager->getConnection()->prepare($sql);
$stmt->bindValue('id', $event->getOrder()->getId());
try
{
$stmt->executeStatement();
$this->printJobManager->printReceiptForOrders([$event->getOrder()]);
}
catch (Exception $ex)
{
$this->logger->info('Prevented double receipt for order nr. '. $event->getOrder()->getNumber() .' (id #'. $event->getOrder()->getId() .')', [
'exception' => $ex
]);
}
}
}
}