<?php declare(strict_types=1);
namespace ProxaCheckoutTemplate\Subscriber\Storefront;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Customer\Event\CustomerRegisterEvent;
use Shopware\Core\Checkout\Customer\Event\GuestCustomerRegisterEvent;
use Shopware\Core\Content\Newsletter\SalesChannel\AbstractNewsletterSubscribeRoute;
use Shopware\Core\Framework\Context;
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\Struct\ArrayEntity;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\Country\CountryCollection;
use Shopware\Core\System\Country\SalesChannel\AbstractCountryRoute;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\Salutation\SalesChannel\AbstractSalutationRoute;
use Shopware\Core\System\Salutation\SalutationCollection;
use Shopware\Core\System\Salutation\SalutationEntity;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Framework\Routing\RequestTransformer;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent;
use Shopware\Storefront\Page\PageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerInterface;
class CheckoutSubscriber implements EventSubscriberInterface
{
private const PLUGIN_CONFIG_LINES_COUNT = 3;
/**
* @var AbstractSalutationRoute
*/
private $salutationRoute;
/**
* @var AbstractCountryRoute
*/
private $countryRoute;
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var EntityRepositoryInterface
*/
private $mediaRepository;
/**
* @var ContainerInterface
*/
private $container;
/**
* @var AbstractNewsletterSubscribeRoute
*/
private $newsletterSubscribeRoute;
/**
* @var EntityRepositoryInterface
*/
private $customerRepository;
/**
* @var EntityRepositoryInterface
*/
private $pluginRepository;
/**
* @var array
*/
private $pluginConfigs;
/**
* @var string
*/
private $pluginName;
/**
* CheckoutSubscriber constructor.
* @param AbstractSalutationRoute $salutationRoute
* @param AbstractCountryRoute $countryRoute
* @param SystemConfigService $systemConfigService
* @param EntityRepositoryInterface $mediaRepository
* @param ContainerInterface $container
* @param AbstractNewsletterSubscribeRoute $newsletterSubscribeRoute
* @param EntityRepositoryInterface $customerRepository
* @param EntityRepositoryInterface $pluginRepository
* @param string $pluginName
*/
public function __construct(
AbstractSalutationRoute $salutationRoute,
AbstractCountryRoute $countryRoute,
SystemConfigService $systemConfigService,
EntityRepositoryInterface $mediaRepository,
ContainerInterface $container,
AbstractNewsletterSubscribeRoute $newsletterSubscribeRoute,
EntityRepositoryInterface $customerRepository,
EntityRepositoryInterface $pluginRepository,
string $pluginName
)
{
$this->salutationRoute = $salutationRoute;
$this->countryRoute = $countryRoute;
$this->systemConfigService = $systemConfigService;
$this->mediaRepository = $mediaRepository;
$this->container = $container;
$this->newsletterSubscribeRoute = $newsletterSubscribeRoute;
$this->customerRepository = $customerRepository;
$this->pluginRepository = $pluginRepository;
$this->pluginName = $pluginName;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
CheckoutRegisterPageLoadedEvent::class => 'onCheckoutRegisterPageLoaded',
CustomerRegisterEvent::class => 'onCustomerRegister',
GuestCustomerRegisterEvent::class => 'onCustomerRegister'
];
}
public function onCustomerRegister(CustomerRegisterEvent $event)
{
$customer = $event->getCustomer();
$request = $this->container->get('request_stack')->getCurrentRequest();
if (!empty($request->get("option"))) {
$dataBag = $this->getDataForSubscribe($request->get("option"), $customer, $request->attributes->get(RequestTransformer::STOREFRONT_URL));
$this->newsletterSubscribeRoute->subscribe(
$dataBag,
$event->getSalesChannelContext(),
false
);
$customer->setNewsletter(true);
$this->customerRepository->update(
[
['id' => $customer->getId(), 'newsletter' => true],
],
$event->getSalesChannelContext()->getContext()
);
}
}
/**
* @param string $subscribeOption
* @param CustomerEntity $customer
* @param string $storefrontUrl
* @return RequestDataBag
*/
private function getDataForSubscribe(string $subscribeOption, CustomerEntity $customer, string $storefrontUrl)
{
return (new RequestDataBag([
"storefrontUrl" => $storefrontUrl,
"option" => $subscribeOption,
"email" => $customer->getEmail(),
"salutationId" => $customer->getSalutationId(),
"title" => $customer->getTitle(),
"firstName" => $customer->getFirstName(),
"lastName" => $customer->getLastName(),
"zipCode" => $customer->getDefaultShippingAddress()->getZipCode(),
"city" => $customer->getDefaultShippingAddress()->getCity(),
"street" => ($customer->getDefaultShippingAddress() ? $customer->getDefaultShippingAddress()->getStreet() : null)
]));
}
/**
* @param PageLoadedEvent $event
*/
public function onCheckoutConfirmPageLoaded(PageLoadedEvent $event): void
{
$request = $event->getRequest();
$proxaPayment = $request->query->get("proxaPayment");
$proxaShipping = $request->query->get("proxaShipping");
$proxaFromPayment = $request->query->get("proxaFromPayment");
if ($proxaPayment) {
$event->getPage()->addExtension("proxaPayment", new ArrayEntity([1]));
}
if ($proxaShipping) {
$event->getPage()->addExtension("proxaShipping", new ArrayEntity([1]));
}
if ($proxaFromPayment) {
$event->getPage()->addExtension("proxaFromPayment", new ArrayEntity([1]));
}
if ($this->checkPluginIsActive($event->getContext(), "KlarnaPayment")) {
$event->getPage()->addExtension("proxaKlarnaPluginIsActive", new ArrayEntity([1]));
}
if ($this->checkPluginIsActive($event->getContext(), "StripeShopwarePayment")) {
$event->getPage()->addExtension("stripeShopwarePaymentIsActive", new ArrayEntity([1]));
}
$event->getPage()->assign([
'salutations' => $this->getSalutations($event->getSalesChannelContext()),
'countries' => $this->getCountries($event->getSalesChannelContext())
]);
$this->addExtensionsToPage($event);
}
/**
* @param PageLoadedEvent $event
*/
public function onCheckoutRegisterPageLoaded(PageLoadedEvent $event)
{
$this->addExtensionsToPage($event);
}
/**
* @param PageLoadedEvent $event
*/
public function addExtensionsToPage(PageLoadedEvent $event)
{
$this->pluginConfigs = $this->getPluginConfig('', $event->getSalesChannelContext()->getSalesChannelId());
$event->getPage()->addExtension("proxaCheckoutInfoLines", new ArrayEntity($this->getCheckoutInfoLines($event->getContext())));
if ($this->pluginConfigs) {
if (!empty($this->pluginConfigs["removeCheckoutHeaderFooter"])) {
$event->getPage()->addExtension("proxaRemoveCheckoutHeaderFooter", new ArrayEntity([$this->pluginConfigs["removeCheckoutHeaderFooter"]]));
}
if (!empty($this->pluginConfigs["showNewsletterRegistration"])) {
$event->getPage()->addExtension("proxaShowNewsletterRegistration", new ArrayEntity([$this->pluginConfigs["showNewsletterRegistration"]]));
}
}
}
/**
* @param SalesChannelContext $context
* @return SalutationCollection
*/
private function getSalutations(SalesChannelContext $context): SalutationCollection
{
$salutations = $this->salutationRoute->load(new Request(), $context, new Criteria())->getSalutations();
$salutations->sort(function (SalutationEntity $a, SalutationEntity $b) {
return $b->getSalutationKey() <=> $a->getSalutationKey();
});
return $salutations;
}
/**
* @param SalesChannelContext $salesChannelContext
* @return CountryCollection
*/
private function getCountries(SalesChannelContext $salesChannelContext): CountryCollection
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter('country.active', true))
->addAssociation('states');
$countries = $this->countryRoute
->load(new Request(), $criteria, $salesChannelContext)
->getCountries();
$countries->sortCountryAndStates();
return $countries;
}
/**
* @param Context $context
* @return array
*/
private function getCheckoutInfoLines(Context $context)
{
$data = [];
if (!empty($this->pluginConfigs)) {
for ($currentLine = 1; $currentLine <= self::PLUGIN_CONFIG_LINES_COUNT; $currentLine++) {
$configMediaLabel = "checkoutMedia" . $currentLine;
$row = [];
if (!empty($this->pluginConfigs[$configMediaLabel])) {
$media = $this->mediaRepository->search((new Criteria([$this->pluginConfigs[$configMediaLabel]])), $context)->first();
if ($media) {
$row["media"] = $media->getUrl();
}
}
$data[] = $row;
}
}
return $data;
}
/**
* @param Context $context
* @param string $pluginName
* @return bool
*/
private function checkPluginIsActive(Context $context, string $pluginName): bool
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter('name', $pluginName))
->addFilter(new EqualsFilter('active', true));
return ($this->pluginRepository->search($criteria, $context)->count() !== 0);
}
/**
* @param string $name
* @param mixed $channelId
* @param mixed $default
* @return mixed
*/
public function getPluginConfig(string $name = '', $channelId = null, $default = null)
{
$domain = $this->systemConfigService->getDomain($this->pluginName, $channelId, true);
$keys = array_map(function ($key) {
return str_replace($this->pluginName . '.config.', '', $key);
}, array_keys($domain));
$config = array_combine($keys, array_values($domain));
if (!empty($name)) {
return isset($config[$name]) ? $config[$name] : $default;
}
return $config;
}
}