1
|
|
|
<?php |
2
|
|
|
declare(strict_types = 1); |
3
|
|
|
|
4
|
|
|
namespace Mikemirten\Component\JsonApi\Mapper\Handler; |
5
|
|
|
|
6
|
|
|
use Mikemirten\Component\JsonApi\Mapper\Handler\DataTypeHandler\DataTypeHandlerInterface; |
7
|
|
|
use Mikemirten\Component\JsonApi\Mapper\Handler\Exception\NotIterableAttribute; |
8
|
|
|
use Mikemirten\Component\JsonApi\Mapper\Handler\Exception\UnknownDataTypeException; |
9
|
|
|
use Mikemirten\Component\JsonApi\Mapper\Definition\Attribute; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Data-type manager |
13
|
|
|
* Serves for data processing of types |
14
|
|
|
* |
15
|
|
|
* @package Mikemirten\Component\JsonApi\Mapper\Handler |
16
|
|
|
*/ |
17
|
|
|
class DataTypeManager |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* Data-type handlers |
21
|
|
|
* |
22
|
|
|
* @var DataTypeHandlerInterface[] |
23
|
|
|
*/ |
24
|
|
|
protected $handlers = []; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Register data-type handler |
28
|
|
|
* |
29
|
|
|
* @param DataTypeHandlerInterface $handler |
30
|
|
|
*/ |
31
|
6 |
|
public function registerDataTypeHandler(DataTypeHandlerInterface $handler) |
32
|
|
|
{ |
33
|
6 |
|
foreach ($handler->supports() as $name) { |
34
|
6 |
|
$this->handlers[$name] = $handler; |
35
|
|
|
} |
36
|
6 |
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Process data-type |
40
|
|
|
* |
41
|
|
|
* @param Attribute $definition |
42
|
|
|
* @param mixed $value |
43
|
|
|
* @return mixed |
44
|
|
|
*/ |
45
|
7 |
View Code Duplication |
public function toResource(Attribute $definition, $value) |
|
|
|
|
46
|
|
|
{ |
47
|
7 |
|
if (! $definition->hasType()) { |
48
|
3 |
|
return $this->processNotTypedToResource($definition, $value); |
49
|
|
|
} |
50
|
|
|
|
51
|
4 |
|
$type = $definition->getType(); |
52
|
|
|
|
53
|
4 |
|
if (isset($this->handlers[$type])) { |
54
|
3 |
|
return $this->processHandlerToResource($definition, $value); |
55
|
|
|
} |
56
|
|
|
|
57
|
1 |
|
throw new UnknownDataTypeException($definition); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* Process data-type |
62
|
|
|
* |
63
|
|
|
* @param Attribute $definition |
64
|
|
|
* @param mixed $value |
65
|
|
|
* @return mixed |
66
|
|
|
*/ |
67
|
7 |
View Code Duplication |
public function fromResource(Attribute $definition, $value) |
|
|
|
|
68
|
|
|
{ |
69
|
7 |
|
if (! $definition->hasType()) { |
70
|
3 |
|
return $this->processNotTypedFromResource($definition, $value); |
71
|
|
|
} |
72
|
|
|
|
73
|
4 |
|
$type = $definition->getType(); |
74
|
|
|
|
75
|
4 |
|
if (isset($this->handlers[$type])) { |
76
|
3 |
|
return $this->processHandlerFromResource($definition, $value); |
77
|
|
|
} |
78
|
|
|
|
79
|
1 |
|
throw new UnknownDataTypeException($definition); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Process not-typed value |
84
|
|
|
* Both directions: from object to resource and from resource to object |
85
|
|
|
* |
86
|
|
|
* @param Attribute $definition |
87
|
|
|
* @param mixed $value |
88
|
|
|
* @return mixed |
89
|
|
|
* @throws NotIterableAttribute |
90
|
|
|
*/ |
91
|
3 |
View Code Duplication |
protected function processNotTypedToResource(Attribute $definition, $value) |
|
|
|
|
92
|
|
|
{ |
93
|
3 |
|
if (! $definition->isMany()) { |
94
|
1 |
|
return $value; |
95
|
|
|
} |
96
|
|
|
|
97
|
2 |
|
if ($value instanceof \Traversable) { |
98
|
|
|
return iterator_to_array($value, false); |
99
|
|
|
} |
100
|
|
|
|
101
|
2 |
|
if (is_array($value)) { |
102
|
1 |
|
return $value; |
103
|
|
|
} |
104
|
|
|
|
105
|
1 |
|
throw new NotIterableAttribute($definition, $value); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Process not-typed value |
110
|
|
|
* Both directions: from object to resource and from resource to object |
111
|
|
|
* |
112
|
|
|
* @param Attribute $definition |
113
|
|
|
* @param mixed $value |
114
|
|
|
* @return mixed |
115
|
|
|
* @throws NotIterableAttribute |
116
|
|
|
*/ |
117
|
3 |
View Code Duplication |
protected function processNotTypedFromResource(Attribute $definition, $value) |
|
|
|
|
118
|
|
|
{ |
119
|
3 |
|
if (! $definition->isMany()) { |
120
|
1 |
|
return $value; |
121
|
|
|
} |
122
|
|
|
|
123
|
2 |
|
if ($value instanceof \Traversable) { |
124
|
|
|
return $value; |
125
|
|
|
} |
126
|
|
|
|
127
|
2 |
|
if (is_array($value)) { |
128
|
1 |
|
return new \ArrayIterator($value); |
129
|
|
|
} |
130
|
|
|
|
131
|
1 |
|
throw new NotIterableAttribute($definition, $value); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Process value by registered data-type handler. |
136
|
|
|
* From object to resource. |
137
|
|
|
* |
138
|
|
|
* @param Attribute $definition |
139
|
|
|
* @param mixed $value |
140
|
|
|
* @return mixed |
141
|
|
|
* @throws NotIterableAttribute |
142
|
|
|
*/ |
143
|
3 |
View Code Duplication |
protected function processHandlerToResource(Attribute $definition, $value) |
|
|
|
|
144
|
|
|
{ |
145
|
3 |
|
$type = $definition->getType(); |
146
|
3 |
|
$handler = $this->handlers[$type]; |
147
|
3 |
|
$parameters = $definition->getTypeParameters(); |
148
|
|
|
|
149
|
3 |
|
if (! $definition->isMany()) { |
150
|
1 |
|
return $handler->toResource($value, $type, $parameters); |
151
|
|
|
} |
152
|
|
|
|
153
|
2 |
|
if (! $value instanceof \Traversable && ! is_array($value)) { |
154
|
1 |
|
throw new NotIterableAttribute($definition, $value); |
155
|
|
|
} |
156
|
|
|
|
157
|
1 |
|
$collection = []; |
158
|
|
|
|
159
|
1 |
|
foreach ($value as $item) { |
160
|
1 |
|
$collection[] = $handler->toResource($item, $type, $parameters); |
161
|
|
|
} |
162
|
|
|
|
163
|
1 |
|
return $collection; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Process value by registered data-type handler. |
168
|
|
|
* From resource to object. |
169
|
|
|
* |
170
|
|
|
* @param Attribute $definition |
171
|
|
|
* @param mixed $value |
172
|
|
|
* @return mixed |
173
|
|
|
* @throws NotIterableAttribute |
174
|
|
|
*/ |
175
|
3 |
View Code Duplication |
protected function processHandlerFromResource(Attribute $definition, $value) |
|
|
|
|
176
|
|
|
{ |
177
|
3 |
|
$type = $definition->getType(); |
178
|
3 |
|
$handler = $this->handlers[$type]; |
179
|
3 |
|
$parameters = $definition->getTypeParameters(); |
180
|
|
|
|
181
|
3 |
|
if (! $definition->isMany()) { |
182
|
1 |
|
return $handler->fromResource($value, $type, $parameters); |
183
|
|
|
} |
184
|
|
|
|
185
|
2 |
|
if (! $value instanceof \Traversable && ! is_array($value)) { |
186
|
1 |
|
throw new NotIterableAttribute($definition, $value); |
187
|
|
|
} |
188
|
|
|
|
189
|
1 |
|
$collection = new \ArrayObject(); |
190
|
|
|
|
191
|
1 |
|
foreach ($value as $item) { |
192
|
1 |
|
$collection[] = $handler->fromResource($item, $type, $parameters); |
193
|
|
|
} |
194
|
|
|
|
195
|
1 |
|
return $collection; |
196
|
|
|
} |
197
|
|
|
} |
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.