Completed
Push — master ( 37a525...60e840 )
by Babak
04:27
created

BaseController   F

Complexity

Total Complexity 61

Size/Duplication

Total Lines 511
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 195
dl 0
loc 511
rs 3.52
c 0
b 0
f 0
wmc 61

14 Methods

Rating   Name   Duplication   Size   Complexity  
A checkExistUniqueRecord() 0 6 2
F index() 0 91 16
A create() 0 9 1
A destroy() 0 20 3
A show() 0 20 3
B update() 0 53 9
A __construct() 0 8 1
A edit() 0 23 4
A message() 0 4 1
B checkRequestValidation() 0 21 7
A setLocale() 0 6 2
A getMessageFromFile() 0 3 1
A getTrans() 0 3 1
C store() 0 50 10

How to fix   Complexity   

Complex Class

Complex classes like BaseController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BaseController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Alive2212\LaravelSmartRestful;
4
5
use Alive2212\ExcelHelper\ExcelHelper;
6
use Alive2212\LaravelQueryHelper\QueryHelper;
0 ignored issues
show
Bug introduced by
The type Alive2212\LaravelQueryHelper\QueryHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Alive2212\LaravelRequestHelper\RequestHelper;
0 ignored issues
show
Bug introduced by
The type Alive2212\LaravelRequestHelper\RequestHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Alive2212\LaravelSmartResponse\ResponseModel;
9
use Alive2212\LaravelSmartResponse\SmartResponse\SmartResponse;
0 ignored issues
show
Bug introduced by
The type Alive2212\LaravelSmartRe...tResponse\SmartResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Alive2212\LaravelStringHelper\StringHelper;
0 ignored issues
show
Bug introduced by
The type Alive2212\LaravelStringHelper\StringHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use App\Car;
0 ignored issues
show
Bug introduced by
The type App\Car was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use App\Http\Controllers\Controller;
0 ignored issues
show
Bug introduced by
The type App\Http\Controllers\Controller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use App\Location;
0 ignored issues
show
Bug introduced by
The type App\Location was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Illuminate\Database\Eloquent\ModelNotFoundException;
15
use Illuminate\Database\QueryException;
16
use Illuminate\Http\Request;
17
use Illuminate\Support\Facades\DB;
18
use Illuminate\Support\MessageBag;
19
use Illuminate\Support\Facades\Validator;
20
21
22
abstract class BaseController extends Controller
23
{
24
    /**
25
     * to use this class
26
     * create message list as messages in message file
27
     * override __constructor and define your model
28
     * define your rules for index,store and update
29
     */
30
31
    protected $locale = 'en';
32
33
    /**
34
     * @var int
35
     */
36
    protected $DEFAULT_RESULT_PER_PAGE = 15;
37
38
    /**
39
     * @var int
40
     */
41
    protected $DEFAULT_PAGE_NUMBER = 1;
42
43
    /**
44
     * @var array
45
     */
46
    protected $pivotFields = [];
47
48
    /**
49
     * @var array
50
     */
51
    protected $uniqueFields = [];
52
53
    /**
54
     * @var bool|string
55
     */
56
    protected $modelName;
57
58
    /**
59
     * @var string
60
     */
61
    protected $messagePrefix = 'messages.api.v1.';
62
63
    /**
64
     * this model
65
     */
66
    protected $model;
67
68
    /**
69
     * index request validator rules
70
     *
71
     * @var array
72
     */
73
    protected $indexValidateArray = [
74
        //
75
    ];
76
77
    /**
78
     * array of relationship for eager loading
79
     *
80
     * @var array
81
     */
82
    protected $indexLoad = [
83
        //
84
    ];
85
86
    /**
87
     * array of relationship for eager loading
88
     *
89
     * @var array
90
     */
91
    protected $editLoad = [
92
        //
93
    ];
94
95
    /**
96
     * array of relationship for eager loading
97
     *
98
     * @var array
99
     */
100
    protected $updateLoad = [
101
        //
102
    ];
103
104
    /**
105
     * store request validator rules
106
     *
107
     * @var array
108
     */
109
    protected $storeValidateArray = [
110
        //
111
    ];
112
113
    /**
114
     * update request validator rules
115
     *
116
     * @var array
117
     */
118
    protected $updateValidateArray = [
119
        //
120
    ];
121
122
    protected $middlewareParams = [];
123
124
    /**
125
     * defaultController constructor.
126
     */
127
    public function __construct()
128
    {
129
//        dd("I have closest relationship with all US celebrities");
130
        // init controller
131
        $this->initController();
132
133
        // set local language
134
        $this->setLocale();
135
    }
136
137
    abstract public function initController();
138
139
    /**
140
     * Display a listing of the resource.
141
     *
142
     * @param Request $request
143
     * @return string
144
     */
145
    public function index(Request $request)
146
    {
147
        // create response model
148
        $response = new ResponseModel();
149
150
        $pageSize = $this->DEFAULT_RESULT_PER_PAGE;
0 ignored issues
show
Unused Code introduced by
The assignment to $pageSize is dead and can be removed.
Loading history...
151
        $pageNumber = 1;
152
153
        //set default pagination
154
155
        //set page size
156
        if (!isset($request->toArray()['page']['size'])) {
157
            $pageSize = $this->DEFAULT_RESULT_PER_PAGE;
158
        } elseif (($request->get('page')['size']) == 0) {
159
            $pageSize = $this->DEFAULT_RESULT_PER_PAGE;
160
        } else {
161
            $pageSize = $request->get('page')['size'];
162
        }
163
164
        //set page number
165
        if (!isset($request->get('page')['number'])) {
166
            $pageNumber = $this->DEFAULT_RESULT_PER_PAGE;
167
        } elseif (($request->get('page')['number']) == 0) {
168
            $pageNumber = $this->DEFAULT_RESULT_PER_PAGE;
169
        } else {
170
            $pageNumber = $request->get('page')['number'];
171
        }
172
        $request['page'] = $pageNumber;
173
174
175
        //set default ordering
176
        if (isset($request->toArray()['order_by'])) {
177
            if (is_null($request['order_by'])) {
178
                $request['order_by'] = "{\"field\":\"id\",\"operator\":\"Desc\"}";
179
            }
180
        }
181
182
        $validationErrors = $this->checkRequestValidation($request, $this->indexValidateArray);
183
        if ($validationErrors != null) {
184
185
            // return response
186
            $response->setData(collect($validationErrors->toArray()));
187
            $response->setMessage($this->getTrans('index', 'failed_validation'));
188
            $response->setStatus(false);
189
            $response->setError(99);
190
            return SmartResponse::response($response);
191
        }
192
193
        try {
194
            $data = $request->get('query') != null ?
195
                $this->model
196
                    ->whereKey(collect($this->model
197
                        ->search(($request->get('query')))
198
                        ->raw())->get('ids')) :
199
                $this->model;
200
            if (array_key_exists('file', $request->toArray())) {
201
                //TODO add relation on top if here and create a tree flatter array in array helper
202
                return (new ExcelHelper())->setOptions([
0 ignored issues
show
Bug introduced by
Are you sure the usage of new Alive2212\ExcelHelpe...ExcelFile()->download() targeting Alive2212\ExcelHelper\ExcelHelper::download() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
203
                    'store_format' => $request->get('file') == null ? 'xls' : $request->get('file'),
204
                    'download_format' => $request->get('file') == null ? 'xls' : $request->get('file'),
205
                ])->table($data->get()->toArray())->createExcelFile()->download();
206
            }
207
208
            // load relations
209
            if (count($this->indexLoad) > 0) {
210
                $data = $data->with($this->indexLoad);
211
            }
212
213
            // filters by
214
            if (isset($request->toArray()['filters'])) {
215
                $data = (new QueryHelper())->deepFilter($data, (new RequestHelper())->getCollectFromJson($request['filters']));
216
            }
217
218
            // order by
219
            if (isset($request->toArray()['order_by'])) {
220
                $data = (new QueryHelper())->orderBy($data, (new RequestHelper())->getCollectFromJson($request['order_by']));
221
            }
222
223
            // return response
224
            $response->setData(collect($data->paginate($pageSize)));
225
            $response->setMessage($this->getTrans('index', 'successful'));
226
            return SmartResponse::response($response);
227
228
        } catch (QueryException $exception) {
229
230
            // return response
231
            $response->setData(collect($exception->getMessage()));
232
            $response->setError($exception->getCode());
233
            $response->setMessage($this->getTrans('index', 'failed'));
234
            $response->setStatus(false);
235
            return SmartResponse::response($response);
236
        }
237
    }
238
239
    public function checkRequestValidation(Request $request, $validationArray)
240
    {
241
        $requestParams = $request->toArray();
242
        $validator = Validator::make($request->all(), $validationArray);
243
        if ($validator->fails()) {
244
            return $validator->errors();
245
        }
246
        if (is_numeric(array_search($request->getMethod(), ["POST", "PUT", "PATCH"]))) {
247
            $errors = new MessageBag();
248
            foreach ($requestParams as $requestParamKey => $requestParamValue) {
249
                if (is_numeric(array_search($requestParamKey, $this->uniqueFields))) {
250
                    if ($this->checkExistUniqueRecord($requestParamKey, $requestParamValue)) {
251
                        $errors->add($requestParamKey, 'This ' . $requestParamKey . ' is exist try another.');
252
                    }
253
                }
254
            }
255
            if (collect($errors)->count() > 0) {
256
                return $errors;
257
            }
258
        }
259
        return null;
260
    }
261
262
    /**
263
     * @param $key
264
     * @param $value
265
     * @return bool
266
     */
267
    public function checkExistUniqueRecord($key, $value)
268
    {
269
        if ($this->model->where($key, $value)->count()) {
270
            return true;
271
        }
272
        return false;
273
    }
274
275
    /**
276
     * @param $status
277
     * @return mixed
278
     */
279
    public function message($status)
280
    {
281
        $key = $this->messagePrefix . $this->modelName . '.' . debug_backtrace()[1]['function'] . '.' . $status;
282
        return $this->getMessageFromFile($key);
283
    }
284
285
    /**
286
     * @param $key
287
     * @return mixed
288
     */
289
    public function getMessageFromFile($key)
290
    {
291
        return config($key);
292
    }
293
294
    /**
295
     * Show the form for creating a new resource.
296
     *
297
     * @return \Illuminate\Http\JsonResponse
298
     */
299
    public function create()
300
    {
301
        // Create Response Model
302
        $response = new ResponseModel();
303
304
        // return response
305
        $response->setData(collect($this->model->getFillable()));
306
        $response->setMessage($this->getTrans('create', 'successful'));
307
        return SmartResponse::response($response);
308
    }
309
310
    /**
311
     * Store a newly created resource in storage.
312
     *
313
     * @param  \Illuminate\Http\Request $request
314
     * @return \Illuminate\Http\JsonResponse
315
     */
316
    public function store(Request $request)
317
    {
318
        // Create Response Model
319
        $response = new ResponseModel();
320
321
        if (!isset($userId)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $userId seems to never exist and therefore isset should always be false.
Loading history...
322
            $userId = 1;
323
        }
324
325
        //add author id into the request if doesn't exist
326
        if (is_null($request->get('author_id'))) {
327
            $request['author_id'] = $userId;
328
        }
329
330
        //add user id into the request if doesn't exist
331
        if (is_null($request->get('user_id'))) {
332
            $request['user_id'] = $userId;
333
        }
334
335
        $validationErrors = $this->checkRequestValidation($request, $this->storeValidateArray);
336
337
        if ($validationErrors != null) {
338
            if (env('APP_DEBUG', false)) {
339
                $response->setMessage(json_encode($validationErrors->getMessages()));
340
            }
341
            $response->setStatus(false);
342
            return SmartResponse::response($response);
343
        }
344
        try {
345
            // get result of model creation
346
            $result = $this->model->create($request->all());
347
            // sync many to many relation
348
            foreach ($this->pivotFields as $pivotField) {
349
                if (collect($request[$pivotField])->count()) {
350
                    $pivotField = (new StringHelper())->toCamel($pivotField);
351
                    $this->model->find($result['id'])->$pivotField()->sync(json_decode($request[$pivotField]));
352
                }
353
            }
354
            $response->setMessage($this->getTrans('store', 'successful'));
355
            $response->setData(collect($result->toArray()));
356
            $response->setStatus(true);
357
        } catch (QueryException $exception) {
358
            $response->setError($exception->getCode());
0 ignored issues
show
Bug introduced by
It seems like $exception->getCode() can also be of type integer; however, parameter $error of Alive2212\LaravelSmartRe...sponseModel::setError() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

358
            $response->setError(/** @scrutinizer ignore-type */ $exception->getCode());
Loading history...
359
            $response->setMessage($this->getTrans('store', 'failed'));
360
            $response->setStatus(false);
361
            if (env('APP_DEBUG', false)) {
362
                $response->setData(collect($exception->getMessage()));
363
            }
364
        }
365
        return SmartResponse::response($response);
366
    }
367
368
    /**
369
     * Display the specdefaultied resource.
370
     *
371
     * @param  int $id
372
     * @return \Illuminate\Http\JsonResponse
373
     */
374
    public function show($id)
375
    {
376
        // Create Response Model
377
        $response = new ResponseModel();
378
379
        // try to get data
380
        try {
381
            $response->setMessage($this->getTrans('show', 'successful'));
382
            $response->setData(collect($this->model->findOrFail($id)));
383
384
            // catch exception
385
        } catch (ModelNotFoundException $exception) {
386
            $response->setError($exception->getCode());
0 ignored issues
show
Bug introduced by
It seems like $exception->getCode() can also be of type integer; however, parameter $error of Alive2212\LaravelSmartRe...sponseModel::setError() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

386
            $response->setError(/** @scrutinizer ignore-type */ $exception->getCode());
Loading history...
387
            $response->setMessage($this->getTrans('show', 'failed'));
388
            $response->setStatus(false);
389
            if (env('APP_DEBUG', false)) {
390
                $response->setData(collect($exception->getMessage()));
391
            }
392
        }
393
        return SmartResponse::response($response);
394
    }
395
396
    /**
397
     * Show the form for editing the specified resource.
398
     *
399
     * @param  int $id
400
     * @return \Illuminate\Http\JsonResponse
401
     */
402
    public function edit($id)
403
    {
404
        // Create Response Model
405
        $response = new ResponseModel();
406
407
        try {
408
            $response->setMessage($this->getTrans('edit', 'successful'));
409
            $response->setData($this->model
410
                ->where($this->model->getKeyName(), $id)
411
                ->with(collect($this->editLoad)->count() == 0 ? $this->indexLoad : $this->editLoad)
412
                ->get());
413
414
        } catch (ModelNotFoundException $exception) {
415
            $response->setError($exception->getCode());
0 ignored issues
show
Bug introduced by
It seems like $exception->getCode() can also be of type integer; however, parameter $error of Alive2212\LaravelSmartRe...sponseModel::setError() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

415
            $response->setError(/** @scrutinizer ignore-type */ $exception->getCode());
Loading history...
416
            $response->setMessage($this->getTrans('edit', 'failed'));
417
            $response->setStatus(false);
418
            if (env('APP_DEBUG', false)) {
419
                $response->setData(collect($exception->getMessage()));
420
            }
421
422
        }
423
424
        return SmartResponse::response($response);
425
    }
426
427
    /**
428
     * Update the specified resource in storage.
429
     *
430
     * @param  \Illuminate\Http\Request $request
431
     * @param  int $id
432
     * @return \Illuminate\Http\JsonResponse
433
     */
434
    public function update(Request $request, $id)
435
    {
436
        // Create Response Model
437
        $response = new ResponseModel();
438
439
        $validationErrors = $this->checkRequestValidation($request, $this->updateValidateArray);
440
        if ($validationErrors != null) {
441
            $response->setData(collect($validationErrors->toArray()));
442
            $response->setMessage($this->getTrans('update', 'failed_validation'));
443
            $response->setStatus(false);
444
            $response->setError(99);
445
            return SmartResponse::response($response);
446
447
        }
448
449
        try {
450
            // sync many to many relation
451
            foreach ($this->pivotFields as $pivotField) {
452
                if (collect($request[$pivotField])->count()) {
453
                    $pivotMethod = (new StringHelper())->toCamel($pivotField);
454
                    $this->model->findOrFail($id)->$pivotMethod()->sync(json_decode($request[$pivotField], true));
455
                }
456
            }
457
            //get result of update
458
            $result = $this->model->findOrFail($id)->update($request->all());
459
460
            // return response
461
            $response->setData(collect(env('APP_DEBUG') ? $this->model->find($id) : []));
462
            $response->setMessage(
463
                $this->getTrans('update', 'successful1') .
0 ignored issues
show
Bug introduced by
Are you sure $this->getTrans('update', 'successful1') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

463
                /** @scrutinizer ignore-type */ $this->getTrans('update', 'successful1') .
Loading history...
464
                $result .
465
                $this->getTrans('update', 'successful2')
0 ignored issues
show
Bug introduced by
Are you sure $this->getTrans('update', 'successful2') of type null|string|array can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

465
                /** @scrutinizer ignore-type */ $this->getTrans('update', 'successful2')
Loading history...
466
            );
467
468
        } catch (ModelNotFoundException $exception) {
469
            $response->setStatus(false);
470
            $response->setMessage($this->getTrans('update', 'model_not_found'));
471
            $response->setError($exception->getCode());
472
            if (env('APP_DEBUG', false)) {
473
                $response->setData(collect($exception->getMessage()));
474
            }
475
476
        } catch (QueryException $exception) {
477
            $response->setStatus(false);
478
            $response->setMessage($this->getTrans('update', 'failed'));
479
            $response->setError($exception->getCode());
480
            if (env('APP_DEBUG', false)) {
481
                $response->setData(collect($exception->getMessage()));
482
            }
483
484
        }
485
486
        return SmartResponse::response($response);
487
    }
488
489
    /**
490
     * Remove the specified resource from storage.
491
     *
492
     * @param  int $id
493
     * @return \Illuminate\Http\JsonResponse
494
     */
495
    public function destroy($id)
496
    {
497
        // Create Response Model
498
        $response = new ResponseModel();
499
500
        try {
501
            $response->setData(collect($this->model->findOrFail($id)->delete()));
502
            $response->setMessage($this->getTrans('destroy', 'successful'));
503
504
        } catch (ModelNotFoundException $exception) {
505
            $response->setMessage($this->getTrans('destroy', 'successful'));
506
            $response->setStatus(false);
507
            $response->setError($exception->getCode());
0 ignored issues
show
Bug introduced by
It seems like $exception->getCode() can also be of type integer; however, parameter $error of Alive2212\LaravelSmartRe...sponseModel::setError() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

507
            $response->setError(/** @scrutinizer ignore-type */ $exception->getCode());
Loading history...
508
            if (env('APP_DEBUG', false)) {
509
                $response->setData(collect($exception->getMessage()));
510
            }
511
512
        }
513
514
        return SmartResponse::response($response);
515
    }
516
517
    /**
518
     * @param $method
519
     * @param $status
520
     * @return array|\Illuminate\Contracts\Translation\Translator|null|string
521
     */
522
    public function getTrans($method, $status)
523
    {
524
        return trans('laravel_smart_restful::'.'laravel_smart_restful.'.get_class($this->model) . '.' . $method . '.' . $status);
525
    }
526
527
    public function setLocale()
528
    {
529
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
530
            $this->locale = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
531
        }
532
        \App::setLocale($this->locale);
533
    }
534
}