<?php declare(strict_types=1);
namespace Cogi\FreeProducts\Subscriber;
use Cogi\FreeProducts\Core\FreeProducts\FreeProductsCollection;
use Cogi\FreeProducts\Core\FreeProducts\FreeProductsEntity;
use Cogi\FreeProducts\Helper\CheckFreeProduct;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemRemovedEvent;
use Shopware\Core\Checkout\Cart\Order\OrderConvertedEvent;
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\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class FreeProductsSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface $freeProductsRepository
*/
private $freeProductsRepository;
/**
* @var EntityRepositoryInterface $customerRepository
*/
private $customerRepository;
/**
* @var SystemConfigService
*/
private $systemConfigService;
/** @var CheckFreeProduct $helperCheckFreeProduct */
private $helperCheckFreeProduct;
private $config;
/**
* @param EntityRepositoryInterface $freeProductsRepository
* @param EntityRepositoryInterface $customerRepository
* @param SystemConfigService $systemConfigService
* @param CheckFreeProduct $helperCheckFreeProduct
*/
public function __construct(
EntityRepositoryInterface $freeProductsRepository,
EntityRepositoryInterface $customerRepository,
SystemConfigService $systemConfigService,
CheckFreeProduct $helperCheckFreeProduct
)
{
$this->freeProductsRepository = $freeProductsRepository;
$this->customerRepository = $customerRepository;
$this->systemConfigService = $systemConfigService;
$this->helperCheckFreeProduct = $helperCheckFreeProduct;
}
public static function getSubscribedEvents(): array
{
return [
CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoadedEvent',
OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPageLoadedEvent',
OrderConvertedEvent::class => 'OnOrderConvertedEvent',
BeforeLineItemRemovedEvent::class => 'OnBeforeLineItemRemoved'
];
}
public function OnOrderConvertedEvent(OrderConvertedEvent $event)
{
$event->getConvertedCart()->addExtension("FreeProductConverted", new ArrayStruct([]));
}
public function OnBeforeLineItemRemoved(BeforeLineItemRemovedEvent $event){
$config = $this->systemConfigService->get('CogiFreeProducts.config', $event->getSalesChannelContext()->getSalesChannelId());
if(!$config['cogiFreeProductsAutoToCart']){
return;
}
if(!empty($event->getLineItem()->getPayloadValue('FreeProduct'))){
$arrayStruct = null;
if(!empty($event->getCart()->getExtension("FreeProductsRemoved"))){
$extension = $event->getCart()->getExtension("FreeProductsRemoved")->getVars();
array_push($extension, $event->getLineItem()->getReferencedId());
$extension = array_unique($extension);
$arrayStruct = new ArrayStruct([...$extension]);
}else {
$arrayStruct = new ArrayStruct([$event->getLineItem()->getReferencedId()]);
}
$event->getCart()->addExtension("FreeProductsRemoved", $arrayStruct);
}
}
public function onCheckoutCartPageLoadedEvent(CheckoutCartPageLoadedEvent $event)
{
$config = $this->systemConfigService->get('CogiFreeProducts.config', $event->getSalesChannelContext()->getSalesChannelId());
$isCustomerGroup = $this->checkCustomerGroup($event->getSalesChannelContext(), $config, 'cogiFreeProductsCustomerGroupIds');
if($isCustomerGroup) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter("isActive", 1));
$criteria->addFilter(new EqualsFilter("product.active", 1));
$criteria->addAssociation('product');
$criteria->addAssociation('productManufacturer');
$criteria->addAssociation('product.options');
if($config['cogiFreeProductsClearanceSale']){
$criteria->addFilter(new RangeFilter('product.stock', ['gt' => 0]),);
}
$criteria->addSorting(new FieldSorting("cartPrice", FieldSorting::ASCENDING));
$freeProducts = $this->freeProductsRepository->search($criteria, $event->getContext())->getEntities();
$freeProductCollection = new FreeProductsCollection();
/** @var FreeProductsEntity $freeProduct */
foreach($freeProducts as $freeProduct) {
if ($this->helperCheckFreeProduct->checkFreeProductIsTimed($event->getContext(), $freeProduct->getId())) {
$freeProductCollection->add($freeProduct);
}
}
$event->getPage()->addExtension("CogiFreeProducts", new ArrayEntity([
'FreeProducts' => $freeProductCollection
]));
}
}
public function onOffcanvasCartPageLoadedEvent(OffcanvasCartPageLoadedEvent $event)
{
$config = $this->systemConfigService->get('CogiFreeProducts.config', $event->getSalesChannelContext()->getSalesChannelId());
$isCustomerGroup = $this->checkCustomerGroup($event->getSalesChannelContext(), $config, 'cogiFreeProductsCustomerGroupIds');
if($isCustomerGroup){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter("isActive", 1));
$criteria->addFilter(new EqualsFilter("product.active", 1));
$criteria->addAssociation('product');
$criteria->addAssociation('productManufacturer');
$criteria->addAssociation('product.options');
if($config['cogiFreeProductsClearanceSale']){
$criteria->addFilter(new RangeFilter('product.stock', ['gt' => 0]),);
}
$criteria->addSorting(new FieldSorting("cartPrice", FieldSorting::ASCENDING));
$freeProducts = $this->freeProductsRepository->search($criteria, $event->getContext())->getEntities();
$freeProductCollection = new FreeProductsCollection();
/** @var FreeProductsEntity $freeProduct */
foreach($freeProducts as $freeProduct) {
if ($this->helperCheckFreeProduct->checkFreeProductIsTimed($event->getContext(), $freeProduct->getId())) {
$freeProductCollection->add($freeProduct);
}
}
$event->getPage()->addExtension("CogiFreeProducts", new ArrayEntity([
'FreeProducts' => $freeProductCollection
]));
}
}
private function checkCustomerGroup(SalesChannelContext $context, Array $config, String $configKey){
if(array_key_exists($configKey, $config)){
$configCustomerGroupIds = $config[$configKey];
} else {
$configCustomerGroupIds = [];
}
$isCustomerGroup = false;
if(empty($configCustomerGroupIds)){
$isCustomerGroup = true;
}
if(!$isCustomerGroup && $context->getCustomer()){
foreach($configCustomerGroupIds as $groupId){
if($groupId === $context->getCustomer()->getGroupId()){
$isCustomerGroup = true;
}
}
}
return $isCustomerGroup;
}
}