From 04db23b2e2007dd5a290946fbf97524ace131101 Mon Sep 17 00:00:00 2001 From: Rafaela Mansini Date: Thu, 14 Nov 2024 13:33:56 +0000 Subject: [PATCH 1/4] MINT-9672: Add mergeMapping function to Tools/Mapper --- Tests/Unit/Tools/Mapper/MapperTest.php | 39 +++++++++++++++++++++++ Tools/Mapper/Mapper.php | 44 ++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/Tests/Unit/Tools/Mapper/MapperTest.php b/Tests/Unit/Tools/Mapper/MapperTest.php index cd26ff1e..6609e4d1 100644 --- a/Tests/Unit/Tools/Mapper/MapperTest.php +++ b/Tests/Unit/Tools/Mapper/MapperTest.php @@ -268,4 +268,43 @@ public function provideEmptyValues() yield 'Empty allowed option' => [['name' => ''], '', $ctx]; yield 'Wrong type' => [null, null, $ctx]; } + + public function testShouldMergeMappings() + { + $expectedResult = [ + ['name' => 'packshot', 'location' => 'https://media.com/1'], + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] + ]; + $mapperMock = $this->getMockBuilder(Mapper::class) + ->setMethods(['mapAll', 'map']) + ->getMock(); + + $mapperMock->method('map')->willReturn(['name' => 'packshot', 'location' => 'https://media.com/1']); + $mapperMock->method('mapAll')->willReturn([['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']]); + + $result = $mapperMock->mergeMapping('mappingName', [ + ['map', ['https://media.com/1'], 'packshot'], + ['mapAll', ['https://media.com/2', 'https://media.com/3'], 'eRetailerNonBrand'] + ]); + + $this->assertSame($expectedResult, $result); + } + + /** + * @dataProvider provideInvalidMappersToMerge + */ + public function testShouldThrowExceptionIfMappersIsNotCorrect(array $mapper = null) + { + $this->expectException(\InvalidArgumentException::class); + $this->mapper->mergeMapping('test', $mapper); + } + + public function provideInvalidMappersToMerge() + { + yield 'Null mappers parameter' => [null]; + yield 'Null map function' => [[null,'test', 'test']]; + yield 'Null map function' => [['map','test', null]]; + yield 'Map function is not mapped' => [['invalid','test', 'test']]; + } } diff --git a/Tools/Mapper/Mapper.php b/Tools/Mapper/Mapper.php index 5eae77a9..0683b318 100644 --- a/Tools/Mapper/Mapper.php +++ b/Tools/Mapper/Mapper.php @@ -89,6 +89,50 @@ public function map($obj, $mappingName, $context = []) return $this->resolve($mapping, $obj, $context); } + /** + * Merge multiples arrays values in a single mappingName + * + * @param string $mappingName + * @param array $mappers + * + * @return null|string + */ + public function mergeMapping($mappingName, $mappers) + { + $response = []; + + if (empty($mappers)) { + throw new \InvalidArgumentException('No mapper provided.'); + } + + foreach ($mappers as $mapper){ + $mapFunction = $mapper[0] ?? null; + $object = $mapper[1] ?? null; + $context = $mapper[2] ?? null; + + if(empty($object)){ + continue; + } + + if(empty($mapFunction) || empty($context)){ + throw new \InvalidArgumentException('No mapper function or context informed'); + } + + switch ($mapFunction){ + case 'map': + $response[] = $this->map($object, $mappingName, $context); + break; + case 'mapAll': + $response = array_merge($response, $this->mapAll($object, $mappingName, $context)); + break; + default: + throw new \InvalidArgumentException(sprintf('Invalid mapping name "%s"', $mappingName)); + } + } + + return $response; + } + /** * @param $mapping * @param $obj From a4b444f6bcddf73ac23284d808b621043cdfd7a0 Mon Sep 17 00:00:00 2001 From: Rafaela Mansini Date: Thu, 14 Nov 2024 19:17:06 +0000 Subject: [PATCH 2/4] MINT-9526: Updating mergeMapper function --- Tests/Unit/Tools/Mapper/MapperTest.php | 42 +++++++++++++++++++++----- Tools/Mapper/Mapper.php | 20 +++++------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/Tests/Unit/Tools/Mapper/MapperTest.php b/Tests/Unit/Tools/Mapper/MapperTest.php index 6609e4d1..2df398e1 100644 --- a/Tests/Unit/Tools/Mapper/MapperTest.php +++ b/Tests/Unit/Tools/Mapper/MapperTest.php @@ -269,19 +269,17 @@ public function provideEmptyValues() yield 'Wrong type' => [null, null, $ctx]; } - public function testShouldMergeMappings() + /** + * @dataProvider provideMergeMappings + */ + public function testShouldMergeMappings($expectedResult, $mockedMapFunction, $mockedMapAllFunction) { - $expectedResult = [ - ['name' => 'packshot', 'location' => 'https://media.com/1'], - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] - ]; $mapperMock = $this->getMockBuilder(Mapper::class) ->setMethods(['mapAll', 'map']) ->getMock(); - $mapperMock->method('map')->willReturn(['name' => 'packshot', 'location' => 'https://media.com/1']); - $mapperMock->method('mapAll')->willReturn([['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']]); + $mapperMock->method('map')->willReturn($mockedMapFunction); + $mapperMock->method('mapAll')->willReturn($mockedMapAllFunction); $result = $mapperMock->mergeMapping('mappingName', [ ['map', ['https://media.com/1'], 'packshot'], @@ -291,6 +289,34 @@ public function testShouldMergeMappings() $this->assertSame($expectedResult, $result); } + public function provideMergeMappings() + { + yield 'Merge mappings' => [ + [ + ['name' => 'packshot', 'location' => 'https://media.com/1'], + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] + ], + ['name' => 'packshot', 'location' => 'https://media.com/1'], + [['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']] + ]; + yield 'Merge mappings with null map' => [ + [ + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], + ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] + ], + null, + [['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']] + ]; + yield 'Merge mappings with null mapAll' => [ + [ + ['name' => 'packshot', 'location' => 'https://media.com/1'] + ], + ['name' => 'packshot', 'location' => 'https://media.com/1'], + null + ]; + } + /** * @dataProvider provideInvalidMappersToMerge */ diff --git a/Tools/Mapper/Mapper.php b/Tools/Mapper/Mapper.php index e0b5ba93..ac46ea9a 100644 --- a/Tools/Mapper/Mapper.php +++ b/Tools/Mapper/Mapper.php @@ -99,12 +99,12 @@ public function map($obj, $mappingName, $context = []) */ public function mergeMapping($mappingName, $mappers) { - $response = []; - if (empty($mappers)) { throw new \InvalidArgumentException('No mapper provided.'); } + $response = []; + foreach ($mappers as $mapper){ $mapFunction = $mapper[0] ?? null; $object = $mapper[1] ?? null; @@ -114,19 +114,15 @@ public function mergeMapping($mappingName, $mappers) continue; } - if(empty($mapFunction) || empty($context)){ + if(empty($mapFunction) || empty($context) || !in_array($mapFunction, ['map', 'mapAll'])){ throw new \InvalidArgumentException('No mapper function or context informed'); } - switch ($mapFunction){ - case 'map': - $response[] = $this->map($object, $mappingName, $context); - break; - case 'mapAll': - $response = array_merge($response, $this->mapAll($object, $mappingName, $context)); - break; - default: - throw new \InvalidArgumentException(sprintf('Invalid mapping name "%s"', $mappingName)); + $mappedObject = $this->$mapFunction($object, $mappingName, $context); + if (!empty($mappedObject)) { + $response = ($mapFunction === 'map') + ? array_merge($response, [$mappedObject]) + : array_merge($response, $mappedObject); } } From 63607f9d105d599fd05d584122a83f79421d08a9 Mon Sep 17 00:00:00 2001 From: Rafaela Mansini Date: Fri, 15 Nov 2024 10:59:41 +0000 Subject: [PATCH 3/4] MINT-9526: Add mergeMapping function to Tools/Mapper --- Tools/Mapper/Mapper.php | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/Tools/Mapper/Mapper.php b/Tools/Mapper/Mapper.php index ac46ea9a..33ef2614 100644 --- a/Tools/Mapper/Mapper.php +++ b/Tools/Mapper/Mapper.php @@ -92,13 +92,18 @@ public function map($obj, $mappingName, $context = []) /** * Merge multiples arrays values in a single mappingName * + * @param array $elements * @param string $mappingName * @param array $mappers * * @return null|string */ - public function mergeMapping($mappingName, $mappers) + public function mergeMapping($elements, $mappingName, $mappers) { + if(empty($elements)) { + return null; + } + if (empty($mappers)) { throw new \InvalidArgumentException('No mapper provided.'); } @@ -106,14 +111,14 @@ public function mergeMapping($mappingName, $mappers) $response = []; foreach ($mappers as $mapper){ - $mapFunction = $mapper[0] ?? null; - $object = $mapper[1] ?? null; - $context = $mapper[2] ?? null; - + $object = $this->getObject($elements, $mapper[1]); if(empty($object)){ continue; } + $mapFunction = $mapper[0] ?? null; + $context = $mapper[2] ?? $mapper[1] ?? null; + if(empty($mapFunction) || empty($context) || !in_array($mapFunction, ['map', 'mapAll'])){ throw new \InvalidArgumentException('No mapper function or context informed'); } @@ -129,6 +134,21 @@ public function mergeMapping($mappingName, $mappers) return $response; } + + private function getObject(array $elements, string $path) { + $keys = explode('.', $path); + $current = $elements; + + foreach ($keys as $key) { + if (!isset($current[$key])) { + return null; + } + $current = $current[$key]; + } + + return $current; + } + /** * @param $mapping * @param $obj From fa2425c1ab123846dfb935cc2513e781fe78c9ea Mon Sep 17 00:00:00 2001 From: Rafaela Mansini Date: Fri, 15 Nov 2024 11:57:34 +0000 Subject: [PATCH 4/4] MINT-9526: Updating tests --- Tests/Unit/Tools/Mapper/MapperTest.php | 82 +++++++++++++++++++------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/Tests/Unit/Tools/Mapper/MapperTest.php b/Tests/Unit/Tools/Mapper/MapperTest.php index 2df398e1..954bd7cb 100644 --- a/Tests/Unit/Tools/Mapper/MapperTest.php +++ b/Tests/Unit/Tools/Mapper/MapperTest.php @@ -272,7 +272,7 @@ public function provideEmptyValues() /** * @dataProvider provideMergeMappings */ - public function testShouldMergeMappings($expectedResult, $mockedMapFunction, $mockedMapAllFunction) + public function testShouldMergeMappings($elements, $mappers, $mockedMapFunction, $mockedMapAllFunction, $expectedResult) { $mapperMock = $this->getMockBuilder(Mapper::class) ->setMethods(['mapAll', 'map']) @@ -281,10 +281,7 @@ public function testShouldMergeMappings($expectedResult, $mockedMapFunction, $mo $mapperMock->method('map')->willReturn($mockedMapFunction); $mapperMock->method('mapAll')->willReturn($mockedMapAllFunction); - $result = $mapperMock->mergeMapping('mappingName', [ - ['map', ['https://media.com/1'], 'packshot'], - ['mapAll', ['https://media.com/2', 'https://media.com/3'], 'eRetailerNonBrand'] - ]); + $result = $mapperMock->mergeMapping($elements, 'mappingName', $mappers); $this->assertSame($expectedResult, $result); } @@ -293,27 +290,65 @@ public function provideMergeMappings() { yield 'Merge mappings' => [ [ - ['name' => 'packshot', 'location' => 'https://media.com/1'], - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] + 'packshot' => 'url://packshot.com', + 'lengow' => null, + 'eRetail' => [ + 'main' => 'url://main.com', + 'nonBrand' => [ + 'url://nonBrand1.com', + 'url://nonBrand2.com' + ] + ] + ], + [ + ['map', 'packshot'], + ['map', 'lengow'], + ['map', 'maps'], + ['map', 'eRetail.main'], + ['mapAll', 'eRetail.nonBrand'], + ], + ['name' => 'singleLine', 'location' => 'https://media.com/1'], + [['name' => 'multipleLines', 'location' => 'https://media.com/2'],['name' => 'multipleLines', 'location' => 'https://media.com/3']], + [ + ['name' => 'singleLine', 'location' => 'https://media.com/1'], + ['name' => 'singleLine', 'location' => 'https://media.com/1'], + ['name' => 'multipleLines', 'location' => 'https://media.com/2'], + ['name' => 'multipleLines', 'location' => 'https://media.com/3'] ], - ['name' => 'packshot', 'location' => 'https://media.com/1'], - [['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']] ]; - yield 'Merge mappings with null map' => [ + yield 'Merge mappings with null mapAll' => [ + [ + 'line' => 'https://media.com/1', + 'lines' => null + ], [ - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'], - ['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3'] + ['map', 'line'], + ['mapAll', 'lines'], ], + ['name' => 'singleLine', 'location' => 'https://media.com/1'], null, - [['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/2'],['name' => 'eRetailerNonBrand', 'location' => 'https://media.com/3']] + [ + ['name' => 'singleLine', 'location' => 'https://media.com/1'] + ], ]; - yield 'Merge mappings with null mapAll' => [ + yield 'Merge mappings with null map' => [ + [ + 'line' => null, + 'lines' => [ + 'https://media.com/2', + 'https://media.com/3' + ] + ], + [ + ['map', 'line'], + ['mapAll', 'lines'], + ], + null, + [['name' => 'multipleLines', 'location' => 'https://media.com/2'],['name' => 'multipleLines', 'location' => 'https://media.com/3']], [ - ['name' => 'packshot', 'location' => 'https://media.com/1'] + ['name' => 'multipleLines', 'location' => 'https://media.com/2'], + ['name' => 'multipleLines', 'location' => 'https://media.com/3'] ], - ['name' => 'packshot', 'location' => 'https://media.com/1'], - null ]; } @@ -323,14 +358,17 @@ public function provideMergeMappings() public function testShouldThrowExceptionIfMappersIsNotCorrect(array $mapper = null) { $this->expectException(\InvalidArgumentException::class); - $this->mapper->mergeMapping('test', $mapper); + $this->mapper->mergeMapping([ + 'line' => 'https://media.com/1', + 'lines' => ['https://media.com/2','https://media.com/3'] + ], 'test', $mapper); +// $this->assertTrue(true); } public function provideInvalidMappersToMerge() { yield 'Null mappers parameter' => [null]; - yield 'Null map function' => [[null,'test', 'test']]; - yield 'Null map function' => [['map','test', null]]; - yield 'Map function is not mapped' => [['invalid','test', 'test']]; + yield 'Map function is not mapped' => [[['invalid', 'line']]]; + yield 'Map function is null' => [[[null, 'line']]]; } }