<?php declare(strict_types=1);
namespace Acris\ProductBadges\Components\ProductBadges;
use Acris\ProductBadges\Components\ProductBadges\Struct\ProductStreamStruct;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
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\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
class ProductBadgesGateway
{
/**
* @var EntityRepositoryInterface
*/
private $productBadgesRepository;
/**
* @var EntityRepositoryInterface
*/
private $productStreamMappingRepository;
/**
* @var EntitySearchResult|null
*/
private $productBadges;
private array $ruleIds;
private array $productStreamIds;
public function __construct(
EntityRepositoryInterface $productBadgesRepository,
EntityRepositoryInterface $productStreamMappingRepository
) {
$this->productBadgesRepository = $productBadgesRepository;
$this->productStreamMappingRepository = $productStreamMappingRepository;
$this->productBadges = [];
$this->ruleIds = [];
$this->productStreamIds = [];
}
public function getAllProductBadges(array $productStreamIds, SalesChannelContext $salesChannelContext): EntityCollection
{
$ruleMatch = count(array_intersect($this->ruleIds, $salesChannelContext->getRuleIds())) === \count($salesChannelContext->getRuleIds())
&& count(array_intersect($this->productStreamIds, $productStreamIds)) === \count($productStreamIds);
if(!empty($this->productBadges) && $this->productBadges instanceof EntitySearchResult && $ruleMatch) {
return $this->productBadges->getEntities();
}
$criteria = (new Criteria());
$criteria = $this->addCriteria($productStreamIds, $criteria, $salesChannelContext);
$this->productBadges = $this->productBadgesRepository->search($criteria, $salesChannelContext->getContext());
$this->ruleIds = $salesChannelContext->getRuleIds();
$this->productStreamIds = $productStreamIds;
return $this->productBadges->getEntities();
}
private function getActiveFilters(): MultiFilter
{
$today = new \DateTime();
$todayStart = $today->format('Y-m-d H:i:s');
$filterActiveDate = new MultiFilter(
MultiFilter::CONNECTION_OR,
[
new MultiFilter(
MultiFilter::CONNECTION_AND,
[
new RangeFilter('activeFrom', ['lte' => $todayStart]),
new RangeFilter('activeUntil', ['gte' => $todayStart]),
]),
new MultiFilter(
MultiFilter::CONNECTION_AND,
[
new RangeFilter('activeFrom', ['lte' => $todayStart]),
new EqualsFilter('activeUntil', null),
]),
new MultiFilter(
MultiFilter::CONNECTION_AND,
[
new EqualsFilter('activeFrom', null),
new RangeFilter('activeUntil', ['gte' => $todayStart]),
]),
new MultiFilter(
MultiFilter::CONNECTION_AND,
[
new EqualsFilter('activeFrom', null),
new EqualsFilter('activeUntil', null),
])
]
);
return $filterActiveDate;
}
private function addCriteria(array $productStreamIds, Criteria $criteria, SalesChannelContext $salesChannelContext): Criteria
{
$filterActiveDate = $this->getActiveFilters();
$criteria->addAssociation('rules')
->addAssociation('productStreams')
->addAssociation('promotions')
->addAssociation('replaceDefaultBadge')
->addAssociation('replaceRules')
->addAssociation('imageSelection')
->addAssociation('imageSelectionShape')
->addFilter(new MultiFilter(MultiFilter::CONNECTION_AND, [
$filterActiveDate,
new EqualsFilter('active', true),
new MultiFilter(MultiFilter::CONNECTION_OR, [
new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('displayCondition', ProductBadgesService::PRODUCT_BADGE_DISPLAY_CONDITION_RULES_AND_DYNAMIC_PRODUCT_GROUPS),
new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsAnyFilter('rules.id', $salesChannelContext->getRuleIds()),
new EqualsFilter('rules.id', null),
]),
new EqualsAnyFilter('productStreams.id', $productStreamIds),
new NotFilter(NotFilter::CONNECTION_AND, [
new EqualsFilter('productStreams.id', null)
])
]),
new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('displayCondition', ProductBadgesService::PRODUCT_BADGE_DISPLAY_CONDITION_PROMOTIONS),
new NotFilter(NotFilter::CONNECTION_AND, [
new EqualsFilter('promotions.id', null),
]),
]),
new MultiFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('displayCondition', ProductBadgesService::PRODUCT_BADGE_DISPLAY_CONDITION_REPLACE_DEFAULT_BADGE),
new MultiFilter(MultiFilter::CONNECTION_OR, [
new EqualsAnyFilter('replaceRules.id', $salesChannelContext->getRuleIds()),
new EqualsFilter('replaceRules.id', null)
])
]),
new EqualsFilter('isDefault', true)
])
]))
->addSorting(new FieldSorting('priority', FieldSorting::DESCENDING));
return $criteria;
}
public function getProductStreamIds(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']);
}
}
}
}
}