1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Author: Nil Portugués Calderó <[email protected]> |
4
|
|
|
* Date: 12/7/15 |
5
|
|
|
* Time: 12:17 AM. |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace NilPortugues\Laravel5\JsonApi\Controller; |
12
|
|
|
|
13
|
|
|
use App\Http\Controllers\Controller; |
14
|
|
|
use Illuminate\Database\Eloquent\Model; |
15
|
|
|
use Illuminate\Http\Request; |
16
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\CreateResource; |
17
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\DeleteResource; |
18
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\ListResource; |
19
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\GetResource; |
20
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\PatchResource; |
21
|
|
|
use NilPortugues\Api\JsonApi\Server\Actions\PutResource; |
22
|
|
|
use NilPortugues\Api\JsonApi\Server\Errors\Error; |
23
|
|
|
use NilPortugues\Api\JsonApi\Server\Errors\ErrorBag; |
24
|
|
|
use NilPortugues\Laravel5\JsonApi\Eloquent\EloquentHelper; |
25
|
|
|
use NilPortugues\Laravel5\JsonApi\JsonApiSerializer; |
26
|
|
|
use Symfony\Component\HttpFoundation\Response; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Class JsonApiController. |
30
|
|
|
*/ |
31
|
|
|
abstract class JsonApiController extends Controller |
32
|
|
|
{ |
33
|
|
|
/** |
34
|
|
|
* @var JsonApiSerializer |
35
|
|
|
*/ |
36
|
|
|
protected $serializer; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @param JsonApiSerializer $serializer |
40
|
|
|
*/ |
41
|
|
|
public function __construct(JsonApiSerializer $serializer) |
42
|
|
|
{ |
43
|
|
|
$this->serializer = $serializer; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
48
|
|
|
*/ |
49
|
|
|
public function listAction() |
50
|
|
|
{ |
51
|
|
|
$resource = new ListResource($this->serializer); |
52
|
|
|
|
53
|
|
|
$totalAmount = $this->totalAmountResourceCallable(); |
54
|
|
|
$results = $this->listResourceCallable(); |
55
|
|
|
|
56
|
|
|
$controllerAction = '\\'.get_class($this).'@listAction'; |
57
|
|
|
$uri = action($controllerAction, []); |
58
|
|
|
|
59
|
|
|
return $this->addHeaders($resource->get($totalAmount, $results, $uri, get_class($this->getDataModel()))); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Returns the total number of results available for the current resource. |
64
|
|
|
* |
65
|
|
|
* @return callable |
66
|
|
|
*/ |
67
|
|
View Code Duplication |
protected function totalAmountResourceCallable() |
|
|
|
|
68
|
|
|
{ |
69
|
|
|
return function () { |
70
|
|
|
$idKey = $this->getDataModel()->getKeyName(); |
71
|
|
|
|
72
|
|
|
return $this->getDataModel()->query()->get([$idKey])->count(); |
73
|
|
|
}; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Returns an Eloquent Model. |
78
|
|
|
* |
79
|
|
|
* @return Model |
80
|
|
|
*/ |
81
|
|
|
abstract public function getDataModel(); |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* Returns a list of resources based on pagination criteria. |
85
|
|
|
* |
86
|
|
|
* @return callable |
87
|
|
|
*/ |
88
|
|
|
protected function listResourceCallable() |
89
|
|
|
{ |
90
|
|
|
return function () { |
91
|
|
|
return EloquentHelper::paginate($this->serializer, $this->getDataModel()->query())->get(); |
92
|
|
|
}; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* @param Response $response |
97
|
|
|
* |
98
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
99
|
|
|
*/ |
100
|
|
|
protected function addHeaders(Response $response) |
101
|
|
|
{ |
102
|
|
|
return $response; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* @param Request $request |
107
|
|
|
* |
108
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
109
|
|
|
*/ |
110
|
|
View Code Duplication |
public function getAction(Request $request) |
|
|
|
|
111
|
|
|
{ |
112
|
|
|
$find = $this->findResourceCallable($request); |
113
|
|
|
$resource = new GetResource($this->serializer); |
114
|
|
|
|
115
|
|
|
return $this->addHeaders($resource->get($request->id, get_class($this->getDataModel()), $find)); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* @param Request $request |
120
|
|
|
* |
121
|
|
|
* @return callable |
122
|
|
|
*/ |
123
|
|
|
protected function findResourceCallable(Request $request) |
124
|
|
|
{ |
125
|
|
View Code Duplication |
return function () use ($request) { |
|
|
|
|
126
|
|
|
$idKey = $this->getDataModel()->getKeyName(); |
127
|
|
|
|
128
|
|
|
return $this->getDataModel()->query()->where($idKey, $request->id)->first(); |
129
|
|
|
}; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param Request $request |
134
|
|
|
* |
135
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
136
|
|
|
*/ |
137
|
|
View Code Duplication |
public function postAction(Request $request) |
|
|
|
|
138
|
|
|
{ |
139
|
|
|
$createResource = $this->createResourceCallable(); |
140
|
|
|
|
141
|
|
|
$resource = new CreateResource($this->serializer); |
142
|
|
|
|
143
|
|
|
return $this->addHeaders( |
144
|
|
|
$resource->get((array) $request->get('data'), get_class($this->getDataModel()), $createResource) |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* Reads the input and creates and saves a new Eloquent Model. |
150
|
|
|
* |
151
|
|
|
* @return callable |
152
|
|
|
*/ |
153
|
|
|
protected function createResourceCallable() |
154
|
|
|
{ |
155
|
|
|
return function (array $data, array $values) { |
156
|
|
|
$model = $this->getDataModel()->newInstance(); |
157
|
|
|
|
158
|
|
|
foreach ($values as $attribute => $value) { |
159
|
|
|
$model->setAttribute($attribute, $value); |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
if (!empty($data['id'])) { |
163
|
|
|
$model->setAttribute($model->getKeyName(), $values['id']); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
try { |
167
|
|
|
$model->save(); |
168
|
|
|
} catch (\Exception $e) { |
169
|
|
|
$errorBag[] = new Error('creation_error', 'Resource could not be created'); |
|
|
|
|
170
|
|
|
throw $e; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $model; |
174
|
|
|
}; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @param Request $request |
179
|
|
|
* |
180
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
181
|
|
|
*/ |
182
|
|
View Code Duplication |
public function patchAction(Request $request) |
|
|
|
|
183
|
|
|
{ |
184
|
|
|
$find = $this->findResourceCallable($request); |
185
|
|
|
$update = $this->updateResourceCallable(); |
186
|
|
|
|
187
|
|
|
$resource = new PatchResource($this->serializer); |
188
|
|
|
|
189
|
|
|
return $this->addHeaders( |
190
|
|
|
$resource->get( |
191
|
|
|
$request->id, |
192
|
|
|
(array) $request->get('data'), |
193
|
|
|
get_class($this->getDataModel()), |
194
|
|
|
$find, |
195
|
|
|
$update |
196
|
|
|
) |
197
|
|
|
); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* @return callable |
202
|
|
|
*/ |
203
|
|
|
protected function updateResourceCallable() |
204
|
|
|
{ |
205
|
|
|
return function (Model $model, array $values, ErrorBag $errorBag) { |
206
|
|
|
foreach ($values as $attribute => $value) { |
207
|
|
|
$model->$attribute = $value; |
208
|
|
|
} |
209
|
|
|
try { |
210
|
|
|
$model->update(); |
211
|
|
|
} catch (\Exception $e) { |
212
|
|
|
$errorBag[] = new Error('update_failed', 'Could not update resource.'); |
213
|
|
|
throw $e; |
214
|
|
|
} |
215
|
|
|
}; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @param Request $request |
220
|
|
|
* |
221
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
222
|
|
|
*/ |
223
|
|
View Code Duplication |
public function putAction(Request $request) |
|
|
|
|
224
|
|
|
{ |
225
|
|
|
$find = $this->findResourceCallable($request); |
226
|
|
|
$update = $this->updateResourceCallable(); |
227
|
|
|
|
228
|
|
|
$resource = new PutResource($this->serializer); |
229
|
|
|
|
230
|
|
|
return $this->addHeaders( |
231
|
|
|
$resource->get( |
232
|
|
|
$request->id, |
233
|
|
|
(array) $request->get('data'), |
234
|
|
|
get_class($this->getDataModel()), |
235
|
|
|
$find, |
236
|
|
|
$update |
237
|
|
|
) |
238
|
|
|
); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* @param Request $request |
243
|
|
|
* |
244
|
|
|
* @return \Symfony\Component\HttpFoundation\Response |
245
|
|
|
*/ |
246
|
|
View Code Duplication |
public function deleteAction(Request $request) |
|
|
|
|
247
|
|
|
{ |
248
|
|
|
$find = $this->findResourceCallable($request); |
249
|
|
|
$resource = new DeleteResource($this->serializer); |
250
|
|
|
|
251
|
|
|
return $this->addHeaders($resource->get($request->id, get_class($this->getDataModel()), $find)); |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.