Completed
Push — master ( a20af9...561d02 )
by Arjay
05:12
created

src/DataTablesEditor.php (2 issues)

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\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
     * Indicates if all mass assignment is enabled on model.
30
     *
31
     * @var bool
32
     */
33
    protected $unguarded = false;
34
35
    /**
36
     * Process dataTables editor action request.
37
     *
38
     * @param Request $request
39
     * @return JsonResponse|mixed
40
     * @throws DataTablesEditorException
41
     */
42
    public function process(Request $request)
43
    {
44
        $action = $request->get('action');
45
46
        if (! in_array($action, $this->actions)) {
47
            throw new DataTablesEditorException('Requested action not supported!');
48
        }
49
50
        return $this->{$action}($request);
51
    }
52
53
    /**
54
     * Process create action request.
55
     *
56
     * @param Request $request
57
     * @return JsonResponse
58
     */
59 View Code Duplication
    public function create(Request $request)
60
    {
61
        $instance   = $this->resolveModel();
62
        $connection = $instance->getConnection();
63
        $affected   = [];
64
        $errors     = [];
65
66
        $connection->beginTransaction();
67
        foreach ($request->get('data') as $data) {
68
            $validator = $this->getValidationFactory()
69
                              ->make($data, $this->createRules(), $this->createMessages(), $this->attributes());
70
            if ($validator->fails()) {
71
                foreach ($this->formatErrors($validator) as $error) {
72
                    $errors[] = $error;
73
                }
74
75
                continue;
76
            }
77
78
            if (method_exists($this, 'creating')) {
79
                $data = $this->creating($instance, $data);
80
            }
81
82
            if (method_exists($this, 'saving')) {
83
                $data = $this->saving($instance, $data);
84
            }
85
86
            $instance->fill($data)->save();
87
88
            if (method_exists($this, 'created')) {
89
                $instance = $this->created($instance, $data);
90
            }
91
92
            if (method_exists($this, 'saved')) {
93
                $instance = $this->saved($instance, $data);
94
            }
95
96
            $instance->setAttribute('DT_RowId', $instance->getKey());
97
            $affected[] = $instance;
98
        }
99
100
        if (! $errors) {
101
            $connection->commit();
102
        } else {
103
            $connection->rollBack();
104
        }
105
106
        return $this->toJson($affected, $errors);
107
    }
108
109
    /**
110
     * Resolve model to used.
111
     *
112
     * @return Model|\Illuminate\Database\Eloquent\SoftDeletes
113
     */
114
    protected function resolveModel()
115
    {
116
        if (! $this->model instanceof Model) {
0 ignored issues
show
The class Illuminate\Database\Eloquent\Model does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
117
            $this->model = new $this->model;
118
        }
119
120
        $this->model->unguard($this->unguarded);
121
122
        return $this->model;
123
    }
124
125
    /**
126
     * Get create action validation rules.
127
     *
128
     * @return array
129
     */
130
    abstract public function createRules();
131
132
    /**
133
     * Get create validation messages.
134
     *
135
     * @return array
136
     */
137
    protected function createMessages()
138
    {
139
        return [];
140
    }
141
142
    /**
143
     * Get custom attributes for validator errors.
144
     *
145
     * @return array
146
     */
147
    public function attributes()
148
    {
149
        return [];
150
    }
151
152
    /**
153
     * @param Validator $validator
154
     * @return array
155
     */
156
    protected function formatErrors(Validator $validator)
157
    {
158
        $errors = [];
159
160
        collect($validator->errors())->each(function ($error, $key) use (&$errors) {
161
            $errors[] = [
162
                'name'   => $key,
163
                'status' => $error[0],
164
            ];
165
        });
166
167
        return $errors;
168
    }
169
170
    /**
171
     * Display success data in dataTables editor format.
172
     *
173
     * @param array $data
174
     * @param array $errors
175
     * @return JsonResponse
176
     */
177
    protected function toJson(array $data, array $errors = [])
178
    {
179
        $response = ['data' => $data];
180
        if ($errors) {
181
            $response['fieldErrors'] = $errors;
182
        }
183
184
        return new JsonResponse($response, 200);
185
    }
186
187
    /**
188
     * Process edit action request.
189
     *
190
     * @param Request $request
191
     * @return JsonResponse
192
     */
193 View Code Duplication
    public function edit(Request $request)
194
    {
195
        $connection = $this->getBuilder()->getConnection();
196
        $affected   = [];
197
        $errors     = [];
198
199
        $connection->beginTransaction();
200
        foreach ($request->get('data') as $key => $data) {
201
            $model     = $this->getBuilder()->findOrFail($key);
202
            $validator = $this->getValidationFactory()
203
                              ->make($data, $this->editRules($model), $this->editMessages(), $this->attributes());
204
            if ($validator->fails()) {
205
                foreach ($this->formatErrors($validator) as $error) {
206
                    $errors[] = $error;
207
                }
208
209
                continue;
210
            }
211
212
            if (method_exists($this, 'updating')) {
213
                $data = $this->updating($model, $data);
214
            }
215
216
            if (method_exists($this, 'saving')) {
217
                $data = $this->saving($model, $data);
218
            }
219
220
            $model->fill($data)->save();
221
222
            if (method_exists($this, 'updated')) {
223
                $model = $this->updated($model, $data);
224
            }
225
226
            if (method_exists($this, 'saved')) {
227
                $model = $this->saved($model, $data);
228
            }
229
230
            $model->setAttribute('DT_RowId', $model->getKey());
231
            $affected[] = $model;
232
        }
233
234
        if (! $errors) {
235
            $connection->commit();
236
        } else {
237
            $connection->rollBack();
238
        }
239
240
        return $this->toJson($affected, $errors);
241
    }
242
243
    /**
244
     * Get elqouent builder of the model.
245
     *
246
     * @return \Illuminate\Database\Eloquent\Builder
247
     */
248
    protected function getBuilder()
249
    {
250
        $model = $this->resolveModel();
251
252
        if (in_array(\Illuminate\Database\Eloquent\SoftDeletes::class, class_uses($model))) {
253
            return $model->newQuery()->withTrashed();
254
        }
255
256
        return $model->newQuery();
257
    }
258
259
    /**
260
     * Get edit action validation rules.
261
     *
262
     * @param Model $model
263
     * @return array
264
     */
265
    abstract public function editRules(Model $model);
266
267
    /**
268
     * Get edit validation messages.
269
     *
270
     * @return array
271
     */
272
    protected function editMessages()
273
    {
274
        return [];
275
    }
276
277
    /**
278
     * Process remove action request.
279
     *
280
     * @param Request $request
281
     * @return JsonResponse
282
     */
283
    public function remove(Request $request)
284
    {
285
        $connection = $this->getBuilder()->getConnection();
286
        $affected   = [];
287
        $errors     = [];
288
289
        $connection->beginTransaction();
290
        foreach ($request->get('data') as $key => $data) {
291
            $model     = $this->getBuilder()->findOrFail($key);
292
            $validator = $this->getValidationFactory()
293
                              ->make($data, $this->removeRules($model), $this->removeMessages(), $this->attributes());
294
            if ($validator->fails()) {
295
                foreach ($this->formatErrors($validator) as $error) {
296
                    $errors[] = $error['status'];
297
                }
298
299
                continue;
300
            }
301
302
            try {
303
                $deleted = clone $model;
304
                if (method_exists($this, 'deleting')) {
305
                    $this->deleting($model, $data);
306
                }
307
308
                $model->delete();
309
310
                if (method_exists($this, 'deleted')) {
311
                    $this->deleted($deleted, $data);
312
                }
313
            } catch (QueryException $exception) {
0 ignored issues
show
The class Illuminate\Database\QueryException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
314
                $error = config('app.debug')
315
                    ? $exception->errorInfo[2]
316
                    : $this->removeExceptionMessage($exception, $model);
317
318
                $errors[] = $error;
319
            }
320
321
            $affected[] = $deleted;
322
        }
323
324
        if (! $errors) {
325
            $connection->commit();
326
        } else {
327
            $connection->rollBack();
328
        }
329
330
        $response = ['data' => $affected];
331
        if ($errors) {
332
            $response['error'] = implode("\n", $errors);
333
        }
334
335
        return new JsonResponse($response, 200);
336
    }
337
338
    /**
339
     * Get remove action validation rules.
340
     *
341
     * @param Model $model
342
     * @return array
343
     */
344
    abstract public function removeRules(Model $model);
345
346
    /**
347
     * Get remove validation messages.
348
     *
349
     * @return array
350
     */
351
    protected function removeMessages()
352
    {
353
        return [];
354
    }
355
356
    /**
357
     * Get remove query exception message.
358
     *
359
     * @param QueryException $exception
360
     * @param Model $model
361
     * @return string
362
     */
363
    protected function removeExceptionMessage(QueryException $exception, Model $model)
364
    {
365
        return "Record {$model->getKey()} is protected and cannot be deleted!";
366
    }
367
368
    /**
369
     * Get dataTables model.
370
     *
371
     * @return Model
372
     */
373
    public function getModel()
374
    {
375
        return $this->model;
376
    }
377
378
    /**
379
     * Set the dataTables model on runtime.
380
     *
381
     * @param Model|string $model
382
     * @return DataTablesEditor
383
     */
384
    public function setModel($model)
385
    {
386
        $this->model = $model;
387
388
        return $this;
389
    }
390
391
    /**
392
     * Set model unguard state.
393
     *
394
     * @param bool $state
395
     * @return $this
396
     */
397
    public function unguard($state = true)
398
    {
399
        $this->unguarded = $state;
400
401
        return $this;
402
    }
403
404
    /**
405
     * Display dataTables editor validation errors.
406
     *
407
     * @param Validator $validator
408
     * @return JsonResponse
409
     */
410
    protected function displayValidationErrors(Validator $validator)
411
    {
412
        $errors = $this->formatErrors($validator);
413
414
        return new JsonResponse([
415
            'data'        => [],
416
            'fieldErrors' => $errors,
417
        ]);
418
    }
419
}
420