<?php declare(strict_types=1);
namespace Crehler\MojeBambinoEngine\Subscriber;
use Crehler\MojeBambinoEngine\Struct\AddressStruct;
use Crehler\MojeBambinoEngine\Struct\NewsletterStruct;
use Crehler\MojeBambinoEngine\Util\Lifecycle\ActivateDeactivate;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Content\Newsletter\SalesChannel\NewsletterSubscribeRoute;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\Country\CountryCollection;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\Salutation\SalutationCollection;
use Shopware\Core\System\Salutation\SalutationEntity;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class CheckoutSubscriber implements EventSubscriberInterface
{
private EntityRepository $salutationRepository;
private EntityRepository $countryRepository;
private EntityRepository $orderAddressRepository;
private EntityRepository $orderRepository;
private NewsletterSubscribeRoute $newsletterService;
private RequestStack $request;
public function __construct(
EntityRepository $salutationRepository,
EntityRepository $countryRepository,
EntityRepository $orderAddressRepository,
EntityRepository $orderRepository,
NewsletterSubscribeRoute $newsletterService,
RequestStack $request
)
{
$this->salutationRepository = $salutationRepository;
$this->countryRepository = $countryRepository;
$this->orderAddressRepository = $orderAddressRepository;
$this->orderRepository = $orderRepository;
$this->newsletterService = $newsletterService;
$this->request = $request;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPage',
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlaced'
];
}
/**
* @param CheckoutConfirmPageLoadedEvent $event
*/
public function onCheckoutConfirmPage(CheckoutConfirmPageLoadedEvent $event)
{
$page = $event->getPage();
$salesChannelContext = $event->getSalesChannelContext();
$page->addExtension(
'address',
(new AddressStruct())
->setSalutations($this->getSalutations($salesChannelContext))
->setCountries($this->getCountries($salesChannelContext))
);
$newsletter = $event->getSalesChannelContext()->getCustomer()->getNewsletter();
$page->addExtension('newsletter', new NewsletterStruct((bool)$newsletter));
}
/**
* @param CheckoutOrderPlacedEvent $event
*/
public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event)
{
$request = $this->request->getCurrentRequest();
$address = $request->get('shippingAddress', null);
$isAfterSellerVisit = $request->get('afterSellerVisit', false);
$custInvoiceValue = $request->get('custInvoiceValue');
$govProject = $request->get('govProject');
$subscribeNewsletter = $request->get('subscribeNewsletter', null);
$emailConfirm = (bool)$request->get('emailConfirm', false);
$telephoneConfirm = (bool)$request->get('telephoneConfirm', false);
$salesChannelContext = $request->attributes->get('sw-sales-channel-context');
$customer = $salesChannelContext->getCustomer();
//Subscribe newsletter
if (!empty($subscribeNewsletter) && !empty($salesChannelContext)) {
$dataBag = new RequestDataBag([
'option' => 'direct',
'storefrontUrl' => $request->attributes->get('sw-sales-channel-absolute-base-url')
]);
try {
$this->newsletterService->subscribe($this->hydrateFromCustomer($dataBag, $customer), $salesChannelContext);
} catch (\Exception $exception) {
}
}
//Insert after Seller visit state
$data = [
'id' => $event->getOrder()->getId(),
'customFields' => [
ActivateDeactivate::ORDER_CUSTOM_FIELDS[0]['name'] => (bool)$isAfterSellerVisit,
ActivateDeactivate::ORDER_CUSTOM_FIELDS[1]['name'] => $custInvoiceValue,
ActivateDeactivate::ORDER_CUSTOM_FIELDS[2]['name'] => $govProject,
'emailconfirm' => $emailConfirm,
'telephoneconfirm' => $telephoneConfirm
]
];
//Insert invoice VAT address
if (!empty($address)) {
$address['salutationId'] = $this->getValidSalutationId($event->getContext());
$address['lastName'] = ' ';
$order = $event->getOrder();
$context = $event->getContext();
$countryId = $customer->getDefaultShippingAddress()->getCountry()->getId();
$id = $this->insertOrderInvoiceAddress($address, $order->getId(), $countryId, $context);
$data['customFields']['invoice_address_id'] = $id;
}
$this->orderRepository->update([$data], $event->getContext());
}
/**
* @throws InconsistentCriteriaIdsException
*/
private function getSalutations(SalesChannelContext $salesChannelContext): SalutationCollection
{
/** @var SalutationCollection $salutations */
$salutations = $this->salutationRepository->search(new Criteria(), $salesChannelContext->getContext())->getEntities();
$salutations->sort(function (SalutationEntity $a, SalutationEntity $b) {
return $b->getSalutationKey() <=> $a->getSalutationKey();
});
return $salutations;
}
/**
* @throws InconsistentCriteriaIdsException
*/
private function getCountries(SalesChannelContext $salesChannelContext): CountryCollection
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter('country.active', true))
->addAssociation('states');
/** @var CountryCollection $countries */
$countries = $this->countryRepository->search($criteria, $salesChannelContext->getContext())->getEntities();
$countries->sortCountryAndStates();
return $countries;
}
private function insertOrderInvoiceAddress(array $invoiceOrderAddress, string $orderId, string $countryId, Context $context): string
{
$id = Uuid::randomHex();
$invoiceOrderAddress['orderId'] = $orderId;
$invoiceOrderAddress['id'] = $id;
if (empty($invoiceOrderAddress['firstName'])) {
$invoiceOrderAddress['firstName'] = ' ';
}
if (empty($invoiceOrderAddress['street'])) {
$invoiceOrderAddress['street'] = ' ';
}
if (empty($invoiceOrderAddress['zipcode'])) {
$invoiceOrderAddress['zipcode'] = ' ';
}
if (empty($invoiceOrderAddress['city'])) {
$invoiceOrderAddress['city'] = ' ';
}
if (empty($invoiceOrderAddress['countryId'])) {
$invoiceOrderAddress['countryId'] = $countryId;
}
$this->orderAddressRepository->upsert([$invoiceOrderAddress], $context);
return $id;
}
private function getValidSalutationId(Context $context): string
{
$criteria = (new Criteria())->setLimit(1);
return $this->salutationRepository->searchIds($criteria, $context)->getIds()[0];
}
private function hydrateFromCustomer(RequestDataBag $dataBag, CustomerEntity $customer): RequestDataBag
{
$dataBag->set('email', $customer->getEmail());
$dataBag->set('salutationId', $customer->getSalutationId());
$dataBag->set('title', $customer->getTitle());
$dataBag->set('firstName', $customer->getFirstName());
$dataBag->set('lastName', $customer->getLastName());
$dataBag->set('zipCode', $customer->getDefaultShippingAddress()->getZipCode());
$dataBag->set('city', $customer->getDefaultShippingAddress()->getCity());
return $dataBag;
}
}