<?php declare(strict_types=1);
namespace HuebertAddOrderAttributes\Subscriber;
use HuebertAddOrderAttributes\Core\Content\Attribute\AttributeEntity;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemRemovedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Content\Media\MediaEntity;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPage;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPage;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Session\Session;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Page\Product\ProductPage;
use Shopware\Storefront\Page\Product\ProductPageCriteriaEvent;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class ProductSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
private $categoryRepository;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var SystemConfigService
*/
private $pluginConfig;
/**
* @var Session
*/
private $session;
/**
* @var EntityRepositoryInterface
*/
private $attributeRepository;
/**
* @var EntityRepositoryInterface
*/
private $productRepository;
/**
* @var EntityRepositoryInterface
*/
private $dependencyepository;
/**
* @var EntityRepositoryInterface
*/
private $mediaEntity;
/**
* @var EntityRepositoryInterface
*/
private $productStreamRepository;
/**
* @param EntityRepositoryInterface $categoryRepository
* @param RequestStack $requestStack
* @param SystemConfigService $pluginConfig
* @param Session $session
* @param EntityRepositoryInterface $attributeRepository
* @param EntityRepositoryInterface $productRepository
* @param EntityRepositoryInterface $mediaEntity
* @param EntityRepositoryInterface $dependencyepository
* @param EntityRepositoryInterface $productStreamRepository
*/
public function __construct(
EntityRepositoryInterface $categoryRepository,
RequestStack $requestStack,
SystemConfigService $pluginConfig,
Session $session,
EntityRepositoryInterface $attributeRepository,
EntityRepositoryInterface $productRepository,
EntityRepositoryInterface $mediaEntity,
EntityRepositoryInterface $dependencyepository,
EntityRepositoryInterface $productStreamRepository
)
{
$this->categoryRepository = $categoryRepository;
$this->requestStack = $requestStack;
$this->pluginConfig = $pluginConfig;
$this->session = $session;
$this->attributeRepository = $attributeRepository;
$this->productRepository = $productRepository;
$this->mediaEntity = $mediaEntity;
$this->dependencyepository = $dependencyepository;
$this->productStreamRepository = $productStreamRepository;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
ProductPageCriteriaEvent::class => 'onProductCriteria',
ProductPageLoadedEvent::class => 'onProductPageLoaded',
CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinish',
BeforeLineItemAddedEvent::class => 'onLineItemAdded',
BeforeLineItemRemovedEvent::class => 'beforeLineItemRemoved',
CheckoutCartPageLoadedEvent::class => 'onCartPage',
OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPage',
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutPage'
];
}
/**
* @param ProductPageCriteriaEvent $event
* @return void
*/
public function onProductCriteria(ProductPageCriteriaEvent $event): void
{
$event->getCriteria()->addAssociations(['attributes', 'categories', 'streams', 'streams.extensions.attributes']);
}
/**
* @param CheckoutFinishPageLoadedEvent $event
* @return void
*/
public function onCheckoutFinish(CheckoutFinishPageLoadedEvent $event)
{
$session = $this->session->all();
unset($session['huebert_attributes']);
$this->session->replace($session);
/**
* @var CheckoutCartPage $page
*/
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$page->assign([
'enabledPrices' => $enablePrices,
'separatedQuantity' => $separatedQuantity
]);
}
/**
* @param ProductPageLoadedEvent $event
* @return void
*/
public function onProductPageLoaded(ProductPageLoadedEvent $event): void
{
/**
* @var ProductPage $page
*/
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$previewImage = $this->pluginConfig->get('HuebertAddOrderAttributes.config.previewImage', $salesChannelId);
$widthImage = $this->pluginConfig->get('HuebertAddOrderAttributes.config.imageWidth', $salesChannelId);
$page->assign([
'session' => $this->session->all(),
'enabledPrices' => $enablePrices,
'separatedQuantity' => $separatedQuantity,
'previewImage' => $previewImage,
'imageWidth' => $widthImage
]);
$product = $page->getProduct();
$extensions = $product->getExtensions();
$attributesFromCategories = new EntityCollection();
// $categoryDependecyAttributes = new EntityCollection();
$attributeIds = [];
$attributeExists = (!empty($extensions['attributes']));
$attributeHasEntry = false;
// if(array_key_exists('attributes', $extensions)) {
$attributesFromCategories = $this->checkIfCategoriesHaveAttributes($product, $event->getContext(), $salesChannelId);
$attributesChild = $this->applyAttributesOnSubcategories($product, $event->getContext(), $event->getSalesChannelContext()->getSalesChannelId());
if($attributeExists) {
if(count($extensions['attributes']->getElements())) {
// $attributeHasEntry = true;
$attributesFromProduct = $extensions['attributes'];
// $attributesFromCategories = $this->sortAttributeEntities($attributesFromCategories);
// $product->assign([
// 'attributesFromProduct' => $attributesFromProduct
// ]);
if($attributesFromProduct) {
foreach ($attributesFromProduct as $child) {
$attributesFromCategories->add($child);
}
}
}
}
if($attributesChild != null) {
foreach ($attributesChild as $child) {
$attributesFromCategories->add($child);
}
}
$attributesFromDynamic = $this->getAttributesByProductStream($product, $event->getContext(), $attributesFromCategories);
if($attributesFromDynamic != null) {
foreach ($attributesFromDynamic as $child) {
$attributesFromCategories->add($child);
}
}
$productStreamDependencies = new EntityCollection();
$productStreamDependencies = $this->getProductStreamDependecnies($product, $event->getContext(), $attributesFromDynamic);
if($productStreamDependencies->count() > 0) {
foreach ($productStreamDependencies as $attribute) {
if ($attribute->hasExtension('dependencies')) {
foreach ($attribute->getExtension('dependencies') as $key => $value) {
if ($attributesFromCategories->has($key)) {
$attributesFromCategories->remove($key);
}
}
}
}
}
// }
// }
if($attributesFromCategories->count() > 0 || $productStreamDependencies->count() > 0) {
$categoryDependecyAttributes = $this->getCategoryAttributes($product->getCategories(), $event->getContext(), $attributesFromCategories);
$applyDependencyOnSubcategories = $this->applyDependencyOnSubcategories($product, $event->getContext(), $salesChannelId);
if($applyDependencyOnSubcategories != null) {
foreach ($applyDependencyOnSubcategories as $dependency) {
$categoryDependecyAttributes->add($dependency);
}
}
$applyDependencyOnParent = $this->applyDependencyOnParentCategories($product, $event->getContext(),$salesChannelId);
if($applyDependencyOnParent != null) {
foreach ($applyDependencyOnParent as $dependency) {
$categoryDependecyAttributes->add($dependency);
}
}
if($categoryDependecyAttributes) {
foreach ($categoryDependecyAttributes as $attribute) {
if ($attribute->hasExtension('dependencies')) {
foreach ($attribute->getExtension('dependencies') as $key => $value) {
if ($attributesFromCategories->has($key)) {
$attributesFromCategories->remove($key);
}
}
}
}
}
$criteria = new Criteria();
$productId = $product->getId();
if($product->getParentId()){
$productId = $product->getParentId();
}
$criteria->addFilter(new EqualsFilter('productId', $productId));
$productDependencies = $this->dependencyepository->search($criteria, $event->getContext())->getEntities();
$dependenciesAttributes = new EntityCollection();
foreach ($productDependencies as $dependency ){
$dependencies = new EntityCollection();
$dependenciesAttributes->add($dependency);
foreach ($dependency['attributes'] as $attr) {
if ( $attributesFromCategories->has($attr)) {
$dependencies->add($attributesFromCategories->get($attr));
$attributesFromCategories->remove($attr);
}
}
$dependenciesAttributes->get($dependency->getId())->addExtension('dependencies', $dependencies);
}
$attributesFromCategories = $this->sortAttributeEntities($attributesFromCategories);
$product->assign([
'attributesFromCategories' => $attributesFromCategories,
'dependenciesAttributes' => $dependenciesAttributes,
'categoryAttributes' => $categoryDependecyAttributes,
'productStreamDependencies' => $productStreamDependencies
]);
}
}
/**
* @param BeforeLineItemAddedEvent $event
* @return void
*/
public function onLineItemAdded(BeforeLineItemAddedEvent $event)
{
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$lineItem = $event->getLineItem();
$lineItemId = $lineItem->getId();
$cart = $event->getCart();
$attributes = [];
$session = $this->session;
$sessionVars = $this->session->all();
$request = $this->requestStack->getCurrentRequest();
/**
* @var ParameterBag $requestBag
*/
$requestBag = $request->request;
$requestValues = $requestBag->all();
if(!empty($requestValues['lineItems'])) {
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$lineItem = $requestValues['lineItems'];
foreach ($lineItem as $item) {
$firstItem = $item;
break;
}
$addedQuantity = $firstItem['quantity'];
if ((isset($requestValues['attributes']) && array_key_first($requestValues['attributes']) === $lineItemId) || (isset($requestValues['dependencies']) && array_key_first($requestValues['dependencies']) === $lineItemId)) {
$uuid = Uuid::randomHex();
$attributesInRequest = array_shift($requestValues['attributes']);
$attributeEntities = $this->getEntiesOfAttributes($attributesInRequest, $event->getContext());
$dependenciesEntitiesFormat = [];
if (isset($requestValues['dependencies'])) {
$dependenciesEntitiesFormat = $this->formatDependencies($requestValues['dependencies'], $lineItemId);
}
//IF QUANTITY IS NOT SEPARATED
if($enablePrices && !$separatedQuantity) {
$arryAttributes = [];
foreach ($attributeEntities as $key => $attribute) {
$lineItemParam = $this->requestStack->getCurrentRequest()->get('lineItems');
$this->updateLineItem($lineItemParam, $event->getLineItem());
$arryAttributes[$lineItemId][$uuid][$key] = [
'name' => $attribute['name'],
'order' => $attribute['entity']->getOrder()
];
if (isset($attribute['value']['attributes_with_prices'])) {
foreach ($attribute['value']['attributes_with_prices'] as $key => $value) {
$attributeName = $key;
$payloadAttribute = [];
if (is_array($value)) {
foreach ($value as $k => $v) {
$payloadAttribute[$attributeName][$k]['price'] = $v;
}
} else {
$array = explode('--', $value);
$payloadAttribute[$attributeName][$array[0]]['price'] = $array[1];
}
$arryAttributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['attributes_with_prices'] = $payloadAttribute;
}
} else {
//FIELD WITHOUT PRICES
if(isset($attribute['value']['media'])){
if($attribute['value']['media'] == "" || $attribute['value']['media'] == null){
unset($arryAttributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
}
if($attribute['value']['media']!=null){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $attribute['value']['media']));
$mediaEntityVar = $this->mediaEntity->search($criteria, $event->getContext())->first();
$arryAttributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['media'] = $mediaEntityVar;
}
}else {
$arryAttributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value'] = $attribute['value'];
if(isset($attribute['value'])) {
if($attribute['value']== "" || $attribute['value'] == null){
unset($arryAttributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
}
}
}
}
$event->getLineItem()->setPayloadValue('huebert_attributes', $arryAttributes);
$event->getLineItem()->setPayloadValue('dependencies', $dependenciesEntitiesFormat);
}
} else {
if ($this->checkSessionForExistingAttributes($sessionVars)) {
$attributes = $sessionVars['huebert_attributes'];
if ($uuidOfSame = $this->checkForSameAttributePair($attributeEntities, $attributes, $lineItemId, $salesChannelId)) {
if (!empty($attributes[$lineItemId][$uuidOfSame]['quantity'])) {
if (count($attributes[$lineItemId][$uuidOfSame]) > 1) {
$attributes[$lineItemId][$uuidOfSame]['quantity'] = ((int)$attributes[$lineItemId][$uuidOfSame]['quantity'] + (int)$addedQuantity);
}
} else {
$attributes[$lineItemId][$uuidOfSame]['quantity'] = $addedQuantity;
}
$this->session->set('huebert_attributes', $attributes);
} else {
foreach ($attributeEntities as $key => $attribute) {
if (!empty($attribute)) {
$attributes[$lineItemId][$uuid][$key] = [
'name' => $attribute['name'],
'order' => $attribute['entity']->getOrder(),
'value' => $attribute['value']
];
if (is_array($attribute['value'])) {
//IF QUANTITY IS NOT SEPARATED
if ($enablePrices && !$separatedQuantity) {
if (isset($attribute['value']['attributes_with_prices'])) {
foreach ($attribute['value']['attributes_with_prices'] as $key => $value) {
$attributeName = $key;
$payloadAttribute = [];
if (is_array($value)) {
foreach ($value as $k => $v) {
$payloadAttribute[$attributeName][$k]['price'] = $v;
}
} else {
$array = explode('--', $value);
$payloadAttribute[$attributeName][$array[0]]['price'] = $array[1];
}
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['attributes_with_prices'] = $payloadAttribute;
}
} else {
//IF QUANTITY IS NOT SEPARATED AND NOT WITH PRICES
if(isset($attribute['value']['media'])){
if($attribute['value']['media'] == "" || $attribute['value']['media'] == null){
unset( $attributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
} if($attribute['value']['media']!=null){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $attribute['value']['media']));
/**
* @var MediaEntity
*/
$mediaEntityVar = $this->mediaEntity->search($criteria, $event->getContext())->first();
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['media'] = $mediaEntityVar;
}
}else{
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value'] = implode(",", $attribute['value']);
}
}
} else {
//IF QUANTITY IS SEPARATED
if(isset($attribute['value']['media'])){
if($attribute['value']['media'] == "" || $attribute['value']['media'] == null){
unset( $attributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
}
if($attribute['value']['media']!=null){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $attribute['value']['media']));
/**
* @var MediaEntity
*/
$mediaEntityVar = $this->mediaEntity->search($criteria, $event->getContext())->first();
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['media'] = $mediaEntityVar;
}
}else{
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value'] = implode(",", $attribute['value']);
}
}
}
}
}
if (!empty($attributes[$lineItemId][$uuid])) {
$attributes[$lineItemId][$uuid]['quantity'] = $addedQuantity;
$this->session->set('huebert_attributes', $attributes);
}
}
} else {
$isEmpty = true;
foreach ($attributeEntities as $attribute) {
if (!empty($attribute['value'])) {
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()] = [
'name' => $attribute['name'],
'order' => $attribute['entity']->getOrder(),
'value' => $attribute['value']
];
if (is_array($attribute['value'])) {
//IF QUANTITY IS NOT SEPARATED
if ($enablePrices && !$separatedQuantity) {
if (isset($attribute['value']['attributes_with_prices'])) {
$lineItemParam = $this->requestStack->getCurrentRequest()->get('lineItems');
$product = $this->getProduct($event, $event->getLineItem());
$this->updateLineItem($lineItemParam, $event->getLineItem(), $product);
foreach ($attribute['value']['attributes_with_prices'] as $key => $value) {
$attributeName = $key;
$payloadAttribute = [];
if (is_array($value)) {
foreach ($value as $k => $v) {
$payloadAttribute[$attributeName][$k]['price'] = $v;
}
} else {
$array = explode('--', $value);
$payloadAttribute[$attributeName][$array[0]]['price'] = $array[1];
}
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['attributes_with_prices'] = $payloadAttribute;
}
} else {
//IF QUANTITY IS NOT SEPARATED AND NOT WITH PRICES
if(isset($attribute['value']['media'])){
if($attribute['value']['media'] == "" || $attribute['value']['media'] == null){
unset( $attributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
}
if($attribute['value']['media']!=null){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $attribute['value']['media']));
/**
* @var MediaEntity
*/
$mediaEntityVar = $this->mediaEntity->search($criteria, $event->getContext())->first();
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['media'] = $mediaEntityVar;
}
}else{
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value'] = implode(",", $attribute['value']);
}
}
} else {
//IF QUANTITY IS SEPARATED
if(isset($attribute['value']['media'])){
if($attribute['value']['media'] == "" || $attribute['value']['media'] == null){
unset( $attributes[$lineItemId][$uuid][$attribute['entity']->getId()]);
}
if($attribute['value']['media']!=null){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $attribute['value']['media']));
/**
* @var MediaEntity
*/
$mediaEntityVar = $this->mediaEntity->search($criteria, $event->getContext())->first();
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value']['media'] = $mediaEntityVar;
}
}else{
$attributes[$lineItemId][$uuid][$attribute['entity']->getId()]['value'] = implode(",", $attribute['value']);
}
}
}
$isEmpty = false;
}
}
if (!$isEmpty) {
$attributes[$lineItemId][$uuid]['quantity'] = $addedQuantity;
$this->session->set('huebert_attributes', $attributes);
}
}
}
}
if (!empty($attributes)) {
if($enablePrices && !$separatedQuantity) {
} else {
$this->assignAttributesToLineItems($cart, $attributes, $dependenciesEntitiesFormat);
}
}
// if($enablePrices && !$separatedQuantity) {
if($enablePrices && $separatedQuantity) {
//WITH PRICES
$lineItem = $event->getLineItem();
$lineItemParam = $this->requestStack->getCurrentRequest()->get('lineItems');
$attributesWithPrices = null;
if($lineItemParam) {
if (array_key_exists($lineItem->getId(), $lineItemParam)) {
foreach ($lineItemParam[$lineItem->getId()] as $key => $value) {
if ($key == 'attributes_with_prices') $attributesWithPrices = $value;
}
}
if ($attributesWithPrices) {
$product = $this->getProduct($event, $lineItem);
$this->updateLineItem($lineItemParam, $lineItem, $product);
$payloadAttribute = [];
foreach ($attributesWithPrices as $key => $value) {
$attributeName = $key;
if(is_array($value)) {
foreach ($value as $k => $v) {
$payloadAttribute[$attributeName][$k]['price'] = $v;
$payloadAttribute[$attributeName][$k]['quantity'] = 1;
}
} else {
$array = explode('--', $value);
$payloadAttribute[$attributeName][$array[0]]['price'] = $array[1];
$payloadAttribute[$attributeName][$array[0]]['quantity'] = 1;
}
}
$lineItem->setPayloadValue('attributes_with_prices', $payloadAttribute);
}
}
}
}
}
/**
* @param BeforeLineItemAddedEvent $event
* @param LineItem $lineItem
* @return ProductEntity
* @throws InconsistentCriteriaIdsException
*/
private function getProduct(BeforeLineItemAddedEvent $event, LineItem $lineItem): ProductEntity
{
$productCollection = $this->productRepository->search(new Criteria([
$lineItem->getReferencedId()
]), $event->getContext());
if ($productCollection->count() === 1) {
/** @var ProductEntity $product */
$product = $productCollection->first();
}
return $product;
}
/**
* @param array $lineItemParam
* @param LineItem $lineItem
* @param ProductEntity $product
* @return array
*/
private function updateLineItem(array $lineItemParam, LineItem $lineItem, ProductEntity $product = null): array
{
//set new ID
$newId = Uuid::randomHex();
if(isset($lineItemParam[$lineItem->getId()])) {
$lineItemParam[$newId] = $lineItemParam[$lineItem->getId()];
$lineItem->setId($newId);
}
return $lineItemParam;
}
/**
* @param BeforeLineItemRemovedEvent $event
* @return void
*/
public function beforeLineItemRemoved(BeforeLineItemRemovedEvent $event)
{
$lineItem = $event->getLineItem();
$lineItemId = $lineItem->getId();
if(!empty($this->session->get('huebert_attributes'))) {
$attributes = $this->session->all();
unset($attributes['huebert_attributes'][$lineItemId]);
$this->session->replace($attributes);
}
}
/**
* @param $session
* @return bool
*/
private function checkSessionForExistingAttributes($session): bool
{
if(!empty($session['huebert_attributes'])) {
return true;
}
return false;
}
/**
* @param $cart
* @param $attributes
* @param $dependenciesEntitiesFormat
* @return void
*/
private function assignAttributesToLineItems($cart, $attributes, $dependenciesEntitiesFormat)
{
/**
* @var Cart $cart
*/
$lineItems = $cart->getLineItems();
foreach($lineItems as $lineItem) {
if(!empty($attributes[$lineItem->getId()])) {
$payload = $lineItem->getPayload();
foreach($attributes[$lineItem->getId()] as $key => $attributeContainer) {
foreach($attributeContainer as $_key => $attribute) {
if(is_array($attribute)) {
$attributes[$lineItem->getId()][$key][$_key] = $attribute;
}
}
}
$payload['huebert_attributes'] = $attributes[$lineItem->getId()];
$lineItem->setPayload($payload);
$lineItem->setPayloadValue('dependencies', $dependenciesEntitiesFormat);
}
}
}
/**
* @param $product
* @param $context
* @param $salesChannelId
* @return EntityCollection|null
*/
private function checkIfCategoriesHaveAttributes($product, $context, $salesChannelId): ?EntityCollection
{
$includeParent = $this->pluginConfig->get('HuebertAddOrderAttributes.config.includeParentCategory', $salesChannelId);
$categories = $product->getCategories();
$categoriesCollection = new EntityCollection();
if(empty($categories)) {
return $categoriesCollection;
}
if(empty($categories->getIds())) {
return $categoriesCollection;
}
$criteria = new Criteria();
$criteria->addAssociations(['categorys']);
$criteria->addFilter(new EqualsAnyFilter('categorys.id', $categories->getIds()));
$categoryResult = $this->attributeRepository->search($criteria, $context);
foreach ($categoryResult as $category){
$categoriesCollection->add($category);
}
if($includeParent) {
// $parentCategoryIds = [];
// /**
// * @var CategoryEntity $category
// */
// foreach($categoryResult->getEntities() as $category) {
// $categories->add($category);
// if(!is_null($category->getParentId())) {
// $parentCategoryIds[] = $category->getParentId();
// }
// }
// if(!empty($parentCategoryIds)) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('parentId', $categories->getIds()));
$result = $this->categoryRepository->search($criteria, $context)->getIds();
$criteria = new Criteria();
$criteria->addAssociations(['categorys']);
$criteria->addFilter(new EqualsAnyFilter('categorys.id', $result));
$categoryResults = $this->attributeRepository->search($criteria, $context);
foreach ($categoryResults as $category){
$categoriesCollection->add($category);
}
// }
}
return $categoriesCollection;
}
/**
* @param SalesChannelProductEntity $product
* @param $context
* @param EntityCollection $attributes
* @return EntityCollection|null
*/
private function getAttributesByProductStream(SalesChannelProductEntity $product, $context, EntityCollection $attributes): ?EntityCollection
{
$attributeIds = [];
$productId = $product->getId();
if($product->getParentId()) {
$productId = $product->getParentId();
}
if($productId){
$mappingCriteria = new Criteria();
$mappingCriteria->addFilter(new EqualsFilter('id', $productId));
$mappingCriteria->addAssociation('productStreams');
$mappingCriteria->addAssociation('productStreams.attributes');
$mappingCriteria->addAssociation('productStreams.mapping');
$product = $this->productRepository->search($mappingCriteria, $context)->getElements();
$productStreamsIds = [];
foreach ($product as $item) {
$productStreamsIds = $item->getStreamIds();
}
if($productStreamsIds) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('id', $productStreamsIds));
$criteria->addAssociation('attributes');
$productStreams = $this->productStreamRepository->search($criteria, $context);
if(!empty($productStreams)) {
foreach($productStreams as $productStream) {
$attributesExtension = $productStream->getExtension('attributes');
if($attributesExtension) {
/**
* @var AttributeEntity $attribute
*/
foreach ($attributesExtension as $attribute) {
if(!in_array($attribute->getId(), $attributeIds)) {
$attributes->add($attribute);
$attributeIds[] = $attribute->getId();
}
}
}
}
}
}
}
return $attributes;
}
/**
* @param $attributes
* @param $context
* @return array
*/
private function getEntiesOfAttributes($attributes, $context)
{
$returnData = [];
foreach ($attributes as $id => $attribute) {
/** @var AttributeEntity $entity */
$entity = $this->attributeRepository->search(new Criteria([$id]), $context)->first();
$returnData[$id] = [
'value' => $attribute,
'name' => $entity->getName(),
'entity' => $entity
];
}
return $returnData;
}
/**
* @param $attributesInRequest
* @param $attributes
* @param $lineItemIdAdded
* @param $salesChannelId
* @return false|int|string
*/
private function checkForSameAttributePair($attributesInRequest, $attributes, $lineItemIdAdded, $salesChannelId)
{
if(empty($attributesInRequest) || empty($attributes)) {
return false;
}
foreach($attributes as $key => $lineItem) {
foreach($lineItem as $_key => $lineItemAttributes) {
foreach ($lineItemAttributes as $__key => $attribute) {
if ($__key === 'quantity') {
continue;
}
if(is_array($attribute['value'])) {
$attributes[$key][$_key][$__key] = $attribute;
}
}
}
}
foreach ($attributesInRequest as $key => $attribute) {
if ($key === 'quantity') {
continue;
}
$attributesInRequest[$key] = [
'name' => $attribute['name'],
'order' => $attribute['entity']->getOrder(),
'value' => $attribute['value']
];
if(is_array($attribute['value'])) {
//IF QUANTITY IS NOT SEPARATED
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
if($enablePrices && !$separatedQuantity) {
if (isset($attribute['value']['attributes_with_prices'])) {
foreach ($attribute['value']['attributes_with_prices'] as $key1 => $value1) {
$attributeName = $key1;
$payloadAttribute = [];
if (is_array($value1)) {
foreach ($value1 as $k => $v) {
$payloadAttribute[$attributeName][$k]['price'] = $v;
}
} else {
$array = explode('--', $value1);
$payloadAttribute[$attributeName][$array[0]]['price'] = $array[1];
}
$attributesInRequest[$key]['value']['attributes_with_prices'] = $payloadAttribute;
}
} else {
//IF QUANTITY IS NOT SEPARATED AND NOT WITH PRICES
$attributesInRequest[$key]['value'] = implode(",", $attribute['value']);
}
} else {
//IF QUANTITY IS SEPARATED
$attributesInRequest[$key]['value'] = implode(",", $attribute['value']);
}
// $attributesInRequest[$key]['value'] = implode(",", $attribute['value']);
}
}
foreach($attributes as $lineItemId => $lineItem) {
if(!empty($lineItem) && $lineItemId === $lineItemIdAdded) {
foreach($lineItem as $key => $lineItemAttributes) {
$diffResult = $this->array_multi_diff($lineItemAttributes, $attributesInRequest);
unset($diffResult['quantity']);
if(count($diffResult) == 0) {
return $key;
}
}
}
}
return false;
}
/**
* @param $array1
* @param $array2
* @return array
*/
private function array_multi_diff( $array1, $array2 )
{
$result = array();
foreach( $array1 as $key => $a1 ) {
if( !is_array($array2) || !array_key_exists( $key, $array2 ) ) {
$result[ $key ] = $a1;
continue;
}
$a2 = $array2[ $key ];
if( is_array( $a1 ) ) {
$recc_array = $this->array_multi_diff( $a1, $a2 );
if( !empty( $recc_array ) ) {
$result[ $key ] = $recc_array;
}
}
else if( $a1 != $a2 ) {
$result[ $key ] = $a1;
}
}
return $result;
}
/**
* @param EntityCollection $attributeEntities
*/
private function sortAttributeEntities(EntityCollection $attributeEntities) {
$switchCollection = new EntityCollection();
$attributeEntitiesCount = count($attributeEntities->getElements());
$i = 0;
while(count($switchCollection->getElements()) != $attributeEntitiesCount) {
foreach($attributeEntities as $attributeEntity) {
if($attributeEntity->getOrder() == $i) {
$switchCollection->add($attributeEntity);
}
}
$i++;
}
return $switchCollection;
}
public function onOffcanvasCartPage(OffcanvasCartPageLoadedEvent $event): void
{
/**
* @var OffcanvasCartPage $page
*/
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$page = $event->getPage();
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$page->assign([
'enabledPrices' => $enablePrices,
'separatedQuantity' => $separatedQuantity
]);
}
public function onCartPage(CheckoutCartPageLoadedEvent $event): void
{
/**
* @var CheckoutCartPage $page
*/
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$page->assign([
'enabledPrices' => $enablePrices,
'separatedQuantity' => $separatedQuantity
]);
}
public function onCheckoutPage(CheckoutConfirmPageLoadedEvent $event): void
{
/**
* @var CheckoutCartPage $page
*/
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannelId();
$enablePrices = $this->pluginConfig->get('HuebertAddOrderAttributes.config.enablePrices', $salesChannelId);
$separatedQuantity = $this->pluginConfig->get('HuebertAddOrderAttributes.config.separatedQuantity', $salesChannelId);
$page->assign([
'enabledPrices' => $enablePrices,
'separatedQuantity' => $separatedQuantity
]);
}
public function getCategoryAttributes($categories, $context, $attributes): EntityCollection
{
$attributesFromCategories = new EntityCollection();
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('categoryId', $categories->getIds()));
$categoryAttributes = $this->dependencyepository->search($criteria, $context)->getEntities();
foreach ($categoryAttributes as $categoryAttribute){
$dependecies = new EntityCollection();
$attributesFromCategories->add($categoryAttribute);
foreach ($categoryAttribute['categoryAttributes'] as $attr){
if($attributes->has($attr)) {
$dependecies->add($attributes->get($attr));
}
}
$attributesFromCategories->get($categoryAttribute->getId())->addExtension('dependencies', $dependecies);
}
return $attributesFromCategories;
}
public function applyAttributesOnSubcategories($product, $context, $salesChannelId): ?EntityCollection{
$includeChildren = $this->pluginConfig->get('HuebertAddOrderAttributes.config.includeChildCategories', $salesChannelId);
if($includeChildren) {
$categories = $product->getCategories();
if (empty($categories)) {
return null;
}
$breadCrumb = [];
foreach ($product->getCategoryTree() as $k) {
$breadCrumb[$k] = $k;
}
$criteria = new Criteria();
$criteria->addAssociations(['categorys']);
$criteria->addFilter(new EqualsAnyFilter('categorys.id', $breadCrumb));
$categoriess = $this->attributeRepository->search($criteria, $context);
$attributes = new EntityCollection();
foreach ($categoriess->getEntities() as $attr) {
$attributes->add($attr);
}
return $attributes;
}
return null;
}
public function applyDependencyOnSubcategories($product, $context, $salesChannelId): ?EntityCollection{
$includeChildren = $this->pluginConfig->get('HuebertAddOrderAttributes.config.includeChildCategories', $salesChannelId);
$attributesFromCategories = new EntityCollection();
if($includeChildren) {
$categories = $product->getCategories();
if (empty($categories)) {
return null;
}
$breadCrumb = [];
foreach ($product->getCategoryTree() as $k) {
$breadCrumb[$k] = $k;
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('categoryId', $breadCrumb));
$categoryAttributes = $this->dependencyepository->search($criteria, $context)->getEntities();
$criteria1 = new Criteria();
$criteria1->addAssociations(['categorys']);
$criteria1->addFilter(new EqualsAnyFilter('categorys.id', $breadCrumb));
$attributes = $this->attributeRepository->search($criteria1, $context)->getEntities();
foreach ($categoryAttributes as $categoryAttribute){
$dependecies = new EntityCollection();
$attributesFromCategories->add($categoryAttribute);
foreach ($categoryAttribute['categoryAttributes'] as $attr){
if($attributes->has($attr)) {
$dependecies->add($attributes->get($attr));
}
}
$attributesFromCategories->get($categoryAttribute->getId())->addExtension('dependencies', $dependecies);
}
return $attributesFromCategories;
}
return null;
}
private function applyDependencyOnParentCategories($product, $context, $salesChannelId): ?EntityCollection {
$includeParent = $this->pluginConfig->get('HuebertAddOrderAttributes.config.includeParentCategory', $salesChannelId);
$categories = $product->getCategories();
$categoriesCollection = new EntityCollection();
if(empty($categories)) {
return null;
}
if(empty($categories->getIds())) {
return null;
}
if($includeParent) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('parentId', $categories->getIds()));
$result = $this->categoryRepository->search($criteria, $context)->getIds();
$criteria2 = new Criteria();
$criteria2->addFilter(new EqualsAnyFilter('categoryId',$result));
$categoryAttributes = $this->dependencyepository->search($criteria2, $context)->getEntities();
$criteria1 = new Criteria();
$criteria1->addAssociations(['categorys']);
$criteria1->addFilter(new EqualsAnyFilter('categorys.id', $result));
$categoryResults = $this->attributeRepository->search($criteria1, $context)->getEntities();
foreach ($categoryAttributes as $categoryAttribute){
$dependecies = new EntityCollection();
$categoriesCollection->add($categoryAttribute);
foreach ($categoryAttribute['categoryAttributes'] as $attr) {
if($categoryResults->has($attr)) {
$dependecies->add($categoryResults->get($attr));
}
}
$categoriesCollection->get($categoryAttribute->getId())->addExtension('dependencies', $dependecies);
}
return $categoriesCollection;
}
return null;
}
private function formatDependencies($dependencies, $lineItemId): array{
$dependenciesArray = [];
foreach ($dependencies[$lineItemId] as $key => $value) {
if ($value !== "") {
$data = explode("--", $value);
if($data[1] !== "0") {
$dependenciesArray[$key] = [
'name' => $data[0],
'price' => (float)$data[1]
];
}
}
}
return $dependenciesArray;
}
private function getProductStreamDependecnies($product, Context $context, ?EntityCollection $attributes)
{
$attributesFromStream= new EntityCollection();
$productId = $product->getId();
if($product->getParentId()) {
$productId = $product->getParentId();
}
if($productId) {
$mappingCriteria = new Criteria();
$mappingCriteria->addFilter(new EqualsFilter('id', $productId));
$mappingCriteria->addAssociation('productStreams');
$mappingCriteria->addAssociation('productStreams.attributes');
$mappingCriteria->addAssociation('productStreams.mapping');
$product = $this->productRepository->search($mappingCriteria, $context)->getElements();
$productStreamsIds = [];
foreach ($product as $item) {
$productStreamsIds = $item->getStreamIds();
}
if ($productStreamsIds) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsAnyFilter('productStreamId', $productStreamsIds));
$productStreamAttribues = $this->dependencyepository->search($criteria, $context)->getEntities();
foreach ($productStreamAttribues as $streamAttribute) {
$dependecies = new EntityCollection();
$attributesFromStream->add($streamAttribute);
foreach ($streamAttribute['productStreamAttributes'] as $attr) {
if ($attributes->has($attr)) {
$dependecies->add($attributes->get($attr));
}
}
$attributesFromStream->get($streamAttribute->getId())->addExtension('dependencies', $dependecies);
}
}
}
return $attributesFromStream;
}
}