From 406074bdba0a2367b20f2e2d0d0056553f4a3391 Mon Sep 17 00:00:00 2001 From: Alexis Thinardon Date: Wed, 6 Mar 2019 12:02:10 +0100 Subject: [PATCH] Returned all errors at a time, #9 --- README.md | 21 +++ composer.json | 3 +- src/AbstractMappingTransformer.php | 33 +++- src/Exception/JsonOptimusException.php | 11 ++ tests/AbstractMappingTransformerTest.php | 194 +++++++++++++++-------- 5 files changed, 194 insertions(+), 68 deletions(-) create mode 100644 src/Exception/JsonOptimusException.php diff --git a/README.md b/README.md index 2f5805d..69c826b 100644 --- a/README.md +++ b/README.md @@ -189,4 +189,25 @@ condition: - c ``` +#### Get all errors mapping at a time + +If you want to return all errors at a time you can set the next parameters in config + +```yaml +# mapping.yaml +transformer: + parameters: + show_all_errors: true + mapping: + title: + from: 'title' + to: 'title' + participants_1_civility: + from: 'user.civility' + to: 'participants.0.civility' + participants_1_name: + from: 'user.lastname' + to: 'participants.0.name' +``` + diff --git a/composer.json b/composer.json index 5d46c0a..943243d 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ }, "require": { "php": "^5.6|>=7.0.8", - "symfony/property-access": "^3.4| ^4.0" + "symfony/property-access": "^3.4| ^4.0", + "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^5.7" diff --git a/src/AbstractMappingTransformer.php b/src/AbstractMappingTransformer.php index f5fb5f4..0a549c7 100644 --- a/src/AbstractMappingTransformer.php +++ b/src/AbstractMappingTransformer.php @@ -2,6 +2,7 @@ namespace Biig\Optimus; +use Biig\Optimus\Exception\JsonOptimusException; use Biig\Optimus\Exception\OptimusException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessor; @@ -40,8 +41,18 @@ abstract public function transform(array $data); protected function transformFromMapping(array $mapping, array $data) { $result = []; + $errors = []; + $returnAllErrors = false; - foreach ($mapping as $node) { + if (array_key_exists('parameters', $mapping) && array_key_exists('show_all_errors', $mapping['parameters'])) { + $returnAllErrors = boolval($mapping['parameters']['show_all_errors']); + } + + if (!array_key_exists('mapping', $mapping)) { + throw new OptimusException('mapping key is missing.'); + } + + foreach ($mapping['mapping'] as $node) { // Only transform current node if no condition prevent it if ($this->areConditionsValidated($node, $data)) { // Get our node value @@ -49,7 +60,13 @@ protected function transformFromMapping(array $mapping, array $data) // If we didn't get value but field was required, throw OptimusException if (isset($node['required']) && true === $node['required'] && null === $nodeValue) { - throw new OptimusException('Field ' . $node['from'] . ' required.'); + $message = 'Field ' . $node['from'] . ' required.'; + if (!$returnAllErrors) { + throw new OptimusException($message); + } else { + $errors[] = $message; + continue; + } } if (isset($node['dependencies'])) { @@ -62,7 +79,13 @@ protected function transformFromMapping(array $mapping, array $data) } if ($dependenciesExist && null === $nodeValue) { - throw new OptimusException('Field ' . $node['from'] . ' required if dependencies true.'); + $message = 'Field ' . $node['from'] . ' required if dependencies true.'; + if (!$returnAllErrors) { + throw new OptimusException($message); + } else { + $errors[] = $message; + continue; + } } } @@ -73,6 +96,10 @@ protected function transformFromMapping(array $mapping, array $data) } } + if ($returnAllErrors && !empty($errors)) { + throw new JsonOptimusException($errors); + } + return $result; } diff --git a/src/Exception/JsonOptimusException.php b/src/Exception/JsonOptimusException.php new file mode 100644 index 0000000..3768b29 --- /dev/null +++ b/src/Exception/JsonOptimusException.php @@ -0,0 +1,11 @@ + [ - 'from' => 'foo', - 'to' => 'bar', - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo', + 'to' => 'bar', + ], + ] ]; $data = [ 'foo' => 'baz', @@ -32,10 +34,12 @@ public function testTransformFromTo() public function testTransformFromToWithDepth() { $mapping = [ - 'node' => [ - 'from' => 'foo1.foo2', - 'to' => 'bar1.bar2.bar3', - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo1.foo2', + 'to' => 'bar1.bar2.bar3', + ], + ] ]; $data = [ 'foo1' => ['foo2' => 'foo'] @@ -53,13 +57,15 @@ public function testTransformFromToWithDepth() public function testTransformToFunction() { $mapping = [ - 'node' => [ - 'to' => 'bar', - 'function' => [ - 'name' => 'getString', - 'params' => ['foo'] - ] - ], + 'mapping' => [ + 'node' => [ + 'to' => 'bar', + 'function' => [ + 'name' => 'getString', + 'params' => ['foo'] + ] + ], + ] ]; $data = [ 'foo' => 'baz', @@ -77,11 +83,13 @@ public function testTransformToFunction() public function testTransformFromToDefaultConstant() { $mapping = [ - 'node' => [ - 'from' => 'foo', - 'to' => 'bar', - 'default' => 'default', - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo', + 'to' => 'bar', + 'default' => 'default', + ], + ] ]; $data = []; $expected = [ @@ -97,15 +105,17 @@ public function testTransformFromToDefaultConstant() public function testTransformFromToDefaultFunction() { $mapping = [ - 'node' => [ - 'to' => 'bar', - 'default' => [ - 'function' => [ - 'name' => 'getString', - 'params' => ['foo'] + 'mapping' => [ + 'node' => [ + 'to' => 'bar', + 'default' => [ + 'function' => [ + 'name' => 'getString', + 'params' => ['foo'] + ], ], ], - ], + ] ]; $data = [ 'foo' => 'I am a string' @@ -127,11 +137,13 @@ public function testTransformFromToDefaultFunction() public function testItThrowAnException() { $mapping = [ - 'node' => [ - 'from' => 'foo', - 'to' => 'bar', - 'required' => true, - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo', + 'to' => 'bar', + 'required' => true, + ], + ] ]; $transformer = new ProxyDummyTransformer(); @@ -141,13 +153,15 @@ public function testItThrowAnException() public function testExistsCondition() { $mapping = [ - 'node' => [ - 'from' => 'foo1.foo2', - 'to' => 'bar1.bar2.bar3', - 'condition' => [ - 'exists' => 'baz' - ] - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo1.foo2', + 'to' => 'bar1.bar2.bar3', + 'condition' => [ + 'exists' => 'baz' + ] + ], + ] ]; $data = [ @@ -168,13 +182,15 @@ public function testExistsCondition() public function testNotValidatedCondition() { $mapping = [ - 'node' => [ - 'from' => 'foo1.foo2', - 'to' => 'bar1.bar2.bar3', - 'condition' => [ - 'exists' => 'baz' - ] - ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo1.foo2', + 'to' => 'bar1.bar2.bar3', + 'condition' => [ + 'exists' => 'baz' + ] + ], + ] ]; $data = [ @@ -192,16 +208,18 @@ public function testNotValidatedCondition() public function testArrayCondition() { $mapping = [ - 'node' => [ - 'from' => 'foo1.foo2', - 'to' => 'bar1.bar2.bar3', - 'condition' => [ - 'exists' => [ - 'baz', - 'boz' + 'mapping' => [ + 'node' => [ + 'from' => 'foo1.foo2', + 'to' => 'bar1.bar2.bar3', + 'condition' => [ + 'exists' => [ + 'baz', + 'boz' + ] ] - ] - ], + ], + ] ]; $data = [ @@ -223,16 +241,18 @@ public function testArrayCondition() public function testNotValidatedArrayCondition() { $mapping = [ - 'node' => [ - 'from' => 'foo1.foo2', - 'to' => 'bar1.bar2.bar3', - 'condition' => [ - 'exists' => [ - 'baz', - 'boz' + 'mapping' => [ + 'node' => [ + 'from' => 'foo1.foo2', + 'to' => 'bar1.bar2.bar3', + 'condition' => [ + 'exists' => [ + 'baz', + 'boz' + ] ] - ] - ], + ], + ] ]; $data = [ @@ -247,6 +267,52 @@ public function testNotValidatedArrayCondition() $this->assertEquals($expected, $result); } + + /** + * @expectedException \Biig\Optimus\Exception\JsonOptimusException + * @expectedExceptionMessage ["Field foo required.","Field bar required."] + */ + public function testItThrowAnJsonOptimusException() + { + $mapping = [ + 'parameters' => [ + 'show_all_errors' => true + ], + 'mapping' => [ + 'node' => [ + 'from' => 'foo', + 'to' => 'bar', + 'required' => true, + ], + 'node2' => [ + 'from' => 'bar', + 'to' => 'foo', + 'required' => true, + ], + ] + ]; + + $transformer = new ProxyDummyTransformer(); + $transformer->transformFromMapping($mapping, []); + } + + /** + * @expectedException \Biig\Optimus\Exception\OptimusException + * @expectedExceptionMessage mapping key is missing. + */ + public function testItThrowAnOptimusExceptionOnMissingMappingKey() + { + $mapping = [ + 'node' => [ + 'from' => 'foo', + 'to' => 'bar', + 'required' => true, + ] + ]; + + $transformer = new ProxyDummyTransformer(); + $transformer->transformFromMapping($mapping, []); + } } class ProxyDummyTransformer extends AbstractMappingTransformer