Passed
Push — listings ( ef25a5 )
by Alex
02:55
created

JsonApiController::transformRecord()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
c 3
b 0
f 2
dl 0
loc 41
rs 8.439
cc 5
eloc 25
nc 8
nop 3
1
<?php
2
3
namespace Huntie\JsonApi\Http\Controllers;
4
5
use Huntie\JsonApi\Http\JsonApiResponse;
6
use Huntie\JsonApi\Support\JsonApiErrors;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Http\Request;
9
use Illuminate\Http\Response;
10
use Illuminate\Routing\Controller;
11
12
abstract class JsonApiController extends Controller
13
{
14
    use JsonApiErrors;
15
16
    /**
17
     * Return the Eloquent Model for the resource.
18
     *
19
     * @return Model
20
     */
21
    abstract protected function getModel();
22
23
    /**
24
     * Return the type name of the resource.
25
     *
26
     * @return string
27
     */
28
    protected function getModelType()
29
    {
30
        return $this->getModel()->getTable();
31
    }
32
33
    /**
34
     * Return a listing of the resource.
35
     *
36
     * @param Request $request
37
     *
38
     * @return JsonApiResponse
39
     */
40
    public function indexAction(Request $request)
41
    {
42
        $records = $this->getModel()->all();
43
        $params = $this->getRequestParameters($request);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
44
45
        return new JsonApiResponse($this->transformCollection($records, $params['fields']));
46
    }
47
48
    /**
49
     * Store a new record.
50
     *
51
     * @param Request $request
52
     *
53
     * @return JsonApiResponse
54
     */
55
    public function storeAction(Request $request)
56
    {
57
        $record = $this->getModel()->create((array) $request->input('data.attributes'));
58
59
        return new JsonApiResponse($this->transformRecord($record), Response::HTTP_CREATED);
60
    }
61
62
    /**
63
     * Return a specified record.
64
     *
65
     * @param Request   $request
66
     * @param Model|int $record
67
     *
68
     * @return JsonApiResponse
69
     */
70
    public function showAction(Request $request, $record)
71
    {
72
        $record = $record instanceof Model ? $record : $this->findModelInstance($record);
73
        $params = $this->getRequestParameters($request);
74
75
        return new JsonApiResponse($this->transformRecord($record, $params['fields'], $params['include']));
76
    }
77
78
    /**
79
     * Update a specified record.
80
     *
81
     * @param Request   $request
82
     * @param Model|int $record
83
     *
84
     * @return JsonApiResponse
85
     */
86
    public function updateAction(Request $request, $record)
87
    {
88
        $record = $record instanceof Model ? $record : $this->findModelInstance($record);
89
        $record->update((array) $request->input('data.attributes'));
90
91
        return $this->showAction($request, $record);
92
    }
93
94
    /**
95
     * Destroy a specified record.
96
     *
97
     * @param Request   $request
98
     * @param Model|int $record
99
     *
100
     * @return JsonApiResponse
101
     */
102
    public function destroyAction(Request $request, $record)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
103
    {
104
        $record = $record instanceof Model ? $record : $this->findModelInstance($record);
105
        $record->delete();
106
107
        return new JsonApiResponse(null, Response::HTTP_NO_CONTENT);
108
    }
109
110
    /**
111
     * Return an instance of the resource by primary key.
112
     *
113
     * @param int $key
114
     *
115
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
116
     *
117
     * @return Model
118
     */
119
    protected function findModelInstance($key)
120
    {
121
        return $this->getModel()->findOrFail($key);
122
    }
123
124
    /**
125
     * Return any JSON API resource parameters from a request.
126
     *
127
     * @param Request $request
128
     *
129
     * @return array
130
     */
131
    protected function getRequestParameters($request)
132
    {
133
        return [
134
            'fields' => $this->getRequestQuerySet($request, 'fields.' . $this->getModelType()),
135
            'include' => $this->getRequestQuerySet($request, 'include'),
136
        ];
137
    }
138
139
    /**
140
     * Return any comma separated values in a request query field as an array.
141
     *
142
     * @param Request $request
143
     * @param string  $key
144
     *
145
     * @return array
146
     */
147
    protected function getRequestQuerySet($request, $key)
148
    {
149
        return preg_split('/,/', $request->input($key), null, PREG_SPLIT_NO_EMPTY);
150
    }
151
152
    /**
153
     * Transform a set of models into a JSON API collection.
154
     *
155
     * @param \Illuminate\Support\Collection $records
156
     * @param array                          $fields
157
     *
158
     * @return array
159
     */
160
    protected function transformCollection($records, array $fields = [])
161
    {
162
        $data = [];
163
164
        foreach ($records as $record) {
165
            $data[] = $this->transformRecord($record, $fields)['data'];
166
        }
167
168
        return compact('data');
169
    }
170
171
    /**
172
     * Transform a model instance into a JSON API object.
173
     *
174
     * @param Model      $record
175
     * @param array|null $fields  Field names of attributes to limit to
176
     * @param array|null $include Relations to include
177
     *
178
     * @return array
179
     */
180
    protected function transformRecord($record, array $fields = [], array $include = [])
181
    {
182
        $relations = array_unique(array_merge($record->getRelations(), $include));
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
183
        $attributes = $record->load($relations)->toArray();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
184
        $relationships = [];
185
        $included = [];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
186
187
        foreach ($relations as $relation) {
188
            $relationships[$relation] = [
189
                'data' => []
190
            ];
191
192
            foreach (array_pull($attributes, $relation) as $relatedRecord) {
193
                $relationships[$relation]['data'][] = [
194
                    'type' => $relation,
195
                    'id' => $relatedRecord['id'],
196
                ];
197
198
                if (in_array($relation, $include)) {
199
                    $included[] = [
200
                        'type' => $relation,
201
                        'id' => $relatedRecord['id'],
202
                        'attributes' => array_except($relatedRecord, ['id', 'pivot']),
203
                    ];
204
                }
205
            }
206
        }
207
208
        if (!empty($fields)) {
209
            $attributes = array_only($attributes, $fields);
210
        }
211
212
        $data = array_filter([
213
            'type' => $record->getTable(),
214
            'id' => $record->id,
215
            'attributes' => array_except($attributes, ['id']),
216
            'relationships' => $relationships,
217
        ]);
218
219
        return array_filter(compact('data', 'included'));
220
    }
221
}
222