HalJsonProcessor::createFieldMapFromObject()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
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
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $data instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
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