<?php declare(strict_types=1);
namespace Crehler\MojeBambinoEngine\Subscriber;
use Crehler\MojeBambinoEngine\Storefront\Controller\SubNavigationController;
use Crehler\MojeBambinoEngine\Util\Lifecycle\ActivateDeactivate;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Category\Event\NavigationLoadedEvent;
use Shopware\Core\Content\Category\Tree\TreeItem;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class NavigationSubscriber implements EventSubscriberInterface
{
private SalesChannelRepositoryInterface $categoryRepository;
public function __construct(
SalesChannelRepositoryInterface $categoryRepository
)
{
$this->categoryRepository = $categoryRepository;
}
public static function getSubscribedEvents(): array
{
return [
NavigationLoadedEvent::class => 'onNavigationLoaded',
];
}
public function onNavigationLoaded(NavigationLoadedEvent $event): void
{
$navigation = $event->getNavigation();
$context = $event->getSalesChannelContext();
$activeCategory = $navigation->getActive();
if (null === $activeCategory->getParent() && $activeCategory->getParentId()) {
$activeCategory->setParent(
$this->loadCategory($activeCategory->getParentId(), $context)
);
}
if (null !== $activeCategory->getParent()
&& isset($activeCategory->getParent()->getCustomFields()[ActivateDeactivate::INTERMEDIATE_CATEGORY])
&& ($activeCategory->getParent()->getCustomFields()[ActivateDeactivate::INTERMEDIATE_CATEGORY])) {
$activeCategory->getParent()->setParent(
$this->loadCategory($activeCategory->getParent()->getParentId(), $context)
);
}
if (in_array(SubNavigationController::PRODUCT_CATEGORY, array_keys($activeCategory->getPlainBreadcrumb()))) {
if ($activeCategory->getChildCount() > 0) {
$activeCategory->setChildren($this->loadCategory($activeCategory->getId(), $context)->getChildren());
}
foreach ($navigation->getTree() as $treeItem) {
if (!in_array($treeItem->getCategory()->getId(), array_keys($activeCategory->getPlainBreadcrumb()))) continue;
$this->loadIntermediateChildren($treeItem, $activeCategory, 1, $context);
}
}
//jeżeli aktywna kategoria ma dzieci to dołatować je do drzewa
if ($activeCategory->getChildCount() > 0) {
foreach ($navigation->getTree() as $treeItem) {
if (!in_array($treeItem->getCategory()->getId(), array_keys($activeCategory->getPlainBreadcrumb()))) continue;
$this->checkTreeChildren($treeItem, $activeCategory, $context);
}
}
}
private function loadCategory(string $id, SalesChannelContext $context): CategoryEntity
{
$criteria = new Criteria([$id]);
$criteria
->getAssociation('children')
->addAssociation('media');
return $this->categoryRepository->search($criteria, $context)->get($id);
}
private function loadIntermediateChildren(TreeItem $treeItem, CategoryEntity $activeCategory, int $level, $context)
{
if (!in_array($treeItem->getCategory()->getId(), array_keys($activeCategory->getPlainBreadcrumb()))
and (!in_array($treeItem->getCategory()->getId(), $activeCategory->getChildren()->getKeys()))
) {
return;
}
if (!empty($activeCategory->getChildren()) and !in_array($treeItem->getCategory()->getId(), $activeCategory->getChildren()->getKeys())) {
foreach ($treeItem->getChildren() as $child) {
$this->loadIntermediateChildren($child, $activeCategory, $level++, $context);
}
return;
}
if ($treeItem->getCategory()->getChildCount() != count($treeItem->getChildren())) {
$category = $this->loadCategory($treeItem->getCategory()->getId(), $context);
$categoryIds = array_keys($treeItem->getChildren());
foreach ($category->getChildren()->sortByPosition() as $child) {
if (!in_array($child->getId(), $categoryIds)) {
$treeItem->addChildren(new TreeItem($child, []));
}
}
}
}
private function checkTreeChildren(TreeItem $treeItem, CategoryEntity $activeCategory, $context, bool $force = false)
{
if ($force) {
if ($treeItem->getCategory()->getChildCount() != count($treeItem->getChildren())) {
$category = $this->loadCategory($treeItem->getCategory()->getId(), $context);
$categoryIds = array_keys($treeItem->getChildren());
foreach ($category->getChildren()->sortByPosition() as $child) {
if (!$child->getActive() || !$child->getVisible()) {
continue;
}
if (!in_array($child->getId(), $categoryIds)) {
$treeItem->addChildren(new TreeItem($child, []));
}
}
}
}
if ((in_array($treeItem->getCategory()->getId(), array_keys($activeCategory->getPlainBreadcrumb()))
and ($treeItem->getCategory()->getChildCount() > 0)
) or $force) {
if (!$force && array_key_last($activeCategory->getPlainBreadcrumb()) === $treeItem->getCategory()->getId()) {
$force = true;
}
foreach ($treeItem->getChildren() as $child) {
$this->checkTreeChildren($child, $activeCategory, $context, $force);
}
}
}
}