<?php
namespace Maxia\MaxiaListingVariants6\Core\Content\Product\Cms;
use Maxia\MaxiaListingVariants6\Service\ConfigService;
use Maxia\MaxiaListingVariants6\Service\ListingVariantsLoader;
use Monolog\Logger;
use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;
use Shopware\Core\Content\Cms\DataResolver\Element\AbstractCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\CmsElementResolverInterface;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductListingStruct;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\SalesChannel\Listing\AbstractProductListingRoute;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\HttpFoundation\Request;
class ProductListingCmsElementResolver extends AbstractCmsElementResolver
{
/**
* @var Logger
*/
protected $logger;
/**
* @var CmsElementResolverInterface
*/
protected $parent;
/**
* @var AbstractProductListingRoute
*/
protected $listingRoute;
/**
* @var ListingVariantsLoader
*/
protected $listingVariantsLoader;
/**
* @var ConfigService
*/
protected $configService;
/**
* @param Logger $logger
* @param CmsElementResolverInterface $parent
* @param AbstractProductListingRoute $listingRoute
* @param ListingVariantsLoader $variantListingService
* @param ConfigService $configService
*/
public function __construct(
Logger $logger,
CmsElementResolverInterface $parent,
AbstractProductListingRoute $listingRoute,
ListingVariantsLoader $variantListingService,
ConfigService $configService
) {
$this->logger = $logger;
$this->parent = $parent;
$this->listingRoute = $listingRoute;
$this->listingVariantsLoader = $variantListingService;
$this->configService = $configService;
}
public function getType(): string
{
return $this->parent->getType();
}
public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
{
return $this->parent->collect($slot, $resolverContext);
}
public function enrich(CmsSlotEntity $slot, ResolverContext $resolverContext, ElementDataCollection $result): void
{
$config = $this->configService->getBaseConfig($resolverContext->getSalesChannelContext());
if (!$config->isPluginEnabled()) {
$this->parent->enrich($slot, $resolverContext, $result);
return;
}
$request = $resolverContext->getRequest();
$context = $resolverContext->getSalesChannelContext();
$route = $request->attributes->get('_route');
if ($route === 'frontend.plugins.maxia-listing-variants.product-box') {
// build different criteria on selection change
$data = new ProductListingStruct();
$navigationId = $this->getNavigationId($request, $context);
$criteria = $this->listingVariantsLoader->buildCriteria($request, $resolverContext->getSalesChannelContext());
$criteria->setTitle('cms::product-listing');
if (class_exists('\Shopware\Core\Content\Product\SalesChannel\Sorting\ProductSortingCollection')) {
$request->request->set('order', 'id');
$criteria->addExtension('sortings', self::createSortings());
}
$listing = $this->listingRoute
->load($navigationId, $request, $context, $criteria)
->getResult();
$data->setListing($listing);
$slot->setData($data);
} else {
$this->parent->enrich($slot, $resolverContext, $result);
}
// load variants data
/** @var ProductListingStruct $listing */
$listing = $slot->getData();
$products = $listing->getListing()->getEntities();
if (!$products || !$products->count()) {
return;
}
foreach ($products->getElements() as $product) {
/** @var ProductEntity $product */
$config = $this->configService->getProductConfig($product, $slot, $resolverContext->getSalesChannelContext());
$product->addExtension('maxiaListingVariants', $config);
}
try {
$this->listingVariantsLoader->load($products->getElements(), $resolverContext->getSalesChannelContext());
} catch (\Exception $e) {
$this->logger->error('Error when loading variants in ProductListingCmsElementResolver: '.
$e->getMessage().",\nStack trace: ".$e->getTraceAsString());
}
}
private function getNavigationId(Request $request, SalesChannelContext $salesChannelContext): string
{
$navigationId = $request->attributes
->get('navigationId', $salesChannelContext->getSalesChannel()->getNavigationCategoryId());
if ($navigationId) {
return $navigationId;
}
$params = $request->attributes->get('_route_params');
if ($params && isset($params['navigationId'])) {
return $params['navigationId'];
}
return $salesChannelContext->getSalesChannel()->getNavigationCategoryId();
}
public static function createSortings()
{
$productSortingEntity = new \Shopware\Core\Content\Product\SalesChannel\Sorting\ProductSortingEntity();
$productSortingEntity->setId(Uuid::randomHex());
$productSortingEntity->setActive(true);
$productSortingEntity->setTranslated(['label' => 'Default']);
$productSortingEntity->setKey('id');
$productSortingEntity->setPriority(5);
$productSortingEntity->setFields([
[
'field' => 'product.id',
'order' => 'desc',
'priority' => 1,
'naturalSorting' => 0,
],
]);
$collection = new \Shopware\Core\Content\Product\SalesChannel\Sorting\ProductSortingCollection();
$collection->add($productSortingEntity);
return $collection;
}
}