Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Shopware Ergonode Integration

## Our modification devEcommerce
- Change php-graphql-client (not compatible with psr/http-message^2.0)
- **Variants**:
- Fix adding new variants (wrong grouping)
- Full inheritance for variants
- **Attributes**:
- Hide attributes with hide metadata value
- Disable default filterable attribute for new attributes
- Add filterProductsNotMatchingSkuPattern (filter not products and parts)
- Languages - updates only active languages
- Category: inject the main category as tree root
- Images: leave the original name as a prefix
- **Change default**
- DEFAULT_STOCK_VALUE to "0"
- DEFAULT_GROSS_PRICE to "99999"
- minPurchaseMapping to "1"
- Use only selected brands (temporary)

## Description

This plugin synchronizes data from Ergonode to Shopware. It takes advantage of Ergonode's GraphQL API and utilizes
Expand Down Expand Up @@ -119,4 +137,4 @@ Available cache pools:
|------------------|-------------|
| 6.6 from 6.6.0.0 | Version 3.x |
| 6.5 from 6.5.0.0 | Version 2.x |
| 6.4 from 6.4.0.0 | Version 1.x |
| 6.4 from 6.4.0.0 | Version 1.x |
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ergonode/integration-shopware",
"description": "Shopware Ergonode Integration",
"version": "3.0.1",
"version": "3.0.10-patch",
"type": "shopware-platform-plugin",
"license": "proprietary",
"authors": [
Expand All @@ -24,9 +24,9 @@
"require": {
"php": ">= 8.2",
"ext-json": "*",
"shopware/administration": "6.6.*",
"shopware/core": "6.6.*",
"gmostafa/php-graphql-client": "^1.13"
"shopware/administration": ">=6.6.0 <6.7.0",
"shopware/core": ">=6.6.0 <6.7.0",
"carnage/php-graphql-client": "^1.14"
},
"require-dev": {
"phpunit/phpunit": "~9.5.17",
Expand Down
11 changes: 8 additions & 3 deletions src/DTO/ProductShopwareData.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function setMedia(array $payloads): void
$this->data['media'] = $payloads;
}

public function setTax(string $taxId): void
public function setTax(?string $taxId): void // devEcommerce change
{
$this->data['taxId'] = $taxId;
}
Expand Down Expand Up @@ -148,7 +148,7 @@ public function setProductNumber(string $sku): void
$this->data['productNumber'] = $sku;
}

public function setPrice(array $pricePayload): void
public function setPrice(?array $pricePayload): void // devEcommerce change
{
$this->data['price'] = $pricePayload;
}
Expand All @@ -170,7 +170,12 @@ public function addChild(ProductShopwareData $productShopwareData): void

public function setDisplayParent(bool $display = true): void
{
$this->data['displayParent'] = $display;
$this->data['variantListingConfig'] = [ // devEcommerce change
'extensions' => [],
'displayParent' => $display,
'mainVariantId' => null,
'configuratorGroupConfig' => null
];
}

public function addConfigrationSettings(array $configurationSettings): void
Expand Down
3 changes: 2 additions & 1 deletion src/Manager/FileManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ private function buildFileName(ProductMultimediaTranslation $image): string
'url' => $image->getUrl(),
];

return md5(json_encode($imageData));
//return md5(json_encode($imageData));
return pathinfo($imageData['name'], PATHINFO_FILENAME) . '_' . pathinfo($imageData['url'], PATHINFO_FILENAME); // devEcommerce change
}
}
16 changes: 16 additions & 0 deletions src/Persistor/ProductPersistor.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ public function persist(array $productListData, Context $context): array

$productListData = $this->filterMainProducts($productListData);

$productListData = $this->filterProductsNotMatchingSkuPattern($productListData); // devEcommerce change

foreach ($productListData as $productData) {
$mainProductPayload = $this->getProductPayload($productData['node'] ?? [], $context);
if (
Expand Down Expand Up @@ -306,6 +308,20 @@ private function filterMainProducts(array $productListData): array
);
}

// start devEcommerce change
private function filterProductsNotMatchingSkuPattern(array $productListData): array
{
return array_values(
array_filter(
$productListData,
static function (array $productData): bool {
return preg_match('/^V[0-9]+$/', $productData['node']['sku']) === 1; // todo move to configuration
}
)
);
}
// stop devEcommerce change

private function extractSkus(array $productListData, bool $onlyVariants = false): array
{
foreach ($productListData as $productData) {
Expand Down
18 changes: 17 additions & 1 deletion src/Persistor/PropertyGroupPersistor.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Ergonode\IntegrationShopware\Processor\Attribute\AttributeCustomProcessorResolver;
use Ergonode\IntegrationShopware\Provider\PropertyGroupProvider;
use Ergonode\IntegrationShopware\Transformer\PropertyGroupTransformer;
use Ergonode\IntegrationShopware\Util\YesNo;
use Ergonode\IntegrationShopware\Service\ConfigService;
use Shopware\Core\Content\Property\PropertyGroupDefinition;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
Expand All @@ -33,7 +35,8 @@ public function __construct(
EntityRepository $propertyGroupOptionRepository,
PropertyGroupTransformer $propertyGroupTransformer,
PropertyGroupProvider $propertyGroupProvider,
AttributeCustomProcessorResolver $attributeCustomProcessorResolver
AttributeCustomProcessorResolver $attributeCustomProcessorResolver,
private ConfigService $configService
) {
$this->propertyGroupRepository = $propertyGroupRepository;
$this->propertyGroupOptionRepository = $propertyGroupOptionRepository;
Expand All @@ -57,6 +60,19 @@ public function persistStream(AttributeStreamResultsProxy $attributes, Context $
continue;
}

// start devEcommerce change
$skipMetaHideAttribute = false;
foreach ($node['metadata'] as $metadata) {
if (($metadata['key'] === $this->configService->getHideMetaDataKey() && YesNo::cast($metadata['value']))) {
$skipMetaHideAttribute = true;
break;
}
}
if ($skipMetaHideAttribute) {
continue;
}
// end devEcommerce change

$propertyGroup = $this->propertyGroupProvider->getPropertyGroupByMapping($code, $context);

$dto = new PropertyGroupTransformationDTO($node);
Expand Down
4 changes: 4 additions & 0 deletions src/Processor/Attribute/ManufacturerAttributeProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public function process(array $node, Context $context): void
$code = $option['code'];
$manufacturerEntity = $this->getExistingManufacturerEntity($code, $context);

if(!in_array($code, ['gymtek', 'outtec', 'kedica', 'queenfit', 'xride', 'luverno', 'stars' ])) { // devEcommerce change
continue;
}

$translations = [];
foreach ($option['name'] as $nameRow) {
$translations[IsoCodeConverter::ergonodeToShopwareIso($nameRow['language'])] = [
Expand Down
38 changes: 37 additions & 1 deletion src/Processor/CategoryTreeSyncProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function processStream(
$stopwatch->start('process');

try {
$leafEdges = $edge['node']['categoryTreeLeafList']['edges'] ?? [];
$leafEdges = $this->normalizeCategoryTreeEdges($edge);

$primaryKeys = $this->categoryTreePersistor->persistLeaves($leafEdges, $currentTreeCode, $context);
$this->categoryTreePersistor->markCategoriesAsActive($primaryKeys);
Expand Down Expand Up @@ -178,6 +178,42 @@ public function processStream(
return $counter;
}

/**
* devEcommerce change
*/
private function normalizeCategoryTreeEdges(mixed $edge): mixed
{
$leafEdges = $edge['node']['categoryTreeLeafList']['edges'] ?? [];
$categoryTreeCode = $edge['node']['code'];
$categoryTreeNames = $edge['node']['name'];
$mainEdgeKeys = array_keys(array_filter(
$leafEdges,
fn($row) => empty($row['node']['parentCategory'])
));

if(!empty($mainEdgeKeys)) {
$firstCategory = [
'node' => [
'category' => [
'code' => $categoryTreeCode,
'name' => $categoryTreeNames,
],
'parentCategory' => null,
]
];
array_unshift($leafEdges,$firstCategory);

foreach ($mainEdgeKeys as $key) {
$leafEdges[$key+1]['node']['parentCategory'] = ['code' => $categoryTreeCode];
}
}

file_put_contents('../custom/plugins/ergo_graph.log', print_r($mainEdgeKeys, true) . "\n-----\n" ,FILE_APPEND);
file_put_contents('../custom/plugins/ergo_graph.log', print_r($leafEdges, true) . "\n-----\n" ,FILE_APPEND);

return $leafEdges;
}

/**
* Gets ID of last existing top level category
*
Expand Down
3 changes: 3 additions & 0 deletions src/Provider/LanguageProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\Language\LanguageEntity;

class LanguageProvider
Expand Down Expand Up @@ -58,6 +59,8 @@ public function getActiveLocaleCodes(Context $context): array
{
$criteria = new Criteria();
$criteria->addAssociation('locale');
$criteria->addAssociation('swagLanguagePackLanguage'); // devEcommerce change
$criteria->addFilter(new EqualsFilter('swagLanguagePackLanguage.salesChannelActive', true)); // devEcommerce change

/** @var LanguageEntity[] $languages */
$languages = $this->languageRepository->search($criteria, $context);
Expand Down
5 changes: 5 additions & 0 deletions src/QueryBuilder/AttributeQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ protected function getAttributeSelectionSet(): array
->setSelectionSet([
'code',
'scope',
(new Query('metadata')) // devEcommerce change
->setSelectionSet([
'key',
'value',
]),
(new Query('name'))
->setSelectionSet([
'language',
Expand Down
5 changes: 5 additions & 0 deletions src/QueryBuilder/CategoryQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ public function buildTreeStream(
(new Query('node'))
->setSelectionSet([
'code',
(new Query('name')) // devEcommerce change
->setSelectionSet([
'value',
'language',
]),
(new Query('categoryTreeLeafList'))
->setArguments($categoryLeafArguments)
->setSelectionSet([
Expand Down
15 changes: 13 additions & 2 deletions src/Resources/config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@
</component>
</card>

<card>
<title>Fields configuration*</title>

<input-field type="text">
<name>hideMetaDataKey</name>
<defaultValue>ukryty_w_sklepie</defaultValue>
<label>Ergonode metadata key value - to hide an attribute</label>
<helpText>Enter the exact name of the metadata key used in Ergonode. Example: "ukryty_w_sklepie". When this key is set on an attribute, that attribute will be hidden in the storefront. This value is inherited by all sales channels.</helpText>
</input-field>
</card>

<card>
<title>Fields mapping</title>
<title lang="de-DE">Fields mapping</title>
Expand Down Expand Up @@ -80,8 +91,8 @@
</input-field>
</card>
<card>
<title>Product sync</title>
<title lang="de-DE">Product sync</title>
<title>Template sync</title>
<title lang="de-DE">Template sync</title>

<component name="ergonode-template-cms-page-mapping">
<name>templateLayoutMapping</name>
Expand Down
1 change: 1 addition & 0 deletions src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ services:
- '@Ergonode\IntegrationShopware\Transformer\ProductScaleUnitTransformer'
- '@Ergonode\IntegrationShopware\Transformer\ProductMinMaxQuantityTransformer'
- '@Ergonode\IntegrationShopware\Transformer\ProductLayoutTransformer'
- '@Ergonode\IntegrationShopware\Transformer\ProductCustomBusinessTransformer'

Ergonode\IntegrationShopware\Transformer\CategoryAttributesTransformerChain:
arguments:
Expand Down
7 changes: 7 additions & 0 deletions src/Service/ConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,11 @@ public function getTemplateLayoutMapping(): array
}, $value)
);
}

// start devEcommerce change
public function getHideMetaDataKey(): string
{
return $this->configService->getString(self::CONFIG_NAMESPACE . 'hideMetaDataKey');
}
// end devEcommerce change
}
43 changes: 43 additions & 0 deletions src/Transformer/ProductCustomBusinessTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace Ergonode\IntegrationShopware\Transformer;

use Ergonode\IntegrationShopware\DTO\ProductTransformationDTO;
use Ergonode\IntegrationShopware\Service\ConfigService;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;

class ProductCustomBusinessTransformer implements ProductDataTransformerInterface {
private ConfigService $configService;

public function __construct(ConfigService $configService) {
$this->configService = $configService;
}

public function transform(ProductTransformationDTO $productData, Context $context): ProductTransformationDTO {
$swData = $productData->getShopwareData();
$ergonodeData = $productData->getErgonodeData();
$sku = $ergonodeData->getSku();

if (preg_match('/^V[0-9]+_.+$/', $sku)) { // handle for good parts
// inherit from a parent
$swData->setName('');
$swData->setTax(null);
$swData->setPrice(null);
$swData->setData('isCloseout', null);
$swData->setData('shippingFree', null);
$swData->setData('markAsTopseller', null);
$swData->setData('minPurchase', null);
$swData->setData('purchaseSteps', null);
$swData->setData('active', null);
$swData->setProperties([]);
}

$productData->setShopwareData($swData);

return $productData;
}

}
2 changes: 1 addition & 1 deletion src/Transformer/ProductDefaultValuesTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class ProductDefaultValuesTransformer implements ProductDataTransformerInterface
{
private const DEFAULT_STOCK_VALUE = 999;
private const DEFAULT_STOCK_VALUE = 0;

private ConfigService $configService;

Expand Down
2 changes: 1 addition & 1 deletion src/Transformer/ProductMinMaxQuantityTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private function getMinPurchase(
$existingMinPurchase = $productData->getSwProduct()?->getMinPurchase();
// if unmapped, return current value
if ($minPurchaseMapping === false) {
return $existingMinPurchase;
return $existingMinPurchase ?? 1; // devEcommerce change
}

$minPurchase = $minPurchaseMapping?->getTranslation($defaultLanguage)?->getValue();
Expand Down
Loading