<?php
namespace Kaylo\Management\Subscriber;
use Kaylo\Management\Service\WorkshopCart\WorkshopCartLineItemHandler;
use NetzpEvents6\Components\EventsHelper;
use NetzpEvents6\Components\SlotStruct;
use NetzpEvents6\Core\Content\Participant\ParticipantEntity;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemQuantityChangedEvent;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
use Shopware\Core\Checkout\Document\DocumentConfigurationFactory;
use Shopware\Core\Checkout\Document\DocumentService;
use Shopware\Core\Checkout\Document\FileGenerator\FileTypes;
use Shopware\Core\Checkout\Order\Event\OrderStateMachineStateChangeEvent;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class WorkshopCheckoutSubscriber implements EventSubscriberInterface {
private $container;
private $config;
private $requestStack;
private $helper;
private $withoutParticipants;
private $documentService;
private $numberRangeValueGenerator;
public function __construct(
ContainerInterface $container,
SystemConfigService $config,
RequestStack $requestStack,
EventsHelper $helper,
DocumentService $documentService,
NumberRangeValueGeneratorInterface $numberRangeValueGenerator
) {
$this->container = $container;
$this->config = $config;
$this->requestStack = $requestStack;
$this->helper = $helper;
$this->documentService = $documentService;
$this->numberRangeValueGenerator = $numberRangeValueGenerator;
$pluginConfig = $this->config->get('NetzpEvents6.config');
$this->withoutParticipants = (bool)$pluginConfig['anonymous'];
}
public static function getSubscribedEvents() {
return [
BeforeLineItemAddedEvent::class => 'onLineItemAdded',
BeforeLineItemQuantityChangedEvent::class => 'onLineItemUpdated',
CartConvertedEvent::class => 'onCartConverted',
CheckoutOrderPlacedEvent::class => 'onOrderPlaced',
AccountOrderPageLoadedEvent::class => 'onOrderLoaded',
'state_enter.order.state.cancelled' => 'orderStateCanceled',
];
}
public function onCartConverted(CartConvertedEvent $event) {
$cart = $event->getCart();
$lineItems = $cart->getLineItems();
foreach ($lineItems as $lineItem) {
if ($lineItem->getType() !== WorkshopCartLineItemHandler::TYPE) {
return;
}
foreach ($lineItem->getChildren() as $childLineItem) {
if ($childLineItem->hasPayloadValue('netzp_event')) {
$this->helper->processEvent($childLineItem, $event->getContext());
}
}
}
}
public function onLineItemAdded(BeforeLineItemAddedEvent $event) {
$lineItem = $event->getLineItem();
if ($lineItem->getType() === WorkshopCartLineItemHandler::TYPE) {
foreach ($lineItem->getChildren() as $childLineItem) {
$eventId = $childLineItem->getPayloadValue('netzpEventId');
$repo = $this->container->get('s_plugin_netzp_events_slots.repository');
$criteria = new Criteria([ $eventId ]);
$criteria->addAssociation('event');
$netzpEventSlot = $repo->search($criteria, $event->getContext())->getEntities()->first();
if ($netzpEventSlot) {
$dateFrom = $netzpEventSlot->getFrom() ?
$netzpEventSlot->getFrom()->format(\DateTimeInterface::ATOM) :
'';
$dateUntil = $netzpEventSlot->getUntil() ?
$netzpEventSlot->getUntil()->format(\DateTimeInterface::ATOM) :
'';
$slot = new SlotStruct();
$slot->setId($netzpEventSlot->getId());
$slot->setTitle($netzpEventSlot->getEvent()->getTranslated()['title']);
$slot->setLocation($netzpEventSlot->getTranslated()['location']);
$slot->setAddress($netzpEventSlot->getTranslated()['address']);
$slot->setFrom($dateFrom);
$slot->setUntil($dateUntil);
$slot->setAvailable($netzpEventSlot->getTicketsAvailable() - $netzpEventSlot->getTicketsBooked());
if ($this->withoutParticipants) {
$participants = [];
$participantsIds = [];
for ($i = 1; $i <= $lineItem->getQuantity(); $i++) {
$participants[$i] = '(' . $i . ')';
$participantsIds[$i] = Uuid::randomHex();
}
$slot->setParticipants($participants);
$slot->setParticipantsIds($participantsIds);
}
$childLineItem->setPayloadValue('netzp_event', $slot->getVars());
}
}
}
}
public function onLineItemUpdated(BeforeLineItemQuantityChangedEvent $event) {
$lineItem = $event->getLineItem();
if ($lineItem->getType() !== WorkshopCartLineItemHandler::TYPE) {
return;
}
foreach ($lineItem->getChildren() as $childLineItem) {
if (!$childLineItem->hasPayloadValue('netzp_event')) {
continue;
}
if ($this->withoutParticipants) {
$participants = [];
$participantsIds = [];
for ($i = 1; $i <= $childLineItem->getQuantity(); $i++) {
$participants[$i] = '(' . $i . ')';
$participantsIds[$i] = Uuid::randomHex();
}
$payload = $childLineItem->getPayloadValue('netzp_event');
$payload['participants'] = $participants;
$payload['participantsIds'] = $participantsIds;
$childLineItem->setPayloadValue('netzp_event', $payload);
}
}
}
public function onOrderLoaded(AccountOrderPageLoadedEvent $event) {
}
public function onOrderPlaced(CheckoutOrderPlacedEvent $event) {
$this->processOrder($event);
}
public function orderStateCanceled(OrderStateMachineStateChangeEvent $event) {
$repoSlots = $this->container->get('s_plugin_netzp_events_slots.repository');
$repoParticipants = $this->container->get('s_plugin_netzp_events_participants.repository');
$context = $event->getContext();
$lineItems = $event->getOrder()->getLineItems();
foreach ($lineItems as $lineItem) {
if ($lineItem->getType() !== WorkshopCartLineItemHandler::TYPE) {
continue;
}
foreach ($lineItem->getChildren() as $childLineItem) {
$payload = $childLineItem->getPayload();
if (array_key_exists('netzp_event', $payload)) {
$ticket = $payload['netzp_event'];
$criteria = new Criteria([ $ticket['id'] ]);
$criteria->addAssociations([ 'event', 'participants', 'event.product' ]);
$slot = $repoSlots->search($criteria, $context)->getEntities()->first();
$numberOfParticipants = count($ticket['participants']);
$newTicketsBooked = $slot->getTicketsBooked() - $numberOfParticipants;
$repoSlots->update([
[
'id' => $slot->getId(),
'ticketsBooked' => $newTicketsBooked
]
], $context);
$this->helper->invalidateProductCache($slot->getEvent()->getProductid());
$this->helper->invalidateEventListing();
foreach ($ticket['participants'] as $participantNo => $participant) {
$participantId = $ticket['participantsIds'][$participantNo];
$repoParticipants->update([
[
'id' => $participantId,
'status' => ParticipantEntity::STATUS_CANCELED
]
], $context);
}
}
}
}
}
public function processOrder(CheckoutOrderPlacedEvent $event) {
$order = $event->getOrder();
$context = $event->getContext();
$orderId = $order->getId();
$pluginConfig = $this->config->get('NetzpEvents6.config', $event->getSalesChannelId());
$repo = $this->container->get('s_plugin_netzp_events_slots.repository');
$repoParticipants = $this->container->get('s_plugin_netzp_events_participants.repository');
$lineItems = $order->getLineItems();
$tickets = [];
$firstTicketNumber = '';
$n = 0;
foreach ($lineItems as $lineItem) {
if ($lineItem->getType() !== WorkshopCartLineItemHandler::CHILD_PRODUCT_TYPE) {
continue;
}
$payload = $lineItem->getPayload();
$productLabel = $lineItem->getLabel();
if (array_key_exists('netzp_event', $payload)) {
$ticket = $payload['netzp_event'];
$criteria = new Criteria([ $ticket['id'] ]);
$criteria->addAssociations([ 'event', 'participants', 'event.product' ]);
$slot = $repo->search($criteria, $context)->getEntities()->first();
foreach ($ticket['participants'] as $index => $participant) {
$participantId = $ticket['participantsIds'][$index];
$ticketNumber = '';
if ($pluginConfig['createpdf']) {
$ticketNumber = $this->numberRangeValueGenerator->getValue(
'event_ticket',
$context,
$event->getSalesChannelId()
);
if ($n === 0) {
$firstTicketNumber = $ticketNumber;
}
$tickets[] = [
'participant' => $participant,
'number' => $ticketNumber,
'slot' => $slot,
'product' => $productLabel
];
}
$repoParticipants->update([
[
'id' => $participantId,
'ticketNumber' => $ticketNumber,
'orderId' => $orderId
]
], $context);
$n++;
}
}
}
if ($pluginConfig['createpdf'] && $firstTicketNumber) {
$repoAddress = $this->container->get('order_address.repository');
$criteriaAddress = new Criteria([ $order->getBillingAddressId() ]);
$billingAddress = $repoAddress->search($criteriaAddress, $context)->getEntities()->first();
$pluginConfig = $this->config->get('NetzpEvents6.config');
$config = DocumentConfigurationFactory::createConfiguration([
'tickets' => $tickets,
'documentDate' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
'documentNumber' => $firstTicketNumber,
'billingAddress' => $billingAddress,
'withoutParticipants' => (bool)$pluginConfig['anonymous']
]);
$doc = $this->documentService->create(
$orderId, 'event_ticket', FileTypes::PDF, $config, $context, null, false
);
// for testing document generation only
/*
echo $doc->getDeepLinkCode() . " - ";
echo "<a href='/api/v3/_action/document/" . $doc->getId() . "/" . $doc->getDeepLinkCode() . "' target='_blank'>Download</a>";
die;
*/
}
}
}