1
|
|
|
<?php |
2
|
|
|
declare(strict_types = 1); |
3
|
|
|
|
4
|
|
|
namespace Mikemirten\Component\JsonApi\Hydrator\Extension; |
5
|
|
|
|
6
|
|
|
use Mikemirten\Component\JsonApi\Document\AbstractRelationship; |
7
|
|
|
use Mikemirten\Component\JsonApi\Document\Behaviour\RelationshipsAwareInterface; |
8
|
|
|
use Mikemirten\Component\JsonApi\Document\IdentifierCollectionRelationship; |
9
|
|
|
use Mikemirten\Component\JsonApi\Document\NoDataRelationship; |
10
|
|
|
use Mikemirten\Component\JsonApi\Document\ResourceIdentifierObject; |
11
|
|
|
use Mikemirten\Component\JsonApi\Document\SingleIdentifierRelationship; |
12
|
|
|
use Mikemirten\Component\JsonApi\Exception\InvalidDocumentException; |
13
|
|
|
use Mikemirten\Component\JsonApi\Hydrator\DocumentHydrator; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* "relationships" object extension |
17
|
|
|
* |
18
|
|
|
* @package Mikemirten\Component\JsonApi\Hydrator\Extension |
19
|
|
|
*/ |
20
|
|
|
class RelationshipExtension implements ExtensionInterface |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* {@inheritdoc} |
24
|
|
|
*/ |
25
|
6 |
View Code Duplication |
public function hydrate($object, $source, DocumentHydrator $hydrator) |
|
|
|
|
26
|
|
|
{ |
27
|
6 |
|
if (! $object instanceof RelationshipsAwareInterface) { |
28
|
|
|
throw new InvalidDocumentException(sprintf( |
29
|
|
|
'Given instance of "%s" does not implements "%s"', |
30
|
|
|
get_class($object), |
31
|
|
|
RelationshipsAwareInterface::class |
32
|
|
|
)); |
33
|
|
|
} |
34
|
|
|
|
35
|
6 |
|
foreach ($source as $name => $content) |
36
|
|
|
{ |
37
|
6 |
|
$relationship = $this->createRelationship($content, $hydrator); |
38
|
|
|
|
39
|
4 |
|
$object->setRelationship($name, $relationship); |
40
|
|
|
} |
41
|
4 |
|
} |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Create relationship |
45
|
|
|
* |
46
|
|
|
* @param mixed $source |
47
|
|
|
* @param DocumentHydrator $hydrator |
48
|
|
|
* @return AbstractRelationship |
49
|
|
|
*/ |
50
|
6 |
|
public function createRelationship($source, DocumentHydrator $hydrator): AbstractRelationship |
51
|
|
|
{ |
52
|
6 |
|
if (! isset($source->data)) { |
53
|
1 |
|
return $this->processNoDataRelationship($source, $hydrator); |
54
|
|
|
} |
55
|
|
|
|
56
|
5 |
|
if (is_object($source->data)) { |
57
|
3 |
|
return $this->processSingleIdentifierRelationship($source, $hydrator); |
58
|
|
|
} |
59
|
|
|
|
60
|
2 |
|
if (is_array($source->data)) { |
61
|
2 |
|
return $this->processIdentifierCollectionRelationship($source, $hydrator); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
throw new InvalidDocumentException('If data is present and is not null it must be an object or an array'); |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* Process relationship contains no data |
69
|
|
|
* |
70
|
|
|
* @param mixed $source |
71
|
|
|
* @param DocumentHydrator $hydrator |
72
|
|
|
* @return NoDataRelationship |
73
|
|
|
*/ |
74
|
1 |
|
protected function processNoDataRelationship($source, DocumentHydrator $hydrator): NoDataRelationship |
75
|
|
|
{ |
76
|
1 |
|
$relationship = new NoDataRelationship(); |
77
|
|
|
|
78
|
1 |
|
$hydrator->hydrateObject($relationship, $source); |
79
|
|
|
|
80
|
1 |
|
return $relationship; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Process relationship with single resource identifier |
85
|
|
|
* |
86
|
|
|
* @param mixed $source |
87
|
|
|
* @param DocumentHydrator $hydrator |
88
|
|
|
* @return SingleIdentifierRelationship |
89
|
|
|
*/ |
90
|
3 |
|
protected function processSingleIdentifierRelationship($source, DocumentHydrator $hydrator): SingleIdentifierRelationship |
91
|
|
|
{ |
92
|
3 |
|
$identifier = $this->createResourceIdentifier($source->data, $hydrator); |
93
|
1 |
|
$relationship = new SingleIdentifierRelationship($identifier); |
94
|
|
|
|
95
|
1 |
|
$hydrator->hydrateObject($relationship, $source); |
96
|
|
|
|
97
|
1 |
|
return $relationship; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Process relationship with collection of resource identifiers |
102
|
|
|
* |
103
|
|
|
* @param mixed $source |
104
|
|
|
* @param DocumentHydrator $hydrator |
105
|
|
|
* @return IdentifierCollectionRelationship |
106
|
|
|
*/ |
107
|
2 |
|
protected function processIdentifierCollectionRelationship($source, DocumentHydrator $hydrator): IdentifierCollectionRelationship |
108
|
|
|
{ |
109
|
2 |
|
$relationship = new IdentifierCollectionRelationship(); |
110
|
|
|
|
111
|
2 |
|
foreach ($source->data as $resourceSrc) |
112
|
|
|
{ |
113
|
1 |
|
$relationship->addIdentifier($this->createResourceIdentifier($resourceSrc, $hydrator)); |
114
|
|
|
} |
115
|
|
|
|
116
|
2 |
|
$hydrator->hydrateObject($relationship, $source); |
117
|
|
|
|
118
|
2 |
|
return $relationship; |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Create resource |
123
|
|
|
* |
124
|
|
|
* @param mixed $source |
125
|
|
|
* @param DocumentHydrator $hydrator |
126
|
|
|
* @return ResourceIdentifierObject |
127
|
|
|
*/ |
128
|
4 |
|
protected function createResourceIdentifier($source, DocumentHydrator $hydrator): ResourceIdentifierObject |
129
|
|
|
{ |
130
|
4 |
|
if (! isset($source->id)) { |
131
|
1 |
|
throw new InvalidDocumentException('Resource identifier contains no ID'); |
132
|
|
|
} |
133
|
|
|
|
134
|
3 |
|
if (! isset($source->type)) { |
135
|
1 |
|
throw new InvalidDocumentException('Resource identifier contains no type'); |
136
|
|
|
} |
137
|
|
|
|
138
|
2 |
|
$identifier = new ResourceIdentifierObject($source->id, $source->type); |
139
|
|
|
|
140
|
2 |
|
$hydrator->hydrateObject($identifier, $source); |
141
|
|
|
|
142
|
2 |
|
return $identifier; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* {@inheritdoc} |
147
|
|
|
*/ |
148
|
1 |
|
public function supports(): array |
149
|
|
|
{ |
150
|
1 |
|
return ['relationships']; |
151
|
|
|
} |
152
|
|
|
} |
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.