<?php
declare(strict_types=1);
namespace SmsBecoTechnicCategoryCustomListing\Subscriber;
use Doctrine\DBAL\Connection;
use phpDocumentor\Reflection\Types\Boolean;
use PhpParser\Node\Expr\BinaryOp\Equal;
use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
use Shopware\Core\Content\Product\Aggregate\ProductManufacturer\ProductManufacturerCollection;
use Shopware\Core\Content\Product\Aggregate\ProductManufacturer\ProductManufacturerEntity;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionEntity;
use Shopware\Core\Content\Property\PropertyGroupCollection;
use Shopware\Core\Content\Property\PropertyGroupEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityWriteGateway;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Metric\EntityResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Struct\StructCollection;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepository;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
class
ListingSubscriber implements EventSubscriberInterface
{
private $categoryRepository;
private $productRepository;
private Connection $connection;
private $propertyRepository;
private $propertyGroupOptionRepository;
private $config;
public function __construct(
EntityRepositoryInterface $categoryRepository,
SalesChannelRepository $productRepository,
Connection $connection,
EntityRepositoryInterface $propertyRepository,
EntityRepositoryInterface $propertyGroupOptionRepository,
SystemConfigService $config
)
{
$this->categoryRepository = $categoryRepository;
$this->productRepository = $productRepository;
$this->connection = $connection;
$this->propertyRepository = $propertyRepository;
$this->propertyGroupOptionRepository = $propertyGroupOptionRepository;
$this->config = $config;
}
public static function getSubscribedEvents()
{
return [
ProductListingCriteriaEvent::class => 'handleListingRequest',
CmsPageLoadedEvent::class => 'handleCMSPageLoadedEvent',
ProductListingResultEvent::class => 'handleProductListingResultEvent'
];
}
/**
* @param $a
* @param $b
* @return bool
*/
function cmpare($a, $b)
{
//Sort Products
$customListingConfig = $this->config->get("SmsBecoTechnicCategoryCustomListing");
if (!is_null($customListingConfig) && isset($customListingConfig["config"])) {
$customListingConfig = $customListingConfig["config"];
}
if (!is_null($customListingConfig) && isset($customListingConfig["movementListingSortProperty"]) && $customListingConfig["movementListingSortProperty"] != "") {
$sortBy = $customListingConfig["movementListingSortProperty"];
if ($sortBy) {
$propertyA = $a->getProperties()->filter(function (PropertyGroupOptionEntity $property) use ($sortBy) {
return $property->getGroupId() == $sortBy;
})->first();
$propertyB = $b->getProperties()->filter(function (PropertyGroupOptionEntity $property) use ($sortBy) {
return $property->getGroupId() == $sortBy;
})->first();
if ($propertyA && $propertyB) {
return intval($propertyA->getName()) > intval($propertyB->getName());
}
return false;
}
}
if (strlen($a->getProductNumber()) > strlen($b->getProductNumber())) {
return true;
} else {
return $a->getProductNumber() > $b->getProductNumber();
}
}
public function handleProductListingResultEvent(ProductListingResultEvent $event): void
{
$mainProduct = null;
/** @var SalesChannelProductEntity[] $products */
$products = $event->getResult()->getElements();
//Get current category and custom fields
$navigationId = $event->getRequest()->get("navigationId");
if (!is_null($navigationId)) {
$categoryCriteria = new Criteria([$navigationId]);
$category = $this->categoryRepository->search(
$categoryCriteria,
\Shopware\Core\Framework\Context::createDefaultContext()
)->first();
$event->getSalesChannelContext()->getSalesChannel()->addExtension("currentCategory", $category);
$customFields = $category->getCustomFields();
if (!empty($customFields)
&& isset($customFields["sms_beco_technic_category_type"])
&& $customFields["sms_beco_technic_category_type"] == 'KAT_WERKE') {
//Try to get MainProduct
$mainProductCriteria = new Criteria();
$mainProductCriteria->addAssociation("categories");
$mainProductCriteria->addAssociation("manufacturer");
$mainProductCriteria->addAssociation('properties');
$mainProductCriteria->addAssociation('properties.group');
$mainProductCriteria->addFilter(new EqualsFilter("categories.id", $category->getId()));
$mainProductCriteria->addFilter(new NotFilter(NotFilter::CONNECTION_AND, [new ContainsFilter("productNumber", ".")]));
$mainProductCriteria->addSorting(new FieldSorting("productNumber", FieldSorting::ASCENDING));
$mainProduct = $this->productRepository->search($mainProductCriteria, $event->getSalesChannelContext())->first();
if ($mainProduct && !in_array($mainProduct->getId(), array_keys($products))) {
$products[$mainProduct->getId()] = $mainProduct;
}
}
// if (isset($_GET["debug"]) && $_GET["debug"] == "true") {
if (!empty($customFields)
&& isset($customFields["sms_beco_technic_category_table_primary_property_option"])
&& isset($customFields["sms_beco_technic_category_type"])
&& (str_contains($customFields["sms_beco_technic_category_type"], 'KAT_ZWEI_TABELLEN')
|| str_contains($customFields["sms_beco_technic_category_type"], 'KAT_WERKE'))
) {
$productCriteria = new Criteria();
$productCriteria->addAssociation('properties');
$productCriteria->addAssociation('properties.group');
$productCriteria->addAssociation('manufacturer');
$productCriteria->addAssociation('manufacturer.media');
$productCriteria->addAssociation('categories');
$productCriteria->addAssociation('media');
$productCriteria->addAssociation('cover');
$productCriteria->addFilter(new EqualsFilter("properties.id", $customFields["sms_beco_technic_category_table_primary_property_option"]));
$productCriteria->addFilter(new EqualsFilter("categoriesRo.id", $navigationId));
$productCriteria->addSorting(new FieldSorting("productNumber", FieldSorting::DESCENDING));
$properties = $event->getRequest()->get("properties");
if (!empty($properties)) {
$productCriteria->addFilter(new EqualsAnyFilter("properties.id", explode("|", $properties)));
}
$newProducts = $this->productRepository->search($productCriteria, $event->getSalesChannelContext())->getElements();
//
/** @var ProductManufacturerCollection $manufacturerAggregation */
$manufacturerAggregation = $event->getResult()->getAggregations()->get("manufacturer");
/** @var EntityResult|null $propertyGroupAggregation */
$propertyGroupAggregation = $event->getResult()->getAggregations()->get("properties");
/** @var SalesChannelProductEntity $product */
foreach ($newProducts as $product) {
// $this->dump($product->getProperties()->first()->getGroup()->getName());
//Enrich manufacturer aggregation
if ($manufacturerAggregation) {
$manufacturer = $product->getManufacturer();
if ($manufacturer) {
$manufacturerAggregation->add($manufacturer);
}
}
//Enrich property aggregation
if ($propertyGroupAggregation instanceof EntityResult) {
/** @var PropertyGroupCollection $propertyGroupsOld */
$propertyGroupCollectionFromAggregation = $propertyGroupAggregation->getEntities();
$properties = $product->getProperties();
if ($properties) {
/** @var PropertyGroupOptionEntity $property */
foreach ($properties as $property) {
//Get property group from aggregation by property group id
/** @var PropertyGroupEntity $propertyGroup */
$propertyGroup = $propertyGroupCollectionFromAggregation->filter(function ($propertyGroup) use ($property) {
return $propertyGroup->getId() == $property->getGroupId();
})->first();
if ($propertyGroup) {
$propertyGroup->getOptions()->add($property);
} elseif ($property->getGroup()->getVisibleOnProductDetailPage()) {
$propertyGroup = $property->getGroup();
$propertyGroupOptionCollection = new PropertyGroupOptionCollection();
$propertyGroupOptionCollection->add($property);
$propertyGroup->setOptions($propertyGroupOptionCollection);
$propertyGroupAggregation->add($propertyGroup);
}
}
}
}
}
if ($event->getRequest()->query->get("manufacturer")) {
//Remove products without manufacturer
$newProducts = array_filter($newProducts, function ($product) use ($event) {
return !is_null($product->getManufacturer()) && in_array($product->getManufacturer()->getId(), explode("|", $event->getRequest()->query->get("manufacturer")));
});
}
if ($event->getRequest()->query->get("properties")) {
//Group the properties from request into correct property groups
$propertiesFromRequest = explode("|", $event->getRequest()->query->get("properties"));
$propertiesFromRequest = $this->propertyGroupOptionRepository->search(new Criteria($propertiesFromRequest), $event->getContext())->getElements();
// if($_GET["debug"] == "true") {
// $this->dump([$propertiesFromRequest]);
// }
if ($propertiesFromRequest) {
//Remove products without properties
$propertiesFromRequestGrouped = [];
foreach ($propertiesFromRequest as $propertyFromRequest) {
$propertiesFromRequestGrouped[$propertyFromRequest->getGroupId()][] = $propertyFromRequest->getId();
}
$newProducts = array_filter($newProducts, function ($product) use ($event, $propertiesFromRequestGrouped) {
/** @var PropertyGroupOptionCollection $properties */
$properties = $product->getProperties();
$propertiesGrouped = [];
foreach ($properties as $property) {
$propertiesGrouped[$property->getGroupId()][] = $property->getId();
}
foreach ($propertiesFromRequestGrouped as $groupId => $propertyFromRequestGrouped) {
$propertyFound = false;
foreach ($propertyFromRequestGrouped as $propertyFromRequest) {
// if($_GET["debug"] == "true") {
// $this->dump([$propertiesFromRequestGrouped, $propertiesGrouped, $groupId, $propertyFromRequest, $propertiesGrouped[$groupId]]);
// }
if (isset($propertiesGrouped[$groupId]) && in_array($propertyFromRequest, $propertiesGrouped[$groupId])) {
$propertyFound = true;
}
}
if (!$propertyFound) {
return false;
}
}
return true;
});
}
}
$products = array_merge($products, $newProducts);
if (str_contains($customFields["sms_beco_technic_category_type"], 'KAT_ZWEI_TABELLEN')) {
$event->getSalesChannelContext()->addExtension("showMoreButton", new ArrayEntity([true]));
} else {
$event->getSalesChannelContext()->addExtension("showMoreButton", new ArrayEntity([false]));
}
} else {
$event->getSalesChannelContext()->addExtension("showMoreButton", new ArrayEntity([false]));
}
}
usort($products, array($this, "cmpare"));
// if (!empty($customFields)
// && isset($customFields["sms_beco_technic_category_table_primary_property_option"])
// && isset($customFields["sms_beco_technic_category_type"])
// && !str_contains($customFields["sms_beco_technic_category_type"], 'KAT_ZWEI_TABELLEN')
// && str_contains($customFields["sms_beco_technic_category_type"], 'KAT_WERKE')
// ) {
// $products = array_slice($products, intval($event->getRequest()->get('p')), 20);
// }
$listingProducts = new ArrayEntity($products);
$event->getSalesChannelContext()->addExtension("listingProducts", $listingProducts);
$event->getSalesChannelContext()->addExtension("mainProduct", $mainProduct);
}
public function handleListingRequest(ProductListingCriteriaEvent $event): void
{
//Get current category and custom fields
$navigationId = $event->getRequest()->get("navigationId");
$customListingConfig = $this->config->get("SmsBecoTechnicCategoryCustomListing");
if (!is_null($navigationId)) {
$category = $this->categoryRepository->search(
new Criteria([$navigationId]),
\Shopware\Core\Framework\Context::createDefaultContext()
)->first();
$customFields = $category->getCustomFields();
} else {
$customFields = null;
}
if (!is_null($customListingConfig) && isset($customListingConfig["config"])) {
$customListingConfig = $customListingConfig["config"];
}
if (!is_null($customListingConfig)
&& isset($customListingConfig["config"]["movementListingMovements"])
&& !is_null($customListingConfig["config"]["movementListingMovements"])
&& $customListingConfig["config"]["movementListingMovements"] != ""
&& !is_null($navigationId)) {
if (!empty($customFields)
&& isset($customFields["sms_beco_technic_category_type"])
&& $customFields["sms_beco_technic_category_type"] == 'KAT_WERKE_KOPF') {
// $event->getCriteria()->addAssociation('properties');
$event->getCriteria()->addPostFilter(new EqualsFilter("properties.id", $customListingConfig["movementListingMovements"]));
}
}
//
$event->getCriteria()->addAssociation('properties');
$event->getCriteria()->addAssociation('properties.group');
$event->getCriteria()->addAssociation('manufacturer');
$event->getCriteria()->addAssociation('manufacturer.media');
$event->getCriteria()->addAssociation('categories');
$event->getCriteria()->addAssociation('media');
$event->getCriteria()->addAssociation('cover');
//Remove Main Articles for Two Table Categories
if (!empty($customFields)
&& isset($customFields["sms_beco_technic_category_table_primary_property_option"])
&& isset($customFields["sms_beco_technic_category_type"])
&& $customFields["sms_beco_technic_category_type"] == 'KAT_ZWEI_TABELLEN'
) {
$event->getCriteria()->addFilter(new NotFilter(NotFilter::CONNECTION_AND, [new EqualsFilter("properties.id", $customFields["sms_beco_technic_category_table_primary_property_option"])]));
}
//Sorting
// $event->getCriteria()->addSorting(new FieldSorting('CustomProductCategoryExtension.sortingPriority', FieldSorting::DESCENDING));
$event->getCriteria()->addSorting(new FieldSorting('productNumber', FieldSorting::ASCENDING));
}
public function handleCMSPageLoadedEvent(CmsPageLoadedEvent $event): void
{
if (!is_null($event->getRequest()->get("navigationId"))) {
/** @var CategoryEntity $category */
$navigationId = $event->getRequest()->get("navigationId");
$categoryCriteria = new Criteria();
$categoryCriteria->addAssociation("properties");
$category = $this->categoryRepository->search(
new Criteria([$navigationId]),
\Shopware\Core\Framework\Context::createDefaultContext()
)->first();
// echo "<pre>";
// die(var_dump($category));
$categoryCustomFields = $category->getCustomFields();
$propertyGroupIds = [];
if ($categoryCustomFields) {
$propertyOne = null;
$propertyTwo = null;
$propertyThree = null;
$propertyFour = null;
$propertyFive = null;
$propertySix = null;
$propertyOneMovement = null;
$propertyTwoMovement = null;
$propertyThreeMovement = null;
$propertyFourMovement = null;
$propertyFiveMovement = null;
$propertyOneMovementPart = null;
$propertyTwoMovementPart = null;
// Table Listing Properties
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_one"]) && $categoryCustomFields["sms_beco_technic_category_table_field_one"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_one"];
$propertyOne = $categoryCustomFields["sms_beco_technic_category_table_field_one"];
}
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_two"]) && $categoryCustomFields["sms_beco_technic_category_table_field_two"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_two"];
$propertyTwo = $categoryCustomFields["sms_beco_technic_category_table_field_two"];
}
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_three"]) && $categoryCustomFields["sms_beco_technic_category_table_field_three"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_three"];
$propertyThree = $categoryCustomFields["sms_beco_technic_category_table_field_three"];
}
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_four"]) && $categoryCustomFields["sms_beco_technic_category_table_field_four"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_four"];
$propertyFour = $categoryCustomFields["sms_beco_technic_category_table_field_four"];
}
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_five"]) && $categoryCustomFields["sms_beco_technic_category_table_field_five"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_five"];
$propertyFive = $categoryCustomFields["sms_beco_technic_category_table_field_five"];
}
if (isset($categoryCustomFields["sms_beco_technic_category_table_field_six"]) && $categoryCustomFields["sms_beco_technic_category_table_field_six"] != "") {
$propertyGroupIds[] = $categoryCustomFields["sms_beco_technic_category_table_field_six"];
$propertySix = $categoryCustomFields["sms_beco_technic_category_table_field_six"];
}
//
}
if (isset ($categoryCustomFields["sms_beco_technic_category_type"])
&& ($categoryCustomFields["sms_beco_technic_category_type"] == 'KAT_WERKE' || $categoryCustomFields["sms_beco_technic_category_type"] == 'KAT_WERKE_KOPF')) {
$propertyOneMovement = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementListingPropertyOne");
$propertyTwoMovement = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementListingPropertyTwo");
$propertyThreeMovement = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementListingPropertyThree");
$propertyFourMovement = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementListingPropertyFour");
$propertyFiveMovement = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementListingPropertyFive");
$propertyOneMovementPart = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementPartsListingPropertyOne");
$propertyTwoMovementPart = $this->config->get("SmsBecoTechnicCategoryCustomListing.config.movementPartsListingPropertyTwo");
//Movement Listing Properties
if ($propertyOneMovement) {
$propertyGroupIds[] = $propertyOneMovement;
}
if ($propertyTwoMovement) {
$propertyGroupIds[] = $propertyTwoMovement;
}
if ($propertyThreeMovement) {
$propertyGroupIds[] = $propertyThreeMovement;
}
if ($propertyFourMovement) {
$propertyGroupIds[] = $propertyFourMovement;
}
if ($propertyFiveMovement) {
$propertyGroupIds[] = $propertyFiveMovement;
}
//Movement Listing Part Properties
if ($propertyOneMovementPart) {
$propertyGroupIds[] = $propertyOneMovementPart;
}
if ($propertyTwoMovementPart) {
$propertyGroupIds[] = $propertyTwoMovementPart;
}
}
if (count($propertyGroupIds) > 0) {
$propertyGroupCriteria = new Criteria();
$propertyGroupCriteria->addFilter(new EqualsAnyFilter("id", $propertyGroupIds));
// $propertyGroupCriteria->addAssociation("options");
$propertyGroups = $this->propertyRepository->search($propertyGroupCriteria, $event->getContext());
/** @var PropertyGroupEntity $propertyGroup */
foreach ($propertyGroups as $propertyGroup) {
if ($propertyOne && $propertyOne == $propertyGroup->getId()) {
$category->addExtension("propOne", $propertyGroup);
}
if ($propertyTwo && $propertyTwo == $propertyGroup->getId()) {
$category->addExtension("propTwo", $propertyGroup);
}
if ($propertyThree && $propertyThree == $propertyGroup->getId()) {
$category->addExtension("propThree", $propertyGroup);
}
if ($propertyFour && $propertyFour == $propertyGroup->getId()) {
$category->addExtension("propFour", $propertyGroup);
}
if ($propertyFive && $propertyFive == $propertyGroup->getId()) {
$category->addExtension("propFive", $propertyGroup);
}
if ($propertySix && $propertySix == $propertyGroup->getId()) {
$category->addExtension("propSix", $propertyGroup);
}
if ($propertyOneMovement && $propertyOneMovement == $propertyGroup->getId()) {
$category->addExtension("propertyOneMovement", $propertyGroup);
}
if ($propertyTwoMovement && $propertyTwoMovement == $propertyGroup->getId()) {
$category->addExtension("propertyTwoMovement", $propertyGroup);
}
if ($propertyThreeMovement && $propertyThreeMovement == $propertyGroup->getId()) {
$category->addExtension("propertyThreeMovement", $propertyGroup);
}
if ($propertyFourMovement && $propertyFourMovement == $propertyGroup->getId()) {
$category->addExtension("propertyFourMovement", $propertyGroup);
}
if ($propertyFiveMovement && $propertyFiveMovement == $propertyGroup->getId()) {
$category->addExtension("propertyFiveMovement", $propertyGroup);
}
if ($propertyOneMovementPart && $propertyOneMovementPart == $propertyGroup->getId()) {
$category->addExtension("propertyOneMovementPart", $propertyGroup);
}
if ($propertyTwoMovementPart && $propertyTwoMovementPart == $propertyGroup->getId()) {
$category->addExtension("propertyTwoMovementPart", $propertyGroup);
}
}
}
$event->getSalesChannelContext()->addExtension("currentCategory", $category);
}
}
public function dump($value)
{
if (class_exists(CliDumper::class)) {
$dumper = 'cli' === PHP_SAPI ? new CliDumper : new HtmlDumper;
$cloner = new VarCloner();
$cloner->setMaxItems(5000);
$cloner->setMinDepth(6);
$dumper->dump($cloner->cloneVar($value));
} else {
var_dump($value);
}
die(1);
}
}