diff --git a/Converter/ArrayToXmlConverter.php b/Converter/ArrayToXmlConverter.php
index 5c102fe..ba00b13 100644
--- a/Converter/ArrayToXmlConverter.php
+++ b/Converter/ArrayToXmlConverter.php
@@ -21,7 +21,8 @@ public function convert(array $rows): string
$xml .= $this->getCreationTimeTag() . PHP_EOL;
foreach ($rows as $row) {
- $xml .= $this->getItem($row) . PHP_EOL;
+ $pattern = "/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/";
+ $xml .= preg_replace($pattern, "\n", $this->getItem($row)) . PHP_EOL;
}
$xml .= $this->getCloseRootTag();
@@ -56,14 +57,15 @@ private function getItem(array $row): string
-
-
-
-
-
-
+ {$this->getOptionalProductAttr($row, 'manufacturer', 'brand')}
+ {$this->getOptionalProductAttr($row, 'ean', 'gtin')}
+ {$this->getOptionalProductAttr($row, 'color')}
+ {$this->getOptionalProductAttr($row, 'gender')}
+ {$this->getOptionalProductAttr($row, 'material')}
+ {$this->getOptionalProductAttr($row, 'size')}
+ {$this->getOptionalProductAttr($row, 'pattern')}
{$this->getProductDetail($row['product_detail'])}
{$this->getShipping($row['shipping'])}
{$this->getAdditionalImageLinks($row['additional_image_link'])}
@@ -71,6 +73,24 @@ private function getItem(array $row): string
XML;
}
+ /**
+ * @param array $row
+ * @param string $attrKey
+ * @param string $tagKey
+ *
+ * @return string
+ */
+ private function getOptionalProductAttr(array $row, string $attrKey, string $tagKey = ''): string
+ {
+ if ($tagKey === '') {
+ $tagKey = $attrKey;
+ }
+ if (!empty($row[$attrKey])) {
+ return "";
+ }
+ return '';
+ }
+
private function getAdditionalImageLinks(array $imageLinks): string
{
$result = '';
diff --git a/DataProvider/AttributeHandlers/ProductTypeProvider.php b/DataProvider/AttributeHandlers/ProductTypeProvider.php
new file mode 100644
index 0000000..db46be4
--- /dev/null
+++ b/DataProvider/AttributeHandlers/ProductTypeProvider.php
@@ -0,0 +1,68 @@
+categoryRepository = $categoryRepository;
+ }
+
+ public function get(Product $product)
+ {
+ return $this->getProductType($product);
+ }
+
+ /**
+ * @param Product $product
+ *
+ * @return string
+ */
+ private function getProductType(Product $product): string
+ {
+ $categoryIds = $product->getCategoryIds();
+ if (empty($categoryIds)) {
+ return '';
+ }
+
+ $categoryId = (int)$categoryIds[0];
+ if (array_key_exists($categoryId, $this->cache)) {
+ return $this->cache[$categoryId];
+ }
+
+ try {
+ $fullCategoryPath = '';
+ $category = $this->categoryRepository->get($categoryId, $product->getStoreId());
+ $pathInStore = $category->getPathInStore();
+ $pathIds = array_reverse(explode(',', $pathInStore));
+
+ $categories = $category->getParentCategories();
+
+ foreach ($pathIds as $categoryId) {
+ if (isset($categories[$categoryId]) && $categories[$categoryId]->getName()) {
+ $fullCategoryPath .= $categories[$categoryId]->getName() . ' > ';
+ }
+ }
+ $this->cache[$categoryId] = rtrim($fullCategoryPath, '> ');
+ return $this->cache[$categoryId];
+
+ } catch (NoSuchEntityException $noSuchEntityException) {
+ return '';
+ }
+ }
+}
\ No newline at end of file
diff --git a/Enum/AttributesToImportEnumInterface.php b/Enum/AttributesToImportEnumInterface.php
index 1f7544a..1eee410 100644
--- a/Enum/AttributesToImportEnumInterface.php
+++ b/Enum/AttributesToImportEnumInterface.php
@@ -16,6 +16,7 @@
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\ItemGroupIdProvider;
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\ManufacturerProvider;
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\MaterialProvider;
+use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\SizeProvider;
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\NameProvider;
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\PatternProvider;
use RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\PriceProvider;
@@ -72,6 +73,10 @@ interface AttributesToImportEnumInterface
AttributeConfigData::FIELD_NAME => 'material',
AttributeConfigData::ATTRIBUTE_HANDLER => MaterialProvider::class,
],
+ 'size' => [
+ AttributeConfigData::FIELD_NAME => 'size',
+ AttributeConfigData::ATTRIBUTE_HANDLER => SizeProvider::class,
+ ],
'material_cloth' => [
AttributeConfigData::FIELD_NAME => 'material_cloth',
AttributeConfigData::ATTRIBUTE_HANDLER => ManufacturerProvider::class,
diff --git a/README.md b/README.md
index 39cbf3a..9d05db3 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Generate feed with product data.
## Installations
```
-composer require run_as_root/ext-magento2-run_as_root-feed
+composer require run_as_root/ext-magento2-google-shopping-feed
bin/magento setup:upgrade
```
@@ -12,7 +12,7 @@ bin/magento setup:upgrade
### Feed generation
-Generate product feed every 15 minutes with minimal required attributes, for each storeview.
+Generate product feed every 2 hours with minimal required attributes, for each storeview.
Places file into `pub/run_as_root/feed/%s_store_%s_feed.csv`.
## Technical Specification
@@ -51,9 +51,9 @@ See configuration list here: `\RunAsRoot\GoogleShoppingFeed\Enum\AttributesToImp
Provides attribute data provider (handler) of type `\RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\AttributeHandlerInterface`, by `AttributeConfigData` DTO.
#### `\RunAsRoot\GoogleShoppingFeed\DataProvider\AttributeHandlers\AttributeHandlerInterface`
-Generic interface for attribute data prviders.
-Each attrbiute has its own data provider, that incapsulates current interface.
-Data provider for spcific attribute is configured here `\RunAsRoot\GoogleShoppingFeed\Enum\AttributesToImportEnumInterface::ATTRIBUTES`.
+Generic interface for attribute data providers.
+Each attribute has its own data provider, that incapsulates current interface.
+Data provider for specific attribute is configured here `\RunAsRoot\GoogleShoppingFeed\Enum\AttributesToImportEnumInterface::ATTRIBUTES`.
### Services
diff --git a/Test/Unit/Converter/ArrayToXmlConverterTest.php b/Test/Unit/Converter/ArrayToXmlConverterTest.php
index 599e20d..731739f 100644
--- a/Test/Unit/Converter/ArrayToXmlConverterTest.php
+++ b/Test/Unit/Converter/ArrayToXmlConverterTest.php
@@ -102,14 +102,11 @@ private function getExpectedResult(): string
+
+
-
-
-
-
-
diff --git a/Test/Unit/DataProvider/AttributeHandlers/ProductTypeProviderTest.php b/Test/Unit/DataProvider/AttributeHandlers/ProductTypeProviderTest.php
new file mode 100644
index 0000000..6310118
--- /dev/null
+++ b/Test/Unit/DataProvider/AttributeHandlers/ProductTypeProviderTest.php
@@ -0,0 +1,67 @@
+categoryRepositoryMock = $this->createMock(CategoryRepositoryInterface::class);
+ $this->productMock = $this->createMock(Product::class);
+
+ $this->sut = new ProductTypeProvider($this->categoryRepositoryMock);
+ }
+
+ public function testProductTypeInCaseOfEmptyCategoryIds(): void
+ {
+ $this->productMock->method('getCategoryIds')->willReturn([]);
+ $this->assertEquals('', $this->sut->get($this->productMock));
+ }
+
+ public function testProductTypeInCaseOfNonExistingCategory(): void
+ {
+ $this->productMock->method('getCategoryIds')->willReturn([1000]);
+ $this->categoryRepositoryMock->method('get')->willThrowException(new NoSuchEntityException());
+ $this->assertEquals('', $this->sut->get($this->productMock));
+ }
+
+ public function testProductTypeInCaseOfExistingCategory(): void
+ {
+ $this->productMock->method('getCategoryIds')->willReturn([10]);
+ $category = $this->createMock(Category::class);
+
+ $this->productMock->method('getStoreId')->willReturn(1);
+
+ $this->categoryRepositoryMock->method('get')->with(10)->willReturn($category);
+
+ $category->method('getPathInStore')->willReturn("10,2");
+
+ $parentCategory = $this->createMock(Category::class);
+ $category->method('getParentCategories')->willReturn([10 => $category, 2 => $parentCategory]);
+
+ $category->method('getName')->willReturn('Child Category Name');
+ $parentCategory->method('getName')->willReturn('Parent Category Name');
+
+ $this->assertEquals('Parent Category Name > Child Category Name', $this->sut->get($this->productMock));
+ }
+}
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 948a0e5..4eb9d52 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -29,7 +29,7 @@
showInWebsite="1"
canRestore="1">
- By default cron will run every 15 minutes.
+ By default cron will run every 2 hours.
RunAsRoot\GoogleShoppingFeed\SourceModel\FrequencySourceModel
1
diff --git a/etc/config.xml b/etc/config.xml
index a86a901..6150970 100644
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -3,7 +3,7 @@
- */15 * * * *
+ 0 */2 * * *
diff --git a/etc/di.xml b/etc/di.xml
index fb41397..e306199 100644
--- a/etc/di.xml
+++ b/etc/di.xml
@@ -26,10 +26,10 @@
pattern
-
- product_type
+ size