<?php declare(strict_types=1);
namespace Acris\Filter\Storefront\Subscriber;
use Acris\Filter\Components\FilterCount\Struct\TermCount;
use Acris\Filter\Components\FilterCount\Struct\TermCountCollection;
use Acris\Filter\Components\FilterCount\Struct\AggregationDocCount;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Content\Product\Events\ProductSearchResultEvent;
use Shopware\Core\Content\Property\PropertyGroupEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class PropertyOptionCountSubscriber implements EventSubscriberInterface
{
private SystemConfigService $configService;
public function __construct(SystemConfigService $configService)
{
$this->configService = $configService;
}
/**
* @var TermCountCollection
*/
private TermCountCollection $termCountCollection;
public static function getSubscribedEvents()
{
return [
ProductListingResultEvent::class => [
['handleSearchResultBefore', 150],
['handleSearchResultAfter', -150]
],
ProductSearchResultEvent::class => [
['handleSearchResultBefore', 150],
['handleSearchResultAfter', -150]
]
];
}
public function handleSearchResultBefore(ProductListingResultEvent $event): void
{
if(!$this->configService->get('AcrisFilterCS.config.filterCount')) {
return;
}
$aggregations = $event->getResult()->getAggregations();
$this->termCountCollection = new TermCountCollection();
/** @var TermsResult|null $properties */
$properties = $aggregations->get('properties');
$this->collectTermCount($this->termCountCollection, $properties);
/** @var TermsResult|null $options */
$options = $aggregations->get('options');
$this->collectTermCount($this->termCountCollection, $options);
}
public function handleSearchResultAfter(ProductListingResultEvent $event): void
{
if(!$this->configService->get('AcrisFilterCS.config.filterCount')) {
return;
}
$aggregations = $event->getResult()->getAggregations();
/** @var EntityResult|null $propertyGroups */
$propertyGroups = $aggregations->get('properties');
if(!$propertyGroups instanceof EntityResult) {
return;
}
/** @var PropertyGroupEntity $propertyGroup */
foreach ($propertyGroups->getEntities() as $propertyGroup) {
foreach ($propertyGroup->getOptions() as $option) {
if($this->termCountCollection->has($option->getId()) === true) {
$option->addExtension(AggregationDocCount::AGGREGATION_DOC_COUNT, new AggregationDocCount($this->termCountCollection->get($option->getId())->getCount()));
}
}
}
}
private function collectTermCount(TermCountCollection $termCountCollection, ?TermsResult $termsResult): void
{
if(!$termsResult instanceof TermsResult) {
return;
}
foreach ($termsResult->getBuckets() as $bucket) {
if($termCountCollection->has($bucket->getKey()) === true) {
$termCount = $termCountCollection->get($bucket->getKey());
} else {
$termCount = new TermCount($bucket->getKey(), 0);
$termCountCollection->set($bucket->getKey(), $termCount);
}
$termCount->setCount($termCount->getCount() + $bucket->getCount());
}
}
}