Completed
Push — master ( dd81ae...8b11c5 )
by Arjay
01:00
created

src/DataTablesEditor.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Yajra\DataTables;
4
5
use Illuminate\Http\Request;
6
use Illuminate\Http\JsonResponse;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\QueryException;
9
use Illuminate\Contracts\Validation\Validator;
10
use Illuminate\Foundation\Validation\ValidatesRequests;
11
12
abstract class DataTablesEditor
13
{
14
    use ValidatesRequests;
15
16
    /**
17
     * Allowed dataTables editor actions.
18
     *
19
     * @var array
20
     */
21
    protected $actions = ['create', 'edit', 'remove'];
22
23
    /**
24
     * @var \Illuminate\Database\Eloquent\Model
25
     */
26
    protected $model = null;
27
28
    /**
29
     * Process dataTables editor action request.
30
     *
31
     * @param Request $request
32
     * @return JsonResponse|mixed
33
     * @throws DataTablesEditorException
34
     */
35
    public function process(Request $request)
36
    {
37
        $action = $request->get('action');
38
39
        if (! in_array($action, $this->actions)) {
40
            throw new DataTablesEditorException('Requested action not supported!');
41
        }
42
43
        return $this->{$action}($request);
44
    }
45
46
    /**
47
     * Process create action request.
48
     *
49
     * @param Request $request
50
     * @return JsonResponse
51
     */
52 View Code Duplication
    public function create(Request $request)
0 ignored issues
show
This method seems to be duplicated in your project.

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.

Loading history...
53
    {
54
        $instance   = $this->resolveModel();
55
        $connection = $instance->getConnection();
56
        $affected   = [];
57
        $errors     = [];
58
59
        $connection->beginTransaction();
60
        foreach ($request->get('data') as $data) {
61
            $validator = $this->getValidationFactory()
62
                              ->make($data, $this->createRules(), $this->createMessages(), $this->attributes());
63
            if ($validator->fails()) {
64
                foreach ($this->formatErrors($validator) as $error) {
65
                    $errors[] = $error;
66
                }
67
68
                continue;
69
            }
70
71
            $instance->fill($data);
72
73
            if (method_exists($this, 'creating')) {
74
                $data = $this->creating($instance, $data);
75
            }
76
77
            if (method_exists($this, 'saving')) {
78
                $data = $this->saving($instance, $data);
79
            }
80
81
            $instance->save();
82
83
            if (method_exists($this, 'created')) {
84
                $instance = $this->created($instance, $data);
85
            }
86
87
            if (method_exists($this, 'saved')) {
88
                $instance = $this->saved($instance, $data);
89
            }
90
91
            $instance->setAttribute('DT_RowId', $instance->getKey());
92
            $affected[] = $instance;
93
        }
94
95
        if (! $errors) {
96
            $connection->commit();
97
        } else {
98
            $connection->rollBack();
99
        }
100
101
        return $this->toJson($affected, $errors);
102
    }
103
104
    /**
105
     * Resolve model to used.
106
     *
107
     * @return Model|\Illuminate\Database\Eloquent\SoftDeletes
108
     */
109
    protected function resolveModel()
110
    {
111
        if (! $this->model instanceof Model) {
112
            $this->model = new $this->model;
113
        }
114
115
        return $this->model;
116
    }
117
118
    /**
119
     * Get create action validation rules.
120
     *
121
     * @return array
122
     */
123
    abstract public function createRules();
124
125
    /**
126
     * Get create validation messages.
127
     *
128
     * @return array
129
     */
130
    protected function createMessages()
131
    {
132
        return [];
133
    }
134
135
    /**
136
     * Get custom attributes for validator errors.
137
     *
138
     * @return array
139
     */
140
    public function attributes()
141
    {
142
        return [];
143
    }
144
145
    /**
146
     * @param Validator $validator
147
     * @return array
148
     */
149
    protected function formatErrors(Validator $validator)
150
    {
151
        $errors = [];
152
153
        collect($validator->errors())->each(function ($error, $key) use (&$errors) {
154
            $errors[] = [
155
                'name'   => $key,
156
                'status' => $error[0],
157
            ];
158
        });
159
160
        return $errors;
161
    }
162
163
    /**
164
     * Display success data in dataTables editor format.
165
     *
166
     * @param array $data
167
     * @param array $errors
168
     * @return JsonResponse
169
     */
170
    protected function toJson(array $data, array $errors = [])
171
    {
172
        $response = ['data' => $data];
173
        if ($errors) {
174
            $response['fieldErrors'] = $errors;
175
        }
176
177
        return new JsonResponse($response, 200);
178
    }
179
180
    /**
181
     * Process edit action request.
182
     *
183
     * @param Request $request
184
     * @return JsonResponse
185
     */
186 View Code Duplication
    public function edit(Request $request)
0 ignored issues
show
This method seems to be duplicated in your project.

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.

Loading history...
187
    {
188
        $connection = $this->getBuilder()->getConnection();
189
        $affected   = [];
190
        $errors     = [];
191
192
193
        $connection->beginTransaction();
194
        foreach ($request->get('data') as $key => $data) {
195
            $model     = $this->getBuilder()->findOrFail($key);
196
            $validator = $this->getValidationFactory()
197
                              ->make($data, $this->editRules($model), $this->editMessages(), $this->attributes());
198
            if ($validator->fails()) {
199
                foreach ($this->formatErrors($validator) as $error) {
200
                    $errors[] = $error;
201
                }
202
203
                continue;
204
            }
205
206
            $model->fill($data);
207
208
            if (method_exists($this, 'updating')) {
209
                $data = $this->updating($model, $data);
210
            }
211
212
            if (method_exists($this, 'saving')) {
213
                $data = $this->saving($model, $data);
214
            }
215
216
            $model->save();
217
218
            if (method_exists($this, 'updated')) {
219
                $model = $this->updated($model, $data);
220
            }
221
222
            if (method_exists($this, 'saved')) {
223
                $model = $this->saved($model, $data);
224
            }
225
226
            $model->setAttribute('DT_RowId', $model->getKey());
227
            $affected[] = $model;
228
        }
229
230
        if (! $errors) {
231
            $connection->commit();
232
        } else {
233
            $connection->rollBack();
234
        }
235
236
        return $this->toJson($affected, $errors);
237
    }
238
239
    /**
240
     * Get elqouent builder of the model.
241
     *
242
     * @return \Illuminate\Database\Eloquent\Builder
243
     */
244
    protected function getBuilder()
245
    {
246
        $model = $this->resolveModel();
247
248
        if (in_array(\Illuminate\Database\Eloquent\SoftDeletes::class, class_uses($model))) {
249
            return $model->newQuery()->withTrashed();
250
        }
251
252
        return $model->newQuery();
253
    }
254
255
    /**
256
     * Get edit action validation rules.
257
     *
258
     * @param Model $model
259
     * @return array
260
     */
261
    abstract public function editRules(Model $model);
262
263
    /**
264
     * Get edit validation messages.
265
     *
266
     * @return array
267
     */
268
    protected function editMessages()
269
    {
270
        return [];
271
    }
272
273
    /**
274
     * Process remove action request.
275
     *
276
     * @param Request $request
277
     * @return JsonResponse
278
     */
279
    public function remove(Request $request)
280
    {
281
        $connection = $this->getBuilder()->getConnection();
282
        $affected   = [];
283
        $errors     = [];
284
285
        $connection->beginTransaction();
286
        foreach ($request->get('data') as $key => $data) {
287
            $model     = $this->getBuilder()->findOrFail($key);
288
            $validator = $this->getValidationFactory()
289
                              ->make($data, $this->removeRules($model), $this->removeMessages(), $this->attributes());
290
            if ($validator->fails()) {
291
                foreach ($this->formatErrors($validator) as $error) {
292
                    $errors[] = $error['status'];
293
                }
294
295
                continue;
296
            }
297
298
            try {
299
                $deleted = clone $model;
300
                if (method_exists($this, 'deleting')) {
301
                    $this->deleting($model, $data);
302
                }
303
304
                $model->delete();
305
306
                if (method_exists($this, 'deleted')) {
307
                    $this->deleted($deleted, $data);
308
                }
309
            } catch (QueryException $exception) {
310
                $error = config('app.debug')
311
                    ? $exception->errorInfo[2]
312
                    : $this->removeExceptionMessage($exception, $model);
313
314
                $errors[] = $error;
315
            }
316
317
            $affected[] = $deleted;
318
        }
319
320
        if (! $errors) {
321
            $connection->commit();
322
        } else {
323
            $connection->rollBack();
324
        }
325
326
        $response = ['data' => $affected];
327
        if ($errors) {
328
            $response['error'] = implode("\n", $errors);
329
        }
330
331
        return new JsonResponse($response, 200);
332
    }
333
334
    /**
335
     * Get remove action validation rules.
336
     *
337
     * @param Model $model
338
     * @return array
339
     */
340
    abstract public function removeRules(Model $model);
341
342
    /**
343
     * Get remove validation messages.
344
     *
345
     * @return array
346
     */
347
    protected function removeMessages()
348
    {
349
        return [];
350
    }
351
352
    /**
353
     * Get remove query exception message.
354
     *
355
     * @param QueryException $exception
356
     * @param Model $model
357
     * @return string
358
     */
359
    protected function removeExceptionMessage(QueryException $exception, Model $model)
360
    {
361
        return "Record {$model->getKey()} is protected and cannot be deleted!";
362
    }
363
364
    /**
365
     * Get dataTables model.
366
     *
367
     * @return Model
368
     */
369
    public function getModel()
370
    {
371
        return $this->model;
372
    }
373
374
    /**
375
     * Set the dataTables model on runtime.
376
     *
377
     * @param Model|string $model
378
     * @return DataTablesEditor
379
     */
380
    public function setModel($model)
381
    {
382
        $this->model = $model;
383
384
        return $this;
385
    }
386
387
    /**
388
     * Display dataTables editor validation errors.
389
     *
390
     * @param Validator $validator
391
     * @return JsonResponse
392
     */
393
    protected function displayValidationErrors(Validator $validator)
394
    {
395
        $errors = $this->formatErrors($validator);
396
397
        return new JsonResponse([
398
            'data'        => [],
399
            'fieldErrors' => $errors,
400
        ]);
401
    }
402
}
403