Test Failed
Pull Request — 1.0.0-release (#18)
by Alex
03:05
created

ResourceSerializer::getIncluded()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 0
1
<?php
2
3
namespace Huntie\JsonApi\Serializers;
4
5
use Illuminate\Support\Collection;
6
7
class ResourceSerializer extends JsonApiSerializer
8
{
9
    /**
10
     * The model instance to transform.
11
     *
12
     * @var \Illuminate\Database\Eloquent\Model
13
     */
14
    protected $record;
15
16
    /**
17
     * The record relationships to return.
18
     *
19
     * @var array
20
     */
21
    protected $relationships;
22
23
    /**
24
     * The subset of attributes to return on each record type.
25
     *
26
     * @var array
27
     */
28
    protected $fields;
29
30
    /**
31
     * The relationships to load and include.
32
     *
33
     * @var array
34
     */
35
    protected $include;
36
37
    /**
38
     * Create a new JSON API resource serializer.
39
     *
40
     * @param \Illuminate\Database\Eloquent\Model $record  The model instance to serialise
41
     * @param array|null                          $fields  Subset of fields to return by record type
42
     * @param array|null                          $include Relations to include
43
     */
44
    public function __construct($record, array $fields = [], array $include = [])
45
    {
46
        parent::__construct();
47
48
        $this->record = $record;
49
        $this->relationships = array_merge(array_keys($record->getRelations()), $include);
50
        $this->fields = array_unique($fields);
51
        $this->include = array_unique($include);
52
    }
53
54
    /**
55
     * Limit which relations can be included.
56
     *
57
     * @param array $include
58
     */
59
    public function scopeIncludes($include)
60
    {
61
        $this->include = array_intersect($this->include, $include);
62
    }
63
64
    /**
65
     * Return a JSON API resource identifier object for the primary record.
66
     *
67
     * @return array
68
     */
69
    public function toResourceIdentifier()
70
    {
71
        return [
72
            'type' => $this->getResourceType(),
73
            'id' => $this->getPrimaryKey(),
74
        ];
75
    }
76
77
    /**
78
     * Return a base JSON API resource object for the primary record containing
79
     * only immediate attributes.
80
     *
81
     * @return array
82
     */
83
    public function toBaseResourceObject()
84
    {
85
        return array_merge($this->toResourceIdentifier(), [
86
            'attributes' => $this->transformRecordAttributes(),
87
        ]);
88
    }
89
90
    /**
91
     * Return a full JSON API resource object for the primary record.
92
     *
93
     * @return array
94
     */
95
    public function toResourceObject()
96
    {
97
        return array_filter(array_merge($this->toBaseResourceObject(), [
98
            'relationships' => $this->transformRecordRelations()->toArray(),
99
        ]));
100
    }
101
102
    /**
103
     * Return primary data for the JSON API document.
104
     *
105
     * @return mixed
106
     */
107
    protected function getPrimaryData()
108
    {
109
        return $this->toResourceObject();
110
    }
111
112
    /**
113
     * Return any secondary included resource objects.
114
     *
115
     * @throws \Huntie\JsonApi\Exceptions\InvalidRelationPathException
116
     *
117
     * @return \Illuminate\Support\Collection
118
     */
119
    public function getIncluded()
120
    {
121
        $included = collect();
122
123
        foreach ($this->include as $relation) {
124
            $records = (new RelationshipSerializer($this->record, $relation, $this->fields))
125
                ->toResourceCollection();
126
127
            if ($records instanceof Collection) {
128
                $included = $included->merge($records);
129
            } else if (!empty($records)) {
130
                $included->push($records);
131
            }
132
        }
133
134
        return $included->unique();
135
    }
136
137
    /**
138
     * Return the primary resource type name.
139
     *
140
     * @return string
141
     */
142
    protected function getResourceType()
143
    {
144
        $modelName = collect(explode('\\', get_class($this->record)))->last();
145
146
        return snake_case(str_plural($modelName), '-');
147
    }
148
149
    /**
150
     * Return the primary key value for the resource.
151
     *
152
     * @return int|string
153
     */
154
    protected function getPrimaryKey()
155
    {
156
        $value = $this->record->getKey();
157
158
        return is_int($value) ? $value : (string) $value;
159
    }
160
161
    /**
162
     * Return the attribute object data for the primary record.
163
     *
164
     * @return array
165
     */
166
    protected function transformRecordAttributes()
167
    {
168
        $attributes = array_diff_key($this->record->toArray(), $this->record->getRelations());
169
        $attributes = array_except($attributes, ['id']);
170
        $fields = array_get($this->fields, $this->getResourceType());
171
172
        if (!empty($fields)) {
173
            $attributes = array_only($attributes, $fields);
174
        }
175
176
        return $attributes;
177
    }
178
179
    /**
180
     * Return a collection of JSON API resource identifier objects by each
181
     * relation on the primary record.
182
     *
183
     * @throws \Huntie\JsonApi\Exceptions\InvalidRelationPathException
184
     *
185
     * @return \Illuminate\Support\Collection
186
     */
187
    protected function transformRecordRelations()
188
    {
189
        return collect($this->relationships)->combine(array_map(function ($relation) {
190
            return [
191
                'data' => (new RelationshipSerializer($this->record, $relation))->toResourceLinkage(),
192
            ];
193
        }, $this->relationships));
194
    }
195
}
196