custom/plugins/SwagPayPal/src/Checkout/ExpressCheckout/ExpressCheckoutSubscriber.php line 91

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /*
  3.  * (c) shopware AG <info@shopware.com>
  4.  * For the full copyright and license information, please view the LICENSE
  5.  * file that was distributed with this source code.
  6.  */
  7. namespace Swag\PayPal\Checkout\ExpressCheckout;
  8. use Psr\Log\LoggerInterface;
  9. use Shopware\Core\Checkout\Customer\CustomerEvents;
  10. use Shopware\Core\Content\Cms\CmsPageCollection;
  11. use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
  12. use Shopware\Core\Framework\Event\DataMappingEvent;
  13. use Shopware\Core\Framework\Validation\BuildValidationEvent;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Shopware\Core\System\SystemConfig\SystemConfigService;
  16. use Shopware\Storefront\Event\SwitchBuyBoxVariantEvent;
  17. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  18. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  19. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  20. use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent;
  21. use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
  22. use Shopware\Storefront\Page\PageLoadedEvent;
  23. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  24. use Shopware\Storefront\Page\Search\SearchPageLoadedEvent;
  25. use Shopware\Storefront\Pagelet\PageletLoadedEvent;
  26. use Shopware\Storefront\Pagelet\Wishlist\GuestWishlistPageletLoadedEvent;
  27. use Swag\CmsExtensions\Storefront\Pagelet\Quickview\QuickviewPageletLoadedEvent;
  28. use Swag\PayPal\Checkout\ExpressCheckout\Service\ExpressCheckoutDataServiceInterface;
  29. use Swag\PayPal\Checkout\ExpressCheckout\Service\ExpressCustomerService;
  30. use Swag\PayPal\Checkout\Payment\PayPalPaymentHandler;
  31. use Swag\PayPal\Setting\Exception\PayPalSettingsInvalidException;
  32. use Swag\PayPal\Setting\Service\SettingsValidationServiceInterface;
  33. use Swag\PayPal\Setting\Settings;
  34. use Swag\PayPal\Util\PaymentMethodUtil;
  35. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  36. class ExpressCheckoutSubscriber implements EventSubscriberInterface
  37. {
  38.     public const PAYPAL_EXPRESS_CHECKOUT_BUTTON_DATA_EXTENSION_ID 'payPalEcsButtonData';
  39.     private ExpressCheckoutDataServiceInterface $expressCheckoutDataService;
  40.     private SettingsValidationServiceInterface $settingsValidationService;
  41.     private SystemConfigService $systemConfigService;
  42.     private PaymentMethodUtil $paymentMethodUtil;
  43.     private LoggerInterface $logger;
  44.     public function __construct(
  45.         ExpressCheckoutDataServiceInterface $service,
  46.         SettingsValidationServiceInterface $settingsValidationService,
  47.         SystemConfigService $systemConfigService,
  48.         PaymentMethodUtil $paymentMethodUtil,
  49.         LoggerInterface $logger
  50.     ) {
  51.         $this->expressCheckoutDataService $service;
  52.         $this->settingsValidationService $settingsValidationService;
  53.         $this->systemConfigService $systemConfigService;
  54.         $this->paymentMethodUtil $paymentMethodUtil;
  55.         $this->logger $logger;
  56.     }
  57.     public static function getSubscribedEvents(): array
  58.     {
  59.         return [
  60.             CheckoutCartPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  61.             CheckoutRegisterPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  62.             NavigationPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  63.             OffcanvasCartPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  64.             ProductPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  65.             SearchPageLoadedEvent::class => 'addExpressCheckoutDataToPage',
  66.             QuickviewPageletLoadedEvent::class => 'addExpressCheckoutDataToPagelet',
  67.             GuestWishlistPageletLoadedEvent::class => 'addExpressCheckoutDataToPagelet',
  68.             SwitchBuyBoxVariantEvent::class => 'addExpressCheckoutDataToBuyBoxSwitch',
  69.             'framework.validation.address.create' => 'disableAddressValidation',
  70.             'framework.validation.customer.create' => 'disableCustomerValidation',
  71.             CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmLoaded',
  72.             CustomerEvents::MAPPING_REGISTER_CUSTOMER => 'addPayerIdToCustomer',
  73.         ];
  74.     }
  75.     public function addExpressCheckoutDataToPage(PageLoadedEvent $event): void
  76.     {
  77.         $salesChannelContext $event->getSalesChannelContext();
  78.         $eventName \get_class($event);
  79.         $addProductToCart $event instanceof ProductPageLoadedEvent
  80.             || $event instanceof NavigationPageLoadedEvent
  81.             || $event instanceof SearchPageLoadedEvent;
  82.         $expressCheckoutButtonData $this->getExpressCheckoutButtonData($salesChannelContext$eventName$addProductToCart);
  83.         if ($expressCheckoutButtonData === null) {
  84.             return;
  85.         }
  86.         $event->getPage()->addExtension(
  87.             self::PAYPAL_EXPRESS_CHECKOUT_BUTTON_DATA_EXTENSION_ID,
  88.             $expressCheckoutButtonData
  89.         );
  90.         $this->logger->debug('Added data to page {page}', ['page' => \get_class($event)]);
  91.     }
  92.     /**
  93.      * @deprecated tag:v4.0.0 - will be removed. Use \Swag\PayPal\Checkout\ExpressCheckout\SalesChannel\ExpressCategoryRoute instead
  94.      */
  95.     public function addExpressCheckoutDataToCmsPage(CmsPageLoadedEvent $event): void
  96.     {
  97.         $salesChannelContext $event->getSalesChannelContext();
  98.         $expressCheckoutButtonData $this->getExpressCheckoutButtonData($salesChannelContext\get_class($event), true);
  99.         if ($expressCheckoutButtonData === null) {
  100.             return;
  101.         }
  102.         /** @var CmsPageCollection $pages */
  103.         $pages $event->getResult();
  104.         $cmsPage $pages->first();
  105.         if ($cmsPage === null) {
  106.             return;
  107.         }
  108.         $cmsPage->addExtension(
  109.             self::PAYPAL_EXPRESS_CHECKOUT_BUTTON_DATA_EXTENSION_ID,
  110.             $expressCheckoutButtonData
  111.         );
  112.     }
  113.     public function addExpressCheckoutDataToPagelet(PageletLoadedEvent $event): void
  114.     {
  115.         $salesChannelContext $event->getSalesChannelContext();
  116.         $expressCheckoutButtonData $this->getExpressCheckoutButtonData($salesChannelContext\get_class($event), true);
  117.         if ($expressCheckoutButtonData === null) {
  118.             return;
  119.         }
  120.         $event->getPagelet()->addExtension(
  121.             self::PAYPAL_EXPRESS_CHECKOUT_BUTTON_DATA_EXTENSION_ID,
  122.             $expressCheckoutButtonData
  123.         );
  124.     }
  125.     public function addExpressCheckoutDataToBuyBoxSwitch(SwitchBuyBoxVariantEvent $event): void
  126.     {
  127.         $salesChannelContext $event->getSalesChannelContext();
  128.         $expressCheckoutButtonData $this->getExpressCheckoutButtonData($salesChannelContext\get_class($event), true);
  129.         if ($expressCheckoutButtonData === null) {
  130.             return;
  131.         }
  132.         $event->getProduct()->addExtension(
  133.             self::PAYPAL_EXPRESS_CHECKOUT_BUTTON_DATA_EXTENSION_ID,
  134.             $expressCheckoutButtonData
  135.         );
  136.     }
  137.     public function disableAddressValidation(BuildValidationEvent $event): void
  138.     {
  139.         if (!$event->getContext()->hasExtension(ExpressCustomerService::EXPRESS_CHECKOUT_ACTIVE)) {
  140.             return;
  141.         }
  142.         $event->getDefinition()->set('additionalAddressLine1')
  143.                                ->set('additionalAddressLine2')
  144.                                ->set('phoneNumber');
  145.     }
  146.     public function disableCustomerValidation(BuildValidationEvent $event): void
  147.     {
  148.         if (!$event->getContext()->hasExtension(ExpressCustomerService::EXPRESS_CHECKOUT_ACTIVE)) {
  149.             return;
  150.         }
  151.         $event->getDefinition()->set('birthdayDay')
  152.                                ->set('birthdayMonth')
  153.                                ->set('birthdayYear');
  154.     }
  155.     public function addPayerIdToCustomer(DataMappingEvent $event): void
  156.     {
  157.         if (!$event->getContext()->hasExtension(ExpressCustomerService::EXPRESS_CHECKOUT_ACTIVE)) {
  158.             return;
  159.         }
  160.         $input $event->getInput();
  161.         $output $event->getOutput();
  162.         $output['customFields'][ExpressCustomerService::EXPRESS_PAYER_ID] = $input->get(ExpressCustomerService::EXPRESS_PAYER_ID);
  163.         $event->setOutput($output);
  164.     }
  165.     public function onCheckoutConfirmLoaded(CheckoutConfirmPageLoadedEvent $event): void
  166.     {
  167.         if ($event->getRequest()->query->has(PayPalPaymentHandler::PAYPAL_EXPRESS_CHECKOUT_ID) === false) {
  168.             return;
  169.         }
  170.         $confirmPage $event->getPage();
  171.         $payPalPaymentMethodId $this->paymentMethodUtil->getPayPalPaymentMethodId($event->getContext());
  172.         if ($payPalPaymentMethodId === null) {
  173.             return;
  174.         }
  175.         $paymentMethods $confirmPage->getPaymentMethods();
  176.         if ($paymentMethods->has($payPalPaymentMethodId) === false) {
  177.             return;
  178.         }
  179.         $filtered $paymentMethods->filterByProperty('id'$payPalPaymentMethodId);
  180.         $confirmPage->setPaymentMethods($filtered);
  181.         $this->logger->debug('Removed other payment methods from selection for Express Checkout');
  182.     }
  183.     private function getExpressCheckoutButtonData(
  184.         SalesChannelContext $salesChannelContext,
  185.         string $eventName,
  186.         bool $addProductToCart false
  187.     ): ?ExpressCheckoutButtonData {
  188.         $settings $this->checkSettings($salesChannelContext$eventName);
  189.         if ($settings === false) {
  190.             return null;
  191.         }
  192.         return $this->expressCheckoutDataService->buildExpressCheckoutButtonData(
  193.             $salesChannelContext,
  194.             $addProductToCart
  195.         );
  196.     }
  197.     private function checkSettings(SalesChannelContext $contextstring $eventName): bool
  198.     {
  199.         if ($this->paymentMethodUtil->isPaypalPaymentMethodInSalesChannel($context) === false) {
  200.             return false;
  201.         }
  202.         try {
  203.             $this->settingsValidationService->validate($context->getSalesChannelId());
  204.         } catch (PayPalSettingsInvalidException $e) {
  205.             return false;
  206.         }
  207.         if ($this->expressOptionForEventEnabled($context->getSalesChannelId(), $eventName) === false) {
  208.             return false;
  209.         }
  210.         return true;
  211.     }
  212.     private function expressOptionForEventEnabled(string $salesChannelIdstring $eventName): bool
  213.     {
  214.         switch ($eventName) {
  215.             case ProductPageLoadedEvent::class:
  216.             case QuickviewPageletLoadedEvent::class:
  217.                 return $this->systemConfigService->getBool(Settings::ECS_DETAIL_ENABLED$salesChannelId);
  218.             case OffcanvasCartPageLoadedEvent::class:
  219.                 return $this->systemConfigService->getBool(Settings::ECS_OFF_CANVAS_ENABLED$salesChannelId);
  220.             case CheckoutRegisterPageLoadedEvent::class:
  221.                 return $this->systemConfigService->getBool(Settings::ECS_LOGIN_ENABLED$salesChannelId);
  222.             case CheckoutCartPageLoadedEvent::class:
  223.                 return $this->systemConfigService->getBool(Settings::ECS_CART_ENABLED$salesChannelId);
  224.             case NavigationPageLoadedEvent::class:
  225.             case CmsPageLoadedEvent::class:
  226.             case SearchPageLoadedEvent::class:
  227.             case GuestWishlistPageletLoadedEvent::class:
  228.             case SwitchBuyBoxVariantEvent::class:
  229.                 return $this->systemConfigService->getBool(Settings::ECS_LISTING_ENABLED$salesChannelId);
  230.             default:
  231.                 return false;
  232.         }
  233.     }
  234. }