diff --git a/CHANGELOG-2.0.md b/CHANGELOG-2.0.md index f68a34c2..e5485f3d 100644 --- a/CHANGELOG-2.0.md +++ b/CHANGELOG-2.0.md @@ -1,3 +1,9 @@ +# 2.0.10 + +## Improvements +- GITHUB-169: Error 500 when trying to use a refdata attribute as a filter in the Export Builder +- GITHUB-170: Fix reference data import with translations + # 2.0.9 ## Improvements diff --git a/Connector/ArrayConverter/FlatToStandard/ReferenceData.php b/Connector/ArrayConverter/FlatToStandard/ReferenceData.php new file mode 100644 index 00000000..9c1421e1 --- /dev/null +++ b/Connector/ArrayConverter/FlatToStandard/ReferenceData.php @@ -0,0 +1,79 @@ + + * @copyright 2018 Akeneo SAS (http://www.akeneo.com) + * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + */ +class ReferenceData implements ArrayConverterInterface +{ + /** @var FieldsRequirementChecker */ + protected $checker; + + /** @var array */ + protected $fieldsPresence; + + /** @var array */ + protected $fieldsFilling; + + /** + * @param FieldsRequirementChecker $checker + * @param array $fieldsPresence + * @param array $fieldsFilling + */ + public function __construct( + FieldsRequirementChecker $checker, + array $fieldsPresence = [], + array $fieldsFilling = [] + ) { + $this->checker = $checker; + $this->fieldsPresence = $fieldsPresence; + $this->fieldsFilling = $fieldsFilling; + } + + /** + * {@inheritdoc} + */ + public function convert(array $item, array $options = []) + { + if (!empty($this->fieldsPresence)) { + $this->checker->checkFieldsPresence($item, $this->fieldsPresence); + } + + if (!empty($this->fieldsFilling)) { + $this->checker->checkFieldsFilling($item, $this->fieldsFilling); + } + + $convertedItem = []; + foreach ($item as $field => $data) { + $convertedItem = $this->convertField($convertedItem, $field, $data); + } + + return $convertedItem; + } + + /** + * @param array $convertedItem + * @param string $field + * @param mixed $data + * + * @return array + */ + protected function convertField(array $convertedItem, $field, $data) + { + if (false !== strpos($field, 'label-', 0)) { + $labelTokens = explode('-', $field); + $labelLocale = $labelTokens[1]; + $convertedItem['labels'][$labelLocale] = $data; + } else { + $convertedItem[$field] = $data; + } + + return $convertedItem; + } +} diff --git a/Resources/config/connectors.yml b/Resources/config/connectors.yml index bb325490..afcac15c 100644 --- a/Resources/config/connectors.yml +++ b/Resources/config/connectors.yml @@ -5,13 +5,15 @@ parameters: pim_custom_entity.processor.denormalization.reference_data.class: Pim\Bundle\CustomEntityBundle\Connector\Processor\Denormalization\ReferenceDataProcessor pim_custom_entity.processor.normalization.reference_data.class: Pim\Bundle\CustomEntityBundle\Connector\Processor\Normalization\ReferenceDataProcessor + pim_custom_entity.array_converter.flat_to_standard.reference_data.class: Pim\Bundle\CustomEntityBundle\Connector\ArrayConverter\FlatToStandard\ReferenceData + services: # Readers pim_custom_entity.reader.file.csv: class: '%pim_connector.reader.file.csv.class%' arguments: - '@pim_connector.reader.file.csv_iterator_factory' - - '@pim_connector.array_converter.dummy' + - '@pim_custom_entity.array_converter.flat_to_standard.reference_data' pim_custom_entity.reader.database.reference_data: class: '%pim_custom_entity.reader.database.reference_data.class%' @@ -55,3 +57,11 @@ services: arguments: - '@doctrine.orm.entity_manager' - '@pim_reference_data.registry' + + # Array converters + pim_custom_entity.array_converter.flat_to_standard.reference_data: + class: '%pim_custom_entity.array_converter.flat_to_standard.reference_data.class%' + arguments: + - '@pim_connector.array_convertor.checker.fields_requirement' + - ['code'] + - ['code'] diff --git a/Resources/config/serializer.yml b/Resources/config/serializer.yml index e91dee70..af2936e9 100644 --- a/Resources/config/serializer.yml +++ b/Resources/config/serializer.yml @@ -22,3 +22,4 @@ services: class: '%pim_custom_entity.normalizer.standard.minimal.class%' tags: - { name: pim_serializer.normalizer, priority: 150 } + diff --git a/Tests/Jobs/AbstractJobTestCase.php b/Tests/Jobs/AbstractJobTestCase.php index dc0de9f5..ddd23e41 100644 --- a/Tests/Jobs/AbstractJobTestCase.php +++ b/Tests/Jobs/AbstractJobTestCase.php @@ -18,7 +18,7 @@ class AbstractJobTestCase extends AbstractTestCase { const DATA_FILE_PATH = __DIR__ . '/../Resources/data/'; - const EXPORT_PATH = '/tmp/test/export'; + const EXPORT_PATH = '/tmp/test/export/'; public function setUp() { diff --git a/Tests/Jobs/Import/CustomEntityImportTest.php b/Tests/Jobs/Import/CustomEntityImportTest.php index 079ca18f..9f1315b4 100644 --- a/Tests/Jobs/Import/CustomEntityImportTest.php +++ b/Tests/Jobs/Import/CustomEntityImportTest.php @@ -5,6 +5,7 @@ use Acme\Bundle\CustomBundle\Entity\Brand; use Acme\Bundle\CustomBundle\Entity\Color; use Acme\Bundle\CustomBundle\Entity\Fabric; +use Acme\Bundle\CustomBundle\Entity\Pictogram; use Akeneo\Bundle\BatchBundle\Command\BatchCommand; use Pim\Bundle\CustomEntityBundle\Tests\Jobs\AbstractJobTestCase; @@ -32,7 +33,6 @@ public function testImportSimpleCustomEntity() $this->assertEquals('Some name', $blue->getName()); $this->assertEquals(18, $blue->getRed()); - $this->createJobInstance( 'csv_colors_import', 'import', @@ -84,7 +84,47 @@ public function testImportLinkedCustomEntity() $brands = $this->manager->findAll(Brand::class); $this->assertCount(3, $brands); + $superBrand = $brands[0]; $this->assertInstanceOf(Fabric::class, $superBrand->getFabric()); $this->assertEquals('Another fabric', $superBrand->getFabric()->getName()); } + + public function testImportTranslatableReferenceData() + { + $this->activateLocales('fr_FR', 'de_DE'); + + $this->createReferenceData( + Pictogram::class, + [ + 'code' => 'picto_1', + 'labels' => [ + 'en_US' => 'an English label', + ], + ] + ); + + $pictos = $this->manager->findAll(Pictogram::class); + $this->assertCount(1, $pictos); + $picto1 = $pictos[0]; + $this->assertCount(1, $picto1->getTranslations()); + $this->assertEquals('an English label', $picto1->getTranslation('en_US')->getLabel()); + + $this->createJobInstance( + 'csv_pictos_import', + 'import', + 'pictogram', + static::DATA_FILE_PATH . 'pictos.csv' + ); + $batchStatus = $this->launch('csv_pictos_import'); + $this->assertEquals(BatchCommand::EXIT_SUCCESS_CODE, $batchStatus); + + $pictos = $this->manager->findAll(Pictogram::class); + + $this->assertCount(2, $pictos); + $picto1 = $pictos[0]; + $this->assertCount(3, $picto1->getTranslations()); + $this->assertEquals('label 1 en', $picto1->getTranslation('en_US')->getLabel()); + $this->assertEquals('label 1 fr', $picto1->getTranslation('fr_FR')->getLabel()); + $this->assertEquals('label 1 de', $picto1->getTranslation('de_DE')->getLabel()); + } } diff --git a/Tests/Resources/data/pictos.csv b/Tests/Resources/data/pictos.csv new file mode 100644 index 00000000..3753071c --- /dev/null +++ b/Tests/Resources/data/pictos.csv @@ -0,0 +1,3 @@ +code;label-en_US;label-fr_FR;label-de_DE;sortOrder +picto_1;"label 1 en";"label 1 fr";"label 1 de";1 +picto_2;"label 2 en";"label 2 fr";;1 diff --git a/spec/Pim/Bundle/CustomEntityBundle/Connector/ArrayConverter/FlatToStandard/ReferenceDataSpec.php b/spec/Pim/Bundle/CustomEntityBundle/Connector/ArrayConverter/FlatToStandard/ReferenceDataSpec.php new file mode 100644 index 00000000..e0a9a610 --- /dev/null +++ b/spec/Pim/Bundle/CustomEntityBundle/Connector/ArrayConverter/FlatToStandard/ReferenceDataSpec.php @@ -0,0 +1,67 @@ +beConstructedWith($checker, ['code'], ['code']); + } + + function it_is_initializable() + { + $this->shouldHaveType(ReferenceData::class); + } + + function it_is_an_array_converter() + { + $this->shouldImplement(ArrayConverterInterface::class); + } + + function it_does_not_update_non_label_fields() + { + $item = [ + 'code' => 'my_code', + 'stringProp' => 'string', + 'array_property' => [ + 'item1', + 'item2', + ], + 'boolProp' => false, + 'numProp' => 42, + ]; + + $this->convert($item, [])->shouldReturn($item); + } + + function it_converts_label_translations() + { + $item = [ + 'code' => 'my_code', + 'label-en_US' => 'An English label', + 'foo' => 'bar', + 'label-fr_FR' => 'Un label en français', + 'label-es_ES' => 'Un label en español', + ]; + + $this->convert($item, [])->shouldReturn( + [ + 'code' => 'my_code', + 'labels' => [ + 'en_US' => 'An English label', + 'fr_FR' => 'Un label en français', + 'es_ES' => 'Un label en español', + ], + 'foo' => 'bar', + ] + ); + } +}