<?php declare(strict_types=1);
namespace Crehler\MojeBambinoEngine\Storefront\Page\Product;
use Shopware\Core\Content\Product\SalesChannel\Detail\ProductDetailRoute;
use Shopware\Core\Content\Product\SalesChannel\Detail\ProductDetailRouteResponse;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\GenericPageLoader;
use Shopware\Storefront\Page\Page;
use Shopware\Storefront\Page\Product\Configurator\ProductPageConfiguratorLoader;
use Shopware\Storefront\Page\Product\ProductPage;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Shopware\Storefront\Page\Product\ProductPageLoader;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
class ModalProductPageLoader
{
/**
* @var GenericPageLoader
*/
private $genericLoader;
/**
* @var SalesChannelRepository
*/
private $productRepository;
/**
* @var ProductPageConfiguratorLoader
*/
private $configuratorLoader;
/**
* @var ProductPageLoader
*/
private $productLoader;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
public function __construct(
GenericPageLoader $genericLoader,
SalesChannelRepository $productRepository,
ProductPageConfiguratorLoader $configuratorLoader,
ProductPageLoader $productLoader,
EventDispatcherInterface $eventDispatcher
) {
$this->genericLoader = $genericLoader;
$this->productRepository = $productRepository;
$this->configuratorLoader = $configuratorLoader;
$this->productLoader = $productLoader;
$this->eventDispatcher = $eventDispatcher;
}
/**
* @param Request $request
* @param string $productId
* @param string|null $variantId
* @param SalesChannelContext $salesChannelContext
* @return ProductPage
*/
public function load(Request $request, string $productId, ?string $variantId, SalesChannelContext $salesChannelContext): ProductPage
{
$page = new Page();
$page = ProductPage::createFrom($page);
if (!$productId) {
throw new MissingRequestParameterException('productId', '/productId');
}
$productId = $this->findBestVariant($productId, $variantId, $salesChannelContext);
$request->attributes->set('productId', $productId);
/** @var SalesChannelProductEntity $product */
$product = $this->productLoader->load($request,$salesChannelContext)->getProduct();
$page->setProduct($product);
$page->setConfiguratorSettings(
$this->configuratorLoader->load($product, $salesChannelContext)
);
$this->loadOptions($page);
$this->eventDispatcher->dispatch(
new ProductPageLoadedEvent($page, $salesChannelContext, $request)
);
return $page;
}
private function loadOptions(ProductPage $page): void
{
$options = new PropertyGroupOptionCollection();
$optionIds = $page->getProduct()->getOptionIds();
foreach ($page->getConfiguratorSettings() as $group) {
$groupOptions = $group->getOptions();
if ($groupOptions === null) {
continue;
}
foreach ($optionIds as $optionId) {
if ($groupOptions->has($optionId)) {
$options->add($groupOptions->get($optionId));
}
}
}
$page->setSelectedOptions($options);
}
/**
* @throws InconsistentCriteriaIdsException
*/
private function findBestVariant(string $productId, ?string $variantId, SalesChannelContext $salesChannelContext):string
{
$criteria = (new Criteria())
->addFilter(new EqualsFilter('product.parentId', $productId))
->addSorting(new FieldSorting('product.price'));
if($variantId) {
$criteria
->addFilter(new EqualsFilter('product.id', $variantId));
}
$variantIds = $this->productRepository->searchIds($criteria, $salesChannelContext);
if (\count($variantIds->getIds()) > 0) {
return $variantIds->getIds()[0];
}
return $productId;
}
}