<?php declare(strict_types=1);
namespace CioAddressbook\Subscriber;
use CioAddressbook\Controller\AddressbookController;
use CioAddressbook\Definition\Addressbook\AddressbookEntity;
use CioAddressbook\Error\CioShippingAddressPermissionsError;
use CioAddressbook\Service\AddressArrayHelper;
use CioAddressbook\Service\AddressbookService;
use CioBudget\Service\SessionService;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
use Shopware\Core\Checkout\Customer\Event\CustomerLogoutEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class AddressbookSubscriber implements EventSubscriberInterface
{
private SessionService $sessionService;
private AddressbookService $addressbookService;
private RequestStack $requestStack;
private ContainerInterface $container;
public function __construct(SessionService $sessionService, AddressbookService $addressbookService, RequestStack $requestStack, ContainerInterface $container)
{
$this->sessionService = $sessionService;
$this->addressbookService = $addressbookService;
$this->requestStack = $requestStack;
$this->container = $container;
}
public static function getSubscribedEvents(): array
{
return [
StorefrontRenderEvent::class => 'onStorefrontRender',
CartConvertedEvent::class => 'onCartConvertedEvent',
KernelEvents::REQUEST => 'onKernelRequest',
CustomerLogoutEvent::class => 'onCustomerLogoutEvent'
];
}
public function onStorefrontRender(StorefrontRenderEvent $event)
{
$route = $event->getRequest()->get('_route');
if ($route == 'frontend.checkout.confirm.page') {
/** @var EntityRepositoryInterface $customerAddressRepository */
$customerAddressRepository = $this->container->get('customer_address.repository');
$addressResultCollection = $customerAddressRepository->search(
(new Criteria())->addFilter(new EqualsFilter('customerId', $event->getSalesChannelContext()->getCustomer()->getId())),
$event->getContext()
);
$budgetStore = $this->sessionService->getBudgetStoreEntityFromSession($event->getContext());
$budgetStoreData = '';
$addressBookEntry = null;
if ($budgetStore) {
/** @var AddressbookEntity $addressBookEntry */
$addressBookEntry = $this->container->get('cio_addressbook.repository')->search(new Criteria([$budgetStore->getAddressbookId()]), $event->getContext())->first();
if ($addressBookEntry) {
$budgetStoreData = json_encode(
AddressArrayHelper::addressEntityToArray($addressBookEntry)
);
}
}
$parentAddressResultCollection = null;
$parentCustomer = $event->getSalesChannelContext()->getCustomer()->getExtension('customerParent');
if($parentCustomer && $this->checkDefaultParentAccountAddressPermissions($event)){
$parentAddressResultCollection = $customerAddressRepository->search(
(new Criteria())->addFilter(new EqualsFilter('customerId', $parentCustomer->getParent())),
$event->getContext()
);
}
$currentSelectedOverrideAddress = null;
try {
$sessionData = $event->getRequest()->getSession()->get(AddressbookController::ADDRESS_TYPE_SESSION_DATA_KEY);
$currentSelectedOverrideAddress = json_decode($sessionData, true);
} catch (\Throwable $throwable) {
}
$currentSelectedOverrideAddress = $this->addressbookService->getCurrentOverrideShippingAddress($event->getRequest()->getSession(), $event->getSalesChannelContext(), $budgetStoreData);
if ($this->checkDefaultAccountAddressPermissions($event) === false && $event->getRequest()->getSession()->get(AddressbookController::ADDRESS_TYPE_SESSION_DATA_KEY) === null) {
/** @var Cart $cart */
$cart = $event->getParameters()['page']->getCart();
$cart->addErrors(new CioShippingAddressPermissionsError());
$event->getRequest()->getSession()->getFlashBag()->add('danger', 'Keine Berechtigungen für die Verwendung der Standard-Adresse im Kundenprofil. Bitte wählen Sie eine andere Adresse aus.');
}
$event->setParameter('allAvailableDefaultShippingAddresses', $addressResultCollection);
$event->setParameter('budgetShippingAddressForCheckout', $budgetStore);
$event->setParameter('budgetShippingAdressbookAddressForCheckout', $addressBookEntry);
$event->setParameter('budgetShippingAddressData', $budgetStoreData);
$event->setParameter('currentlySelectedOverrideAddress', $currentSelectedOverrideAddress);
$event->setParameter('addressBookShippingAddressesForCheckout', $this->addressbookService->getShippingAddressesForCheckout($event->getContext()));
$event->setParameter('allAvailableParentShippingAddresses', $parentAddressResultCollection);
$event->setParameter('parentShippingAddressForCheckout', null);
$event->setParameter('parentShippingAdressbookAddressForCheckout', null);
}
}
protected function checkDefaultAccountAddressPermissions(StorefrontRenderEvent $event)
{
return $this->container->get('customer.cio_customer_permission_service')->check($event->getSalesChannelContext()->getCustomer(), 'ADDRESS_DELIVERY_CUSTOM', $event->getContext());
}
protected function checkDefaultParentAccountAddressPermissions(StorefrontRenderEvent $event)
{
return $this->container->get('customer.cio_customer_permission_service')->check($event->getSalesChannelContext()->getCustomer(), 'ADDRESS_DELIVERY_CUSTOM', $event->getContext());
}
public function onCartConvertedEvent(CartConvertedEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
$isOverrideActive = $request->get('cioOverrideShippingAddressActive') !== null;
$addressOverrideData = $request->get('cioOverrideShippingAddressData');
if ($addressOverrideData) {
$currentSelectedOverrideAddress = null;
try {
$currentSelectedOverrideAddress = json_decode($addressOverrideData, true);
/** @var EntityRepositoryInterface $orderRepository */
$orderRepository = $this->container->get('order_address.repository');
/** @var EntityRepositoryInterface $orderDeliveryRepository */
$orderDeliveryRepository = $this->container->get('order_delivery.repository');
/** @var EntityRepositoryInterface $salutationRepository */
$salutationRepository = $this->container->get('salutation.repository');
/** @var EntityRepositoryInterface $countryStateRepository */
$countryStateRepository = $this->container->get('country_state.repository');
/** @var EntityRepositoryInterface $countryRepository */
$countryRepository = $this->container->get('country.repository');
/** @var array $originalOrderShippingAddress */
$originalOrderShippingAddress = $event->getConvertedCart()['deliveries'][0]['shippingOrderAddress'];
$originalOrder = $event->getConvertedCart();
// start validate foreign keys or fallback to default
$salutation = null;
if ($currentSelectedOverrideAddress['salutationId'] && Uuid::isValid($currentSelectedOverrideAddress['salutationId'])) {
$salutation = $salutationRepository->search(new Criteria([$currentSelectedOverrideAddress['salutationId']]), $event->getContext())->first();
}
$salutationId = $salutation ? $salutation->getId() : (array_key_exists('salutationId', $originalOrderShippingAddress) ? $originalOrderShippingAddress['salutationId'] : null);
$countryState = null;
if ($currentSelectedOverrideAddress['countryStateId'] && Uuid::isValid($currentSelectedOverrideAddress['countryStateId'])) {
$countryState = $countryStateRepository->search(new Criteria([$currentSelectedOverrideAddress['countryStateId']]), $event->getContext())->first();
}
$countryStateId = $countryState ? $countryState->getId() : (array_key_exists('countryStateId', $originalOrderShippingAddress) ? $originalOrderShippingAddress['countryStateId'] : null);
$country = null;
if ($currentSelectedOverrideAddress['countryId'] && Uuid::isValid($currentSelectedOverrideAddress['countryId'])) {
$country = $countryRepository->search(new Criteria([$currentSelectedOverrideAddress['countryId']]), $event->getContext())->first();
}
$countryId = $country ? $country->getId() : (array_key_exists('countryId', $originalOrderShippingAddress) ? $originalOrderShippingAddress['countryId'] : null);
// end validate foreign keys or fallback to default
$newOrderAddressId = Uuid::randomHex();
$originalOrder['deliveries'][0]['shippingOrderAddress'] = [
'id' => $newOrderAddressId,
'department' => $currentSelectedOverrideAddress['department'],
'title' => $currentSelectedOverrideAddress['title'],
'firstName' => $currentSelectedOverrideAddress['firstName'],
'lastName' => $currentSelectedOverrideAddress['lastName'],
'street' => $currentSelectedOverrideAddress['street'],
'zipcode' => (string)$currentSelectedOverrideAddress['zipcode'],
'phoneNumber' => (string)$currentSelectedOverrideAddress['phoneNumber'],
'additionalAddressLine1' => (string)$currentSelectedOverrideAddress['additionalAddressLine1'],
'additionalAddressLine2' => (string)$currentSelectedOverrideAddress['additionalAddressLine2'],
'city' => $currentSelectedOverrideAddress['city'],
'salutationId' => $salutationId,
'countryStateId' => $countryStateId,
'countryId' => $countryId
];
$originalOrder['billingAddressId'] = $originalOrderShippingAddress['id'];
$originalOrder['addresses'][0] = $originalOrderShippingAddress;
$event->setConvertedCart($originalOrder);
} catch (\Throwable $throwable) {
// dd($throwable);
}
}
$request->getSession()->set(AddressbookController::ADDRESS_TYPE_SESSION_TYPE_KEY, null);
$request->getSession()->set(AddressbookController::ADDRESS_TYPE_SESSION_DATA_KEY, null);
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
$attributes = $request->attributes;
$route = $attributes->get('_route');
if ($route == 'frontend.checkout.confirm.page') {
if ($event->getRequest()->getSession()->get(AddressbookController::ADDRESS_TYPE_SESSION_DATA_KEY) === null && $this->container->get('customer.cio_customer_permission_service')) {
//$event->getRequest()->getSession()->getFlashBag()->add('danger', 'Keine Berechtigungen für die Verwendung der Standard-Adresse im Kundenprofil. Bitte wählen Sie eine andere Adresse aus.');
}
}
}
public function onCustomerLogoutEvent(CustomerLogoutEvent $event)
{
$request = $this->requestStack->getCurrentRequest();
// reset selection in session
$request->getSession()->set(AddressbookController::ADDRESS_TYPE_SESSION_TYPE_KEY, null);
$request->getSession()->set(AddressbookController::ADDRESS_TYPE_SESSION_DATA_KEY, null);
}
}