<?php declare(strict_types=1);
namespace Acris\CheckoutMethodPreselect\Storefront\Subscriber;
use Acris\CheckoutMethodPreselect\Components\ValidatorCallbackService;
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPage;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ShippingPaymentSubscriber implements EventSubscriberInterface
{
const CHECKOUT_CUSTOMER_CANCELED_EXTERNAL_PAYMENT = 'CHECKOUT__CUSTOMER_CANCELED_EXTERNAL_PAYMENT';
private ValidatorCallbackService $validatorCallbackService;
public function __construct(
ValidatorCallbackService $validatorCallbackService
) {
$this->validatorCallbackService = $validatorCallbackService;
}
public static function getSubscribedEvents(): array
{
return [
AccountEditOrderPageLoadedEvent::class => 'onAccountEditOrderPageLoaded'
];
}
public function onAccountEditOrderPageLoaded(AccountEditOrderPageLoadedEvent $event): void
{
$context = $event->getSalesChannelContext();
$page = $event->getPage();
$this->sortPaymentMethods($page);
$paymentMethod = null;
$shippingMethod = null;
$contextShippingMethod = !empty($context->getShippingMethod()) ? $context->getShippingMethod() : null;
if (!empty($contextShippingMethod) && !empty($page->getSalesChannelShippingMethods()) && !$page->getSalesChannelShippingMethods()->has($contextShippingMethod->getId())) {
$shippingMethod = $this->validatorCallbackService->getFirstActiveShippingMethod($context);
if($shippingMethod instanceof ShippingMethodEntity) {
if($context->getShippingMethod() && $shippingMethod->getId() === $context->getShippingMethod()->getId()) {
$shippingMethod = null;
}
}
}
if (!empty($event->getRequest()) && !empty($event->getRequest()->get('error-code')) && $event->getRequest()->get('error-code') === self::CHECKOUT_CUSTOMER_CANCELED_EXTERNAL_PAYMENT) {
$paymentMethod = $this->validatorCallbackService->getFirstActivePaymentMethod($context);
if($paymentMethod instanceof PaymentMethodEntity) {
if($context->getPaymentMethod() && $paymentMethod->getId() === $context->getPaymentMethod()->getId()) {
$paymentMethod = null;
}
}
}
if($paymentMethod instanceof PaymentMethodEntity || $shippingMethod instanceof ShippingMethodEntity) {
$this->changeMethods($paymentMethod, $shippingMethod, $context);
}
}
private function changeMethods(?PaymentMethodEntity $paymentMethod, ?ShippingMethodEntity $shippingMethod, SalesChannelContext $context): void
{
if($paymentMethod instanceof PaymentMethodEntity) {
$context->assign(['paymentMethod' => $paymentMethod]);
}
if($shippingMethod instanceof ShippingMethodEntity) {
$context->assign(['shippingMethod' => $shippingMethod]);
}
}
private function sortPaymentMethods(AccountEditOrderPage $page): void
{
$paymentMethods = $page->getPaymentMethods();
if($paymentMethods && $paymentMethods->count() > 0) {
$paymentMethods->sort(function (PaymentMethodEntity $a, PaymentMethodEntity $b) {
$prioA = 0;
$prioB = 0;
if(array_key_exists('acris_checkout_payment_preselect_priority', $a->getTranslation('customFields'))) {
$prioA = (int) $a->getTranslation('customFields')['acris_checkout_payment_preselect_priority'];
}
if(array_key_exists('acris_checkout_payment_preselect_priority', $b->getTranslation('customFields'))) {
$prioB = (int) $b->getTranslation('customFields')['acris_checkout_payment_preselect_priority'];
}
return $prioB <=> $prioA;
});
}
}
}