<?php declare(strict_types=1);
/**
* (c) 2Hats Logic Solutions <info@2hatslogic.com>
*/
namespace Hatslogic\CategoryWiseHidePrice\Subscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Context;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductSuggestCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Storefront\Page\Product\ProductPageCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Content\Product\Events\ProductCrossSellingStreamCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductCrossSellingIdsCriteriaEvent;
class ProductSubscriber implements EventSubscriberInterface
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var Connection
*/
private $connection;
/**
* @var RouterInterface
*/
private $router;
/**
* @var RequestStack
*/
private $requestStack;
/** @var ResponseEvent */
private $event;
/**
* @var EntityRepositoryInterface
*/
private $productRepository;
/**
* @var Session
*/
private $session;
/**
* @var EntityRepositoryInterface
*/
private $categoryRepository;
public function __construct(
ContainerInterface $container,
Connection $connection,
RouterInterface $router,
RequestStack $requestStack,
EntityRepositoryInterface $productRepository,
Session $session,
EntityRepositoryInterface $categoryRepository
) {
$this->container = $container;
$this->connection = $connection;
$this->router = $router;
$this->productRepository = $productRepository;
$this->requestStack = $requestStack;
$this->session = $session;
$this->categoryRepository = $categoryRepository;
}
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_LOADED_EVENT => 'onProductLoaded',
ProductEvents::PRODUCT_LISTING_CRITERIA => 'productListingCriteria',
ProductEvents::PRODUCT_SEARCH_CRITERIA => 'productSearchCriteria',
ProductEvents::PRODUCT_SUGGEST_CRITERIA => 'productSuggestCriteria',
ProductPageCriteriaEvent::class => 'productPageCriteria',
ProductCrossSellingStreamCriteriaEvent::class => 'productCrossSellingStreamCriteria',
ProductCrossSellingIdsCriteriaEvent::class => 'productCrossSellingIdsCriteria'
];
}
public function onProductLoaded(EntityLoadedEvent $event): void
{
$customerLoggedIn = $this->session->get('customerLoggedIn');
$masterRequest = $this->requestStack->getMasterRequest();
if(empty($masterRequest)) {
return;
}
$isSalesChannel = $masterRequest->get('_is_sales_channel');
if(empty($isSalesChannel)) {
return;
}
/** @var ProductEntity $product */
foreach ($event->getEntities() as $product) {
$showProductPrice = new ArrayEntity(['showProductPrice' => true]);
if($customerLoggedIn)
{
$showProductPrice = new ArrayEntity(['showProductPrice' => true]);
} else {
if(!empty($product->getParentId()))
{
$productDetails = $this->getProductDetailsById($product->getParentId());
$categoryTreeIds = $productDetails->getCategoryTree();
} else {
$categoryTreeIds = $product->getCategoryTree();
}
if(!empty($categoryTreeIds))
{
$categoryTree = $this->loadCategoriesTree($categoryTreeIds);
$showProductPriceStatus = $this->checkShowPriceOrNotFromTree($categoryTree);
$showProductPrice = new ArrayEntity(['showProductPrice' => $showProductPriceStatus]);
}
}
$product->addExtension("showProductPrice", $showProductPrice);
}
}
private function loadCategoriesTree(array $ids)
{
if(empty($ids)) return null;
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('id', $ids));
$criteria->addAssociation('customFields');
$criteria->addSorting(new FieldSorting('level'));
$categoryTree = $this->categoryRepository->search($criteria, Context::createDefaultContext())->getEntities();
return $categoryTree;
}
public function getProductDetailsById($id)
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter(
'product.id', $id));
$criteria->addAssociation('categories');
$criteria->addAssociation('categories.customFields');
$result = $this->productRepository->search($criteria, Context::createDefaultContext());
$productDetails = $result->first();
return ($productDetails) ? $productDetails: null;
}
public function checkShowPriceOrNotFromTree($categoryTree)
{
foreach($categoryTree as $category)
{
$customFields = $category->getCustomFields();
if($customFields)
{
if($customFields['implify_show_price_after_login'] == true)
{
return false;
}
}
}
return true;
}
public function productSuggestCriteria(ProductSuggestCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function productSearchCriteria(ProductSearchCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function productListingCriteria(ProductListingCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function productPageCriteria(ProductPageCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function productCrossSellingStreamCriteria(ProductCrossSellingStreamCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function productCrossSellingIdsCriteria(ProductCrossSellingIdsCriteriaEvent $event)
{
$this->addCategoryAssociation($event);
return true;
}
public function addCategoryAssociation($event)
{
$event->getCriteria()->addAssociation('categories');
$event->getCriteria()->addAssociation('categories.customFields');
return;
}
}