1<?php
2
3declare(strict_types=1);
4
5namespace JMS\Serializer\Handler;
6
7use JMS\Serializer\GraphNavigatorInterface;
8use JMS\Serializer\JsonSerializationVisitor;
9use JMS\Serializer\SerializationContext;
10use JMS\Serializer\XmlSerializationVisitor;
11use Symfony\Component\Validator\ConstraintViolation;
12use Symfony\Component\Validator\ConstraintViolationList;
13
14final class ConstraintViolationHandler implements SubscribingHandlerInterface
15{
16    /**
17     * {@inheritdoc}
18     */
19    public static function getSubscribingMethods()
20    {
21        $methods = [];
22        $formats = ['xml', 'json'];
23        $types = ['Symfony\Component\Validator\ConstraintViolationList' => 'serializeList', 'Symfony\Component\Validator\ConstraintViolation' => 'serializeViolation'];
24
25        foreach ($types as $type => $method) {
26            foreach ($formats as $format) {
27                $methods[] = [
28                    'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
29                    'type' => $type,
30                    'format' => $format,
31                    'method' => $method . 'To' . $format,
32                ];
33            }
34        }
35
36        return $methods;
37    }
38
39    public function serializeListToXml(XmlSerializationVisitor $visitor, ConstraintViolationList $list, array $type): void
40    {
41        $currentNode = $visitor->getCurrentNode();
42        if (!$currentNode) {
43            $visitor->createRoot();
44        }
45
46        foreach ($list as $violation) {
47            $this->serializeViolationToXml($visitor, $violation);
48        }
49    }
50
51    /**
52     * @return array|\ArrayObject
53     */
54    public function serializeListToJson(JsonSerializationVisitor $visitor, ConstraintViolationList $list, array $type, SerializationContext $context)
55    {
56        return $visitor->visitArray(iterator_to_array($list), $type);
57    }
58
59    public function serializeViolationToXml(XmlSerializationVisitor $visitor, ConstraintViolation $violation, ?array $type = null): void
60    {
61        $violationNode = $visitor->getDocument()->createElement('violation');
62
63        $parent = $visitor->getCurrentNode();
64        if (!$parent) {
65            $visitor->setCurrentAndRootNode($violationNode);
66        } else {
67            $parent->appendChild($violationNode);
68        }
69
70        $violationNode->setAttribute('property_path', $violation->getPropertyPath());
71        $violationNode->appendChild($messageNode = $visitor->getDocument()->createElement('message'));
72
73        $messageNode->appendChild($visitor->getDocument()->createCDATASection($violation->getMessage()));
74    }
75
76    public function serializeViolationToJson(JsonSerializationVisitor $visitor, ConstraintViolation $violation, ?array $type = null): array
77    {
78        return [
79            'property_path' => $violation->getPropertyPath(),
80            'message' => $violation->getMessage(),
81        ];
82    }
83}
84