<?php declare(strict_types=1);
namespace EnnoTabsAdvanced\Subscriber;
use EnnoTabsAdvanced\Struct\EnnoTabsStruct;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Content\Product\SalesChannel\CrossSelling\AbstractProductCrossSellingRoute;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
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\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
class ProductSubscriber implements EventSubscriberInterface
{
private $systemConfigService;
private $ennoTabRepository;
private $mediaRepository;
private AbstractProductCrossSellingRoute $crossSellingRoute;
public function __construct(
SystemConfigService $systemConfigService,
EntityRepositoryInterface $ennoTabRepository,
EntityRepositoryInterface $mediaRepository,
AbstractProductCrossSellingRoute $crossSellingRoute
)
{
$this->ennoTabRepository = $ennoTabRepository;
$this->systemConfigService = $systemConfigService;
$this->mediaRepository = $mediaRepository;
$this->crossSellingRoute = $crossSellingRoute;
}
public static function getSubscribedEvents(): array
{
return [
ProductPageLoadedEvent::class => 'onProductsLoaded'
];
}
public function onProductsLoaded(ProductPageLoadedEvent $event): void
{
$salesChannel = $event->getSalesChannelContext()->getSalesChannel();
if( $salesChannel && $this->systemConfigService->get('EnnoTabsAdvanced.config.active', $salesChannel->getId() ) )
{
$hideEmpty = $this->systemConfigService->get('EnnoTabsAdvanced.config.hideEmpty', $salesChannel->getId());
$customer = $event->getSalesChannelContext()->getCustomer();
$customerGroup = $event->getSalesChannelContext()->getCurrentCustomerGroup();
$product = $event->getPage()->getProduct();
$productTranslatedFields = $product->getTranslated();
$productCategories = $product->getCategoryTree();
$criteria = (new Criteria())
->addAssociation('salesChannels')
->addAssociation('categoriesList')
->addAssociation('productsList')
->addAssociation('productCustomFields')
->addAssociation('productCustomFields.customField')
->addAssociation('productCustomFields.customField.customFieldSet')
->addFilter(new EqualsFilter('enno_tab.salesChannels.salesChannel.id', $salesChannel->getId()))
->addFilter(new EqualsFilter('enno_tab.active', 1))
->addSorting(new FieldSorting('enno_tab.position'));
// customFieldPosition Wert ist in einem json Feld und kann daher nicht zur Sortierung genutzt werden
// $criteria->getAssociation('productCustomFields.customField')->addSorting(new FieldSorting('customField.config.customFieldPosition'));
$ennoTabs = $this->ennoTabRepository->search($criteria, $event->getContext())->getEntities();
$tabIterator = $ennoTabs->getIterator();
foreach ($tabIterator as $ennoTabKey => $ennoTab)
{
// if($this->isCustomergroupExcluded($article, $tab)) continue;
if(
$this->isProductExcluded($product, $ennoTab)
|| $this->isCategoryExcluded($productCategories, $ennoTab)
// || $this->isCustomergroupExcluded($product, $ennoTab)
)
{
$ennoTabs->remove($ennoTabKey);
continue;
}
$tabContentLength = 0;
$productManufacturer = $product->getManufacturer();
$productManufacturerTranslated = $productManufacturer ? $productManufacturer->getTranslated() : [];
$tabProductCustomFields = $ennoTab->getProductCustomFields();
if($tabProductCustomFields->count() > 0)
{
$this->removeDeletedCustomFields($tabProductCustomFields);
$tabProductCustomFields->sort(function($one,$two){
$a = $one->getCustomField()->getConfig()["customFieldPosition"];
$b = $two->getCustomField()->getConfig()["customFieldPosition"];
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
});
$productCustomFields = $productTranslatedFields['customFields'];
$locale = $event->getRequest()->getLocale();
$defaultLocale = $event->getRequest()->getDefaultLocale();
$tabProductCustomFieldsIterator = $tabProductCustomFields->getIterator();
foreach ($tabProductCustomFieldsIterator as $customFieldKey => $tabCustomField)
{
$customFieldName = $tabCustomField->getCustomFieldName();
$customFieldValue = isset($productCustomFields[$customFieldName]) ? $productCustomFields[$customFieldName] : '';
if( $customFieldValue !== '' || ( $ennoTab->getCustomFieldsAsTable() && !$ennoTab->getCustomFieldsTableHideEmpty() ) )
{
$customFieldSetLabels = $tabCustomField->getCustomField()->getCustomFieldSet()->getConfig()['label'];
$customFieldSetLabel = '';
if ( array_key_exists($locale, $customFieldSetLabels) )
{
$customFieldSetLabel = $customFieldSetLabels[$locale];
}
else if ( array_key_exists($defaultLocale, $customFieldSetLabels) )
{
$customFieldSetLabel = $customFieldSetLabels[$defaultLocale];
}
$customFieldLabels = $tabCustomField->getCustomField()->getConfig()['label'];
$customFieldLabel = '';
if ( array_key_exists($locale, $customFieldLabels) )
{
$customFieldLabel = $customFieldLabels[$locale];
}
else if ( array_key_exists($defaultLocale, $customFieldLabels) )
{
$customFieldLabel = $customFieldLabels[$defaultLocale];
}
$customFieldType = $tabCustomField->getCustomField()->getConfig()['customFieldType'];
$customFieldTitle = '';
$customFieldAlt = '';
if($customFieldType === 'media' && $customFieldValue !== '')
{
$media = $this->mediaRepository->search(new Criteria([$customFieldValue]), $event->getContext())->get($customFieldValue);
if($media)
{
$customFieldValue = $media->getUrl();
$customFieldType = $media->getMediaType() ? strtolower($media->getMediaType()->getName()) : $media->getFileExtension();
$customFieldTitle = $media->getTitle() ? $media->getTitle() : $media->getFileName();
$customFieldAlt = $media->getAlt() ? $media->getAlt() : $customFieldTitle;
}
}
$tabCustomField->setCustomFieldInfo([
'value' => $customFieldValue,
'label' => $customFieldLabel,
'setLabel' => $customFieldSetLabel,
'type' => $customFieldType,
'title' => $customFieldTitle,
'alt' => $customFieldAlt,
]);
$tabContentLength += 1;
}
else
{
$tabProductCustomFields->remove($customFieldKey);
}
}
$ennoTab->setProductCustomFields($tabProductCustomFields);
}
if($ennoTab->getTemplateFile())
{
$ennoTab->setTemplateFile($this->normalizePath('storefront/page/product-detail/tabs/' . $ennoTab->getTemplateFile()));
$tabContentLength += 1;
}
$tabContentLength += (is_string($ennoTab->getHeadline()) ? 1 : 0);
$tabContentLength += (is_string($ennoTab->getContent()) ? 1 : 0);
$tabContentLength += ($ennoTab->getShowProperties() && $product->getSortedProperties()) ? 1 : 0;
$tabContentLength += ($ennoTab->getShowProperties() && $product->getSortedProperties()) ? 1 : 0;
$tabContentLength += ($ennoTab->getShowDescription() && is_array($productTranslatedFields) && array_key_exists('description', $productTranslatedFields) && $productTranslatedFields['description']) ? 1 : 0;
$tabContentLength += ($ennoTab->getShowManufacturer() && is_array($productManufacturerTranslated) && array_key_exists('description', $productManufacturerTranslated) && $productManufacturerTranslated['description']) ? 1 : 0;
$tabContentLength += ($ennoTab->getShowManufacturerImage() && $productManufacturer && $productManufacturer->getMedia() ) ? 1 : 0;
$tabContentLength += ($ennoTab->getShowReviews()) ? 1 : 0;
// $tabContentLength += ($tab['cmsSupportID']) ? 1 : 0;
// $tabContentLength += ($tab['showDownloads'] && $article['sDownloads']) ? 1 : 0;
// $tabContentLength += ($tab['showLinks'] && $article['sLinks']) ? 1 : 0;
if($hideEmpty && $tabContentLength <= 0)
{
$ennoTabs->remove($ennoTabKey);
}
if(!$ennoTab->getSorting())
{
$ennoTab->setSorting("h,c,d,p,f,m,r");
}
}
$showCrossSelling = $this->systemConfigService->get('EnnoTabsAdvanced.config.crossSelling', $salesChannel->getId());
if ( $showCrossSelling && $product->getCmsPage() )
{
$crossSellings = $this->crossSellingRoute->load($product->getId(), new Request(), $event->getSalesChannelContext(), new Criteria());
$event->getPage()->setCrossSellings($crossSellings->getResult());
}
$event->getPage()->getProduct()->addExtension('ennoTabs',$ennoTabs );
}
}
private function isProductExcluded($product, $ennoTab)
{
$isProductListed = false;
if($ennoTab->getProductsList()->count() > 0)
{
$isProductListed = $ennoTab->getProductsList()->has( $product->getId() );
}
return $ennoTab->getProductsWhitelist() ? !$isProductListed:$isProductListed;
}
private function isCategoryExcluded($productCategories, $ennoTab)
{
$isCategoryListed = false;
if(is_array($productCategories) && !empty($productCategories))
{
$categoriesList = $ennoTab->getCategoriesList();
$categoriesListIterator = $categoriesList->getIterator();
foreach ($categoriesListIterator as $category)
{
if(in_array($category->getId(), $productCategories) )
{
$isCategoryListed = true;
break;
}
}
}
return $ennoTab->getCategoriesWhitelist() ? !$isCategoryListed:$isCategoryListed;
}
private function removeDeletedCustomFields($tabProductCustomFields)
{
$tabProductCustomFieldsIterator = $tabProductCustomFields->getIterator();
foreach ($tabProductCustomFieldsIterator as $customFieldKey => $tabCustomField)
{
if(!$tabCustomField->getCustomField())
{
$tabProductCustomFields->remove($customFieldKey);
}
}
return $tabProductCustomFields;
}
private function normalizePath($path) {
return array_reduce(
explode('/', $path),
function($a, $b)
{
if($a === 0)
$a = "/";
if($b === "" || $b === ".")
return $a;
if($b === "..")
return dirname($a);
return preg_replace("/\/+/", "/", "$a/$b");
},
0
);
}
}