<?php
/**
* Shopware
* Copyright © 2020
*
* @category Shopware
* @package SwpRealProductVariantsSix
* @subpackage Frontend.php
*
* @copyright 2020 Iguana-Labs GmbH
* @author Module Factory <info at module-factory.com>
* @license https://www.module-factory.com/eula
*/
namespace Swp\RealProductVariantsSix\Subscriber;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
use Shopware\Core\Content\Property\PropertyGroupCollection;
use Shopware\Core\Framework\DataAbstractionLayer\Dbal\Common\RepositoryIterator;
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\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
class Frontend implements EventSubscriberInterface
{
/** @var SalesChannelRepository */
private $salesChannelProductRepository;
/** @var EntityRepositoryInterface */
private $optionRepository;
/** @var SystemConfigService */
private $systemConfigService;
public function __construct(
SalesChannelRepository $salesChannelProductRepository,
EntityRepositoryInterface $optionRepository,
SystemConfigService $systemConfigService)
{
$this->salesChannelProductRepository = $salesChannelProductRepository;
$this->optionRepository = $optionRepository;
$this->systemConfigService = $systemConfigService;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
ProductPageLoadedEvent::class => 'onProductPageLoaded'
];
}
/**
* @param ProductPageLoadedEvent $event
*/
public function onProductPageLoaded(ProductPageLoadedEvent $event) : void
{
if ($this->isCannelActive($event) !== true) {
return;
}
$product = $event->getPage()->getProduct();
$criteria = new Criteria();
$criteria->addAssociations([
'group',
'properties.group'
]);
$criteria->addSorting(new FieldSorting('customFields.swp_real_product_variants_six_position', FieldSorting::ASCENDING));
$criteria->setLimit(1000);
$criteria->addFilter(new EqualsFilter('customFields.swp_real_product_variants_six_master_product_number', $product->getProductNumber()));
$slaveProducts = $this->salesChannelProductRepository->search(
$criteria,
$event->getSalesChannelContext()
);
if (!$slaveProducts->getTotal()) {
return;
}
$filters = $this->getFilter($slaveProducts->getElements(), $event);
$product->addExtension(
'swp_real_product_variants_six',
(new ArrayStruct())->assign([
'slaveProducts' => $slaveProducts,
'filters' => $filters
])
);
}
/**
* @param array $slaveProducts
* @param ProductPageLoadedEvent $event
* @return PropertyGroupCollection|null
*/
private function getFilter(
array $slaveProducts,
ProductPageLoadedEvent $event
): ?PropertyGroupCollection {
$propertyIds = $this->getPropertyIds($slaveProducts);
if (count($propertyIds) === 0) {
return null;
}
$criteria = new Criteria($propertyIds);
$criteria->setLimit(500);
$criteria->addAssociation('group');
$criteria->addAssociation('media');
$criteria->addFilter(new EqualsFilter('group.filterable', true));
$criteria->setTitle('product-listing::property-filter');
$criteria->addSorting(new FieldSorting('id', FieldSorting::ASCENDING));
$mergedOptions = new PropertyGroupOptionCollection();
$repositoryIterator = new RepositoryIterator($this->optionRepository, $event->getContext(), $criteria);
while (($result = $repositoryIterator->fetch()) !== null) {
$mergedOptions->merge($result->getEntities());
}
// group options by their property-group
$groupedFilters = $mergedOptions->groupByPropertyGroups();
$groupedFilters->sortByPositions();
$groupedFilters->sortByConfig();
return $groupedFilters;
}
/**
* @param array $slaveProducts
* @return array
*/
private function getPropertyIds(array $slaveProducts): array
{
$propertyIds = [];
/** @var SalesChannelProductEntity $slaveProduct */
foreach ($slaveProducts as $slaveProduct) {
if($slaveProduct->getPropertyIds()) {
$propertyIds = \array_merge($propertyIds, $slaveProduct->getPropertyIds());
}
}
return \array_unique($propertyIds);
}
/**
* @param ProductPageLoadedEvent $event
* @return array|bool|float|int|string|null
*/
private function isCannelActive(ProductPageLoadedEvent $event)
{
return $this->systemConfigService->get(
'SwpRealProductVariantsSix.config.channelActive',
$event->getSalesChannelContext()->getSalesChannel()->getId()
);
}
}