<?php
declare(strict_types=1);
namespace LDSCustom\Subscriber;
use Shopware\Storefront\Page\GenericPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\HttpFoundation\Request;
use Shopware\Core\Framework\Context;
use Nds\RecipeManager\Core\Content\Recipe\RecipeEntity;
use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CheapestPriceContainer;
use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\Framework\Feature;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use LDSCustom\Core\Recipe\Extension\RecipeDataExtension;
class Recipe implements EventSubscriberInterface
{
private AbstractProductPriceCalculator $calculator;
private EntityRepository $recipeRepository;
private EntityRepository $productRepository;
public function __construct(AbstractProductPriceCalculator $calculator, EntityRepository $recipeRepository, EntityRepository $productRepository)
{
$this->calculator = $calculator;
$this->recipeRepository = $recipeRepository;
$this->productRepository = $productRepository;
}
public static function getSubscribedEvents(): array
{
return [
GenericPageLoadedEvent::class => 'onRecipePageLoaded',
];
}
public function onRecipePageLoaded(GenericPageLoadedEvent $event): void
{
$salesChannelContext = $event->getSalesChannelContext();
$page = $event->getPage();
/** @var Context $context */
$context = $salesChannelContext->getContext();
/** @var Request $request */
$request = $event->getRequest();
$uri = explode('/', $request->getRequestUri());
if (count($uri) < 3) {
return;
}
list(, $target, $slug) = $uri;
if ($target !== 'rcp_recipe' || empty($slug)) {
return;
}
/** @var RecipeEntity $recipeProducts */
$products = $this->getRecipeProductInfo($slug, $context);
if (empty($products)) {
return;
}
$this->productSalesChannelLoaded($products, $salesChannelContext);
$productExtension = new RecipeDataExtension();
$productExtension->assign([
'data' => $products,
]);
$page->addExtension(RecipeDataExtension::EXTENSION_NAME, $productExtension);
}
protected function getRecipeProductInfo(string $slug, Context $context)
{
$criteria = new Criteria();
$criteria
->addFilter(new EqualsFilter('slug', $slug))
->addFilter(new EqualsFilter('active', '1'))
->addAssociations(
[
'ingredients',
'ingredients.product',
]
);
$recipeProducts = $this->recipeRepository->search($criteria, $context)->first();
$ingredients = $recipeProducts->getIngredients();
$products = [];
foreach ($ingredients as $ingredient) {
if ($ingredient->getProduct() !== null) {
$products[] = $ingredient->getProduct();
}
}
if (empty($products)) {
return;
}
$return = [];
foreach ($products as $product) {
$criteria = new Criteria();
$criteria
->addFilter(new EqualsFilter('id', $product->getId()))
->addFilter(new EqualsFilter('active', '1'))
->addAssociations(
[
'prices',
'deliveryTime',
'cover',
'productReviews',
]
);
$return[] = $this->productRepository->search($criteria, $context)->first();
}
if (empty($return)) {
return;
}
return $return;
}
/**
* @param Entity[] $elements
*/
private function productSalesChannelLoaded(array $elements, SalesChannelContext $context): void
{
/** @var SalesChannelProductEntity $product */
foreach ($elements as $product) {
if (Feature::isActive('FEATURE_NEXT_16151')) {
$price = $product->get('cheapestPrice');
if ($price instanceof CheapestPriceContainer) {
$resolved = $price->resolve($context->getContext());
$product->assign([
'cheapestPrice' => $resolved,
'cheapestPriceContainer' => $price,
]);
}
}
}
$this->calculator->calculate($elements, $context);
}
}