<?php
namespace Selfdelve\Cms\Subscriber;
use MoorlFormBuilder\Core\Event\FormOptionCriteriaEvent;
use Shopware\Core\Checkout\Cart\Event\AfterLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Content\Category\CategoryDefinition;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Media\MediaEntity;
use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Property\PropertyGroupEntity;
use Shopware\Core\Framework\DataAbstractionLayer\DefinitionInstanceRegistry;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\AndFilter;
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\OrFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Framework\Routing\Router;
use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
use Shopware\Storefront\Pagelet\Header\HeaderPageletLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
class StorefrontSubscriber implements EventSubscriberInterface
{
const PROPERTY_GROUP_NAMES = [
'COLOUR' => [
'Farbe Konfigurator',
'Colour Configurator'
],
'CORPUS' => [
'Grundkörper',
'Base Body'
]
];
const FORM_ELEMENT_TO_PROPERTY_GROUP_MAPPING = [
'color_1' => 'COLOUR',
'color_2' => 'COLOUR',
'color_3' => 'COLOUR',
'base_body' => 'CORPUS'
];
const CUSTOM_FIELD_CATEGORY_TOKEN = 'selfdelve_theme_category_access_token';
const CATEGORY_NAME_TOPBAR = 'Topbar';
private DefinitionInstanceRegistry $definitionInstanceRegistry;
private SystemConfigService $systemConfigService;
private ?Router $router = null;
public function __construct(
DefinitionInstanceRegistry $definitionInstanceRegistry,
SystemConfigService $systemConfigService,
?Router $router
)
{
$this->definitionInstanceRegistry = $definitionInstanceRegistry;
$this->systemConfigService = $systemConfigService;
$this->router = $router;
}
public static function getSubscribedEvents(): array
{
return [
HeaderPageletLoadedEvent::class => 'onHeaderLoaded',
FormOptionCriteriaEvent::class => 'onProductRequest',
NavigationPageLoadedEvent::class => 'onNavigationPageLoaded',
BeforeLineItemAddedEvent::class => 'beforeLineItemAdded',
];
}
public function onHeaderLoaded(HeaderPageletLoadedEvent $event): void
{
$repository = $this->definitionInstanceRegistry->getRepository('category');
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('name', self::CATEGORY_NAME_TOPBAR));
$criteria->addAssociation('children');
/** @var CategoryEntity $category */
$category = $repository->search($criteria, $event->getContext())->first();
if (!$category instanceof CategoryEntity) {
return;
}
$event->getContext()->addExtension(
'topnav',
new ArrayEntity(['categories' => $category->getChildren()])
);
}
public function onProductRequest(FormOptionCriteriaEvent $event): void
{
if (intval($event->getElement()['isEntitySelect']) !== 1) {
return;
}
if (!array_key_exists($event->getElement()['name'], self::FORM_ELEMENT_TO_PROPERTY_GROUP_MAPPING)) {
return;
}
$m = self::FORM_ELEMENT_TO_PROPERTY_GROUP_MAPPING[$event->getElement()['name']];
if (!array_key_exists($m, self::PROPERTY_GROUP_NAMES)) {
return;
}
$repository = $this->definitionInstanceRegistry->getRepository('property_group');
$criteria = new Criteria();
$criteria->addAssociation('options');
$criteria->addFilter(new EqualsAnyFilter('name', self::PROPERTY_GROUP_NAMES[$m]));
/** @var PropertyGroupEntity $propertyGroupEntity */
$productGroup = $repository->search($criteria, $event->getContext())->first();
if (!$productGroup) {
return;
}
$event->setCriteria(
$event->getCriteria()
->addAssociation('group')
->addFilter(new EqualsFilter('group.id', $productGroup->getId()))
->resetSorting()
->addSorting(new FieldSorting('position', FieldSorting::ASCENDING))
);
}
public function onNavigationPageLoaded(NavigationPageLoadedEvent $event): void
{
$navigationId = $event->getRequest()->get(
'navigationId',
$event->getSalesChannelContext()->getSalesChannel()->getNavigationCategoryId()
);
$repository = $this->definitionInstanceRegistry->getRepository(CategoryDefinition::ENTITY_NAME);
if (!$repository) {
return;
}
/** @var CategoryEntity $category */
$category = $repository->search(new Criteria([$navigationId]), $event->getContext())->first();
if (!$category instanceof CategoryEntity) {
return;
}
// Handle only pages that are not visible
if ($category->getType() !== CategoryDefinition::TYPE_PAGE || $category->getVisible() !== false) {
return;
}
// Custom fields with required token
$customFields = $category->getCustomFields();
if (!isset($customFields[self::CUSTOM_FIELD_CATEGORY_TOKEN]) || $customFields[self::CUSTOM_FIELD_CATEGORY_TOKEN] === '') {
return;
}
// Check failed
if ($event->getRequest()->get('t') !== $customFields[self::CUSTOM_FIELD_CATEGORY_TOKEN]) {
$path = $this->router->generate('frontend.home.page');
(new RedirectResponse($path))->send();
return;
}
}
public function beforeLineItemAdded(BeforeLineItemAddedEvent $event)
{
$lineItem = $event->getLineItem();
if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
return;
}
$repository = $this->definitionInstanceRegistry->getRepository(ProductDefinition::ENTITY_NAME);
if (!$repository instanceof EntityRepository) {
return;
}
$criteria = new Criteria();
$criteria->addAssociations([
'options',
'options.group',
'options.media'
]);
$criteria->addFilter(new EqualsFilter('id', $lineItem->getId()));
$criteria->setLimit(1);
$product = $repository->search($criteria, $event->getContext())->first();
if (!$product instanceof ProductEntity) {
return;
}
if (
!isset($product->getCustomFields()['selfdelve_theme_product_is_configurator']) ||
true !== $product->getCustomFields()['selfdelve_theme_product_is_configurator'] ||
0 === count($product->getOptions())
) {
return;
}
$groupId = $this->systemConfigService->get('SelfdelveCms.config.colorOptionId');
if ('' === $groupId) {
return;
}
foreach ($product->getOptions() as $option) {
if ($option->getGroup()->getId() === $groupId && $option->getMedia()) {
$lineItem->setPayloadValue('cover_url', $option->getMedia()->getUrl());
// Setting the cover is not possible
// $lineItem->setCover($option->getMedia());
return;
}
}
}
}