1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types = 1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the FiveLab Resource package |
7
|
|
|
* |
8
|
|
|
* (c) FiveLab |
9
|
|
|
* |
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
11
|
|
|
* file that was distributed with this source code |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
namespace FiveLab\Component\Resource\Serializer; |
15
|
|
|
|
16
|
|
|
use FiveLab\Component\Resource\Resource\ResourceInterface; |
17
|
|
|
use FiveLab\Component\Resource\Serializer\Events\AfterDenormalizationEvent; |
18
|
|
|
use FiveLab\Component\Resource\Serializer\Events\AfterNormalizationEvent; |
19
|
|
|
use FiveLab\Component\Resource\Serializer\Events\BeforeDenormalizationEvent; |
20
|
|
|
use FiveLab\Component\Resource\Serializer\Events\BeforeNormalizationEvent; |
21
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
22
|
|
|
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; |
23
|
|
|
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; |
24
|
|
|
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; |
25
|
|
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface; |
26
|
|
|
use Symfony\Component\Serializer\Serializer as SymfonySerializer; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Override the default serializer for add ability for adding dynamically |
30
|
|
|
* normalizers before serialization and deserialization processes. |
31
|
|
|
* |
32
|
|
|
* @author Vitaliy Zhuk <[email protected]> |
33
|
|
|
*/ |
34
|
|
|
class Serializer extends SymfonySerializer implements SerializerInterface |
35
|
|
|
{ |
36
|
|
|
/** |
37
|
|
|
* @var EventDispatcherInterface |
38
|
|
|
*/ |
39
|
|
|
private $eventDispatcher; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Constructor. |
43
|
|
|
* |
44
|
|
|
* @param array $normalizers |
45
|
|
|
* @param array $encoders |
46
|
|
|
* @param EventDispatcherInterface $eventDispatcher |
47
|
|
|
*/ |
48
|
8 |
|
public function __construct(array $normalizers, array $encoders, EventDispatcherInterface $eventDispatcher) |
49
|
|
|
{ |
50
|
8 |
|
parent::__construct($normalizers, $encoders); |
51
|
|
|
|
52
|
8 |
|
$this->eventDispatcher = $eventDispatcher; |
53
|
8 |
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* {@inheritdoc} |
57
|
|
|
* |
58
|
|
|
* @throws \Exception |
59
|
|
|
*/ |
60
|
4 |
|
public function normalize($data, $format = null, array $context = []) |
61
|
|
|
{ |
62
|
4 |
|
if ($data instanceof ResourceInterface) { |
63
|
4 |
|
$event = new BeforeNormalizationEvent($data, (string) $format, $context); |
64
|
4 |
|
$this->eventDispatcher->dispatch(SerializationEvents::BEFORE_NORMALIZATION, $event); |
65
|
|
|
} |
66
|
|
|
|
67
|
4 |
|
$countNormalizers = 0; |
68
|
|
|
|
69
|
4 |
View Code Duplication |
if (\array_key_exists('normalizers', $context)) { |
|
|
|
|
70
|
|
|
/** @var NormalizerInterface[] $normalizers */ |
71
|
2 |
|
$normalizers = \array_reverse($context['normalizers']); |
72
|
|
|
|
73
|
2 |
|
foreach ($normalizers as $normalizer) { |
74
|
2 |
|
if ($normalizer instanceof NormalizerInterface) { |
75
|
2 |
|
$countNormalizers++; |
76
|
|
|
|
77
|
2 |
|
$this->prepareNormalizer($normalizer); |
78
|
2 |
|
\array_unshift($this->normalizers, $normalizer); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
try { |
84
|
4 |
|
$normalized = parent::normalize($data, $format, $context); |
85
|
3 |
|
} finally { |
86
|
4 |
|
for ($i = 0; $i < $countNormalizers; $i++) { |
|
|
|
|
87
|
2 |
|
\array_shift($this->normalizers); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
3 |
View Code Duplication |
if ($data instanceof ResourceInterface) { |
|
|
|
|
92
|
3 |
|
$event = new AfterNormalizationEvent($data, $normalized, (string) $format, $context); |
93
|
3 |
|
$this->eventDispatcher->dispatch(SerializationEvents::AFTER_NORMALIZATION, $event); |
94
|
|
|
} |
95
|
|
|
|
96
|
3 |
|
return $normalized; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* {@inheritdoc} |
101
|
|
|
*/ |
102
|
4 |
|
public function denormalize($data, $type, $format = null, array $context = []) |
103
|
|
|
{ |
104
|
4 |
View Code Duplication |
if (\is_a($type, ResourceInterface::class, true)) { |
|
|
|
|
105
|
4 |
|
$event = new BeforeDenormalizationEvent($data, $type, $format, $context); |
106
|
4 |
|
$this->eventDispatcher->dispatch(SerializationEvents::BEFORE_DENORMALIZATION, $event); |
107
|
|
|
} |
108
|
|
|
|
109
|
4 |
|
$countDenormalizers = 0; |
110
|
|
|
|
111
|
4 |
View Code Duplication |
if (\array_key_exists('normalizers', $context)) { |
|
|
|
|
112
|
|
|
/** @var NormalizerInterface[] $normalizers */ |
113
|
2 |
|
$normalizers = \array_reverse($context['normalizers']); |
114
|
|
|
|
115
|
2 |
|
foreach ($normalizers as $normalizer) { |
116
|
2 |
|
if ($normalizer instanceof DenormalizerInterface) { |
117
|
2 |
|
$countDenormalizers++; |
118
|
|
|
|
119
|
2 |
|
$this->prepareDenormalizer($normalizer); |
120
|
2 |
|
\array_unshift($this->normalizers, $normalizer); |
121
|
|
|
} |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
try { |
126
|
4 |
|
$denormalized = parent::denormalize($data, $type, $format, $context); |
127
|
3 |
|
} finally { |
128
|
4 |
|
for ($i = 0; $i < $countDenormalizers; $i++) { |
|
|
|
|
129
|
2 |
|
\array_shift($this->normalizers); |
130
|
|
|
} |
131
|
|
|
} |
132
|
|
|
|
133
|
3 |
View Code Duplication |
if (\is_a($type, ResourceInterface::class, true)) { |
|
|
|
|
134
|
3 |
|
$event = new AfterDenormalizationEvent($data, $denormalized, (string) $format, $context); |
|
|
|
|
135
|
3 |
|
$this->eventDispatcher->dispatch(SerializationEvents::AFTER_DENORMALIZATION, $event); |
136
|
|
|
} |
137
|
|
|
|
138
|
3 |
|
return $denormalized; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Prepare normalizer |
143
|
|
|
* |
144
|
|
|
* @param NormalizerInterface $normalizer |
145
|
|
|
*/ |
146
|
2 |
|
private function prepareNormalizer(NormalizerInterface $normalizer): void |
147
|
|
|
{ |
148
|
2 |
|
if ($normalizer instanceof NormalizerAwareInterface) { |
149
|
2 |
|
$normalizer->setNormalizer($this); |
150
|
|
|
} |
151
|
2 |
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Prepare denormalizer |
155
|
|
|
* |
156
|
|
|
* @param DenormalizerInterface $denormalizer |
157
|
|
|
*/ |
158
|
2 |
|
private function prepareDenormalizer(DenormalizerInterface $denormalizer): void |
159
|
|
|
{ |
160
|
2 |
|
if ($denormalizer instanceof DenormalizerAwareInterface) { |
161
|
2 |
|
$denormalizer->setDenormalizer($this); |
162
|
|
|
} |
163
|
2 |
|
} |
164
|
|
|
} |
165
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.