<?php declare(strict_types=1);
namespace Acris\ProductInfoText\Components\ProductInfoText;
use Acris\ProductInfoText\Components\ProductInfoText\Struct\ProductStreamStruct;
use Acris\ProductInfoText\Custom\ProductInfoTextDefinition;
use Acris\ProductInfoText\Subscriber\InfoTextTagSubscriber;
use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupDefinition;
use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\System\Currency\CurrencyDefinition;
use Shopware\Core\System\Language\LanguageDefinition;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use Symfony\Contracts\Cache\ItemInterface;
class InfoTextGateway
{
public const BUILD_NAME = 'acris-product-info-text';
private EntityRepositoryInterface $infoTextRepository;
private EntityRepositoryInterface $productStreamMappingRepository;
private TagAwareAdapterInterface $cache;
public function __construct(
EntityRepositoryInterface $infoTextRepository,
EntityRepositoryInterface $productStreamMappingRepository,
TagAwareAdapterInterface $cache
) {
$this->infoTextRepository = $infoTextRepository;
$this->productStreamMappingRepository = $productStreamMappingRepository;
$this->cache = $cache;
}
public function getProductDetailInfoText(array $productStreamIds, SalesChannelContext $salesChannelContext): ?EntitySearchResult
{
return $this->getCachedValue('detail-', $salesChannelContext, $productStreamIds,'displayProductDetail', ProductInfoTextDefinition::DISPLAY_PRODUCT_NO);
}
public function getCartDetailInfoText(array $productStreamIds, SalesChannelContext $salesChannelContext): ?EntitySearchResult
{
return $this->getCachedValue('cart-', $salesChannelContext, $productStreamIds,'displayCheckout', ProductInfoTextDefinition::DISPLAY_CHECKOUT_NOT);
}
public function getProductStreamIds(array $productIds, Context $context): array
{
$productStreamIds = [];
$idSearchResult = $this->productStreamMappingRepository->searchIds((new Criteria())->addFilter(new EqualsAnyFilter('productId', $productIds)), $context);
if ($idSearchResult->getTotal() > 0) {
foreach ($idSearchResult->getIds() as $ids) {
if (!empty($ids) && is_array($ids) && array_key_exists('productStreamId', $ids) && !empty($ids['productStreamId'])) {
$productStreamIds[] = $ids['productStreamId'];
}
}
}
return $productStreamIds;
}
public function getAllProductStreamIds(ProductStreamStruct $productStreamStruct, array $productIds, Context $context): void
{
$idSearchResult = $this->productStreamMappingRepository->searchIds((new Criteria())->addFilter(new EqualsAnyFilter('productId', $productIds)), $context);
if ($idSearchResult->getTotal() > 0) {
foreach ($idSearchResult->getIds() as $ids) {
if (!empty($ids) && is_array($ids) && array_key_exists('productStreamId', $ids) && !empty($ids['productStreamId']) && array_key_exists('productId', $ids) && !empty($ids['productId'])) {
$productStreamStruct->addProductStreamId($ids['productId'], $ids['productStreamId']);
}
}
}
}
private function getCachedValue(string $keyPrefix, SalesChannelContext $salesChannelContext, array $productStreamIds, string $displayTypeName, string $displayTypeValue): ?EntitySearchResult
{
if(empty($productStreamIds)) {
return null;
}
$salesChannelId = $salesChannelContext->getSalesChannelId();
$ruleIds = $salesChannelContext->getRuleIds();
$key = $this->getCacheKey($keyPrefix, $salesChannelContext, $productStreamIds, $ruleIds);
$value = $this->cache->get($key, function (ItemInterface $item) use ($productStreamIds, $salesChannelContext, $salesChannelId, $ruleIds, $displayTypeName, $displayTypeValue) {
$infoTexts = $this->infoTextRepository->search((new Criteria())
->addSorting(new FieldSorting('priority',FieldSorting::DESCENDING, true))->addFilter(
new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('active', true),
new NotFilter(MultiFilter::CONNECTION_AND, [new EqualsFilter($displayTypeName, $displayTypeValue)]),
new OrFilter([new EqualsFilter('rules.id', null), new EqualsAnyFilter('rules.id', $ruleIds)]),
new EqualsFilter('salesChannels.id', $salesChannelId),
new EqualsAnyFilter('productStream.id', $productStreamIds),
new NotFilter(NotFilter::CONNECTION_AND, [
new EqualsFilter('productStream.id', null)
])
])
)->addAssociation('productStream')->addAssociation('salesChannels')->addAssociation('rules'), $salesChannelContext->getContext());
$item->tag([InfoTextTagSubscriber::ACRIS_INFO_TEXT_ENTITY]);
$this->addCacheTagsForSalesChannelContext($item, $salesChannelContext);
return CacheValueCompressor::compress($infoTexts);
});
return CacheValueCompressor::uncompress($value);
}
private function getCacheKey(string $prefix, SalesChannelContext $salesChannelContext, array $productStreamIds, array $ruleIds): string
{
return self::BUILD_NAME . '-' . md5(\json_encode([
$prefix,
$salesChannelContext->getSalesChannel()->getId(),
$salesChannelContext->getCurrentCustomerGroup()->getId(),
$salesChannelContext->getCurrency()->getId(),
$salesChannelContext->getContext()->getLanguageId(),
$ruleIds,
$productStreamIds
]));
}
private function addCacheTagsForSalesChannelContext(ItemInterface $item, SalesChannelContext $salesChannelContext)
{
$item->tag(CustomerGroupDefinition::ENTITY_NAME . '-' . $salesChannelContext->getCurrentCustomerGroup()->getId());
$item->tag(CurrencyDefinition::ENTITY_NAME . '-' . $salesChannelContext->getCurrency()->getId());
$item->tag(LanguageDefinition::ENTITY_NAME . '-' . $salesChannelContext->getContext()->getLanguageId());
}
}