<?php declare(strict_types=1);
namespace DonCarneTheme\Subscriber;
use Doctrine\DBAL\Connection;
use Psr\Log\LoggerInterface;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AccountOrderSubscriber implements EventSubscriberInterface
{
private Connection $connection;
private LoggerInterface $logger;
public function __construct(Connection $connection, LoggerInterface $logger)
{
$this->connection = $connection;
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
AccountEditOrderPageLoadedEvent::class => 'onAccountOrderPageLoaded',
AccountOrderPageLoadedEvent::class => 'onAccountOrderPageLoaded'
];
}
public function onAccountOrderPageLoaded($event): void
{
$this->logger->info('AccountOrderSubscriber called for event: ' . get_class($event));
// For AccountEditOrderPageLoadedEvent, process single order
if ($event instanceof AccountEditOrderPageLoadedEvent) {
$this->logger->info('Processing AccountEditOrderPageLoadedEvent');
try {
$order = $event->getPage()->getOrder();
$this->logger->info('Got order: ' . ($order ? $order->getOrderNumber() : 'null'));
if ($order) {
$this->processOrder($order, $event);
} else {
$this->logger->warning('Order is null in AccountEditOrderPageLoadedEvent');
}
} catch (\Exception $e) {
$this->logger->error('Error in AccountEditOrderPageLoadedEvent: ' . $e->getMessage());
}
return;
}
// For AccountOrderPageLoadedEvent (Order History), process all orders
if ($event instanceof AccountOrderPageLoadedEvent) {
$this->logger->info('Processing AccountOrderPageLoadedEvent (Order History)');
try {
$orders = $event->getPage()->getOrders();
$this->logger->info('Got ' . $orders->count() . ' orders');
foreach ($orders as $order) {
$this->processOrder($order, $event);
}
} catch (\Exception $e) {
$this->logger->error('Error in AccountOrderPageLoadedEvent: ' . $e->getMessage());
}
}
}
private function processOrder($order, $event): void
{
$customerId = $event->getSalesChannelContext()->getCustomer()?->getId();
$this->logger->info('Order Number: ' . $order->getOrderNumber());
$this->logger->info('Customer ID: ' . ($customerId ?? 'null'));
if (!$customerId) {
$this->logger->warning('No customer ID found');
return;
}
// Get all product numbers from the order
$productNumbers = [];
foreach ($order->getLineItems() as $lineItem) {
if ($lineItem->getType() === 'product' && $lineItem->getPayload()['productNumber']) {
$productNumbers[] = $lineItem->getPayload()['productNumber'];
}
}
$this->logger->info('Product numbers found: ' . implode(', ', $productNumbers));
if (empty($productNumbers)) {
$this->logger->warning('No product numbers found');
return;
}
// Check which products already have reviews from this customer for this order
$placeholders = str_repeat('?,', count($productNumbers) - 1) . '?';
$existingReviews = $this->connection->executeQuery("
SELECT article as productNumber
FROM `trusted_reviews`
WHERE order_number = ?
AND article IN ($placeholders)
", array_merge([$order->getOrderNumber()], $productNumbers))
->fetchAllAssociative();
$this->logger->info('Existing reviews found: ' . count($existingReviews));
// Create a map of reviewed product numbers
$reviewedProducts = [];
foreach ($existingReviews as $review) {
$reviewedProducts[$review['productNumber']] = true;
$this->logger->info('Product ' . $review['productNumber'] . ' already reviewed');
}
// Add extension to order entity with reviewed products info
$order->addExtension('reviewedProducts', new \Shopware\Core\Framework\Struct\ArrayStruct([
'reviewedProducts' => $reviewedProducts,
'debug_order_number' => $order->getOrderNumber(),
'debug_product_numbers' => $productNumbers,
'debug_query_result_count' => count($existingReviews)
]));
$this->logger->info('Extension added to order');
}
}