1 | <?php |
||
26 | final class ObjectNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface, CacheableSupportsMethodInterface |
||
27 | { |
||
28 | // To not use the current normalizer |
||
29 | const WONT_DENORMALIZE = 'wont_denormalize'; |
||
30 | const TYPE_FIELD = '#type'; |
||
31 | |||
32 | /** |
||
33 | * @var NormalizerInterface|DenormalizerInterface |
||
34 | */ |
||
35 | private $serializer; |
||
36 | private $objectNormalizer; |
||
37 | |||
38 | public function __construct(NormalizerInterface $objectNormalizer) |
||
39 | { |
||
40 | if (!$objectNormalizer instanceof DenormalizerInterface) { |
||
41 | throw new \InvalidArgumentException(sprintf('The normalizer used must implement the "%s" interface.', DenormalizerInterface::class)); |
||
42 | } |
||
43 | |||
44 | $this->objectNormalizer = $objectNormalizer; |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * {@inheritdoc} |
||
49 | */ |
||
50 | public function normalize($object, $format = null, array $context = []) |
||
51 | { |
||
52 | return \array_merge([self::TYPE_FIELD => ClassUtils::getClass($object)], $this->objectNormalizer->normalize($object, $format, $context)); |
||
53 | } |
||
54 | |||
55 | /** |
||
56 | * {@inheritdoc} |
||
57 | */ |
||
58 | public function supportsNormalization($data, $format = null) |
||
59 | { |
||
60 | return \is_object($data); |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * {@inheritdoc} |
||
65 | */ |
||
66 | public function denormalize($data, $class, $format = null, array $context = []) |
||
67 | { |
||
68 | if (isset($context[self::WONT_DENORMALIZE]) || \is_object($data) || !\is_iterable($data)) { |
||
69 | return $data; |
||
70 | } |
||
71 | |||
72 | if (null !== $type = $this->extractType($data)) { |
||
73 | return $this->denormalizeObject($data, $type, $format, $context); |
||
|
|||
74 | } |
||
75 | |||
76 | foreach ($data as $key => $value) { |
||
77 | if (!\is_object($value)) { |
||
78 | $data[$key] = $this->denormalizeValue($value, $class, $format, $context); |
||
79 | } |
||
80 | } |
||
81 | |||
82 | return $data; |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * {@inheritdoc} |
||
87 | */ |
||
88 | public function supportsDenormalization($data, $type, $format = null) |
||
92 | |||
93 | /** |
||
94 | * {@inheritdoc} |
||
95 | */ |
||
96 | public function setSerializer(SerializerInterface $serializer) |
||
110 | |||
111 | /** |
||
112 | * {@inheritdoc} |
||
113 | */ |
||
114 | public function hasCacheableSupportsMethod(): bool |
||
118 | |||
119 | /** |
||
120 | * Converts data to $class' object if possible. |
||
121 | * |
||
122 | * @param array $data |
||
123 | * @param string $class |
||
124 | * @param null $format |
||
125 | * @param array $context |
||
126 | * |
||
127 | * @return object|null |
||
128 | */ |
||
129 | private function denormalizeObject(array $data, string $class, $format = null, array $context = []) |
||
134 | |||
135 | /** |
||
136 | * Tries to convert data to $class' object not using current normalizer. |
||
137 | * This is useful if you have your own normalizers - they will have priority over this one. |
||
138 | * |
||
139 | * @param array $data |
||
140 | * @param string $class |
||
141 | * @param null $format |
||
142 | * @param array $context |
||
143 | * |
||
144 | * @return object|null |
||
145 | */ |
||
146 | private function denormalizeObjectInOtherNormalizer(array $data, string $class, $format = null, array $context = []) |
||
152 | |||
153 | /** |
||
154 | * Default denormalization $data to class using symfony's object normalizer. |
||
155 | * |
||
156 | * @param array $data |
||
157 | * @param string $class |
||
158 | * @param null $format |
||
159 | * @param array $context |
||
160 | * |
||
161 | * @return object |
||
162 | */ |
||
163 | private function denormalizeObjectInDefaultObjectNormalizer(array $data, string $class, $format = null, array $context = []) |
||
171 | |||
172 | /** |
||
173 | * Convert raw value to normalized value - object or primitive type. |
||
174 | * |
||
175 | * @param mixed $value |
||
176 | * @param string $class |
||
177 | * @param null $format |
||
178 | * @param array $context |
||
179 | * |
||
180 | * @return object|null |
||
181 | */ |
||
182 | private function denormalizeValue($value, string $class, $format = null, array $context = []) |
||
188 | |||
189 | /** |
||
190 | * Grab class from array. |
||
191 | * |
||
192 | * @param $data |
||
193 | * |
||
194 | * @return string|null |
||
195 | */ |
||
196 | private function extractType(&$data): ?string |
||
207 | |||
208 | /** |
||
209 | * To determine is passed data is a representation of some object. |
||
210 | * |
||
211 | * @param $data |
||
212 | * |
||
213 | * @return bool |
||
214 | */ |
||
215 | private function isObjectArray($data): bool |
||
219 | } |
||
220 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.