<?php
namespace CioPodProducts\Subscriber;
use CioPodProducts\CioPodProducts;
use CioPodProducts\Error\PodMixedCartError;
use CioPodProducts\Event\PodCustomerApprovalEvent;
use CioPodProducts\Event\PodFinalApprovalEvent;
use CioPodProducts\Event\PodOrderCreatedEvent;
use CioPodProducts\Event\PodPhotographerGalleryUploadedEvent;
use CioPodProducts\Event\PodSupplierPreviewUploadedEvent;
use CioPodProducts\Helper\PodOrdersAssociationsHelper;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Event\BusinessEventCollectorEvent;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPage;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Framework\Event\BusinessEventCollector;
class BusinessEventCollectorSubscriber implements EventSubscriberInterface
{
protected BusinessEventCollector $businessEventCollector;
protected EventDispatcherInterface $eventDispatcher;
protected EntityRepository $entityRepository;
protected EntityRepository $orderRepository;
public function __construct(BusinessEventCollector $businessEventCollector, EventDispatcherInterface $eventDispatcher, EntityRepository $productRepository, EntityRepository $orderRepository)
{
$this->businessEventCollector = $businessEventCollector;
$this->eventDispatcher = $eventDispatcher;
$this->entityRepository = $productRepository;
$this->orderRepository = $orderRepository;
}
public static function getSubscribedEvents()
{
return [
BusinessEventCollectorEvent::NAME => 'onBusinessEventCollectorEvent',
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent',
StorefrontRenderEvent::class => 'onStorefrontRenderEvent'
];
}
public function onBusinessEventCollectorEvent(BusinessEventCollectorEvent $event)
{
$collection = $event->getCollection();
// add event PodOrderCreatedEvent to the collection
$definition = $this->businessEventCollector->define(PodOrderCreatedEvent::class);
if (!$definition) {
return;
}
$collection->set($definition->getName(), $definition);
// add event PodPhotographerGalleryUploadedEvent to the collection
$definition = $this->businessEventCollector->define(PodPhotographerGalleryUploadedEvent::class);
if (!$definition) {
return;
}
$collection->set($definition->getName(), $definition);
// add event PodSupplierPreviewUploadedEvent to the collection
$definition = $this->businessEventCollector->define(PodSupplierPreviewUploadedEvent::class);
if (!$definition) {
return;
}
$collection->set($definition->getName(), $definition);
// add event PodCustomerApprovalEvent to the collection
$definition = $this->businessEventCollector->define(PodCustomerApprovalEvent::class);
if (!$definition) {
return;
}
$collection->set($definition->getName(), $definition);
// add event PodFinalApprovalEvent to the collection
$definition = $this->businessEventCollector->define(PodFinalApprovalEvent::class);
if (!$definition) {
return;
}
$collection->set($definition->getName(), $definition);
}
public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event)
{
// pod orders are limited to a single line item
if ($event->getOrder()->getLineItems()->count() === 1) {
$lineItem = $event->getOrder()->getLineItems()->first();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $lineItem->getProductId()));
$product = $this->entityRepository->search($criteria, $event->getContext())->first();
if ($product instanceof ProductEntity) {
$productCustomFields = $product->getCustomFields();
// check if the line item is a pod product
if (is_array($productCustomFields) && array_key_exists(CioPodProducts::POD_PRODUCTS_CUSTOM_FIELD_IS_POD, $productCustomFields) && $productCustomFields[CioPodProducts::POD_PRODUCTS_CUSTOM_FIELD_IS_POD]) {
$lineItems = $event->getOrder()->getLineItems();
if ($lineItems && $lineItems->count() > 0) {
$firstLineItem = $lineItems->first();
$payload = $firstLineItem->getPayload();
if (!isset($payload['customFields']) || !\is_array($payload['customFields'])) {
$payload['customFields'] = [];
}
$this->orderRepository->update([
[
'id' => $event->getOrder()->getId(),
'lineItems' => [
[
'id' => $firstLineItem->getId(),
'payload' => $payload,
'productId' => $firstLineItem->getProductId(),
'referencedId' => $firstLineItem->getReferencedId()
]
],
]
], $event->getContext());
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $event->getOrder()->getId()));
PodOrdersAssociationsHelper::addAssociationsToCriteria($criteria);
$order = $this->orderRepository->search($criteria, $event->getContext())->first();
// this event triggers the initial flow of the pod flows
$podOrderCreatedEvent = new PodOrderCreatedEvent($event->getContext(), $order, $event->getSalesChannelId());
$this->eventDispatcher->dispatch($podOrderCreatedEvent);
}
}
}
}
public function onStorefrontRenderEvent(StorefrontRenderEvent $event)
{
$parameters = $event->getParameters();
if (!\is_array($parameters) || !array_key_exists('page', $parameters)) {
return;
}
$page = $parameters['page'];
if (!$page instanceof CheckoutConfirmPage) {
return;
}
$lineItems = $page->getCart()->getLineItems();
$hasPodProduct = false;
$errors = [];
foreach ($lineItems as $lineItem) {
$payload = $lineItem->getPayload();
if (array_key_exists('customFields', $payload) && is_array($payload['customFields']) && array_key_exists('custom_pod_products_isPodProduct', $payload['customFields']) && $payload['customFields']['custom_pod_products_isPodProduct'] === true) {
$hasPodProduct = true;
break;
}
}
if ($lineItems->count() > 1 && $hasPodProduct) {
$page->getCart()->addErrors(new PodMixedCartError());
$errors[] = ['type' => 'norm', 'message' => 'pod.checkout.noMixedBasketsError' ];
if (array_key_exists('errors', $event->getParameters())) {
$event->setParameter('errors', array_merge($event->getParameters()['errors'], $errors));
} else {
$event->setParameter('errors', $errors);
}
}
}
}