<?php
declare(strict_types=1);
namespace WbfkExtensions\Subscriber;
use Exception;
use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
use Shopware\Core\Content\Product\Events\ProductCrossSellingIdsCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductCrossSellingStreamCriteriaEvent;
use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Storefront\Page\Product\ProductPageCriteriaEvent;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use WbfkExtensions\Core\Content\ProductAdditionalService\SalesChannel\AdditionalServiceRoute;
class ProductPageSubscriber implements EventSubscriberInterface
{
/** @var EntityRepositoryInterface */
private $customFieldSetRepository;
public function __construct(private readonly AdditionalServiceRoute $additionalServiceRoute, Container $container)
{
try {
$this->customFieldSetRepository = $container->get('custom_field_set.repository');
} catch (Exception) {
}
}
public static function getSubscribedEvents(): array
{
return [
ProductPageLoadedEvent::class => 'onProductPageLoadedEvent',
ProductPageCriteriaEvent::class => 'onProductPageCriteriaEvent',
ProductCrossSellingIdsCriteriaEvent::class => 'onProductCrossSellingIdsCriteriaEvent',
ProductCrossSellingStreamCriteriaEvent::class => 'onProductCrossSellingStreamCriteriaEvent',
];
}
public function onProductPageLoadedEvent(ProductPageLoadedEvent $event): void
{
$product = $event->getPage()->getProduct();
$this->loadAdditionalServiceToPage($product, $event);
$this->loadCustomFieldSet($product, $event->getContext());
}
public function loadAdditionalServiceToPage(SalesChannelProductEntity $product, ProductPageLoadedEvent $event): void
{
try {
$additionalService = $this->additionalServiceRoute->load(
$product->getId(),
$event->getRequest(),
$event->getSalesChannelContext(),
new Criteria()
)->getAdditionalService();
/** @noinspection PhpDeprecationInspection */
$event->getPage()->addExtension('additionalService', $additionalService);
} catch (NotFoundHttpException) {
// No additional services found
}
}
private function loadCustomFieldSet(SalesChannelProductEntity $product, Context $context): void
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('name', 'wbfk_further_technical_data'));
$criteria->addAssociation('customFields');
$customFieldSet = $this->customFieldSetRepository->search($criteria, $context)->first();
$customFieldSetFields = $customFieldSet->getCustomFields()->getElements();
$filledCustomFieldSetFields = $product->getCustomFields();
$matchingCustomFieldSetFields = [];
foreach ($customFieldSetFields as $key => $customFieldSetField) {
$customFieldSetFields[$key] = $customFieldSetField;
$customFieldSetName = $customFieldSetField->getName();
if (isset($filledCustomFieldSetFields["$customFieldSetName"]) ?? null) {
$object = new \stdClass();
$object->label = $customFieldSetField->getConfig()['label'];
$object->position = $customFieldSetField->getConfig()['customFieldPosition'];
$object->type = $customFieldSetField->getType();
$object->value = $filledCustomFieldSetFields["$customFieldSetName"];
$matchingCustomFieldSetFields[] = $object;
}
}
usort($matchingCustomFieldSetFields, function ($a, $b) {
return $a->position > $b->position;
});
if ($matchingCustomFieldSetFields) {
$product->addExtension('wbfk_additional_data_customFieldset', new ArrayEntity($matchingCustomFieldSetFields));
}
}
public function onProductPageCriteriaEvent(ProductPageCriteriaEvent $event): void
{
$event->getCriteria()->addFilter(
new OrFilter(
[
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_ALL),
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_SEARCH),
]
)
);
}
public function onProductCrossSellingIdsCriteriaEvent(ProductCrossSellingIdsCriteriaEvent $event): void
{
$event->getCriteria()->addFilter(
new OrFilter(
[
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_ALL),
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_SEARCH),
]
)
);
}
public function onProductCrossSellingStreamCriteriaEvent(ProductCrossSellingStreamCriteriaEvent $event): void
{
$event->getCriteria()->addFilter(
new OrFilter(
[
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_ALL),
new ProductAvailableFilter($event->getSalesChannelContext()->getSalesChannel()->getId(), ProductVisibilityDefinition::VISIBILITY_SEARCH),
]
)
);
}
}