Passed
Push — documentation ( 2ee0b9...bd9b8c )
by Alex
06:37 queued 03:20
created

JsonApiTransforms::transformRecordIdentifier()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace Huntie\JsonApi\Support;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Pagination\LengthAwarePaginator;
7
use Illuminate\Support\Collection;
8
9
/**
10
 * Transform Eloquent models and collections into JSON API objects.
11
 */
12
trait JsonApiTransforms
13
{
14
    /**
15
     * Transform a model instance into a JSON API object.
16
     *
17
     * @param Model      $record
18
     * @param array|null $fields  Field subset to return
19
     * @param array|null $include Relations to include
20
     *
21
     * @return array
22
     */
23
    protected function transformRecord($record, array $fields = [], array $include = [])
24
    {
25
        $relations = array_unique(array_merge($record->getRelations(), $include));
26
        $attributes = $record->toArray();
27
        $record = $record->load($relations);
28
        $relationships = [];
29
        $included = collect([]);
30
31
        foreach ($relations as $relation) {
32
            $relationships[$relation] = $this->transformRelationship($record, $relation);
33
34
            if (in_array($relation, $include)) {
35
                if ($record->{$relation} instanceof Collection) {
36
                    $included->merge($this->transformCollectionSimple($record->{$relation})['data']);
37
                } else if ($record->{$relation} instanceof Model) {
38
                    $included->push($this->transformRecordSimple($record->{$relation})['data']);
39
                }
40
            }
41
        }
42
43
        array_forget($attributes, $relations);
44
        $included = array_filter($included->toArray());
45
46
        if (!empty($fields)) {
47
            $attributes = array_only($attributes, $fields);
48
        }
49
50
        $data = array_filter([
51
            'type' => str_slug($record->getTable()),
52
            'id' => $record->id,
53
            'attributes' => array_except($attributes, ['id']),
54
            'relationships' => $relationships,
55
        ]);
56
57
        return array_filter(compact('data', 'included'));
58
    }
59
60
    /**
61
     * Transform a model instance into a JSON API object without additonal data.
62
     *
63
     * @param Model $record
64
     *
65
     * @return array
66
     */
67
    protected function transformRecordSimple($record)
68
    {
69
        $attributes = array_diff_key($record->toArray(), $record->getRelations());
70
        $attributes = array_except($attributes, ['id']);
71
72
        return [
73
            'data' => [
74
                'type' => str_slug($record->getTable()),
75
                'id' => $record->id,
76
                'attributes' => $attributes,
77
            ]
78
        ];
79
    }
80
81
    /**
82
     * Transform a model instance into a JSON API resource identifier.
83
     *
84
     * @param Model $record
85
     *
86
     * @return array
87
     */
88
    protected function transformRecordIdentifier($record)
89
    {
90
        return [
91
            'data' => [
92
                'type' => str_slug($record->getTable()),
93
                'id' => $record->id,
94
            ]
95
        ];
96
    }
97
98
    /**
99
     * Transform a set of models into a JSON API collection.
100
     *
101
     * @param Collection|LengthAwarePaginator $records
102
     * @param array                           $fields
103
     * @param array|null                      $include
104
     *
105
     * @return array
106
     */
107
    protected function transformCollection($records, array $fields = [], array $include = [])
108
    {
109
        $data = [];
110
        $links = [];
111
        $meta = [];
112
        $included = [];
113
114
        foreach ($records as $record) {
115
            $object = $this->transformRecord($record, $fields, $include);
116
117
            if (isset($object['included'])) {
118
                $included = array_merge($included, $object['included']);
119
            }
120
121
            $data[] = $object['data'];
122
        }
123
124
        $included = collect($included)->unique()->values()->toArray();
125
126
        if ($records instanceof LengthAwarePaginator) {
127
            $links['first'] = $records->url(1);
128
            $links['last'] = $records->url($records->lastPage());
129
            $links['prev'] = $records->previousPageUrl();
130
            $links['next'] = $records->nextPageUrl();
131
            $meta['total'] = $records->total();
132
        }
133
134
        return array_merge(compact('data'), array_filter(compact('links', 'included', 'meta')));
135
    }
136
137
    /**
138
     * Transform a set of models into a JSON API collection without additional data.
139
     *
140
     * @param Collection $records
141
     *
142
     * @return array
143
     */
144
    protected function transformCollectionSimple($records)
145
    {
146
        $data = $records->map(function ($record) {
147
            return $this->transformRecordSimple($record)['data'];
148
        })->toArray();
149
150
        return compact('data');
151
    }
152
153
    /**
154
     * Transform a set of models into a collection of JSON API resource
155
     * identifier objects.
156
     *
157
     * @param Collection $records
158
     *
159
     * @return array
160
     */
161
    protected function transformCollectionIdentifiers($records)
162
    {
163
        $data = $records->map(function ($record) {
164
            return $this->transformRecordIdentifier($record)['data'];
165
        });
166
167
        return compact('data');
168
    }
169
170
    /**
171
     * Transform a model relationship into a single, or collection of, JSON API
172
     * resource identifier objects.
173
     *
174
     * @param Model  $record
175
     * @param string $relation
176
     *
177
     * @return array
178
     */
179
    protected function transformRelationship($record, $relation)
180
    {
181
        $data = null;
182
183
        if ($record->{$relation} instanceof Collection) {
184
            return $this->transformCollectionIdentifiers($record->{$relation});
185
        } else if ($record->{$relation} instanceof Model) {
186
            return $this->transformRecordIdentifier($record->{$relation});
187
        }
188
189
        return compact('data');
190
    }
191
}
192