<?php
namespace Boldr\Shop\IngredientsBundle\Presenter;
use Doctrine\ORM\EntityManagerInterface;
use Boldr\Shop\IngredientsBundle\Entity\{ ProductIngredient, IngredientsOption };
use Boldr\Shop\ShopBundle\Entity\{ Product, OrderItem };
use Boldr\Shop\ShopBundle\Presenter\Product\{ ProductView, ProductViewProcessorInterface };
use Boldr\Shop\ShopBundle\Presenter\Order\{ OrderItemView, OrderItemViewProcessorInterface };
use Symfony\Contracts\Cache\TagAwareCacheInterface;
class ViewProcessor implements ProductViewProcessorInterface, OrderItemViewProcessorInterface
{
private IngredientPresenter $ingredientPresenter;
private EntityManagerInterface $em;
private TagAwareCacheInterface $cache;
public function __construct(IngredientPresenter $ingredientPresenter, EntityManagerInterface $em, TagAwareCacheInterface $cache)
{
$this->ingredientPresenter = $ingredientPresenter;
$this->em = $em;
$this->cache = $cache;
}
public function processProductView(ProductView $productView, Product $product, string $locale): ProductView
{
$cacheKey = 'boldr_ingredients.product_ingredient_views.'. $product->getId().'.'.$locale;
$ingredientViews = $this->cache->get($cacheKey, function($item) use ($product, $locale) {
$item->tag('boldr_ingredients.product_ingredient_views.product.'. $product->getId());
$productIngredientRepository = $this->em->getRepository(ProductIngredient::class);
$productIngredients = $productIngredientRepository->createQueryBuilder('pi')
->where('pi.product = ?1 AND (pi.optional = false OR pi.defaultValue = true)')
->setParameter(1, $product)
->addOrderBy('pi.sortOrder', 'ASC')
->getQuery()
->getResult();
foreach ($productIngredients as $productIngredient)
{
$item->tag('boldr_ingredients.product_ingredient_views.ingredient.'. $productIngredient->getIngredient()->getId());
}
$ingredientViews = array_map(
fn($productIngredients) => $this->ingredientPresenter->createIngredientView($productIngredients->getIngredient(), $locale),
$productIngredients
);
return $ingredientViews;
});
$productView->ingredients = $ingredientViews;
return $productView;
}
public function processOrderItemView(OrderItemView $orderItemView, OrderItem $orderItem, string $locale): OrderItemView
{
$productVariant = $orderItem->getProductVariant();
$value = null;
$result = [];
$optionValues = $orderItem->getOptionValues();
foreach ($this->em->getRepository(IngredientsOption::class)->findAll() as $option)
{
if (isset($optionValues[$option->getId()]))
{
$value = $optionValues[$option->getId()];
break;
}
}
if ($value !== null)
{
$productIngredients = $this->em->getRepository(ProductIngredient::class)
->findBy(['product' => $productVariant->getProduct()], ['sortOrder' => 'ASC']);
foreach ($productIngredients as $productIngredient)
{
if ($productIngredient->getOptional() && (!$productIngredient->getDefaultValue() && in_array($productIngredient->getIngredient()->getId(), $value)))
{
$ingredientView = $this->ingredientPresenter->createIngredientView($productIngredient->getIngredient(), $locale);
$amount = $productIngredient->getIngredient()->getAmountByCurrency()[$orderItem->getOrder()->getCurrency()] ?? 0;
$result[] = [
'with' => true,
'ingredient' => $ingredientView,
'amount' => $amount
];
}
}
foreach ($productIngredients as $productIngredient)
{
if ($productIngredient->getOptional() && in_array($productIngredient->getIngredient()->getId(), $value))
{
$ingredientView = $this->ingredientPresenter->createIngredientView($productIngredient->getIngredient(), $locale);
if ($productIngredient->getDefaultValue())
{
$result[] = [
'with' => false,
'ingredient' => $ingredientView,
'amount' => 0
];
}
}
}
}
$orderItemView->ingredients = $result;
return $orderItemView;
}
}