Completed
Pull Request — master (#81)
by
unknown
62:45
created

Resource::fields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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
    public function __construct($data, SerializerInterface $serializer)
55
    {
56
        $this->data = $data;
57
        $this->serializer = $serializer;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function getResources()
64
    {
65
        return [$this];
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function toArray()
72
    {
73
        $array = $this->toIdentifier();
74
75
        $array['attributes'] = $this->getAttributes();
76
77
        $relationships = $this->getRelationshipsAsArray();
78
79
        if (count($relationships)) {
80
            $array['relationships'] = $relationships;
81
        }
82
83
        $links = [];
84
        if (! empty($this->links)) {
85
            $links = $this->links;
86
        }
87
        $serializerLinks = $this->serializer->getLinks($this->data);
88
        if (! empty($serializerLinks)) {
89
            $links = array_merge($serializerLinks, $links);
90
        }
91
        if (! empty($links)) {
92
            $array['links'] = $links;
93
        }
94
95
        $meta = [];
96
        if (! empty($this->meta)) {
97
            $meta = $this->meta;
98
        }
99
        $serializerMeta = $this->serializer->getMeta();
100
        if (! empty($serializerMeta)) {
101
            $meta = array_merge($serializerMeta, $meta);
102
        }
103
        if (! empty($meta)) {
104
            $array['meta'] = $meta;
105
        }
106
107
        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
    public function isIdentifier()
117
    {
118
        return ! is_object($this->data) && ! is_array($this->data);
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function toIdentifier()
125
    {
126
        $array = [
127
            'type' => $this->getType(),
128
            'id' => $this->getId()
129
        ];
130
131
        if (! empty($this->meta)) {
132
            $array['meta'] = $this->meta;
133
        }
134
135
        return $array;
136
    }
137
138
    /**
139
     * Get the resource type.
140
     *
141
     * @return string
142
     */
143
    public function getType()
144
    {
145
        return $this->serializer->getType($this->data);
146
    }
147
148
    /**
149
     * Get the resource ID.
150
     *
151
     * @return string
152
     */
153
    public function getId()
154
    {
155
        if (! is_object($this->data) && ! is_array($this->data)) {
156
            return (string) $this->data;
157
        }
158
159
        return (string) $this->serializer->getId($this->data);
160
    }
161
162
    /**
163
     * Get the resource attributes.
164
     *
165
     * @return array
166
     */
167
    public function getAttributes()
168
    {
169
        $attributes = (array) $this->serializer->getAttributes($this->data, $this->getOwnFields());
170
171
        $attributes = $this->filterFields($attributes);
172
173
        $attributes = $this->mergeAttributes($attributes);
174
175
        return $attributes;
176
    }
177
178
    /**
179
     * Get the requested fields for this resource type.
180
     *
181
     * @return array|null
182
     */
183
    protected function getOwnFields()
184
    {
185
        $type = $this->getType();
186
187
        if (isset($this->fields[$type])) {
188
            return $this->fields[$type];
189
        }
190
    }
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
    protected function filterFields(array $fields)
200
    {
201
        if ($requested = $this->getOwnFields()) {
202
            $fields = array_intersect_key($fields, array_flip($requested));
203
        }
204
205
        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
    protected function mergeAttributes(array $attributes)
215
    {
216
        foreach ($this->merged as $resource) {
217
            $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
        }
219
220
        return $attributes;
221
    }
222
223
    /**
224
     * Get the resource relationships.
225
     *
226
     * @return Relationship[]
227
     */
228
    public function getRelationships()
229
    {
230
        $relationships = $this->buildRelationships();
231
232
        return $this->filterFields($relationships);
233
    }
234
235
    /**
236
     * Get the resource relationships without considering requested ones.
237
     *
238
     * @return Relationship[]
239
     */
240
    public function getUnfilteredRelationships()
241
    {
242
        return $this->buildRelationships();
243
    }
244
245
    /**
246
     * Get the resource relationships as an array.
247
     *
248
     * @return array
249
     */
250
    public function getRelationshipsAsArray()
251
    {
252
        $relationships = $this->getRelationships();
253
254
        $relationships = $this->convertRelationshipsToArray($relationships);
255
256
        return $this->mergeRelationships($relationships);
257
    }
258
259
    /**
260
     * Get an array of built relationships.
261
     *
262
     * @return Relationship[]
263
     */
264
    protected function buildRelationships()
265
    {
266
        $paths = Util::parseRelationshipPaths($this->includes);
267
268
        $relationships = [];
269
270
        foreach ($paths as $name => $nested) {
271
            $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
            if ($relationship) {
274
                $relationship->getData()->with($nested)->fields($this->fields);
275
276
                $relationships[$name] = $relationship;
277
            }
278
        }
279
280
        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
    protected function mergeRelationships(array $relationships)
291
    {
292
        foreach ($this->merged as $resource) {
293
            $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
        }
295
296
        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
        return array_map(function (Relationship $relationship) {
308
            return $relationship->toArray();
309
        }, $relationships);
310
    }
311
312
    /**
313
     * Merge a resource into this one.
314
     *
315
     * @param Resource $resource
316
     */
317
    public function merge(Resource $resource)
318
    {
319
        $this->merged[] = $resource;
320
    }
321
322
    /**
323
     * {@inheritdoc}
324
     */
325
    public function with($relationships)
326
    {
327
        $this->includes = array_unique(array_merge($this->includes, (array) $relationships));
328
329
        return $this;
330
    }
331
332
    /**
333
     * {@inheritdoc}
334
     */
335
    public function fields($fields)
336
    {
337
        $this->fields = $fields;
338
339
        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