Skip to content

Commit

Permalink
[Serializer] Allow to include the severity in ConstraintViolationList
Browse files Browse the repository at this point in the history
  • Loading branch information
dunglas authored and fabpot committed May 5, 2020
1 parent 0c19435 commit b06e9ae
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGELOG
* added support for scalar values denormalization
* added support for `\stdClass` to `ObjectNormalizer`
* added the ability to ignore properties using metadata (e.g. `@Symfony\Component\Serializer\Annotation\Ignore`)
* added an option to serialize constraint violations payloads (e.g. severity)

5.0.0
-----
Expand Down
24 changes: 24 additions & 0 deletions Normalizer/ConstraintViolationListNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ConstraintViolationListNormalizer implements NormalizerInterface, Cacheabl
const STATUS = 'status';
const TITLE = 'title';
const TYPE = 'type';
const PAYLOAD_FIELDS = 'payload_fields';

private $defaultContext;
private $nameConverter;
Expand All @@ -43,6 +44,18 @@ public function __construct($defaultContext = [], NameConverterInterface $nameCo
*/
public function normalize($object, string $format = null, array $context = [])
{
if (\array_key_exists(self::PAYLOAD_FIELDS, $context)) {
$payloadFieldsToSerialize = $context[self::PAYLOAD_FIELDS];
} elseif (\array_key_exists(self::PAYLOAD_FIELDS, $this->defaultContext)) {
$payloadFieldsToSerialize = $this->defaultContext[self::PAYLOAD_FIELDS];
} else {
$payloadFieldsToSerialize = [];
}

if (\is_array($payloadFieldsToSerialize) && [] !== $payloadFieldsToSerialize) {
$payloadFieldsToSerialize = array_flip($payloadFieldsToSerialize);
}

$violations = [];
$messages = [];
foreach ($object as $violation) {
Expand All @@ -57,6 +70,17 @@ public function normalize($object, string $format = null, array $context = [])
$violationEntry['type'] = sprintf('urn:uuid:%s', $code);
}

$constraint = $violation->getConstraint();
if (
[] !== $payloadFieldsToSerialize &&
$constraint &&
$constraint->payload &&
// If some or all payload fields are whitelisted, add them
$payloadFields = null === $payloadFieldsToSerialize || true === $payloadFieldsToSerialize ? $constraint->payload : array_intersect_key($constraint->payload, $payloadFieldsToSerialize)
) {
$violationEntry['payload'] = $payloadFields;
}

$violations[] = $violationEntry;

$prefix = $propertyPath ? sprintf('%s: ', $propertyPath) : '';
Expand Down
29 changes: 29 additions & 0 deletions Tests/Normalizer/ConstraintViolationListNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

Expand Down Expand Up @@ -106,4 +107,32 @@ public function testNormalizeWithNameConverter()

$this->assertEquals($expected, $normalizer->normalize($list));
}

/**
* @dataProvider payloadFieldsProvider
*/
public function testNormalizePayloadFields($fields, array $expected = null)
{
$constraint = new NotNull();
$constraint->payload = ['severity' => 'warning', 'anotherField2' => 'aValue'];
$list = new ConstraintViolationList([
new ConstraintViolation('a', 'b', [], 'c', 'd', 'e', null, null, $constraint),
]);

$violation = $this->normalizer->normalize($list, null, [ConstraintViolationListNormalizer::PAYLOAD_FIELDS => $fields])['violations'][0];
if ([] === $fields) {
$this->assertArrayNotHasKey('payload', $violation);

return;
}
$this->assertSame($expected, $violation['payload']);
}

public function payloadFieldsProvider(): iterable
{
yield [['severity', 'anotherField1'], ['severity' => 'warning']];
yield [null, ['severity' => 'warning', 'anotherField2' => 'aValue']];
yield [true, ['severity' => 'warning', 'anotherField2' => 'aValue']];
yield [[]];
}
}

0 comments on commit b06e9ae

Please sign in to comment.