8000 [Serializer] Added a ConstraintViolationListNormalizer by lyrixx · Pull Request #22150 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Serializer] Added a ConstraintViolationListNormalizer #22150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
Expand Down Expand Up @@ -1227,6 +1228,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
$container->removeDefinition('serializer.normalizer.dateinterval');
}

if (!class_exists(ConstraintViolationListNormalizer::class)) {
$container->removeDefinition('serializer.normalizer.constraint_violation_list');
}

if (!class_exists(ClassDiscriminatorFromClassMetadata::class)) {
$container->removeAlias('Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface');
$container->removeDefinition('serializer.mapping.class_discriminator_resolver');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
<service id="Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface" alias="serializer.mapping.class_discriminator_resolver" />

<!-- Normalizer -->
<service id="serializer.normalizer.constraint_violation_list" class="Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer">
<!-- Run before serializer.normalizer.object -->
<tag name="serializer.normalizer" priority="-915" />
</service>

<service id="serializer.normalizer.dateinterval" class="Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer">
<!-- Run before serializer.normalizer.object -->
<tag name="serializer.normalizer" priority="-915" />
Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/Component/Serializer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CHANGELOG
maximum depth is reached
* added optional `int[] $ignoredNodeTypes` argument to `XmlEncoder::__construct`. XML decoding now
ignores comment node types by default.
* added `ConstraintViolationListNormalizer`

4.0.0
-----
Expand All @@ -33,7 +34,7 @@ CHANGELOG
* added support for serializing `DateInterval` objects
* added getter for extra attributes in `ExtraAttributesException`
* improved `CsvEncoder` to handle variable nested structures
* CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable
* CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable
* added `$context` when checking for encoding, decoding and normalizing in `Serializer`

3.3.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Normalizer;

use Symfony\Component\Validator\ConstraintViolationListInterface;

/**
* A normalizer that normalizes a ConstraintViolationListInterface instance.
*
* This Normalizer implements RFC7807 {@link https://tools.ietf.org/html/rfc7807}.
*
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ConstraintViolationListNormalizer implements NormalizerInterface
{
/**
* {@inheritdoc}
*/
public function normalize($object, $format = null, array $context = array())
{
$violations = array();
$messages = array();
foreach ($object as $violation) {
$violations[] = array(
'propertyPath' => $violation->getPropertyPath(),
'message' => $violation->getMessage(),
'code' => $violation->getCode(),
);
$propertyPath = $violation->getPropertyPath();
$prefix = $propertyPath ? sprintf('%s: ', $propertyPath) : '';
$messages[] = $prefix.$violation->getMessage();
}

return array(
'title' => isset($context['title']) ? $context['title'] : 'An error occurred',
'detail' => $messages ? implode("\n", $messages) : '',
'violations' => $violations,
);
}

/**
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = null)
{
return $data instanceof ConstraintViolationListInterface;
}
}
EDBE
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Serializer\Tests\Normalizer;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

/**
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class ConstraintViolationListNormalizerTest extends TestCase
{
private $normalizer;

protected function setUp()
{
$this->normalizer = new ConstraintViolationListNormalizer();
}

public function testSupportsNormalization()
{
$this->assertTrue($this->normalizer->supportsNormalization(new ConstraintViolationList()));
$this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
}

public function testNormalize()
{
$list = new ConstraintViolationList(array(
new ConstraintViolation('a', 'b', array(), 'c', 'd', 'e', null, 'f'),
new ConstraintViolation('1', '2', array(), '3', '4', '5', null, '6'),
));

$expected = array(
'title' => 'An error occurred',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RFC 7807 is unambiguous on this point:

3.1. Members of a Problem Details Object

A problem details object can have the following members:

  • "type" (string) - ... When
    this member is not present, its value is assumed to be
    "about:blank".

4.2. Predefined Problem Types

This specification reserves the use of one URI as a problem type:

The "about:blank" URI [RFC6694], when used as a problem type,
indicates that the problem has no additional semantics beyond that of
the HTTP status code.

When "about:blank" is used, the title SHOULD be the same as the
recommended HTTP status phrase for that code (e.g., "Not Found" for
404, and so on), although it MAY be localized to suit client
preferences (expressed with the Accept-Language request header).

Please note that according to how the "type" member is defined
(Section 3.1), the "about:blank" URI is the default value for that
member. Consequently, any problem details object not carrying an
explicit "type" member implicitly uses this URI.

Perhaps:

{
  "type": "/validation-error",
  "title": "Validation failed",
  ...
}

'detail' => 'd: a
4: 1',
'violations' => array(
array(
'propertyPath' => 'd',
'message' => 'a',
'code' => 'f',
),
array(
'propertyPath' => '4',
'message' => '1',
'code' => '6',
),
),
);

$this->assertEquals($expected, $this->normalizer->normalize($list));
}
}
1E0A
1 change: 1 addition & 0 deletions src/Symfony/Component/Serializer/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"symfony/http-foundation": "~3.4|~4.0",
"symfony/cache": "~3.4|~4.0",
"symfony/property-info": "~3.4|~4.0",
"symfony/validator": "~3.4|~4.0",
"doctrine/annotations": "~1.0",
"symfony/dependency-injection": "~3.4|~4.0",
"doctrine/cache": "~1.0",
Expand Down
0