Passed
Push — develop ( 5ba985...eddaa9 )
by Alex
05:54 queued 02:44
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
        $included = [];
112
113
        foreach ($records as $record) {
114
            $object = $this->transformRecord($record, $fields, $include);
115
116
            if (isset($object['included'])) {
117
                $included = array_merge($included, $object['included']);
118
            }
119
120
            $data[] = $object['data'];
121
        }
122
123
        if ($records instanceof LengthAwarePaginator) {
124
            $links['first'] = $records->url(1);
125
            $links['last'] = $records->url($records->lastPage());
126
            $links['prev'] = $records->previousPageUrl();
127
            $links['next'] = $records->nextPageUrl();
128
        }
129
130
        return array_merge(compact('data'), array_filter(compact('links', 'included')));
131
    }
132
133
    /**
134
     * Transform a set of models into a JSON API collection without additional data.
135
     *
136
     * @param Collection $records
137
     *
138
     * @return array
139
     */
140
    protected function transformCollectionSimple($records)
141
    {
142
        $data = $records->map(function ($record) {
143
            return $this->transformRecordSimple($record)['data'];
144
        })->toArray();
145
146
        return compact('data');
147
    }
148
149
    /**
150
     * Transform a set of models into a collection of JSON API resource
151
     * identifier objects.
152
     *
153
     * @param Collection $records
154
     *
155
     * @return array
156
     */
157
    protected function transformCollectionIdentifiers($records)
158
    {
159
        $data = $records->map(function ($record) {
160
            return $this->transformRecordIdentifier($record)['data'];
161
        });
162
163
        return compact('data');
164
    }
165
166
    /**
167
     * Transform a model relationship into a single, or collection of, JSON API
168
     * resource identifier objects.
169
     *
170
     * @param Model  $record
171
     * @param string $relation
172
     *
173
     * @return array
174
     */
175
    protected function transformRelationship($record, $relation)
176
    {
177
        $data = null;
178
179
        if ($record->{$relation} instanceof Collection) {
180
            return $this->transformCollectionIdentifiers($record->{$relation});
181
        } else if ($record->{$relation} instanceof Model) {
182
            return $this->transformRecordIdentifier($record->{$relation});
183
        }
184
185
        return compact('data');
186
    }
187
}
188