Completed
Push — master ( 67587b...b83d27 )
by Arjay
01:07
created

src/DataTablesEditor.php (1 issue)

Labels
Severity

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\Support\Facades\Storage;
10
use Illuminate\Contracts\Validation\Validator;
11
use Illuminate\Validation\ValidationException;
12
use Illuminate\Foundation\Validation\ValidatesRequests;
13
14
abstract class DataTablesEditor
15
{
16
    use ValidatesRequests;
17
18
    /**
19
     * Allowed dataTables editor actions.
20
     *
21
     * @var array
22
     */
23
    protected $actions = ['create', 'edit', 'remove', 'upload'];
24
25
    /**
26
     * @var \Illuminate\Database\Eloquent\Model
27
     */
28
    protected $model = null;
29
30
    /**
31
     * Indicates if all mass assignment is enabled on model.
32
     *
33
     * @var bool
34
     */
35
    protected $unguarded = false;
36
37
    /**
38
     * Upload directory relative to storage path.
39
     *
40
     * @var string
41
     */
42
    protected $uploadDir = 'editor';
43
44
    /**
45
     * Filesystem disk config to use for upload.
46
     *
47
     * @var string
48
     */
49
    protected $disk = 'public';
50
51
    /**
52
     * Process dataTables editor action request.
53
     *
54
     * @param Request $request
55
     * @return JsonResponse|mixed
56
     * @throws DataTablesEditorException
57
     */
58
    public function process(Request $request)
59
    {
60
        $action = $request->get('action');
61
62
        if (! in_array($action, $this->actions)) {
63
            throw new DataTablesEditorException('Requested action not supported!');
64
        }
65
66
        return $this->{$action}($request);
67
    }
68
69
    /**
70
     * Process create action request.
71
     *
72
     * @param Request $request
73
     * @return JsonResponse
74
     */
75 View Code Duplication
    public function create(Request $request)
76
    {
77
        $instance   = $this->resolveModel();
78
        $connection = $instance->getConnection();
79
        $affected   = [];
80
        $errors     = [];
81
82
        $connection->beginTransaction();
83
        foreach ($request->get('data') as $data) {
84
            $validator = $this->getValidationFactory()
85
                              ->make($data, $this->createRules(), $this->messages() + $this->createMessages(), $this->attributes());
86
            if ($validator->fails()) {
87
                foreach ($this->formatErrors($validator) as $error) {
88
                    $errors[] = $error;
89
                }
90
91
                continue;
92
            }
93
94
            if (method_exists($this, 'creating')) {
95
                $data = $this->creating($instance, $data);
96
            }
97
98
            if (method_exists($this, 'saving')) {
99
                $data = $this->saving($instance, $data);
100
            }
101
102
            $instance->fill($data)->save();
103
104
            if (method_exists($this, 'created')) {
105
                $instance = $this->created($instance, $data);
106
            }
107
108
            if (method_exists($this, 'saved')) {
109
                $instance = $this->saved($instance, $data);
110
            }
111
112
            $instance->setAttribute('DT_RowId', $instance->getKey());
113
            $affected[] = $instance;
114
        }
115
116
        if (! $errors) {
117
            $connection->commit();
118
        } else {
119
            $connection->rollBack();
120
        }
121
122
        return $this->toJson($affected, $errors);
123
    }
124
125
    /**
126
     * Resolve model to used.
127
     *
128
     * @return Model|\Illuminate\Database\Eloquent\SoftDeletes
129
     */
130
    protected function resolveModel()
131
    {
132
        if (! $this->model instanceof Model) {
133
            $this->model = new $this->model;
134
        }
135
136
        $this->model->unguard($this->unguarded);
137
138
        return $this->model;
139
    }
140
141
    /**
142
     * Get create action validation rules.
143
     *
144
     * @return array
145
     */
146
    abstract public function createRules();
147
148
    /**
149
     * Get create validation messages.
150
     *
151
     * @deprecated deprecated since v1.12.0, please use messages() instead.
152
     * @return array
153
     */
154
    protected function createMessages()
155
    {
156
        return [];
157
    }
158
159
    /**
160
     * Get custom attributes for validator errors.
161
     *
162
     * @return array
163
     */
164
    public function attributes()
165
    {
166
        return [];
167
    }
168
169
    /**
170
     * @param Validator $validator
171
     * @return array
172
     */
173
    protected function formatErrors(Validator $validator)
174
    {
175
        $errors = [];
176
177
        collect($validator->errors())->each(function ($error, $key) use (&$errors) {
178
            $errors[] = [
179
                'name'   => $key,
180
                'status' => $error[0],
181
            ];
182
        });
183
184
        return $errors;
185
    }
186
187
    /**
188
     * Display success data in dataTables editor format.
189
     *
190
     * @param array $data
191
     * @param array $errors
192
     * @return JsonResponse
193
     */
194
    protected function toJson(array $data, array $errors = [])
195
    {
196
        $response = ['data' => $data];
197
        if ($errors) {
198
            $response['fieldErrors'] = $errors;
199
        }
200
201
        return new JsonResponse($response, 200);
202
    }
203
204
    /**
205
     * Process edit action request.
206
     *
207
     * @param Request $request
208
     * @return JsonResponse
209
     */
210 View Code Duplication
    public function edit(Request $request)
211
    {
212
        $connection = $this->getBuilder()->getConnection();
213
        $affected   = [];
214
        $errors     = [];
215
216
        $connection->beginTransaction();
217
        foreach ($request->get('data') as $key => $data) {
218
            $model     = $this->getBuilder()->findOrFail($key);
219
            $validator = $this->getValidationFactory()
220
                              ->make($data, $this->editRules($model), $this->messages() + $this->editMessages(), $this->attributes());
221
            if ($validator->fails()) {
222
                foreach ($this->formatErrors($validator) as $error) {
223
                    $errors[] = $error;
224
                }
225
226
                continue;
227
            }
228
229
            if (method_exists($this, 'updating')) {
230
                $data = $this->updating($model, $data);
231
            }
232
233
            if (method_exists($this, 'saving')) {
234
                $data = $this->saving($model, $data);
235
            }
236
237
            $model->fill($data)->save();
238
239
            if (method_exists($this, 'updated')) {
240
                $model = $this->updated($model, $data);
241
            }
242
243
            if (method_exists($this, 'saved')) {
244
                $model = $this->saved($model, $data);
245
            }
246
247
            $model->setAttribute('DT_RowId', $model->getKey());
248
            $affected[] = $model;
249
        }
250
251
        if (! $errors) {
252
            $connection->commit();
253
        } else {
254
            $connection->rollBack();
255
        }
256
257
        return $this->toJson($affected, $errors);
258
    }
259
260
    /**
261
     * Get elqouent builder of the model.
262
     *
263
     * @return \Illuminate\Database\Eloquent\Builder
264
     */
265
    protected function getBuilder()
266
    {
267
        $model = $this->resolveModel();
268
269
        if (in_array(\Illuminate\Database\Eloquent\SoftDeletes::class, class_uses($model))) {
270
            return $model->newQuery()->withTrashed();
271
        }
272
273
        return $model->newQuery();
274
    }
275
276
    /**
277
     * Get edit action validation rules.
278
     *
279
     * @param Model $model
280
     * @return array
281
     */
282
    abstract public function editRules(Model $model);
283
284
    /**
285
     * Get edit validation messages.
286
     *
287
     * @deprecated deprecated since v1.12.0, please use messages() instead.
288
     * @return array
289
     */
290
    protected function editMessages()
291
    {
292
        return [];
293
    }
294
295
    /**
296
     * Process remove action request.
297
     *
298
     * @param Request $request
299
     * @return JsonResponse
300
     */
301
    public function remove(Request $request)
302
    {
303
        $connection = $this->getBuilder()->getConnection();
304
        $affected   = [];
305
        $errors     = [];
306
307
        $connection->beginTransaction();
308
        foreach ($request->get('data') as $key => $data) {
309
            $model     = $this->getBuilder()->findOrFail($key);
310
            $validator = $this->getValidationFactory()
311
                              ->make($data, $this->removeRules($model), $this->messages() + $this->removeMessages(), $this->attributes());
312
            if ($validator->fails()) {
313
                foreach ($this->formatErrors($validator) as $error) {
314
                    $errors[] = $error['status'];
315
                }
316
317
                continue;
318
            }
319
320
            try {
321
                $deleted = clone $model;
322
                if (method_exists($this, 'deleting')) {
323
                    $this->deleting($model, $data);
324
                }
325
326
                $model->delete();
327
328
                if (method_exists($this, 'deleted')) {
329
                    $this->deleted($deleted, $data);
330
                }
331
            } catch (QueryException $exception) {
332
                $error = config('app.debug')
333
                    ? $exception->errorInfo[2]
334
                    : $this->removeExceptionMessage($exception, $model);
335
336
                $errors[] = $error;
337
            }
338
339
            $affected[] = $deleted;
340
        }
341
342
        if (! $errors) {
343
            $connection->commit();
344
        } else {
345
            $connection->rollBack();
346
        }
347
348
        $response = ['data' => $affected];
349
        if ($errors) {
350
            $response['error'] = implode("\n", $errors);
351
        }
352
353
        return new JsonResponse($response, 200);
354
    }
355
356
    /**
357
     * Get remove action validation rules.
358
     *
359
     * @param Model $model
360
     * @return array
361
     */
362
    abstract public function removeRules(Model $model);
363
364
    /**
365
     * Get remove validation messages.
366
     *
367
     * @deprecated deprecated since v1.12.0, please use messages() instead.
368
     * @return array
369
     */
370
    protected function removeMessages()
371
    {
372
        return [];
373
    }
374
375
    /**
376
     * Get remove query exception message.
377
     *
378
     * @param QueryException $exception
379
     * @param Model $model
380
     * @return string
381
     */
382
    protected function removeExceptionMessage(QueryException $exception, Model $model)
383
    {
384
        return "Record {$model->getKey()} is protected and cannot be deleted!";
385
    }
386
387
    /**
388
     * Get dataTables model.
389
     *
390
     * @return Model
391
     */
392
    public function getModel()
393
    {
394
        return $this->model;
395
    }
396
397
    /**
398
     * Set the dataTables model on runtime.
399
     *
400
     * @param Model|string $model
401
     * @return DataTablesEditor
402
     */
403
    public function setModel($model)
404
    {
405
        $this->model = $model;
406
407
        return $this;
408
    }
409
410
    /**
411
     * Set model unguard state.
412
     *
413
     * @param bool $state
414
     * @return $this
415
     */
416
    public function unguard($state = true)
417
    {
418
        $this->unguarded = $state;
419
420
        return $this;
421
    }
422
423
    /**
424
     * Handle uploading of file.
425
     *
426
     * @param \Illuminate\Http\Request $request
427
     * @return \Illuminate\Http\JsonResponse
428
     */
429
    public function upload(Request $request)
430
    {
431
        $field   = $request->input('uploadField');
432
        $storage = Storage::disk($this->disk);
433
434
        try {
435
            $rules      = $this->uploadRules();
436
            $fieldRules = ['upload' => data_get($rules, $field, [])];
437
438
            $this->validate($request, $fieldRules, $this->uploadMessages(), $this->attributes());
0 ignored issues
show
The method uploadMessages() does not exist on Yajra\DataTables\DataTablesEditor. Did you maybe mean upload()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
439
440
            $id = $storage->putFile($this->uploadDir, $request->file('upload'));
441
442
            if (method_exists($this, 'uploaded')) {
443
                $id = $this->uploaded($id);
444
            }
445
446
            return response()->json([
447
                'data'   => [],
448
                'file'   => [
449
                    'filename'  => $id,
450
                    'size'      => $request->file('upload')->getSize(),
451
                    'directory' => $this->uploadDir,
452
                    'disk'      => $this->disk,
453
                    'url'       => $storage->url($id),
454
                ],
455
                'upload' => [
456
                    'id' => $id,
457
                ],
458
            ]);
459
        } catch (ValidationException $exception) {
460
            return response()->json([
461
                'data'        => [],
462
                'fieldErrors' => [
463
                    [
464
                        'name'   => $field,
465
                        'status' => str_replace('upload', $field, $exception->errors()['upload'][0]),
466
                    ],
467
                ],
468
            ]);
469
        }
470
    }
471
472
    /**
473
     * Upload validation rules.
474
     *
475
     * @return array
476
     */
477
    public function uploadRules()
478
    {
479
        return [];
480
    }
481
482
    /**
483
     * Get validation messages.
484
     *
485
     * @return array
486
     */
487
    protected function messages()
488
    {
489
        return [];
490
    }
491
492
    /**
493
     * Display dataTables editor validation errors.
494
     *
495
     * @param Validator $validator
496
     * @return JsonResponse
497
     */
498
    protected function displayValidationErrors(Validator $validator)
499
    {
500
        $errors = $this->formatErrors($validator);
501
502
        return new JsonResponse([
503
            'data'        => [],
504
            'fieldErrors' => $errors,
505
        ]);
506
    }
507
}
508