<?php declare(strict_types=1);
namespace Nd\Theme\Subscriber;
use DateTime;
use Nd\Coef\Service\ProductManufacturerUrlService;
use Shopware\Core\Content\Product\Aggregate\ProductMedia\ProductMediaEntity;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\SalesChannel\Detail\ProductConfiguratorLoader;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Struct\ArrayStruct;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Content\Product\ProductEvents;
class AddProductLabels implements EventSubscriberInterface
{
private EventDispatcherInterface $dispatcher;
private string $labelPropertyId;
private string $labelFitId;
private int $labelMaxDaysNewProduct;
private EntityRepository $productManufacturerRepository;
private EntityRepository $productRepository;
private EntityRepository $propertyGroupOptionRepository;
private array $results;
public function __construct( EventDispatcherInterface $dispatcher,
EntityRepository $productManufacturerRepository, EntityRepository $productRepository,
EntityRepository $propertyGroupOptionRepository,
string $labelPropertyId, string $labelFitId, int $labelMaxDaysNewProduct)
{
$this->dispatcher = $dispatcher;
$this->labelPropertyId = $labelPropertyId;
$this->labelFitId = $labelFitId;
$this->labelMaxDaysNewProduct = $labelMaxDaysNewProduct;
$this->productManufacturerRepository = $productManufacturerRepository;
$this->productRepository = $productRepository;
$this->propertyGroupOptionRepository = $propertyGroupOptionRepository;
$this->results = [];
}
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_LOADED_EVENT => 'onProductsLoaded'
];
}
public function onProductsLoaded(EntityLoadedEvent $event): void
{
// $this->dispatcher->removeSubscriber($this);
/** @var ProductEntity $productEntity */
foreach ($event->getEntities() as $productEntity) {
if(in_array($productEntity->getId(), array_keys($this->results))){
$label = $this->results[$productEntity->getId()]['label'];
$fit = $this->results[$productEntity->getId()]['fit'];
}else{
$label = $this->getLabel($productEntity, $event->getContext());
$fit = $this->getFit($productEntity, $event->getContext());
$this->results[$productEntity->getId()] = [
'label' => $label,
'fit' => $fit
];
}
if ($label) {
$productEntity->addExtension('labelData', new ArrayStruct($label));
}
if ($fit) {
$productEntity->addExtension('fitName', new ArrayStruct([$fit]));
}
if (!$productEntity->getManufacturer() && $productEntity->getManufacturerId()) {
$criteria = new Criteria([$productEntity->getManufacturerId()]);
$manufacturers = $this->productManufacturerRepository->search($criteria, $event->getContext());
if ($manufacturers->count() > 0) {
$productEntity->setManufacturer($manufacturers->first());
}
}
}
}
public function getFit(ProductEntity $product, Context $context)
{
$sizeFitId = $this->labelFitId;
if(!$sizeFitId || $sizeFitId == "undefined"){
return false;
}
if($product->getProperties()){
$fits = $product->getProperties()->filterByGroupId($sizeFitId);
} else {
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('productProperties.id', $product->getId()));
$criteria->addFilter(new EqualsFilter('productProperties.versionId', $product->getVersionId()));
$criteria->addFilter(new EqualsFilter('groupId', $sizeFitId));
$fits = $this->propertyGroupOptionRepository->search($criteria, $context);
}
if ($fits->count() === 0) {
return false;
}
return $fits->first()->getName();
}
private function getProductProperties(ProductEntity $product, Context $context){
$properties = $product->getProperties();
if (! $properties) {
$criteria = new Criteria([$product->getId()]);
$criteria->addAssociation("properties.group");
$productSearch = $this->productRepository->search($criteria, $context);
if($productSearch->count() != 1) {
return false;
}
$product->setProperties($productSearch->first()->getProperties());
$properties = $product->getProperties();
}
return $properties;
}
public function getLabel(ProductEntity $product, Context $context)
{
$price = $product->getCurrencyPrice($context->getCurrencyId());
if ($price && $price->getPercentage() && $price->getPercentage()["net"] > 0) {
return ['label' => 'sale', 'text' => "SALE"];
}
if (!$this->labelPropertyId || $this->labelPropertyId == "undefined") {
return false;
}
if(!$product->getProperties()){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('productProperties.id', $product->getId()));
$criteria->addFilter(new EqualsFilter('productProperties.versionId', $product->getVersionId()));
$criteria->addFilter(new EqualsFilter('groupId', $this->labelPropertyId));
$labelProperties = $this->propertyGroupOptionRepository->search($criteria, $context);
}else{
$labelProperties = $product->getProperties()->filterByGroupId($this->labelPropertyId);
}
if ($labelProperties->count() > 0) {
$highestProperty = null;
$highest = -1;
foreach ($labelProperties as $labelProperty) {
if ($labelProperty->getPosition() > $highest) {
$highestProperty = $labelProperty;
$highest = $labelProperty->getPosition();
}
}
if ($highestProperty) {
return ['label' => 'property', 'text' => $highestProperty->getName(), 'color' => $highestProperty->getColorHexCode()];
} else {
return false;
}
}
$now = new DateTime();
if ($product->getCreatedAt()->diff($now)->format('%a') < $this->labelMaxDaysNewProduct) {
return ['label' => 'NEW', 'text' => "Nieuw"];
}
return false;
}
}