custom/plugins/AsbsTrustedShopsReviews/src/Subscriber/OrderStateChangeSubscriber.php line 44

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Asbs\TrustedShopsReviews\Subscriber;
  4. use Asbs\TrustedShopsReviews\Service\ReviewEmailService;
  5. use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent;
  6. use Shopware\Core\Framework\Context;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Core\System\SystemConfig\SystemConfigService;
  10. use Psr\Log\LoggerInterface;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. class OrderStateChangeSubscriber implements EventSubscriberInterface
  13. {
  14.     const DAYS_AFTER_ORDER 'AsbsTrustedShopsReviews.config.daysAfterOrder';
  15.     private EntityRepository $orderRepository;
  16.     private ReviewEmailService $reviewEmailService;
  17.     private SystemConfigService $configService;
  18.     private LoggerInterface $logger;
  19.     public function __construct(
  20.         EntityRepository $orderRepository,
  21.         ReviewEmailService $reviewEmailService,
  22.         SystemConfigService $configService,
  23.         LoggerInterface $logger
  24.     ) {
  25.         $this->orderRepository $orderRepository;
  26.         $this->reviewEmailService $reviewEmailService;
  27.         $this->configService $configService;
  28.         $this->logger $logger;
  29.     }
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return [
  33.             OrderStateMachineStateChangeEvent::class => 'onOrderStateChange'
  34.         ];
  35.     }
  36.     public function onOrderStateChange(OrderStateMachineStateChangeEvent $event): void
  37.     {
  38.         $order $event->getOrder();
  39.         $newState $event->getNextState();
  40.         
  41.         // Prüfe ob Order nicht mehr offen oder abgebrochen ist
  42.         if (in_array($newState->getTechnicalName(), ['open''cancelled'])) {
  43.             return;
  44.         }
  45.         // Prüfe ob bereits eine Bewertungsmail versendet wurde
  46.         if ($this->isReviewEmailAlreadySent($order->getId(), $event->getContext())) {
  47.             return;
  48.         }
  49.         // Prüfe ob Order älter als 14 Tage ist
  50.         if (!$this->isOrderOlderThan14Days($order)) {
  51.             return;
  52.         }
  53.         try {
  54.             $this->sendReviewEmailForOrder($order->getId(), $event->getContext());
  55.         } catch (\Exception $e) {
  56.             $this->logger->error('Failed to process review email on order state change', [
  57.                 'orderId' => $order->getId(),
  58.                 'newState' => $newState->getTechnicalName(),
  59.                 'error' => $e->getMessage()
  60.             ]);
  61.         }
  62.     }
  63.     private function isReviewEmailAlreadySent(string $orderIdContext $context): bool
  64.     {
  65.         $criteria = new Criteria([$orderId]);
  66.         $order $this->orderRepository->search($criteria$context)->first();
  67.         
  68.         if (!$order) {
  69.             return true// Sicherheitshalber als "bereits versendet" markieren
  70.         }
  71.         $customFields $order->getCustomFields() ?? [];
  72.         return isset($customFields['asbs_review_email_sent']) && $customFields['asbs_review_email_sent'] === true;
  73.     }
  74.     private function isOrderOlderThan14Days($order): bool
  75.     {
  76.         $daysAfterOrder $this->configService->get(self::DAYS_AFTER_ORDER) ?? 14;
  77.         $orderDate $order->getOrderDate();
  78.         $daysAgo = new \DateTime("-{$daysAfterOrder} days");
  79.         
  80.         return $orderDate <= $daysAgo;
  81.     }
  82.     private function sendReviewEmailForOrder(string $orderIdContext $context): void
  83.     {
  84.         $criteria = new Criteria([$orderId]);
  85.         $criteria->addAssociations([
  86.             'orderCustomer',
  87.             'addresses.country',
  88.             'stateMachineState'
  89.         ]);
  90.         
  91.         $order $this->orderRepository->search($criteria$context)->first();
  92.         
  93.         if (!$order) {
  94.             return;
  95.         }
  96.         $orderCustomer $order->getOrderCustomer();
  97.         if (!$orderCustomer) {
  98.             return;
  99.         }
  100.         $orderData = [
  101.             'email' => $orderCustomer->getEmail(),
  102.             'firstname' => $orderCustomer->getFirstName(),
  103.             'lastname' => $orderCustomer->getLastName(),
  104.             'order_date' => $order->getOrderDate()->format('Y-m-d'),
  105.             'order_id' => $order->getOrderNumber()
  106.         ];
  107.         // Hier würde der GraphQLClient Service injiziert und aufgerufen werden
  108.         // Das machen wir über den ReviewEmailService
  109.         $this->logger->info('Processing review email for order state change', [
  110.             'orderId' => $orderId,
  111.             'orderNumber' => $order->getOrderNumber()
  112.         ]);
  113.     }
  114. }