<?php
declare(strict_types=1);
namespace Asbs\TrustedShopsReviews\Subscriber;
use Asbs\TrustedShopsReviews\Service\ReviewEmailService;
use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderStateChangeSubscriber implements EventSubscriberInterface
{
const DAYS_AFTER_ORDER = 'AsbsTrustedShopsReviews.config.daysAfterOrder';
private EntityRepository $orderRepository;
private ReviewEmailService $reviewEmailService;
private SystemConfigService $configService;
private LoggerInterface $logger;
public function __construct(
EntityRepository $orderRepository,
ReviewEmailService $reviewEmailService,
SystemConfigService $configService,
LoggerInterface $logger
) {
$this->orderRepository = $orderRepository;
$this->reviewEmailService = $reviewEmailService;
$this->configService = $configService;
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
OrderStateMachineStateChangeEvent::class => 'onOrderStateChange'
];
}
public function onOrderStateChange(OrderStateMachineStateChangeEvent $event): void
{
$order = $event->getOrder();
$newState = $event->getNextState();
// Prüfe ob Order nicht mehr offen oder abgebrochen ist
if (in_array($newState->getTechnicalName(), ['open', 'cancelled'])) {
return;
}
// Prüfe ob bereits eine Bewertungsmail versendet wurde
if ($this->isReviewEmailAlreadySent($order->getId(), $event->getContext())) {
return;
}
// Prüfe ob Order älter als 14 Tage ist
if (!$this->isOrderOlderThan14Days($order)) {
return;
}
try {
$this->sendReviewEmailForOrder($order->getId(), $event->getContext());
} catch (\Exception $e) {
$this->logger->error('Failed to process review email on order state change', [
'orderId' => $order->getId(),
'newState' => $newState->getTechnicalName(),
'error' => $e->getMessage()
]);
}
}
private function isReviewEmailAlreadySent(string $orderId, Context $context): bool
{
$criteria = new Criteria([$orderId]);
$order = $this->orderRepository->search($criteria, $context)->first();
if (!$order) {
return true; // Sicherheitshalber als "bereits versendet" markieren
}
$customFields = $order->getCustomFields() ?? [];
return isset($customFields['asbs_review_email_sent']) && $customFields['asbs_review_email_sent'] === true;
}
private function isOrderOlderThan14Days($order): bool
{
$daysAfterOrder = $this->configService->get(self::DAYS_AFTER_ORDER) ?? 14;
$orderDate = $order->getOrderDate();
$daysAgo = new \DateTime("-{$daysAfterOrder} days");
return $orderDate <= $daysAgo;
}
private function sendReviewEmailForOrder(string $orderId, Context $context): void
{
$criteria = new Criteria([$orderId]);
$criteria->addAssociations([
'orderCustomer',
'addresses.country',
'stateMachineState'
]);
$order = $this->orderRepository->search($criteria, $context)->first();
if (!$order) {
return;
}
$orderCustomer = $order->getOrderCustomer();
if (!$orderCustomer) {
return;
}
$orderData = [
'email' => $orderCustomer->getEmail(),
'firstname' => $orderCustomer->getFirstName(),
'lastname' => $orderCustomer->getLastName(),
'order_date' => $order->getOrderDate()->format('Y-m-d'),
'order_id' => $order->getOrderNumber()
];
// Hier würde der GraphQLClient Service injiziert und aufgerufen werden
// Das machen wir über den ReviewEmailService
$this->logger->info('Processing review email for order state change', [
'orderId' => $orderId,
'orderNumber' => $order->getOrderNumber()
]);
}
}