<?php
declare(strict_types=1);
namespace NetInventors\NetiNextOrderFields\Subscriber;
use NetInventors\NetiNextOrderFields\Core\Content\OrderFields\OrderFieldsEntity;
use NetInventors\NetiNextOrderFields\Service\OrderAttributes;
use NetInventors\NetiNextOrderFields\Service\PluginConfig;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Content\MailTemplate\Service\Event\MailBeforeValidateEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class Checkout implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
private $orderFieldRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderFieldsOrderRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderFieldsOrderValueRepository;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var OrderAttributes
*/
private $orderAttributeService;
/**
* @var PluginConfig
*/
private $pluginConfig;
public function __construct(
EntityRepositoryInterface $orderFieldRepository,
EntityRepositoryInterface $orderFieldsOrderRepository,
EntityRepositoryInterface $orderFieldsOrderValueRepository,
RequestStack $requestStack,
OrderAttributes $orderAttributeService,
PluginConfig $pluginConfig
) {
$this->orderFieldRepository = $orderFieldRepository;
$this->orderFieldsOrderRepository = $orderFieldsOrderRepository;
$this->orderFieldsOrderValueRepository = $orderFieldsOrderValueRepository;
$this->requestStack = $requestStack;
$this->orderAttributeService = $orderAttributeService;
$this->pluginConfig = $pluginConfig;
}
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'onConfirmLoaded',
CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
MailBeforeValidateEvent::class => 'beforeMailValidated',
];
}
public function onConfirmLoaded(CheckoutConfirmPageLoadedEvent $event): void
{
if (!$this->pluginConfig->isActive()) {
return;
}
$salesChannelContext = $event->getSalesChannelContext();
$salesChannelId = $salesChannelContext->getSalesChannel()->getId();
$criteria = (new Criteria())->addFilter(
new EqualsFilter('salesChannelId', $salesChannelId),
new EqualsFilter('active', 1)
)
->addAssociation('customerGroups')
->addSorting(new FieldSorting('position'));
$orderFields = $this->orderFieldRepository->search($criteria, $event->getContext());
$event->getPage()->addExtension('neti_order_fields', $orderFields);
}
public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
if (!$this->pluginConfig->isActive()) {
return;
}
$request = $this->requestStack->getCurrentRequest();
$parameter = $request->request->get('orderField') ?? [];
$orderId = $event->getOrder()->getId();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('active', true));
$criteria->addFilter(new EqualsFilter('salesChannelId', $event->getSalesChannelId()));
$orderFieldEntities = $this->orderFieldRepository->search($criteria, $event->getContext())->getElements();
$orderFields = [];
$orderFieldsValues = [];
/** @var OrderFieldsEntity $entity */
foreach ($orderFieldEntities as $id => $entity) {
$orderFields[$id]['label'] = $entity->getTranslation('label');
$orderFields[$id]['name'] = $entity->getName();
$orderFields[$id]['type'] = $entity->getType();
$orderFields[$id]['orderId'] = $orderId;
$orderFields[$id]['orderVersionId'] = $event->getOrder()->getVersionId();
$orderFields[$id]['orderFieldId'] = $entity->getId();
$orderFields[$id]['versionId'] = $event->getOrder()->getVersionId();
$orderFieldsValues[$id]['value'] = is_string($parameter[$id] ?? null)
? substr($parameter[$id], 0, 512)
: null;
foreach ($entity->getExtension('netiOrderFieldsVal')->getElements() as $value) {
if ($value->getValue() === $orderFieldsValues[$id]['value']) {
$orderFieldsValues[$id]['valueLabel'] = $value->getTranslated()['label'];
break;
}
}
}
if ($orderFields === []) {
return;
}
$orderFields = array_intersect_key($orderFields, $orderFieldsValues);
$context = $event->getContext();
$result = $this->orderFieldsOrderRepository->create(array_values($orderFields), $context);
/** @var EntityWrittenEvent|null $event */
$entityEvent = $result->getEvents()->first();
$entityIds = [];
if ($entityEvent instanceof EntityWrittenEvent) {
foreach ($entityEvent->getIds() as $id) {
$entityIds[] = $id;
}
}
$criteria = new Criteria($entityIds);
$orderFieldAttributes = $this->orderFieldsOrderRepository->search($criteria, $context)->getElements();
foreach ($orderFieldAttributes as $attribute) {
$orderFieldsValues[$attribute->getOrderFieldId()]['orderAttributeId'] = $attribute->getId();
$orderFieldsValues[$attribute->getOrderFieldId()]['orderAttributeVersionId'] = $event->getOrder()->getVersionId();
}
$this->orderFieldsOrderValueRepository->create(array_values($orderFieldsValues), $context);
}
public function beforeMailValidated(MailBeforeValidateEvent $event)
{
if (!$this->pluginConfig->isActive()) {
return;
}
$templateData = $event->getTemplateData();
if (!(isset($templateData['order']) && $templateData['order'] instanceof OrderEntity)) {
return;
}
$order = $templateData['order'];
$orderId = $order->getId();
$criteria = (new Criteria())->addFilter(new EqualsFilter('orderId', $orderId));
$context = $event->getContext();
$orderFields = $this->orderFieldsOrderRepository->search(
$criteria,
$context
)->getEntities();
if ([] === $orderFields->getElements()) {
return;
}
$order->addExtension('netiOrderFieldsOrderAttribute', $orderFields);
$this->orderAttributeService->getAttributeValues([ $order->getId() => $order ], $context);
}
}