<?php declare(strict_types=1);
namespace S360\MegaMenu\Storefront\Subscriber;
use S360\MegaMenu\Core\Content\Menu\MenuCollection;
use S360\MegaMenu\Core\Content\Menu\MenuEntity;
use S360\MegaMenu\Core\Content\MenuItem\MenuItemCollection;
use S360\MegaMenu\Service\MenuLoader;
use S360\MegaMenu\Storefront\Pagelet\NavigationPagelet;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Storefront\Pagelet\Header\HeaderPageletLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Adds the MegaMenus to the header Pagelet.
*
* @package S360\MegaMenu\Storefront\Subscriber
*/
class HeaderSubscriber extends AbstractMenuSubscriber implements EventSubscriberInterface
{
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
HeaderPageletLoadedEvent::class => 'onPageLoaded'
];
}
/**
* Adds the MegaMenus to the header Pagelet.
*
* @param HeaderPageletLoadedEvent $event
* @return void
*/
public function onPageLoaded(HeaderPageletLoadedEvent $event): void
{
$salesChannel = $event->getSalesChannelContext()->getSalesChannel();
$navigationId = $event->getRequest()->get('navigationId', $salesChannel->getNavigationCategoryId());
$menues = $this->menuLoader->load(
$event->getContext(),
$event->getRequest(),
(string) $navigationId,
MenuLoader::ACTIVE_PROPERTY_CATEGORY_ID
);
// Load Pseudo-Category Content
$pseudoItem = $this->loadPseudoCategoryContent(
$menues->getByType(MenuCollection::MOBILE_MENU_TYPE),
$navigationId
);
$this->menuLoader->sortCategories($pseudoItem);
$event->getPagelet()->addExtension(
's360_megamenu',
new NavigationPagelet(
$menues->getByType(MenuCollection::DESKTOP_MENU_TYPE),
$menues->getByType(MenuCollection::MOBILE_MENU_TYPE),
$pseudoItem,
$this->loadActiveCategory($menues->getByType(MenuCollection::MOBILE_MENU_TYPE), $navigationId)
)
);
}
/**
* Load the active category
*
* @param MenuEntity|null $menu
* @param string $navigationId
* @return CategoryEntity|null
*/
private function loadActiveCategory(?MenuEntity $menu, string $navigationId): ?CategoryEntity
{
if ($menu) {
return $this->menuLoader->loadActiveCategory($menu->getTree(), $navigationId);
}
return null;
}
/**
* Load Pseudo Category Content, ie the active category entity.
*
* @param MenuEntity|null $menu
* @param string $navigationId
* @return CategoryEntity|null
*/
private function loadPseudoCategoryContent(?MenuEntity $menu, string $navigationId): ?CategoryEntity
{
if (empty($menu)) {
return null;
}
$activeCategory = $this->loadActiveCategory($menu, $navigationId);
// Get the active category parent if the active category is a leaf node (ie has no children),
// as then we want to display the active cats siblings instead!
if ($activeCategory && empty($activeCategory->getChildren())) {
return $this->getPseudoCategoryParent($activeCategory, $menu->getItems()) ?? $activeCategory;
}
return $activeCategory;
}
/**
* Get Category Parent
*
* @param CategoryEntity $category
* @param MenuItemCollection|null $items
* @return CategoryEntity|null
*/
private function getPseudoCategoryParent(CategoryEntity $category, ?MenuItemCollection $items): ?CategoryEntity
{
if (empty($items)) {
return null;
}
$parentId = $category->getParentId();
foreach ($items as $item) {
if ($item->getCategoryLinkId() == $parentId) {
return $item->getCategoryLink();
}
if ($item->getCategoryLink() && $item->getCategoryLink()->getChildren()) {
$parent = $this->menuLoader->getDeepCategory($item->getCategoryLink(), $parentId);
if ($parent) {
return $parent;
}
}
}
return null;
}
}