Completed
Push — master ( 2e1d78...d4a74e )
by Toby
66:55 queued 03:07
created

Resource::toArray()   D

Complexity

Conditions 8
Paths 128

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 8

Importance

Changes 4
Bugs 0 Features 4
Metric Value
c 4
b 0
f 4
dl 0
loc 38
ccs 30
cts 30
cp 1
rs 4.6666
cc 8
eloc 23
nc 128
nop 0
crap 8
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
class Resource implements ElementInterface
15
{
16
    use LinksTrait;
17
    use MetaTrait;
18
19
    /**
20
     * @var mixed
21
     */
22
    protected $data;
23
24
    /**
25
     * @var SerializerInterface
26
     */
27
    protected $serializer;
28
29
    /**
30
     * A list of relationships to include.
31
     *
32
     * @var array
33
     */
34
    protected $includes = [];
35
36
    /**
37
     * A list of fields to restrict to.
38
     *
39
     * @var array|null
40
     */
41
    protected $fields;
42
43
    /**
44
     * An array of Resources that should be merged into this one.
45
     *
46
     * @var Resource[]
47
     */
48
    protected $merged = [];
49
50
    /**
51
     * @param mixed $data
52
     * @param SerializerInterface $serializer
53
     */
54 33
    public function __construct($data, SerializerInterface $serializer)
55
    {
56 33
        $this->data = $data;
57 33
        $this->serializer = $serializer;
58 33
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 3
    public function getResources()
64
    {
65 3
        return [$this];
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 21
    public function toArray()
72
    {
73 21
        $array = $this->toIdentifier();
74
75 21
        $array['attributes'] = $this->getAttributes();
76
77 21
        $relationships = $this->getRelationshipsAsArray();
78
79 21
        if (count($relationships)) {
80 3
            $array['relationships'] = $relationships;
81 3
        }
82
83 21
        $links = [];
84 21
        if (! empty($this->links)) {
85 3
            $links = $this->links;
86 3
        }
87 21
        $serializerLinks = $this->serializer->getLinks($this->data);
88 21
        if (! empty($serializerLinks)) {
89 9
            $links = array_merge($serializerLinks, $links);
90 9
        }
91 21
        if (! empty($links)) {
92 9
            $array['links'] = $links;
93 9
        }
94
95 21
        $meta = [];
96 21
        if (! empty($this->meta)) {
97 3
            $meta = $this->meta;
98 3
        }
99 21
        $serializerMeta = $this->serializer->getMeta($this->data);
100 21
        if (! empty($serializerMeta)) {
101 9
            $meta = array_merge($serializerMeta, $meta);
102 9
        }
103 21
        if (! empty($meta)) {
104 9
            $array['meta'] = $meta;
105 9
        }
106
107 21
        return $array;
108
    }
109
110
    /**
111
     * Check whether or not this resource is an identifier (i.e. does it have
112
     * any data attached?).
113
     *
114
     * @return bool
115
     */
116 3
    public function isIdentifier()
117
    {
118 3
        return ! is_object($this->data) && ! is_array($this->data);
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124 27
    public function toIdentifier()
125
    {
126
        $array = [
127 27
            'type' => $this->getType(),
128 27
            'id' => $this->getId()
129 27
        ];
130
131 27
        if (! empty($this->meta)) {
132 6
            $array['meta'] = $this->meta;
133 6
        }
134
135 27
        return $array;
136
    }
137
138
    /**
139
     * Get the resource type.
140
     *
141
     * @return string
142
     */
143 27
    public function getType()
144
    {
145 27
        return $this->serializer->getType($this->data);
146
    }
147
148
    /**
149
     * Get the resource ID.
150
     *
151
     * @return string
152
     */
153 33
    public function getId()
154
    {
155 33
        if (! is_object($this->data) && ! is_array($this->data)) {
156 6
            return (string) $this->data;
157
        }
158
159 30
        return (string) $this->serializer->getId($this->data);
160
    }
161
162
    /**
163
     * Get the resource attributes.
164
     *
165
     * @return array
166
     */
167 21
    public function getAttributes()
168
    {
169 21
        $attributes = (array) $this->serializer->getAttributes($this->data, $this->getOwnFields());
170
171 21
        $attributes = $this->filterFields($attributes);
172
173 21
        $attributes = $this->mergeAttributes($attributes);
174
175 21
        return $attributes;
176
    }
177
178
    /**
179
     * Get the requested fields for this resource type.
180
     *
181
     * @return array|null
182
     */
183 21
    protected function getOwnFields()
184
    {
185 21
        $type = $this->getType();
186
187 21
        if (isset($this->fields[$type])) {
188 3
            return $this->fields[$type];
189
        }
190 18
    }
191
192
    /**
193
     * Filter the given fields array (attributes or relationships) according
194
     * to the requested fieldset.
195
     *
196
     * @param array $fields
197
     * @return array
198
     */
199 21
    protected function filterFields(array $fields)
200
    {
201 21
        if ($requested = $this->getOwnFields()) {
202 3
            $fields = array_intersect_key($fields, array_flip($requested));
203 3
        }
204
205 21
        return $fields;
206
    }
207
208
    /**
209
     * Merge the attributes of merged resources into an array of attributes.
210
     *
211
     * @param array $attributes
212
     * @return array
213
     */
214 21
    protected function mergeAttributes(array $attributes)
215
    {
216 21
        foreach ($this->merged as $resource) {
217 3
            $attributes = array_replace_recursive($attributes, $resource->getAttributes());
0 ignored issues
show
Bug introduced by
The method getAttributes cannot be called on $resource (of type resource).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
218 21
        }
219
220 21
        return $attributes;
221
    }
222
223
    /**
224
     * Get the resource relationships.
225
     *
226
     * @return Relationship[]
227
     */
228 21
    public function getRelationships()
229
    {
230 21
        $relationships = $this->buildRelationships();
231
232 21
        return $this->filterFields($relationships);
233
    }
234
235
    /**
236
     * Get the resource relationships without considering requested ones.
237
     *
238
     * @return Relationship[]
239
     */
240 3
    public function getUnfilteredRelationships()
241
    {
242 3
        return $this->buildRelationships();
243
    }
244
245
    /**
246
     * Get the resource relationships as an array.
247
     *
248
     * @return array
249
     */
250 21
    public function getRelationshipsAsArray()
251
    {
252 21
        $relationships = $this->getRelationships();
253
254 21
        $relationships = $this->convertRelationshipsToArray($relationships);
255
256 21
        return $this->mergeRelationships($relationships);
257
    }
258
259
    /**
260
     * Get an array of built relationships.
261
     *
262
     * @return Relationship[]
263
     */
264 21
    protected function buildRelationships()
265
    {
266 21
        $paths = Util::parseRelationshipPaths($this->includes);
267
268 21
        $relationships = [];
269
270 21
        foreach ($paths as $name => $nested) {
271 3
            $relationship = $this->serializer->getRelationship($this->data, $name);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $relationship is correct as $this->serializer->getRe...hip($this->data, $name) (which targets Tobscure\JsonApi\Seriali...face::getRelationship()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
272
273 3
            if ($relationship) {
274 3
                $relationship->getData()->with($nested)->fields($this->fields);
275
276 3
                $relationships[$name] = $relationship;
277 3
            }
278 21
        }
279
280 21
        return $relationships;
281
    }
282
283
    /**
284
     * Merge the relationships of merged resources into an array of
285
     * relationships.
286
     *
287
     * @param array $relationships
288
     * @return array
289
     */
290 21
    protected function mergeRelationships(array $relationships)
291
    {
292 21
        foreach ($this->merged as $resource) {
293 3
            $relationships = array_replace_recursive($relationships, $resource->getRelationshipsAsArray());
0 ignored issues
show
Bug introduced by
The method getRelationshipsAsArray cannot be called on $resource (of type resource).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
294 21
        }
295
296 21
        return $relationships;
297
    }
298
299
    /**
300
     * Convert the given array of Relationship objects into an array.
301
     *
302
     * @param Relationship[] $relationships
303
     * @return array
304
     */
305
    protected function convertRelationshipsToArray(array $relationships)
306
    {
307 21
        return array_map(function (Relationship $relationship) {
308 3
            return $relationship->toArray();
309 21
        }, $relationships);
310
    }
311
312
    /**
313
     * Merge a resource into this one.
314
     *
315
     * @param Resource $resource
316
     */
317 3
    public function merge(Resource $resource)
318
    {
319 3
        $this->merged[] = $resource;
320 3
    }
321
322
    /**
323
     * {@inheritdoc}
324
     */
325 3
    public function with($relationships)
326
    {
327 3
        $this->includes = array_unique(array_merge($this->includes, (array) $relationships));
328
329 3
        return $this;
330
    }
331
332
    /**
333
     * {@inheritdoc}
334
     */
335 6
    public function fields($fields)
336
    {
337 6
        $this->fields = $fields;
338
339 6
        return $this;
340
    }
341
342
    /**
343
     * @return mixed
344
     */
345
    public function getData()
346
    {
347
        return $this->data;
348
    }
349
350
    /**
351
     * @param mixed $data
352
     */
353
    public function setData($data)
354
    {
355
        $this->data = $data;
356
    }
357
358
    /**
359
     * @return SerializerInterface
360
     */
361
    public function getSerializer()
362
    {
363
        return $this->serializer;
364
    }
365
366
    /**
367
     * @param SerializerInterface $serializer
368
     */
369
    public function setSerializer(SerializerInterface $serializer)
370
    {
371
        $this->serializer = $serializer;
372
    }
373
}
374