<?php
declare(strict_types=1);
/**
* @copyright 2023 Crehler Sp. z o.o.
*
* https://crehler.com/
* support@crehler.com
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Crehler\AdvancedSort\Subscriber;
use Crehler\AdvancedSort\Services\PositionConfigService;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\SalesChannel\Sorting\ProductSortingCollection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
class ProductSubscriber implements EventSubscriberInterface
{
private PositionConfigService $positionConfigService;
private EntityRepository $sortingRepository;
public function __construct(
PositionConfigService $positionConfigService,
EntityRepository $productSortingRepository)
{
$this->positionConfigService = $positionConfigService;
$this->sortingRepository = $productSortingRepository;
}
public static function getSubscribedEvents(): array
{
return [
ProductListingCriteriaEvent::class => ['handleProductListingCriteria', -170]
];
}
public function handleProductListingCriteria(ProductListingCriteriaEvent $event): void
{
$request = $event->getRequest();
if (!$request->query->get('order', false) && $this->positionConfigService->getDefaultSorting($event->getSalesChannelContext())) {
$availableSorting = $this->getAvailableSorting($request, $event->getContext());
if ($this->sortingAvailable($availableSorting, $this->positionConfigService->getDefaultSorting($event->getSalesChannelContext()))) {
// $request->query->set('order', $this->positionConfigService->getDefaultSorting($event->getSalesChannelContext()));
}
}
}
private function getAvailableSorting(Request $request, Context $context): EntityCollection
{
$criteria = new Criteria();
$availableSorting = $request->get('availableSortings');
$availableSortingFilter = [];
if ($availableSorting) {
if ($request->get("order") === "position" && !isset($availableSorting['position'])) {
$availableSorting += [ "position" => 0 ];
$request->request->set("availableSortings", $availableSorting);
}
arsort($availableSorting, \SORT_DESC | \SORT_NUMERIC);
$availableSortingFilter = array_keys($availableSorting);
$criteria->addFilter(new EqualsAnyFilter('key', $availableSortingFilter));
}
$criteria
->addFilter(new EqualsFilter('active', true))
->addSorting(new FieldSorting('priority', 'DESC'));
/** @var ProductSortingCollection $sortings */
$sortings = $this->sortingRepository->search($criteria, $context)->getEntities();
if ($availableSorting) {
$sortings->sortByKeyArray($availableSortingFilter);
}
return $sortings;
}
private function sortingAvailable($availableSorting, $defaultSorting): bool
{
if (!empty($availableSorting) and $availableSorting instanceof ProductSortingCollection) {
$elements = $availableSorting->getElements();
foreach ($elements as $aSortElement) {
if ($defaultSorting === $aSortElement->getKey()) {
return true;
}
}
}
return false;
}
}