Completed
Push — master ( 328300...dbef74 )
by Babak
07:23
created

BaseController   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 485
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 485
rs 6.4799
c 0
b 0
f 0
wmc 54

12 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 2
A show() 0 19 2
B update() 0 47 7
A __construct() 0 4 1
A edit() 0 18 3
A message() 0 4 1
A getMessageFromFile() 0 3 1
B checkRequestValidation() 0 21 7
D store() 0 55 11

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\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...
12
use Illuminate\Database\Eloquent\ModelNotFoundException;
13
use Illuminate\Database\QueryException;
14
use Illuminate\Http\Request;
15
use Illuminate\Support\Facades\DB;
16
use Illuminate\Support\MessageBag;
17
use Illuminate\Support\Facades\Validator;
18
19
20
abstract class BaseController extends Controller
21
{
22
    /**
23
     * to use this class
24
     * create message list as messages in message file
25
     * override __constructor and define your model
26
     * define your rules for index,store and update
27
     */
28
29
    /**
30
     * @var int
31
     */
32
    protected $DEFAULT_RESULT_PER_PAGE = 15;
33
34
    /**
35
     * @var int
36
     */
37
    protected $DEFAULT_PAGE_NUMBER = 1;
38
39
    /**
40
     * @var array
41
     */
42
    protected $pivotFields = [];
43
44
    /**
45
     * @var array
46
     */
47
    protected $uniqueFields = [];
48
49
    /**
50
     * @var bool|string
51
     */
52
    protected $modelName;
53
54
    /**
55
     * @var string
56
     */
57
    protected $messagePrefix = 'messages.api.v1.';
58
59
    /**
60
     * this model
61
     */
62
    protected $model;
63
64
    /**
65
     * index request validator rules
66
     *
67
     * @var array
68
     */
69
    protected $indexValidateArray = [
70
        //
71
    ];
72
73
    /**
74
     * array of relationship for eager loading
75
     *
76
     * @var array
77
     */
78
    protected $indexLoad = [
79
        //
80
    ];
81
82
    /**
83
     * array of relationship for eager loading
84
     *
85
     * @var array
86
     */
87
    protected $editLoad = [
88
        //
89
    ];
90
91
    /**
92
     * array of relationship for eager loading
93
     *
94
     * @var array
95
     */
96
    protected $updateLoad = [
97
        //
98
    ];
99
100
    /**
101
     * store request validator rules
102
     *
103
     * @var array
104
     */
105
    protected $storeValidateArray = [
106
        //
107
    ];
108
109
    /**
110
     * update request validator rules
111
     *
112
     * @var array
113
     */
114
    protected $updateValidateArray = [
115
        //
116
    ];
117
118
    protected $middlewareParams = [];
119
120
    /**
121
     * defaultController constructor.
122
     */
123
    public function __construct()
124
    {
125
//        dd("I have closest relationship with all US celebrities");
126
        $this->initController();
127
    }
128
129
    abstract public function initController();
130
131
    /**
132
     * Display a listing of the resource.
133
     *
134
     * @param Request $request
135
     * @return string
136
     */
137
    public function index(Request $request)
138
    {
139
        // create response model
140
        $response = new ResponseModel();
141
142
        $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...
143
        $pageNumber = 1;
144
145
        //set default pagination
146
147
        //set page size
148
        if (!isset($request->toArray()['page']['size'])){
149
            $pageSize = $this->DEFAULT_RESULT_PER_PAGE;
150
        }elseif(($request->get('page')['size'])==0){
151
            $pageSize = $this->DEFAULT_RESULT_PER_PAGE;
152
        }else{
153
            $pageSize = $request->get('page')['size'];
154
        }
155
156
        //set page number
157
        if (!isset($request->get('page')['number'])){
158
            $pageNumber = $this->DEFAULT_RESULT_PER_PAGE;
159
        }elseif(($request->get('page')['number'])==0){
160
            $pageNumber = $this->DEFAULT_RESULT_PER_PAGE;
161
        }else{
162
            $pageNumber = $request->get('page')['number'];
163
        }
164
        $request['page'] = $pageNumber;
165
166
167
        //set default ordering
168
        if (isset($request->toArray()['order_by'])) {
169
            if (is_null($request['order_by'])) {
170
                $request['order_by'] = "{\"field\":\"id\",\"operator\":\"Desc\"}";
171
            }
172
        }
173
174
        $validationErrors = $this->checkRequestValidation($request, $this->indexValidateArray);
175
        if ($validationErrors != null) {
176
177
            // return response
178
            $response->setData(collect($validationErrors->toArray()));
179
            $response->setMessage("Validation Failed");
180
            $response->setStatus(false);
181
            $response->setError(99);
182
            return SmartResponse::response($response);
183
        }
184
185
        try {
186
            $data = $request->get('query') != null ?
187
                $this->model
188
                    ->whereKey(collect($this->model
189
                        ->search(($request->get('query')))
190
                        ->raw())->get('ids')) :
191
                $this->model;
192
            if (array_key_exists('file', $request->toArray())) {
193
                //TODO add relation on top if here and create a tree flatter array in array helper
194
                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...
195
                    'store_format' => $request->get('file') == null ? 'xls' : $request->get('file'),
196
                    'download_format' => $request->get('file') == null ? 'xls' : $request->get('file'),
197
                ])->table($data->get()->toArray())->createExcelFile()->download();
198
            }
199
200
            // load relations
201
            if (count($this->indexLoad) > 0) {
202
                $data = $data->with($this->indexLoad);
203
            }
204
205
            // filters by
206
            if (isset($request->toArray()['filters'])) {
207
                $data = (new QueryHelper())->deepFilter($data, (new RequestHelper())->getCollectFromJson($request['filters']));
208
            }
209
210
            // order by
211
            if (isset($request->toArray()['order_by'])) {
212
                $data = (new QueryHelper())->orderBy($data, (new RequestHelper())->getCollectFromJson($request['order_by']));
213
            }
214
215
            // return response
216
            $response->setData(collect($data->setPerPage($pageSize)->paginate()));
217
            $response->setMessage("Successful");
218
            return SmartResponse::response($response);
219
220
        } catch (QueryException $exception) {
221
222
            // return response
223
            $response->setData(collect($exception->getMessage()));
224
            $response->setError($exception->getCode());
225
            $response->setMessage("Failed");
226
            $response->setStatus(false);
227
            return SmartResponse::response($response);
228
        }
229
    }
230
231
    public function checkRequestValidation(Request $request, $validationArray)
232
    {
233
        $requestParams = $request->toArray();
234
        $validator = Validator::make($request->all(), $validationArray);
235
        if ($validator->fails()) {
236
            return $validator->errors();
237
        }
238
        if (is_numeric(array_search($request->getMethod(), ["POST", "PUT", "PATCH"]))) {
239
            $errors = new MessageBag();
240
            foreach ($requestParams as $requestParamKey => $requestParamValue) {
241
                if (is_numeric(array_search($requestParamKey, $this->uniqueFields))) {
242
                    if ($this->checkExistUniqueRecord($requestParamKey, $requestParamValue)) {
243
                        $errors->add($requestParamKey, 'This ' . $requestParamKey . ' is exist try another.');
244
                    }
245
                }
246
            }
247
            if (collect($errors)->count() > 0) {
248
                return $errors;
249
            }
250
        }
251
        return null;
252
    }
253
254
    /**
255
     * @param $key
256
     * @param $value
257
     * @return bool
258
     */
259
    public function checkExistUniqueRecord($key, $value)
260
    {
261
        if ($this->model->where($key, $value)->count()) {
262
            return true;
263
        }
264
        return false;
265
    }
266
267
    /**
268
     * @param $status
269
     * @return mixed
270
     */
271
    public function message($status)
272
    {
273
        $key = $this->messagePrefix . $this->modelName . '.' . debug_backtrace()[1]['function'] . '.' . $status;
274
        return $this->getMessageFromFile($key);
275
    }
276
277
    /**
278
     * @param $key
279
     * @return mixed
280
     */
281
    public function getMessageFromFile($key)
282
    {
283
        return config($key);
284
    }
285
286
    /**
287
     * Show the form for creating a new resource.
288
     *
289
     * @return \Illuminate\Http\JsonResponse
290
     */
291
    public function create()
292
    {
293
        // Create Response Model
294
        $response = new ResponseModel();
295
296
        // return response
297
        $response->setData(collect($this->model->getFillable()));
298
        $response->setMessage("Successful");
299
        return SmartResponse::response($response);
300
    }
301
302
    /**
303
     * Store a newly created resource in storage.
304
     *
305
     * @param  \Illuminate\Http\Request $request
306
     * @return \Illuminate\Http\JsonResponse
307
     */
308
    public function store(Request $request)
309
    {
310
        // Create Response Model
311
        $response = new ResponseModel();
312
313
        // TODO must set access in middle ware
314
        //get user id
315
        $userId = auth()->id();
316
317
        //add author id into the request if doesn't exist
318
        if (isset($request['author_id'])) {
319
            if (is_null($request['author_id'])) {
320
                $request['author_id'] = $userId;
321
            }
322
        } else {
323
            $request['author_id'] = $userId;
324
        }
325
326
        //add user id into the request if doesn't exist
327
        if (isset($request['user_id'])) {
328
            if (is_null($request['user_id'])) {
329
                $request['user_id'] = $userId;
330
            }
331
        } else {
332
            $request['user_id'] = $userId;
333
        }
334
335
        $validationErrors = $this->checkRequestValidation($request, $this->storeValidateArray);
336
        if ($validationErrors != null) {
337
            if (env('APP_DEBUG', false)) {
338
                $response->setMessage(json_encode($validationErrors->getMessages()));
339
            }
340
            $response->setStatus(false);
341
            return SmartResponse::response($response);
342
        }
343
        try {
344
            // get result of model creation
345
            $result = $this->model->create($request->all());
346
            // sync many to many relation
347
            foreach ($this->pivotFields as $pivotField) {
348
                if (collect($request[$pivotField])->count()) {
349
                    $pivotField = (new StringHelper())->toCamel($pivotField);
350
                    $this->model->find($result['id'])->$pivotField()->sync(json_decode($request[$pivotField]));
351
                }
352
            }
353
            $response->setMessage('successful');
354
            $response->setData(collect($result->toArray()));
355
            $response->setStatus(true);
356
            return SmartResponse::response($response);
357
        } catch (QueryException $exception) {
358
            if (env('APP_DEBUG', false)) {
359
                $response->setMessage($exception->getMessage());
360
            }
361
            $response->setStatus(false);
362
            return SmartResponse::response($response);
363
        }
364
    }
365
366
    /**
367
     * Display the specdefaultied resource.
368
     *
369
     * @param  int $id
370
     * @return \Illuminate\Http\Response
371
     */
372
    public function show($id)
373
    {
374
        // Create Response Model
375
        $response = new ResponseModel();
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
376
377
        try {
378
379
            return SmartResponse::json(
380
                $this->message('successful'),
381
                true,
382
                200,
383
                $this->model->findOrFail($id)
384
            );
385
        } catch (ModelNotFoundException $exception) {
386
            return SmartResponse::json(
387
                $this->message('failed'),
388
                false,
389
                200,
390
                $exception->getMessage()
391
            );
392
        }
393
    }
394
395
    /**
396
     * Show the form for editing the specified resource.
397
     *
398
     * @param  int $id
399
     * @return \Illuminate\Http\JsonResponse
400
     */
401
    public function edit($id)
402
    {
403
        // Create Response Model
404
        $response = new ResponseModel();
405
406
        try {
407
            $response->setMessage('Successful');
408
            $response->setData($this->model
409
                ->where($this->model->getKeyName(), $id)
410
                ->with(collect($this->editLoad)->count() == 0 ? $this->indexLoad : $this->editLoad)
411
                ->get());
412
            return SmartResponse::response($response);
413
        } catch (ModelNotFoundException $exception) {
414
            $response->setData(collect($exception->getMessage()));
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('Failed');
417
            $response->setStatus(false);
418
            return SmartResponse::response($response);
419
        }
420
    }
421
422
    /**
423
     * Update the specified resource in storage.
424
     *
425
     * @param  \Illuminate\Http\Request $request
426
     * @param  int $id
427
     * @return \Illuminate\Http\JsonResponse
428
     */
429
    public function update(Request $request, $id)
430
    {
431
        // Create Response Model
432
        $response = new ResponseModel();
433
434
        $validationErrors = $this->checkRequestValidation($request, $this->updateValidateArray);
435
        if ($validationErrors != null) {
436
437
            // return response
438
            $response->setData(collect($validationErrors->toArray()));
439
            $response->setMessage("Validation Failed");
440
            $response->setStatus(false);
441
            $response->setError(99);
442
            return SmartResponse::response($response);
443
        }
444
        try {
445
            // sync many to many relation
446
            foreach ($this->pivotFields as $pivotField) {
447
                if (collect($request[$pivotField])->count()) {
448
                    $pivotMethod = (new StringHelper())->toCamel($pivotField);
449
                    $this->model->findOrFail($id)->$pivotMethod()->sync(json_decode($request[$pivotField], true));
450
                }
451
            }
452
            //get result of update
453
            $result = $this->model->findOrFail($id)->update($request->all());
454
455
            // return response
456
            $response->setData(collect(env('APP_DEBUG') ? $this->model->find($id) : []));
457
            $response->setMessage('Successful to change ' . $result . ' record');
458
            return SmartResponse::response($response);
459
460
        } catch (ModelNotFoundException $exception) {
461
462
            // return response
463
            $response->setData(collect($exception->getMessage()));
464
            $response->setStatus(false);
465
            $response->setMessage('Not found record');
466
467
            return SmartResponse::response($response);
468
469
        } catch (QueryException $exception) {
470
            // return response
471
            $response->setData(collect($exception->getMessage()));
472
            $response->setStatus(false);
473
            $response->setMessage('Failed');
474
475
            return SmartResponse::response($response);
476
        }
477
    }
478
479
    /**
480
     * Remove the specified resource from storage.
481
     *
482
     * @param  int $id
483
     * @return \Illuminate\Http\JsonResponse
484
     */
485
    public function destroy($id)
486
    {
487
        // Create Response Model
488
        $response = new ResponseModel();
489
490
        try {
491
            // return response
492
            $response->setData(collect($this->model->findOrFail($id)->delete()));
493
            $response->setMessage('Successful');
494
495
            return SmartResponse::response($response);
496
497
        } catch (ModelNotFoundException $exception) {
498
            // return response
499
            $response->setData(collect($exception->getMessage()));
500
            $response->setMessage('Failed');
501
            $response->setStatus(false);
502
            $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

502
            $response->setError(/** @scrutinizer ignore-type */ $exception->getCode());
Loading history...
503
504
            return SmartResponse::response($response);
505
        }
506
    }
507
}