Completed
Push — master ( f43770...25a62d )
by Toby
47:32 queued 45:20
created

Document::setJsonapi()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 3
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of JSON-API.
5
 *
6
 * (c) Toby Zerner <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tobscure\JsonApi;
13
14
use JsonSerializable;
15
16
class Document implements JsonSerializable
17
{
18
    use LinksTrait;
19
    use MetaTrait;
20
21
    /**
22
     * The included array.
23
     *
24
     * @var array
25
     */
26
    protected $included = [];
27
28
    /**
29
     * The errors array.
30
     *
31
     * @var array
32
     */
33
    protected $errors;
34
35
    /**
36
     * The jsonapi array.
37
     *
38
     * @var array
39
     */
40
    protected $jsonapi;
41
42
    /**
43
     * The data object.
44
     *
45
     * @var ElementInterface
46
     */
47
    protected $data;
48
49
    /**
50
     * @param ElementInterface $data
0 ignored issues
show
Documentation introduced by
Should the type for parameter $data not be null|ElementInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
51
     */
52 12
    public function __construct(ElementInterface $data = null)
53
    {
54 12
        $this->data = $data;
55 12
    }
56
57
    /**
58
     * Get included resources.
59
     *
60
     * @param \Tobscure\JsonApi\ElementInterface $element
61
     * @param bool $includeParent
62
     *
63
     * @return \Tobscure\JsonApi\Resource[]
64
     */
65 9
    protected function getIncluded(ElementInterface $element, $includeParent = false)
66
    {
67 9
        $included = [];
68
69 9
        foreach ($element->getResources() as $resource) {
70 9
            if ($resource->isIdentifier()) {
71
                continue;
72
            }
73
74 9
            if ($includeParent) {
75 3
                $included = $this->mergeResource($included, $resource);
76 3
            } else {
77 9
                $type = $resource->getType();
78 9
                $id = $resource->getId();
79
            }
80
81 9
            foreach ($resource->getUnfilteredRelationships() as $relationship) {
82 3
                $includedElement = $relationship->getData();
83
84 3
                if (! $includedElement instanceof ElementInterface) {
85
                    continue;
86
                }
87
88 3
                foreach ($this->getIncluded($includedElement, true) as $child) {
89
                    // If this resource is the same as the top-level "data"
90
                    // resource, then we don't want it to show up again in the
91
                    // "included" array.
92 3
                    if (! $includeParent && $child->getType() === $type && $child->getId() === $id) {
0 ignored issues
show
Bug introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $id does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
93
                        continue;
94
                    }
95
96 3
                    $included = $this->mergeResource($included, $child);
97 3
                }
98 9
            }
99 9
        }
100
101 9
        $flattened = [];
102
103
        array_walk_recursive($included, function ($a) use (&$flattened) {
104 3
            $flattened[] = $a;
105 9
        });
106
107 9
        return $flattened;
108
    }
109
110
    /**
111
     * @param \Tobscure\JsonApi\Resource[] $resources
112
     * @param \Tobscure\JsonApi\Resource $newResource
113
     *
114
     * @return \Tobscure\JsonApi\Resource[]
115
     */
116 3
    protected function mergeResource(array $resources, Resource $newResource)
117
    {
118 3
        $type = $newResource->getType();
119 3
        $id = $newResource->getId();
120
121 3
        if (isset($resources[$type][$id])) {
122
            $resources[$type][$id]->merge($newResource);
123
        } else {
124 3
            $resources[$type][$id] = $newResource;
125
        }
126
127 3
        return $resources;
128
    }
129
130
    /**
131
     * Set the data object.
132
     *
133
     * @param \Tobscure\JsonApi\ElementInterface $element
134
     *
135
     * @return $this
136
     */
137
    public function setData(ElementInterface $element)
138
    {
139
        $this->data = $element;
140
141
        return $this;
142
    }
143
144
    /**
145
     * Set the errors array.
146
     *
147
     * @param array $errors
148
     *
149
     * @return $this
150
     */
151
    public function setErrors($errors)
152
    {
153
        $this->errors = $errors;
154
155
        return $this;
156
    }
157
158
    /**
159
     * Set the jsonapi array.
160
     *
161
     * @param array $jsonapi
162
     *
163
     * @return $this
164
     */
165
    public function setJsonapi($jsonapi)
166
    {
167
        $this->jsonapi = $jsonapi;
168
169
        return $this;
170
    }
171
172
    /**
173
     * Map everything to arrays.
174
     *
175
     * @return array
176
     */
177 12
    public function toArray()
178
    {
179 12
        $document = [];
180
181 12
        if (! empty($this->links)) {
182
            $document['links'] = $this->links;
183
        }
184
185 12
        if (! empty($this->data)) {
186 9
            $document['data'] = $this->data->toArray();
187
188 9
            $resources = $this->getIncluded($this->data);
189
190 9
            if (count($resources)) {
191 3
                $document['included'] = array_map(function (Resource $resource) {
192 3
                    return $resource->toArray();
193 3
                }, $resources);
194 3
            }
195 9
        }
196
197 12
        if (! empty($this->meta)) {
198
            $document['meta'] = $this->meta;
199
        }
200
201 12
        if (! empty($this->errors)) {
202
            $document['errors'] = $this->errors;
203
        }
204
205 12
        if (! empty($this->jsonapi)) {
206
            $document['jsonapi'] = $this->jsonapi;
207
        }
208
209 12
        return $document;
210
    }
211
212
    /**
213
     * Map to string.
214
     *
215
     * @return string
216
     */
217 6
    public function __toString()
218
    {
219 6
        return json_encode($this->toArray());
220
    }
221
222
    /**
223
     * Serialize for JSON usage.
224
     *
225
     * @return array
226
     */
227
    public function jsonSerialize()
228
    {
229
        return $this->toArray();
230
    }
231
}
232