1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace TomPHP\HalClient\Processor; |
4
|
|
|
|
5
|
|
|
use Psr\Http\Message\ResponseInterface; |
6
|
|
|
use TomPHP\HalClient\Exception\ProcessingException; |
7
|
|
|
use TomPHP\HalClient\Processor; |
8
|
|
|
use TomPHP\HalClient\ResourceFetcher; |
9
|
|
|
use TomPHP\HalClient\Resource\Field; |
10
|
|
|
use TomPHP\HalClient\Resource\FieldCollection; |
11
|
|
|
use TomPHP\HalClient\Resource\FieldMap; |
12
|
|
|
use TomPHP\HalClient\Resource\Link; |
13
|
|
|
use TomPHP\HalClient\Resource\Resource; |
14
|
|
|
use TomPHP\HalClient\Resource\ResourceCollection; |
15
|
|
|
use stdClass; |
16
|
|
|
use Zend\Diactoros\Stream; |
17
|
|
|
|
18
|
|
|
final class HalJsonProcessor implements Processor |
19
|
|
|
{ |
20
|
|
|
/** @var ResponseInterface */ |
21
|
|
|
private $response; |
22
|
|
|
|
23
|
|
|
/** @var mixed */ |
24
|
|
|
private $data; |
25
|
|
|
|
26
|
|
|
/** @var ResourceFetcher */ |
27
|
|
|
private $fetcher; |
28
|
|
|
|
29
|
|
|
public function getContentType() |
30
|
|
|
{ |
31
|
|
|
return 'application/hal+json'; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** @return Resource */ |
35
|
|
|
public function process(ResponseInterface $response, ResourceFetcher $fetcher) |
36
|
|
|
{ |
37
|
|
|
$this->response = $response; |
38
|
|
|
$this->fetcher = $fetcher; |
39
|
|
|
$this->data = json_decode($response->getBody()); |
40
|
|
|
|
41
|
|
|
if ($this->data === null) { |
42
|
|
|
throw ProcessingException::badJson(json_last_error_msg()); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
return new Resource( |
46
|
|
|
$this->getFields(), |
47
|
|
|
$this->getLinks(), |
48
|
|
|
$this->getResources() |
49
|
|
|
); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** @return Field[] */ |
53
|
|
|
private function getFields() |
54
|
|
|
{ |
55
|
|
|
$fields = []; |
56
|
|
|
|
57
|
|
|
foreach ($this->data as $name => $value) { |
58
|
|
|
if ($name === '_links' || $name === '_embedded') { |
59
|
|
|
continue; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
$fields[$name] = self::createFieldNode($value); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
return $fields; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** @return Link[] */ |
69
|
|
|
private function getLinks() |
70
|
|
|
{ |
71
|
|
|
if (!isset($this->data->_links)) { |
72
|
|
|
return []; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
$links = []; |
76
|
|
|
|
77
|
|
|
foreach ($this->data->_links as $name => $params) { |
78
|
|
|
$links[$name] = new Link( |
79
|
|
|
$this->fetcher, |
80
|
|
|
$params->href |
81
|
|
|
//isset($params->rel) ? $params->rel : null |
|
|
|
|
82
|
|
|
); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
return $links; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** @return Resource[] */ |
89
|
|
|
private function getResources() |
90
|
|
|
{ |
91
|
|
|
if (!isset($this->data->_embedded)) { |
92
|
|
|
return []; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
$resources = []; |
96
|
|
|
|
97
|
|
|
foreach ($this->data->_embedded as $name => $params) { |
98
|
|
|
if (is_array($params)) { |
99
|
|
|
$resources[$name] = new ResourceCollection(array_map( |
100
|
|
|
function ($params) { |
101
|
|
|
return $this->createResourceFromObject($params); |
102
|
|
|
}, |
103
|
|
|
$params |
104
|
|
|
)); |
105
|
|
|
continue; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$resources[$name] = $this->createResourceFromObject($params); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return $resources; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** @return Resource */ |
115
|
|
|
private function createResourceFromObject(stdClass $object) |
116
|
|
|
{ |
117
|
|
|
$processor = new self(); |
118
|
|
|
|
119
|
|
|
return $processor->process( |
120
|
|
|
$this->response->withBody($this->createStream(json_encode($object))), |
121
|
|
|
$this->fetcher |
122
|
|
|
); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param string $data |
127
|
|
|
* |
128
|
|
|
* @return Stream |
129
|
|
|
*/ |
130
|
|
|
private function createStream($data) |
131
|
|
|
{ |
132
|
|
|
return new Stream("data://text/plain,$data"); |
|
|
|
|
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* @param mixed $value |
137
|
|
|
* |
138
|
|
|
* @return FieldMap|FieldCollection|Field |
139
|
|
|
*/ |
140
|
|
|
private function createFieldNode($value) |
141
|
|
|
{ |
142
|
|
|
if (is_object($value)) { |
143
|
|
|
return $this->createFieldMapFromObject($value); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
if (is_array($value)) { |
147
|
|
|
return $this->fromArray($value); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
return new Field($value); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** @return FieldMap */ |
154
|
|
|
private function createFieldMapFromObject(stdClass $object) |
155
|
|
|
{ |
156
|
|
|
$fields = []; |
157
|
|
|
|
158
|
|
|
foreach ($object as $property => $value) { |
159
|
|
|
$fields[$property] = $this->createFieldNode($value); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
return new FieldMap($fields); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* @param mixed[] $values |
167
|
|
|
* |
168
|
|
|
* @return FieldCollection |
169
|
|
|
*/ |
170
|
|
|
public function fromArray(array $values) |
171
|
|
|
{ |
172
|
|
|
return new FieldCollection(array_map(function ($field) { |
173
|
|
|
return $this->createFieldNode($field); |
174
|
|
|
}, $values)); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.