Passed
Push — 1.0.0-alpha ( f08152...da9fae )
by Alex
42s
created

ResourceSerializer::getRequestedFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
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
    protected function getResourceType(): string
141
    {
142
        $modelName = collect(explode('\\', get_class($this->record)))->last();
143
144
        if (config('jsonapi.singular_type_names') !== true) {
145
            $modelName = str_plural($modelName);
146
        }
147
148
        return snake_case($modelName, '-');
149
    }
150
151
    /**
152
     * Return the primary key value for the resource.
153
     *
154
     * @return int|string
155
     */
156
    protected function getPrimaryKey()
157
    {
158
        $value = $this->record->getKey();
159
160
        return is_int($value) ? $value : (string) $value;
161
    }
162
163
    /**
164
     * Return the attribute subset requested for the primary resource type.
165
     */
166
    protected function getRequestedFields(): array
167
    {
168
        $fields = array_get($this->fields, $this->getResourceType());
169
170
        return is_array($fields) ? $fields : preg_split('/,/', $fields, null, PREG_SPLIT_NO_EMPTY);
171
    }
172
173
    /**
174
     * Return the attribute object data for the primary record.
175
     */
176
    protected function transformRecordAttributes(): array
177
    {
178
        $attributes = array_diff_key($this->record->toArray(), $this->record->getRelations());
179
        $attributes = array_except($attributes, ['id']);
180
        $fields = $this->getRequestedFields();
181
182
        if (!empty($fields)) {
183
            $attributes = array_only($attributes, $fields);
184
        }
185
186
        return $attributes;
187
    }
188
189
    /**
190
     * Return a collection of JSON API resource identifier objects by each
191
     * relation on the primary record.
192
     *
193
     * @throws \Huntie\JsonApi\Exceptions\InvalidRelationPathException
194
     *
195
     * @return \Illuminate\Support\Collection
196
     */
197
    protected function transformRecordRelations()
198
    {
199
        return collect($this->relationships)->combine(array_map(function ($relation) {
200
            return [
201
                'data' => (new RelationshipSerializer($this->record, $relation))->toResourceLinkage(),
202
            ];
203
        }, $this->relationships));
204
    }
205
}
206