<?php declare(strict_types=1);
/**
* Shopware
* Copyright © 2021
*
* @category Shopware
* @package SwpProductOptionsSix
* @subpackage ProductSubscriber.php
*
* @copyright 2021 Iguana-Labs GmbH
* @author Module Factory <info at module-factory.com>
* @license https://www.module-factory.com/eula
*/
namespace Swp\ProductOptionsSix\Subscriber\Page\Product;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
use Shopware\Core\Content\Property\PropertyGroupCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\ProductOptionsLoader;
use Swp\ProductOptionsSix\Core\Content\ProductOptions\SalesChannel\ProductOptionsLoaderInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ProductSubscriber implements EventSubscriberInterface
{
/** @var SystemConfigService */
private $systemConfigService;
/** @var ProductOptionsLoaderInterface */
private $productOptionsLoader;
/** @var EntityRepository */
private $filterRepository;
/**
* ProductSubscriber constructor.
*
* @param SystemConfigService $systemConfigService
* @param EntityRepository $filterRepository
* @param ProductOptionsLoaderInterface $productOptionsLoader
*/
public function __construct(
SystemConfigService $systemConfigService,
EntityRepository $filterRepository,
ProductOptionsLoaderInterface $productOptionsLoader
) {
$this->systemConfigService = $systemConfigService;
$this->filterRepository = $filterRepository;
$this->productOptionsLoader = $productOptionsLoader;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
ProductPageLoadedEvent::class => 'onProductPageLoaded'
];
}
/**
* @param ProductPageLoadedEvent $event
*/
public function onProductPageLoaded(ProductPageLoadedEvent $event): void
{
if (!$this->isCannelActive($event)) {
return;
}
$product = $event->getPage()->getProduct();
if($product->getChildCount() && !$product->getParentId()) {
return;
}
list ($productOptions, $parentProducts) = $this->productOptionsLoader->load($product->getId(), $event->getSalesChannelContext());
$propertyIds = $this->getOptionPropertys($productOptions);
$filters = $this->getFilters($event, $propertyIds);
// add to extensions
$product->addExtension(
ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY,
(new ArrayStruct())->assign([
'assignedOptions' => $productOptions,
'parentProducts' => $parentProducts,
'filters' => $filters
])
);
}
/**
* @param ProductPageLoadedEvent $event
* @param array $propertyIds
* @return PropertyGroupCollection|null
*/
private function getFilters(ProductPageLoadedEvent $event, array $propertyIds = []): ?PropertyGroupCollection
{
$propertyIds = \array_unique($propertyIds);
if (count($propertyIds) === 0) {
return null;
}
/** @var array $propertyIds */
$criteria = new Criteria($propertyIds);
$criteria->addAssociation('group');
$criteria->setTitle('product-listing::property-filter');
/** @var PropertyGroupOptionCollection $filters */
$filters = $this->filterRepository->search($criteria, $event->getContext())->getEntities();
// group options by their property-group
$groupedFilters = $filters->groupByPropertyGroups();
$groupedFilters->sortByPositions();
$groupedFilters->sortByConfig();
return $groupedFilters;
}
/**
* @param array $productOptions
* @param array $propertyIds
* @return array
*/
private function getOptionPropertys(
array $productOptions,
array $propertyIds = []
): array
{
foreach ($productOptions as $productOption) {
if ($productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->has('children')) {
$propertyIds = $this->getOptionPropertys(
$productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->get('children'),
$propertyIds
);
continue;
}
$options = $productOption->getExtension(ProductOptionsLoader::PRODUCT_OPTIONS_EXT_KEY)->get('options');
if (!\is_array($options)) {
continue;
}
foreach ($options as $option) {
$addIds = $option->getPropertyIds();
if (\is_array($addIds)) {
$propertyIds = \array_merge($propertyIds, $addIds);
}
}
}
return $propertyIds;
}
/**
* @param ProductPageLoadedEvent $event
* @return array|mixed|null
*/
private function isCannelActive(ProductPageLoadedEvent $event)
{
return $this->systemConfigService->get(
'SwpProductOptionsSix.config.channelActive',
$event->getSalesChannelContext()->getSalesChannel()->getId()
);
}
}