Completed
Push — develop ( 4968a5...ffa447 )
by Alex
02:12
created

JsonApiController::getRequestParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace Huntie\JsonApi\Http\Controllers;
4
5
use Huntie\JsonApi\Support\JsonApiErrors;
6
use Huntie\JsonApi\Http\JsonApiResponse;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Http\Request;
9
use Illuminate\Routing\Controller;
10
11
abstract class JsonApiController extends Controller
12
{
13
    use JsonApiErrors;
14
15
    /**
16
     * Return the Eloquent Model for the resource.
17
     *
18
     * @return Model
19
     */
20
    abstract protected function getModel();
21
22
    /**
23
     * Return the type name of the resource.
24
     *
25
     * @return string
26
     */
27
    protected function getModelType()
28
    {
29
        return $this->getModel()->getTable();
30
    }
31
32
    /**
33
     * Return a listing of the resource.
34
     *
35
     * @param Request $request
36
     *
37
     * @return JsonApiResponse
38
     */
39
    public function indexAction(Request $request)
40
    {
41
        $records = $this->getModel()->all();
42
        $params = $this->getRequestParameters($request);
43
44
        return new JsonApiResponse($this->transformCollection($records, $params['fields']));
45
46
    }
47
48
    /**
49
     * Return a specified record.
50
     *
51
     * @param Request   $request
52
     * @param Model|int $record
53
     *
54
     * @return JsonApiResponse
55
     */
56
    public function showAction(Request $request, $record)
57
    {
58
        $record = $record instanceof Model ? $record : $this->findModelInstance($record);
59
        $params = $this->getRequestParameters($request);
60
61
        return new JsonApiResponse($this->transformRecord($record, $params['fields'], $params['include']));
62
63
    }
64
65
    /**
66
     * Return an instance of the resource by primary key.
67
     *
68
     * @param int $key
69
     *
70
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
71
     *
72
     * @return Model
73
     */
74
    protected function findModelInstance($key)
75
    {
76
        return $this->getModel()->findOrFail($key);
77
    }
78
79
    /**
80
     * Return any JSON API resource parameters from a request.
81
     *
82
     * @param Request $request
83
     *
84
     * @return array
85
     */
86
    protected function getRequestParameters($request)
87
    {
88
        return [
89
            'fields' => $this->getRequestQuerySet($request, 'fields.' . $this->getModelType()),
90
            'include' => $this->getRequestQuerySet($request, 'include'),
91
        ];
92
    }
93
94
    /**
95
     * Return any comma separated values in a request query field as an array.
96
     *
97
     * @param Request $request
98
     * @param string  $key
99
     *
100
     * @return array
101
     */
102
    protected function getRequestQuerySet($request, $key)
103
    {
104
        return preg_split('/,/', $request->input($key), null, PREG_SPLIT_NO_EMPTY);
105
    }
106
107
    /**
108
     * Transform a set of models into a JSON API collection.
109
     *
110
     * @param \Illuminate\Support\Collection $records
111
     * @param array                          $fields
112
     *
113
     * @return array
114
     */
115
    protected function transformCollection($records, array $fields = [])
116
    {
117
        $data = [];
118
119
        foreach ($records as $record) {
120
            $data[] = $this->transformRecord($record, $fields)['data'];
121
        }
122
123
        return compact('data');
124
    }
125
126
    /**
127
     * Transform a model instance into a JSON API object.
128
     *
129
     * @param Model      $record
130
     * @param array|null $fields  Field names of attributes to limit to
131
     * @param array|null $include Relations to include
132
     *
133
     * @return array
134
     */
135
    protected function transformRecord($record, array $fields = [], array $include = [])
136
    {
137
        $relations = array_unique(array_merge($record->getRelations(), $include));
138
        $attributes = $record->load($relations)->toArray();
139
        $relationships = [];
140
        $included = [];
141
142
        foreach ($relations as $relation) {
143
            $relationships[$relation] = [
144
                'data' => []
145
            ];
146
147
            foreach (array_pull($attributes, $relation) as $relatedRecord) {
148
                $relationships[$relation]['data'][] = [
149
                    'type' => $relation,
150
                    'id' => $relatedRecord['id'],
151
                ];
152
153
                if (in_array($relation, $include)) {
154
                    $included[] = [
155
                        'type' => $relation,
156
                        'id' => $relatedRecord['id'],
157
                        'attributes' => array_except($relatedRecord, ['id', 'pivot']),
158
                    ];
159
                }
160
            }
161
        }
162
163
        if (!empty($fields)) {
164
            $attributes = array_only($attributes, $fields);
165
        }
166
167
        $data = [
168
            'type' => $record->getTable(),
169
            'id' => $record->id,
170
            'attributes' => array_except($attributes, ['id']),
171
        ];
172
173
        if (!empty($relationships)) {
174
            $data['relationships'] = $relationships;
175
        }
176
177
        return !empty($included) ? compact('data', 'included') : compact('data');
178
    }
179
}
180