<?php declare(strict_types=1);
namespace Nimbits\NimbitsPriceOnRequestNext\Subscriber;
use Nimbits\NimbitsPriceOnRequestNext\Service\PriceOnRequestService;
use Nimbits\NimbitsPriceOnRequestNext\Setting\Service\SettingService;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Rule\LineItemScope;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Content\Product\SalesChannel\Detail\AbstractProductDetailRoute;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Struct\StructCollection;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Shopware\Storefront\Pagelet\Footer\FooterPageletLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Shopware\Storefront\Page\PageLoadedEvent;
use Shopware\Core\Checkout\Cart\RuleLoader;
use Shopware\Core\Checkout\Cart\CartRuleLoader;
use Shopware\Core\Checkout\Cart\AbstractRuleLoader;
use Shopware\Core\Checkout\Cart\CachedRuleLoader;
use Shopware\Core\Framework\Rule\Rule;
//use Symfony\Component\DependencyInjection\ContainerBuilder;
class StorefrontSubscriber implements EventSubscriberInterface
{
private SettingService $settingsService;
private CartService $cartService;
private $productRepository;
private $productDetailRoute;
private PriceOnRequestService $priceOnRequestService;
private SalesChannelRepositoryInterface $salesChannelProductRepository;
private CartRuleLoader $cartRuleLoader;
private CachedRuleLoader $cachedRuleLoader;
public function __construct(
SettingService $settingsService,
CartService $cartService,
EntityRepositoryInterface $productRepository,
AbstractProductDetailRoute $productDetailRoute,
PriceOnRequestService $priceOnRequestService,
SalesChannelRepositoryInterface $salesChannelProductRepository,
CartRuleLoader $cartRuleLoader,
CachedRuleLoader $cachedRuleLoader
)
{
$this->settingsService = $settingsService;
$this->cartService = $cartService;
$this->productRepository = $productRepository;
$this->productDetailRoute = $productDetailRoute;
$this->priceOnRequestService = $priceOnRequestService;
$this->salesChannelProductRepository = $salesChannelProductRepository;
$this->cartRuleLoader = $cartRuleLoader;
$this->cachedRuleLoader = $cachedRuleLoader;
}
public static function getSubscribedEvents(): array
{
// Return the events to listen to as array like this: <event to listen to> => <method to execute>
return [
KernelEvents::CONTROLLER_ARGUMENTS => 'beforeController',
//ProductPageLoadedEvent::class => 'onProductPageLoaded',
'sales_channel.product.loaded' => 'productsLoaded', //TODO
OffcanvasCartPageLoadedEvent::class => 'onCheckoutPageLoaded', //TODO ALl poroducts
CheckoutCartPageLoadedEvent::class => 'onCheckoutPageLoaded', //TODO ALl poroducts
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutPageLoaded', //TODO ALl poroducts
CheckoutRegisterPageLoadedEvent::class => 'onCheckoutPageLoaded', //TODO ALl poroducts
FooterPageletLoadedEvent::class => 'onFooterLoaded'
];
}
public function beforeController(ControllerArgumentsEvent $event)
{
if ($event->getRequest()->getPathInfo() == '/checkout/product/add-by-number' && isset($event->getArguments()[1])) {
/** @var $salesChannelContext SalesChannelContext */
$salesChannelContext = $event->getArguments()[1];
$product = $this->salesChannelProductRepository->search(
(new Criteria())
->addFilter(new EqualsFilter('productNumber', $event->getRequest()->get('number'))),
$salesChannelContext
);
if ($product->count() > 0) {
$productId = $product->first()->getId();
$productPorRuleset = $this->priceOnRequestService->getProductRuleSet($salesChannelContext, $this->priceOnRequestService->createMockLineItem($product->first()));
//if the product is not addable to cart
if ($productPorRuleset->getVars()["por_add_to_cart_not_visible"]) {
$event->setController(function (Request $request, SalesChannelContext $salesChannelContext) {
return new RedirectResponse($request->getUriForPath('/checkout/cart?nb_por_nbpn=1'));
});
}
}
}
}
public function onProductPageLoaded(ProductPageLoadedEvent $event)
{
//evaluate products
$salesChannelContext = $event->getSalesChannelContext();
$productId = $event->getPage()->getProduct()->getId();
$productPorRuleset = $this->priceOnRequestService->getProductRuleSet($salesChannelContext, $this->priceOnRequestService->createMockLineItem($event->getPage()->getProduct()));
$event->getPage()->getProduct()->addExtension('nimbits_por_product_ruleset', $productPorRuleset);
}
public function productsLoaded(SalesChannelEntityLoadedEvent $event): void
{
//evaluate products
$salesChannelContext = $event->getSalesChannelContext();
foreach ($event->getEntities() as $product) {
$productPorRuleset = $this->priceOnRequestService->getProductRuleSet($salesChannelContext, $this->priceOnRequestService->createMockLineItem($product));
$product->addExtension('nimbits_por_product_ruleset', $productPorRuleset);
}
}
public function getUnitsForProductByLineitem($item, $salesChannelContext)
{
if (isset($item->getPayload()["productNumber"])) {
$productNumber = $item->getPayload()["productNumber"];
$product = $this->salesChannelProductRepository->search(
(new Criteria())
->addFilter(new EqualsFilter('productNumber', $productNumber)),
$salesChannelContext
);
if(empty($product)){
return ["packUnit" => "", "packUnitPlural" => ""];
}
$pu = "";
$pup = "";
if($product->first() && $product->first()->getTranslated())
{
$pu = $product->first()->getTranslated()["packUnit"] ?? "";
$pup = $product->first()->getTranslated()["packUnitPlural"] ?? "";
}
if(empty($pu) && $product->first()){
$pu = $product->first()->packUnit;
$pup = $product->first()->packUnitPlural;
}
return ["packUnit" => $pu, "packUnitPlural" => $pup];
}
else{
return ["packUnit" => "", "packUnitPlural" => ""];
}
}
public function onCheckoutPageLoaded(PageLoadedEvent $event)
{
//evaluate products
$salesChannelContext = $event->getSalesChannelContext();
$currentCart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext);
$lineItems = $currentCart->getLineItems();
$priceOnRequestCartRuleset = $this->priceOnRequestService->getCartRuleSet($salesChannelContext);
$cartHasNoPrice = false;
$cartNotPurchasable = $priceOnRequestCartRuleset["cart_is_not_purchaseable"];
foreach ($lineItems as $item) {
$productPorRuleset = $this->priceOnRequestService->getProductRuleSet($salesChannelContext, $item);
foreach($item->getChildren() AS $child){
$childPorRuleset = $this->priceOnRequestService->getProductRuleSet($salesChannelContext, $child);
$productPorRuleset->por_dont_show_price = $productPorRuleset["por_dont_show_price"] || $childPorRuleset["por_dont_show_price"];
$productPorRuleset->por_product_not_purchasable = $productPorRuleset["por_product_not_purchasable"]
|| $childPorRuleset["por_product_not_purchasable"]
|| $productPorRuleset["por_dont_show_price"];
}
foreach($item->getChildren() AS $child){
$child->addExtension('nimbits_por_product_ruleset', $productPorRuleset);
}
$cartHasNoPrice = $cartHasNoPrice || $productPorRuleset["por_dont_show_price"];
$cartNotPurchasable = $cartNotPurchasable || $productPorRuleset["por_product_not_purchasable"] || $productPorRuleset["por_dont_show_price"];
$item->addExtension('nimbits_por_product_ruleset', $productPorRuleset);
//add unit set
$item->addExtension('nimbits_por_product_units', (new StructCollection())->assign($this->getUnitsForProductByLineitem($item, $salesChannelContext)));
}
$priceOnRequestCartRuleset->assign(["cart_has_no_price" => $cartHasNoPrice]);
//cart is also not purchasable if no price can be determined
$priceOnRequestCartRuleset->assign(["cart_is_not_purchaseable" => $cartNotPurchasable]);
$event->getPage()->addExtension('nimbits_por_cart_ruleset', $priceOnRequestCartRuleset);
//handling for add by productnumber error
$dontAddByProductNumber = ($event->getRequest()->get('nb_por_nbpn', 0) == 1);
$showerror = ["showerror" => $dontAddByProductNumber];
$errorStruct = (new StructCollection())->assign($showerror);
$event->getPage()->addExtension('nimbits_por_cart_producnumber_add_error', $errorStruct);
}
public function onFooterLoaded(FooterPageletLoadedEvent $event)
{
$event->getPagelet()->addExtension('nimbitsPriceOnRequestSettings',
$this->settingsService->getSettingsAsStruct($event->getSalesChannelContext()->getSalesChannel()->getId())
);
}
}