diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/Api/Pimcore/PimcoreAttributeMapperInterface.php b/Api/Pimcore/PimcoreAttributeMapperInterface.php
index 673c247..71a89fb 100644
--- a/Api/Pimcore/PimcoreAttributeMapperInterface.php
+++ b/Api/Pimcore/PimcoreAttributeMapperInterface.php
@@ -33,6 +33,11 @@ interface PimcoreAttributeMapperInterface
*/
const WYSIWYG= 'wysiwyg';
+ /**
+ * Pimcore quantityValue type
+ */
+ const QVALUE= 'quantityValue';
+
/**
* Pimcore object type object
*/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d48d4f5..052a02a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+1.0.8.1
+=============
+- add missing data transformator for a quantityValue type attribute
+
+1.0.8
+=============
+- add quantity value strategy type
+
+1.0.7
+=============
+* add price override configuration `configuration/prices/is_override_enabled`. If yes then price from Pimcore will override current price, otherwise price will be set only on the first one.
+
+1.0.6.0
+=============
+* now it is possible to configure attribute data from a Pimcore. Additional informations kept in 'attr_conf' key in attribute will be merged and override default configuration of an attribute. `\Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy\AbstractStrategy::getMergedConfig`
+
+1.0.5.5
+=============
+* add .gitignore
+* update console commands to be compatible with 2.3.x
+
1.0.5.4
=============
* GitHub PR:
@@ -19,4 +40,4 @@
1.0.4.13
=============
-* Initial commit
\ No newline at end of file
+* Initial commit
diff --git a/Console/Command/AssetsImportCommand.php b/Console/Command/AssetsImportCommand.php
index 2fcfa03..fb3c332 100644
--- a/Console/Command/AssetsImportCommand.php
+++ b/Console/Command/AssetsImportCommand.php
@@ -76,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// fail gracefully
}
- $this->registry->register('isSecureArea', true);
+ $this->registry->register('isSecureArea', true, true);
$start = $this->getCurrentMs();
diff --git a/Console/Command/CategoryImportCommand.php b/Console/Command/CategoryImportCommand.php
index 5793f4c..5a5cc97 100644
--- a/Console/Command/CategoryImportCommand.php
+++ b/Console/Command/CategoryImportCommand.php
@@ -83,7 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// fail gracefully
}
- $this->registry->register('isSecureArea', true);
+ $this->registry->register('isSecureArea', true, true);
$start = $this->getCurrentMs();
diff --git a/Console/Command/ProductImportCommand.php b/Console/Command/ProductImportCommand.php
index cad4b5f..bd66449 100644
--- a/Console/Command/ProductImportCommand.php
+++ b/Console/Command/ProductImportCommand.php
@@ -82,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// fail gracefully
}
- $this->registry->register('isSecureArea', true);
+ $this->registry->register('isSecureArea', true, true);
$start = $this->getCurrentMs();
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategy.php
index 5d130f3..2f8a8f6 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategy.php
@@ -37,27 +37,6 @@ abstract class AbstractStrategy implements AttributeCreationStrategyInterface
*/
protected $code;
- /**
- * @var array
- */
- protected static $defaultAttrConfig = [
- 'backend' => '',
- 'frontend' => '',
- 'input' => 'text',
- 'class' => '',
- 'source' => '',
- 'global' => ScopedAttributeInterface::SCOPE_STORE,
- 'visible' => true,
- 'required' => false,
- 'user_defined' => true,
- 'searchable' => true,
- 'filterable' => true,
- 'comparable' => true,
- 'visible_on_front' => true,
- 'used_in_product_listing' => true,
- 'unique' => false,
- ];
-
/**
* AbstractStrategy constructor.
*
@@ -77,4 +56,43 @@ public function __construct(
$this->attrData = $attrData;
$this->code = $code;
}
+
+ /**
+ * @param array $base
+ *
+ * @return array
+ */
+ public function getMergedConfig(array $base = []): array
+ {
+ return array_merge($this->getDefaultAttributeConfig(), $base, $this->attrData['attr_conf'] ?? []);
+ }
+
+ /**
+ * @return array
+ */
+ abstract public function getBaseAttrConfig(): array;
+
+ /**
+ * @return array
+ */
+ public function getDefaultAttributeConfig(): array
+ {
+ return [
+ 'backend' => '',
+ 'frontend' => '',
+ 'input' => 'text',
+ 'class' => '',
+ 'source' => '',
+ 'global' => ScopedAttributeInterface::SCOPE_STORE,
+ 'visible' => true,
+ 'required' => false,
+ 'user_defined' => true,
+ 'searchable' => true,
+ 'filterable' => true,
+ 'comparable' => true,
+ 'visible_on_front' => true,
+ 'used_in_product_listing' => true,
+ 'unique' => false,
+ ];
+ }
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/DatetimeStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/DatetimeStrategy.php
index f4bd98c..827d3df 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/DatetimeStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/DatetimeStrategy.php
@@ -22,17 +22,26 @@ class DatetimeStrategy extends AbstractStrategy
public function execute(): int
{
$eavSetup = $this->eavSetupFactory->create();
+
$eavSetup->addAttribute(
Product::ENTITY,
$this->code,
- array_merge(self::$defaultAttrConfig, [
- 'type' => 'datetime',
- 'label' => $this->attrData['label'],
- 'input' => 'date',
- 'backend' => Datetime::class,
- ])
+ $this->getMergedConfig($this->getBaseAttrConfig())
);
return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
}
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'datetime',
+ 'label' => $this->attrData['label'],
+ 'input' => 'date',
+ 'backend' => Datetime::class,
+ ];
+ }
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/MultiselectStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/MultiselectStrategy.php
index fc17cda..7a7c109 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/MultiselectStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/MultiselectStrategy.php
@@ -84,18 +84,24 @@ protected function createNewAttribute(array $options)
{
$eavSetup = $this->eavSetupFactory->create();
- $data = [
+ $eavSetup->addAttribute(
+ Product::ENTITY,
+ $this->code,
+ $this->getMergedConfig($this->getBaseAttrConfig())
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
'type' => 'varchar',
'label' => $this->attrData['label'],
'input' => 'multiselect',
'user_defined' => true,
'backend' => ArrayBackend::class,
];
-
- $eavSetup->addAttribute(
- Product::ENTITY,
- $this->code,
- array_merge(self::$defaultAttrConfig, $data)
- );
}
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategy.php
new file mode 100644
index 0000000..11bd1f3
--- /dev/null
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategy.php
@@ -0,0 +1,54 @@
+
+ * @copyright 2020 Divante Sp. z o.o.
+ * @license See LICENSE_DIVANTE.txt for license details.
+ */
+
+namespace Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy;
+
+use Magento\Catalog\Model\Product;
+use Magento\Eav\Setup\EavSetup;
+
+/**
+ * Class QuantityValueStrategy
+ */
+class QuantityValueStrategy extends AbstractStrategy
+{
+ /**
+ * @return int
+ */
+ public function execute(): int
+ {
+ /** @var EavSetup $eavSetup */
+ $eavSetup = $this->eavSetupFactory->create();
+ $eavSetup->addAttribute(
+ Product::ENTITY,
+ $this->code,
+ $this->getMergedConfig($this->getBaseAttrConfig())
+ );
+
+ return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
+ }
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'decimal',
+ 'label' => $this->getLabel(),
+ 'input' => 'text',
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ private function getLabel(): string
+ {
+ return $this->attrData['label'] . ' (' . $this->attrData['unit'] . ')';
+ }
+}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/SelectStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/SelectStrategy.php
index 9251724..3fef171 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/SelectStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/SelectStrategy.php
@@ -80,6 +80,26 @@ protected function createNewAttribute(array $options)
{
$eavSetup = $this->eavSetupFactory->create();
+ $eavSetup->addAttribute(
+ Product::ENTITY,
+ $this->code,
+ $this->getMergedConfig($this->getBaseAttrConfig())
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ private function isConfigurable(): bool
+ {
+ return (!empty($this->attrData['is_configurable']) && true === $this->attrData['is_configurable']);
+ }
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
$data = [
'type' => 'int',
'label' => $this->attrData['label'],
@@ -93,18 +113,6 @@ protected function createNewAttribute(array $options)
]);
}
- $eavSetup->addAttribute(
- Product::ENTITY,
- $this->code,
- array_merge(self::$defaultAttrConfig, $data)
- );
- }
-
- /**
- * @return bool
- */
- private function isConfigurable(): bool
- {
- return (!empty($this->attrData['is_configurable']) && true === $this->attrData['is_configurable']);
+ return $data;
}
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategy.php
index e131d75..89cd7ce 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategy.php
@@ -26,13 +26,21 @@ public function execute(): int
$eavSetup->addAttribute(
Product::ENTITY,
$this->code,
- array_merge(self::$defaultAttrConfig, [
- 'type' => 'varchar',
- 'label' => $this->attrData['label'],
- 'input' => 'text',
- ])
+ $this->getMergedConfig($this->getBaseAttrConfig())
);
return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
}
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'varchar',
+ 'label' => $this->attrData['label'],
+ 'input' => 'text',
+ ];
+ }
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/TextareaStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/TextareaStrategy.php
index a4ff65a..63a7f93 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/TextareaStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/TextareaStrategy.php
@@ -24,15 +24,23 @@ public function execute(): int
$eavSetup->addAttribute(
Product::ENTITY,
$this->code,
- array_merge(self::$defaultAttrConfig, [
- 'type' => 'text',
- 'label' => $this->attrData['label'],
- 'input' => 'textarea',
- 'wysiwyg_enabled' => false,
- 'is_html_allowed_on_front' => false,
- ])
+ $this->getMergedConfig($this->getBaseAttrConfig())
);
return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
}
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'text',
+ 'label' => $this->attrData['label'],
+ 'input' => 'textarea',
+ 'wysiwyg_enabled' => false,
+ 'is_html_allowed_on_front' => false,
+ ];
+ }
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/WysiwygStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/WysiwygStrategy.php
index a42e00b..b435e28 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/WysiwygStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/WysiwygStrategy.php
@@ -24,15 +24,23 @@ public function execute(): int
$eavSetup->addAttribute(
Product::ENTITY,
$this->code,
- array_merge(self::$defaultAttrConfig, [
- 'type' => 'text',
- 'label' => $this->attrData['label'],
- 'input' => 'textarea',
- 'wysiwyg_enabled' => true,
- 'is_html_allowed_on_front' => true,
- ])
+ $this->getMergedConfig($this->getBaseAttrConfig())
);
return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
}
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'text',
+ 'label' => $this->attrData['label'],
+ 'input' => 'textarea',
+ 'wysiwyg_enabled' => true,
+ 'is_html_allowed_on_front' => true,
+ ];
+ }
}
diff --git a/Model/Catalog/Product/Attribute/Creator/Strategy/YesnoStrategy.php b/Model/Catalog/Product/Attribute/Creator/Strategy/YesnoStrategy.php
index 4866ca8..0c71894 100644
--- a/Model/Catalog/Product/Attribute/Creator/Strategy/YesnoStrategy.php
+++ b/Model/Catalog/Product/Attribute/Creator/Strategy/YesnoStrategy.php
@@ -24,14 +24,22 @@ public function execute(): int
$eavSetup->addAttribute(
Product::ENTITY,
$this->code,
- array_merge(self::$defaultAttrConfig, [
- 'type' => 'int',
- 'label' => $this->attrData['label'],
- 'input' => 'boolean',
- 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class,
- ])
+ $this->getMergedConfig($this->getBaseAttrConfig())
);
return $eavSetup->getAttributeId(Product::ENTITY, $this->code);
}
+
+ /**
+ * @return array
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'int',
+ 'label' => $this->attrData['label'],
+ 'input' => 'boolean',
+ 'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class,
+ ];
+ }
}
diff --git a/Model/Pimcore/SimpleAttributeMapper.php b/Model/Pimcore/SimpleAttributeMapper.php
index 993b5a2..de422bf 100644
--- a/Model/Pimcore/SimpleAttributeMapper.php
+++ b/Model/Pimcore/SimpleAttributeMapper.php
@@ -31,6 +31,7 @@ public function mapUsingType(array $attributeData)
case self::YESNO:
case self::DATETIME:
case self::WYSIWYG:
+ case self::QVALUE:
return $this->mapText($attributeData);
case self::SELECT:
return $this->mapSelect($attributeData);
diff --git a/Queue/Action/Product/CategoryIdsModifier.php b/Queue/Action/Product/CategoryIdsModifier.php
index 913f082..5636175 100644
--- a/Queue/Action/Product/CategoryIdsModifier.php
+++ b/Queue/Action/Product/CategoryIdsModifier.php
@@ -77,7 +77,8 @@ public function __construct(
*/
public function handle(Product $product, PimcoreProductInterface $pimcoreProduct): array
{
- $pimCatIds = $pimcoreProduct->getData('category_ids');
+ $pimCatIds = $pimcoreProduct->getData('category_ids') ?? [];
+
$catCollection = $this->getMageCatCollection($pimcoreProduct);
$mageCatIds = $catCollection->getAllIds();
$pimcoreProduct->setData('category_ids', $mageCatIds);
diff --git a/Queue/Action/Product/PriceModifier.php b/Queue/Action/Product/PriceModifier.php
index 38d1267..8940fbd 100644
--- a/Queue/Action/Product/PriceModifier.php
+++ b/Queue/Action/Product/PriceModifier.php
@@ -9,6 +9,7 @@
namespace Divante\PimcoreIntegration\Queue\Action\Product;
use Divante\PimcoreIntegration\Api\Pimcore\PimcoreProductInterface;
+use Divante\PimcoreIntegration\System\ConfigInterface;
use Magento\Catalog\Model\Product;
/**
@@ -21,6 +22,21 @@ class PriceModifier implements DataModifierInterface
*/
public static $defaultPriceValue = 0;
+ /**
+ * @var ConfigInterface
+ */
+ private $config;
+
+ /**
+ * PriceModifier constructor.
+ *
+ * @param ConfigInterface $config
+ */
+ public function __construct(ConfigInterface $config)
+ {
+ $this->config = $config;
+ }
+
/**
* @param Product $product
* @param PimcoreProductInterface $pimcoreProduct
@@ -32,12 +48,26 @@ public function handle(Product $product, PimcoreProductInterface $pimcoreProduct
if (null === $pimcoreProduct->getData('price') && null === $product->getPrice()) {
$pimcoreProduct->setData('price', self::$defaultPriceValue);
$pimcoreProduct->setData('base_price', self::$defaultPriceValue);
- } elseif (null !== $product->getPrice()) {
- $pimcoreProduct->setData('price', $product->getPrice());
+ } elseif ($this->isPriceAlreadySet($product)) {
+ if ($this->config->getIsPriceOverride()) {
+ $pimcoreProduct->setData('price', $pimcoreProduct->getData('price') ?? self::$defaultPriceValue);
+ } else {
+ $pimcoreProduct->setData('price', $product->getPrice());
+ }
}
$pimcoreProduct->setData('base_price', $pimcoreProduct->getData('price'));
return [$product, $pimcoreProduct];
}
+
+ /**
+ * @param Product $product
+ *
+ * @return bool
+ */
+ private function isPriceAlreadySet(Product $product): bool
+ {
+ return (null !== $product->getPrice());
+ }
}
diff --git a/System/Config.php b/System/Config.php
index f12a23f..2c2d6ed 100644
--- a/System/Config.php
+++ b/System/Config.php
@@ -142,4 +142,12 @@ public function getIsProductPublishActive(): bool
{
return (bool) $this->scopeConfig->getValue(static::XML_PATH_CRON_PUBLISH_IS_ACTIVE, $this->scope);
}
+
+ /**
+ * @return bool
+ */
+ public function getIsPriceOverride(): bool
+ {
+ return (bool) $this->scopeConfig->getValue(static::XML_PATH_PRICES_OVERRIDE, $this->scope);
+ }
}
diff --git a/System/ConfigInterface.php b/System/ConfigInterface.php
index fe10a48..ec83e54 100644
--- a/System/ConfigInterface.php
+++ b/System/ConfigInterface.php
@@ -28,6 +28,11 @@ interface ConfigInterface
*/
const XML_PATH_QUEUE_OUTDATED = 'configuration/basic/queue_outdated';
+ /**
+ * Configuration path for rices override settings
+ */
+ const XML_PATH_PRICES_OVERRIDE = 'configuration/prices/is_override_enabled';
+
/**
* Configuration path for Pimcore API Key used for request authorization
*/
@@ -63,6 +68,7 @@ interface ConfigInterface
*/
const XML_PATH_CRON_PUBLISH_IS_ACTIVE = 'cron/enable_products/is_active';
+
/**
* @return bool
*/
@@ -117,4 +123,9 @@ public function getQueueOutdatedValue(): string;
* @return bool
*/
public function getIsProductPublishActive(): bool;
+
+ /**
+ * @return bool
+ */
+ public function getIsPriceOverride(): bool;
}
diff --git a/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategyTest.php b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategyTest.php
new file mode 100644
index 0000000..8d17cff
--- /dev/null
+++ b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/AbstractStrategyTest.php
@@ -0,0 +1,139 @@
+
+ * @copyright 2020 Divante Sp. z o.o.
+ * @license See LICENSE_DIVANTE.txt for license details.
+ */
+
+namespace Divante\PimcoreIntegration\Test\Unit\Model\Catalog\Product\Attribute\Creator\Strategy;
+
+use Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy\AbstractStrategy;
+use Magento\Catalog\Model\Category\AttributeRepository;
+use Magento\Eav\Api\AttributeRepositoryInterface;
+use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
+use Magento\Eav\Setup\EavSetup;
+use Magento\Eav\Setup\EavSetupFactory;
+use PHPUnit\Framework\MockObject\MockObject;
+
+/**
+ * Class TextStrategyTest
+ */
+class AbstractStrategyTest extends \PHPUnit\Framework\TestCase
+{
+ /**
+ * @var MockObject|EavSetupFactory
+ */
+ private $eavSetupFactoryMock;
+
+ /**
+ * @var MockObject|EavSetup
+ */
+ private $eavSetupMock;
+
+ /**
+ * @var MockObject|AttributeRepository
+ */
+ private $attributeRepositoryMock;
+
+ /**
+ * @var array
+ */
+ private $defaultAttrConfig = [
+ 'backend' => '',
+ 'frontend' => '',
+ 'input' => 'text',
+ 'class' => '',
+ 'source' => '',
+ 'global' => ScopedAttributeInterface::SCOPE_STORE,
+ 'visible' => true,
+ 'required' => false,
+ 'user_defined' => true,
+ 'searchable' => true,
+ 'filterable' => true,
+ 'comparable' => true,
+ 'visible_on_front' => true,
+ 'used_in_product_listing' => true,
+ 'unique' => false,
+ ];
+
+ public function setUp()
+ {
+ $this->eavSetupFactoryMock = $this->getMockBuilder(EavSetupFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+
+ $this->eavSetupMock = $this->getMockBuilder(EavSetup::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+
+ $this->eavSetupMock = $this->getMockBuilder(EavSetup::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+
+ $this->attributeRepositoryMock = $this->getMockBuilder(AttributeRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+ }
+
+ /**
+ * @return array[]
+ */
+ public function attrDataProvider()
+ {
+ return [
+ [['attr_conf' => ['test' => 1]], []],
+ [['attr_conf' => ['test' => 1]], ['input' => 'select']],
+ [['attr_conf' => ['test' => 1]], ['input' => 'select']],
+ [['attr_conf' => ['test' => 1]], ['input' => 'select']],
+ [['something_else' => [], 'attr_conf' => ['test' => 1]], ['input' => 'select']],
+ [['missed_key' => ['test' => 1, 'required' => true]], []],
+ ];
+ }
+
+ public function testGetDefaultAttrConfig()
+ {
+ $strategy = $this->getAbstractStrategyMockImplementation('test');
+ $this->assertEquals($this->defaultAttrConfig, $strategy->getDefaultAttributeConfig());
+ }
+
+ /**
+ * @dataProvider attrDataProvider
+ */
+ public function testGetMergedConfig(array $attrData, $base)
+ {
+ $strategy = $this->getAbstractStrategyMockImplementation('test', $attrData);
+ $result = array_merge($this->defaultAttrConfig, $base, $attrData['attr_conf'] ?? []);
+ $this->assertEquals($result, $strategy->getMergedConfig($base));
+ }
+
+ /**
+ * @param string $code
+ * @param array $attrData
+ *
+ * @return AbstractStrategy
+ */
+ private function getAbstractStrategyMockImplementation(string $code, array $attrData = [])
+ {
+ return new class(
+ $this->eavSetupFactoryMock,
+ $this->attributeRepositoryMock,
+ $attrData,
+ $code
+ ) extends AbstractStrategy {
+ public function getBaseAttrConfig(): array
+ {
+ return [];
+ }
+
+ public function execute(): int
+ {
+ return 1;
+ }
+ };
+ }
+}
diff --git a/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/BaseTestAbstract.php b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/BaseTestAbstract.php
new file mode 100644
index 0000000..4ba411f
--- /dev/null
+++ b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/BaseTestAbstract.php
@@ -0,0 +1,120 @@
+
+ * @copyright 2020 Divante Sp. z o.o.
+ * @license See LICENSE_DIVANTE.txt for license details.
+ */
+
+namespace Divante\PimcoreIntegration\Test\Unit\Model\Catalog\Product\Attribute\Creator\Strategy;
+
+use Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy\TextStrategy;
+use Magento\Catalog\Model\Category\AttributeRepository;
+use Magento\Eav\Api\AttributeRepositoryInterface;
+use Magento\Eav\Setup\EavSetup;
+use Magento\Eav\Setup\EavSetupFactory;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Class TestAbstract
+ */
+abstract class BaseTestAbstract extends TestCase
+{
+ /**
+ * @var ObjectManager
+ */
+ protected $om;
+
+ /**
+ * @var MockObject|EavSetupFactory
+ */
+ protected $eavSetupFactoryMock;
+
+ /**
+ * @var MockObject|EavSetup
+ */
+ protected $eavSetupMock;
+
+ /**
+ * @var MockObject|AttributeRepository
+ */
+ protected $attributeRepositoryMock;
+
+ /**
+ * Test Setup
+ */
+ public function setUp()
+ {
+ $this->om = new ObjectManager($this);
+
+ $this->eavSetupFactoryMock = $this->getMockBuilder(EavSetupFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+
+ $this->eavSetupMock = $this->getMockBuilder(EavSetup::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['addAttribute', 'getAttributeId'])
+ ->getMock();
+
+ $this->eavSetupMock = $this->getMockBuilder(EavSetup::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+
+ $this->attributeRepositoryMock = $this->getMockBuilder(AttributeRepositoryInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+ }
+
+ /**
+ * @return array[]
+ */
+ abstract public function attrDataProvider(): array;
+
+ /**
+ * @return string
+ */
+ abstract public function getStrategyClass(): string;
+
+ /**
+ * @return array
+ */
+ abstract public function getBaseAttrConfig(): array;
+
+ /**
+ * @dataProvider attrDataProvider
+ */
+ public function testExecution(array $attrData, $code)
+ {
+ $this->markTestIncomplete('You must implement execution test.');
+ }
+
+ /**
+ * @dataProvider attrDataProvider
+ */
+ public function testGetBaseAttrConf(array $attrData, $code)
+ {
+ $strategy = $this->createStrategyObject($this->getStrategyClass(), $code, $attrData);
+ $this->assertEquals($this->getBaseAttrConfig(), $strategy->getBaseAttrConfig());
+ }
+
+ /**
+ * @param string $code
+ * @param array $attrData
+ *
+ * @return object
+ */
+ protected function createStrategyObject(string $strategyClass, string $code, array $attrData = [])
+ {
+ return $this->om->getObject($strategyClass, [
+ 'eavSetupFactory' => $this->eavSetupFactoryMock,
+ 'attributeRepository' => $this->attributeRepositoryMock,
+ 'attrData' => $attrData,
+ 'code' => $code
+ ]);
+ }
+}
diff --git a/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategyTest.php b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategyTest.php
new file mode 100644
index 0000000..de307bf
--- /dev/null
+++ b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/QuantityValueStrategyTest.php
@@ -0,0 +1,68 @@
+
+ * @copyright 2020 Divante Sp. z o.o.
+ * @license See LICENSE_DIVANTE.txt for license details.
+ */
+
+namespace Divante\PimcoreIntegration\Test\Unit\Model\Catalog\Product\Attribute\Creator\Strategy;
+
+use Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy\QuantityValueStrategy;
+
+/**
+ * Class QuantityValueStrategyTest
+ */
+class QuantityValueStrategyTest extends BaseTestAbstract
+{
+ /**
+ * @dataProvider attrDataProvider
+ */
+ public function testExecution(array $attrData, $code)
+ {
+ $strategy = $this->createStrategyObject($this->getStrategyClass(), $code, $attrData);
+
+ $this->eavSetupFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->eavSetupMock);
+
+ $this->eavSetupMock->expects($this->once())
+ ->method('addAttribute');
+
+ $this->eavSetupMock->expects($this->once())
+ ->method('getAttributeId')
+ ->willReturn(1);
+
+ $strategy->execute();
+ }
+
+ /**
+ * @return array|array[]
+ */
+ public function attrDataProvider(): array
+ {
+ return [
+ [['label' => 'quantity', 'unit' => 'km'], 'test'],
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function getStrategyClass(): string
+ {
+ return QuantityValueStrategy::class;
+ }
+
+ /**
+ * @return array|string[]
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'decimal',
+ 'label' => 'quantity (km)',
+ 'input' => 'text',
+ ];
+ }
+}
diff --git a/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategyTest.php b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategyTest.php
new file mode 100644
index 0000000..9ebdbe3
--- /dev/null
+++ b/Test/Unit/Model/Catalog/Product/Attribute/Creator/Strategy/TextStrategyTest.php
@@ -0,0 +1,76 @@
+
+ * @copyright 2020 Divante Sp. z o.o.
+ * @license See LICENSE_DIVANTE.txt for license details.
+ */
+
+namespace Divante\PimcoreIntegration\Test\Unit\Model\Catalog\Product\Attribute\Creator\Strategy;
+
+use Divante\PimcoreIntegration\Model\Catalog\Product\Attribute\Creator\Strategy\TextStrategy;
+use Magento\Catalog\Model\Category\AttributeRepository;
+use Magento\Catalog\Model\Product;
+use Magento\Eav\Api\AttributeRepositoryInterface;
+use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
+use Magento\Eav\Setup\EavSetup;
+use Magento\Eav\Setup\EavSetupFactory;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit\Framework\MockObject\MockObject;
+
+/**
+ * Class TextStrategyTest
+ */
+class TextStrategyTest extends BaseTestAbstract
+{
+ /**
+ * @return array[]
+ */
+ public function attrDataProvider(): array
+ {
+ return [
+ [['label' => 'test_label'], 'test'],
+ ];
+ }
+
+ /**
+ * @dataProvider attrDataProvider
+ */
+ public function testExecution(array $attrData, $code)
+ {
+ $strategy = $this->createStrategyObject($this->getStrategyClass(), $code, $attrData);
+
+ $this->eavSetupFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->eavSetupMock);
+
+ $this->eavSetupMock->expects($this->once())
+ ->method('addAttribute');
+
+ $this->eavSetupMock->expects($this->once())
+ ->method('getAttributeId')
+ ->willReturn(1);
+
+ $strategy->execute();
+ }
+
+ /**
+ * @return string
+ */
+ public function getStrategyClass(): string
+ {
+ return TextStrategy::class;
+ }
+
+ /**
+ * @return array|string[]
+ */
+ public function getBaseAttrConfig(): array
+ {
+ return [
+ 'type' => 'varchar',
+ 'label' => 'test_label',
+ 'input' => 'text',
+ ];
+ }
+}
diff --git a/Test/Unit/Queue/Action/Product/PriceModifierTest.php b/Test/Unit/Queue/Action/Product/PriceModifierTest.php
index 461a94a..88c6c47 100644
--- a/Test/Unit/Queue/Action/Product/PriceModifierTest.php
+++ b/Test/Unit/Queue/Action/Product/PriceModifierTest.php
@@ -11,8 +11,12 @@
use Divante\PimcoreIntegration\Model\Pimcore\PimcoreProduct;
use Divante\PimcoreIntegration\Queue\Action\Product\DataModifierInterface;
use Divante\PimcoreIntegration\Queue\Action\Product\PriceModifier;
+use Divante\PimcoreIntegration\System\Config;
+use Divante\PimcoreIntegration\System\ConfigInterface;
use Magento\Catalog\Model\Product;
+use Magento\Catalog\Model\Product\Type\Price;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* PriceModifierTest
@@ -25,12 +29,12 @@ class PriceModifierTest extends \PHPUnit\Framework\TestCase
private $priceModifier;
/**
- * @var PimcoreProduct|\PHPUnit_Framework_MockObject_MockObject
+ * @var PimcoreProduct|MockObject
*/
private $pimcoreProduct;
/**
- * @var Product|\PHPUnit_Framework_MockObject_MockObject
+ * @var Product|MockObject
*/
private $product;
@@ -39,21 +43,40 @@ class PriceModifierTest extends \PHPUnit\Framework\TestCase
*/
private $objectManager;
+ /**
+ * @var ConfigInterface|MockObject
+ */
+ private $configMock;
+
+ /**
+ * @var Price|MockObject
+ */
+ private $mockPriceModel;
+
public function setUp()
{
$this->objectManager = new ObjectManager($this);
- $this->product = $this->mockProduct = $this->getMockBuilder(Product::class)
+ $this->mockPriceModel = $this->getMockBuilder(Price::class)
->disableOriginalConstructor()
->setMethods(['getPrice'])
->getMock();
- $this->pimcoreProduct = $this->mockPimcoreProduct = $this->getMockBuilder(PimcoreProduct::class)
+ $this->product = $this->getMockBuilder(Product::class)
->disableOriginalConstructor()
- ->setMethods(['getData', 'setData'])
+ ->setMethods(['getPriceModel'])
->getMock();
- $this->priceModifier = $this->objectManager->getObject(PriceModifier::class);
+ $this->pimcoreProduct = $this->objectManager->getObject(PimcoreProduct::class);
+
+ $this->configMock = $this->getMockBuilder(Config::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getIsPriceOverride'])
+ ->getMock();
+
+ $this->priceModifier = $this->objectManager->getObject(PriceModifier::class, [
+ 'config' => $this->configMock
+ ]);
}
/**
@@ -66,22 +89,32 @@ public function priceDataProvider(): array
[10, null, 10],
[null, 10, 10],
[12, 10, 12],
+ [15, 20, 20, true],
+ [15, 20, 15, false],
];
}
/**
* @dataProvider priceDataProvider
*/
- public function testHandle($price, $pimPrice, $final)
+ public function testHandle($price, $pimPrice, $final, $override = false)
{
- $this->pimcoreProduct->expects($this->exactly(2))
- ->method('getData')
- ->willReturn($pimPrice);
+ $this->product->setPrice($price);
+ $this->product->expects($this->any())
+ ->method('getPriceModel')
+ ->willReturn($this->mockPriceModel);
- $this->product->expects($this->atLeast(1))
+ $this->mockPriceModel->expects($this->any())
->method('getPrice')
->willReturn($price);
- $this->priceModifier->handle($this->product, $this->pimcoreProduct);
+ $this->configMock->expects($this->any())
+ ->method('getIsPriceOverride')
+ ->willReturn($override);
+
+ $this->pimcoreProduct->setData('price', $pimPrice);
+
+ $result = $this->priceModifier->handle($this->product, $this->pimcoreProduct);
+ $this->assertEquals($final, $result[1]->getPrice());
}
}
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index bb61b6d..05d01c3 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -38,6 +38,16 @@
+
+
+
+
+ Magento\Config\Model\Config\Source\Yesno
+
+
+
separator-top
diff --git a/etc/config.xml b/etc/config.xml
index 04e8a87..f1881a2 100644
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -6,6 +6,9 @@
0
60
+
+ 1
+