<?php
declare(strict_types=1);
namespace Vio\B2BWorkflow\Core\Subscriber;
use NetInventors\NetiNextOrderFields\Core\Content\OrderFields\OrderFieldsEntity;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use VioB2BLogin\Core\Services\EmployeeService;
use VioB2BLogin\Entity\Employee\EmployeeEntity;
use VioB2BLogin\VioB2BLogin;
use Vio\B2BWorkflow\Core\Checkout\Cart\Event\CheckoutCustomerOrderRequestPlacedEvent;
use Vio\B2BWorkflow\Core\Checkout\Cart\Event\CheckoutEmployeeOrderRequestPlacedEvent;
use Vio\B2BWorkflow\Core\ContextExtension;
use Vio\B2BWorkflow\Services\StateService;
class CartSubscriber implements EventSubscriberInterface
{
private EmployeeService $employeeService;
private StateService $stateService;
private EventDispatcherInterface $eventDispatcher;
private EntityRepositoryInterface $employeeRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderFieldRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderFieldsOrderRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderFieldsOrderValueRepository;
/**
* @var RequestStack
*/
private $requestStack;
public function __construct(
EmployeeService $employeeService,
StateService $stateService,
EventDispatcherInterface $eventDispatcher,
EntityRepositoryInterface $employeeRepository,
EntityRepositoryInterface $orderFieldRepository,
EntityRepositoryInterface $orderFieldsOrderRepository,
EntityRepositoryInterface $orderFieldsOrderValueRepository,
RequestStack $requestStack
)
{
$this->employeeService = $employeeService;
$this->stateService = $stateService;
$this->eventDispatcher = $eventDispatcher;
$this->employeeRepository = $employeeRepository;
$this->orderFieldRepository = $orderFieldRepository;
$this->orderFieldsOrderRepository = $orderFieldsOrderRepository;
$this->orderFieldsOrderValueRepository = $orderFieldsOrderValueRepository;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents(): array
{
return [
CartConvertedEvent::class => 'onCartConverted',
CheckoutOrderPlacedEvent::class => ['onOrderPlaced', 999]
];
}
public function onCartConverted(CartConvertedEvent $event): void
{
$cart = $event->getCart();
$convertedCart = $event->getConvertedCart();
$salesChannelContext = $event->getSalesChannelContext();
$employee = $this->employeeService->getEmployeeByContext($salesChannelContext);
// check rights
if ($employee
&& $cart->hasExtensionOfType(ContextExtension::KEY, ContextExtension::class)) {
$convertedCart['stateId'] = $this->stateService->getApprovalState($event->getContext())->getId();
foreach ($convertedCart['transactions'] as &$transaction) {
$transaction['stateId'] = $this->stateService->getPresetState($event->getContext())->getId();
}
unset($transaction);
$extension = (new ContextExtension())->setActive(true);
$event->getContext()->addExtension(ContextExtension::KEY, $extension);
}
$event->setConvertedCart($convertedCart);
}
public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
$order = $event->getOrder();
if ($order->getStateId() === $this->stateService->getApprovalState($event->getContext())->getId()) {
///// added fix by Mindaugas
$request = $this->requestStack->getCurrentRequest();
$parameter = $request->request->get('orderField') ?? [];
foreach ($parameter as $key => $value) {
if ($value === '') {
unset($parameter[$key]);
}
}
if ([] === $parameter || !\is_array($parameter)) {
return;
}
$orderId = $event->getOrder()->getId();
$criteria = new Criteria(array_keys($parameter));
$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'] = substr($parameter[$id], 0, 512);
foreach ($entity->getExtension('netiOrderFieldsVal')->getElements() as $value) {
if ($value->getValue() === $orderFieldsValues[$id]['value']) {
$orderFieldsValues[$id]['valueLabel'] = $value->getTranslated()['label'];
break;
}
}
}
if ($orderFields === []) {
return;
}
$filterClosure = static function ($arr) {
return isset($arr['value']) && '' !== $arr['value'];
};
$orderFieldsValues = array_filter($orderFieldsValues, $filterClosure);
$orderFields = array_intersect_key($orderFields, $orderFieldsValues);
$context = $event->getContext();
$result = $this->orderFieldsOrderRepository->create(array_values($orderFields), $context);
/** @var EntityWrittenEvent $event */
$entityEvent = $result->getEvents()->first();
$entityIds = [];
foreach ($entityEvent->getIds() as $entry) {
$entityIds[] = $entry['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);
///// end of fix
// when the order has an employee
$orderCustomFields = $event->getOrder()->getCustomFields();
if (is_array($orderCustomFields)
&& array_key_exists(VioB2BLogin::EMPLOYEE_FIELD, $orderCustomFields)) {
// load Employee
$employeeId = $orderCustomFields[VioB2BLogin::EMPLOYEE_FIELD];
$criteria = new Criteria([$employeeId]);
$criteria->addAssociation('customer');
$employee = $this->employeeRepository->search($criteria, $event->getContext())->first();
if ($employee instanceof EmployeeEntity) {
$this->eventDispatcher->dispatch(new CheckoutEmployeeOrderRequestPlacedEvent(
$event->getContext(),
$event->getOrder(),
$employee,
$event->getSalesChannelId()
));
$this->eventDispatcher->dispatch(new CheckoutCustomerOrderRequestPlacedEvent(
$event->getContext(),
$event->getOrder(),
$employee,
$event->getSalesChannelId()
));
}
}
$event->stopPropagation();
}
}
}