Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Completed
Pull Request — master (#109)
by
unknown
08:27
created

CrudController   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 345
Duplicated Lines 15.36 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 53
loc 345
rs 10
wmc 27
lcom 1
cbo 9

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A index() 0 16 2
A create() 12 12 1
B storeCrud() 0 31 5
A edit() 15 15 1
B updateCrud() 0 25 4
A show() 12 12 1
A listRevisions() 14 14 1
A restoreRevision() 0 23 2
A destroy() 0 6 1
A reorder() 0 16 2
A saveReorder() 0 14 2
A showDetailsRow() 0 10 1
B search() 0 37 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Backpack\CRUD\app\Http\Controllers;
4
5
use Backpack\CRUD\app\Http\Requests\CrudRequest as StoreRequest;
6
use Backpack\CRUD\app\Http\Requests\CrudRequest as UpdateRequest;
7
use Backpack\CRUD\CrudPanel;
8
use Illuminate\Foundation\Bus\DispatchesJobs;
9
use Illuminate\Foundation\Validation\ValidatesRequests;
10
// VALIDATION: change the requests to match your own file names if you need form validation
11
use Illuminate\Routing\Controller as BaseController;
12
use Illuminate\Support\Facades\Form as Form;
13
use LiveControl\EloquentDataTable\DataTable;
14
15
class CrudController extends BaseController
16
{
17
    use DispatchesJobs, ValidatesRequests;
18
19
    public $data = [];
20
    public $crud;
21
22
    public function __construct()
23
    {
24
        $this->crud = new CrudPanel();
25
    }
26
27
    /**
28
     * Display all rows in the database for this entity.
29
     *
30
     * @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
31
     */
32
    public function index()
33
    {
34
        $this->crud->hasAccessOrFail('list');
35
36
        $this->data['crud'] = $this->crud;
37
        $this->data['title'] = ucfirst($this->crud->entity_name_plural);
38
39
        // get all entries if AJAX is not enabled
40
        if (! $this->data['crud']->ajaxTable()) {
41
            $this->data['entries'] = $this->data['crud']->getEntries();
42
        }
43
44
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
45
        // $this->crud->getListView() returns 'list' by default, or 'list_ajax' if ajax was enabled
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
46
        return view('crud::list', $this->data);
47
    }
48
49
    /**
50
     * Show the form for creating inserting a new row.
51
     *
52
     * @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
53
     */
54 View Code Duplication
    public function create()
0 ignored issues
show
Duplication introduced by
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...
55
    {
56
        $this->crud->hasAccessOrFail('create');
57
58
        // prepare the fields you need to show
59
        $this->data['crud'] = $this->crud;
60
        $this->data['fields'] = $this->crud->getCreateFields();
61
        $this->data['title'] = trans('backpack::crud.add').' '.$this->crud->entity_name;
62
63
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
64
        return view('crud::create', $this->data);
65
    }
66
67
    /**
68
     * Store a newly created resource in the database.
69
     *
70
     * @param StoreRequest $request - type injection used for validation using Requests
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be null|StoreRequest?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
71
     *
72
     * @return \Illuminate\Http\RedirectResponse
73
     */
74
    public function storeCrud(StoreRequest $request = null)
75
    {
76
        $this->crud->hasAccessOrFail('create');
77
78
        // fallback to global request instance
79
        if (is_null($request)) {
80
            $request = \Request::instance();
81
        }
82
83
        // replace empty values with NULL, so that it will work with MySQL strict mode on
84
        foreach ($request->input() as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $request->input() of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
85
            if (empty($value)) {
86
                $request->request->set($key, null);
87
            }
88
        }
89
90
        // insert item in the db
91
        $item = $this->crud->create($request->except(['redirect_after_save', 'password']));
92
93
        // show a success message
94
        \Alert::success(trans('backpack::crud.insert_success'))->flash();
95
96
        // redirect the user where he chose to be redirected
97
        switch ($request->input('redirect_after_save')) {
98
            case 'current_item_edit':
99
                return \Redirect::to($this->crud->route.'/'.$item->getKey().'/edit');
100
101
            default:
102
                return \Redirect::to($request->input('redirect_after_save'));
0 ignored issues
show
Bug introduced by
It seems like $request->input('redirect_after_save') targeting Illuminate\Http\Request::input() can also be of type array; however, Illuminate\Routing\Redirector::to() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
103
        }
104
    }
105
106
    /**
107
     * Show the form for editing the specified resource.
108
     *
109
     * @param int $id
110
     *
111
     * @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
112
     */
113 View Code Duplication
    public function edit($id)
0 ignored issues
show
Duplication introduced by
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...
114
    {
115
        $this->crud->hasAccessOrFail('update');
116
117
        // get the info for that entry
118
        $this->data['entry'] = $this->crud->getEntry($id);
119
        $this->data['crud'] = $this->crud;
120
        $this->data['fields'] = $this->crud->getUpdateFields($id);
121
        $this->data['title'] = trans('backpack::crud.edit').' '.$this->crud->entity_name;
122
123
        $this->data['id'] = $id;
124
125
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
126
        return view('crud::edit', $this->data);
127
    }
128
129
    /**
130
     * Update the specified resource in the database.
131
     *
132
     * @param UpdateRequest $request - type injection used for validation using Requests
0 ignored issues
show
Documentation introduced by
Should the type for parameter $request not be null|StoreRequest?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
133
     *
134
     * @return \Illuminate\Http\RedirectResponse
135
     */
136
    public function updateCrud(UpdateRequest $request = null)
137
    {
138
        $this->crud->hasAccessOrFail('update');
139
140
        // fallback to global request instance
141
        if (is_null($request)) {
142
            $request = \Request::instance();
143
        }
144
145
        // replace empty values with NULL, so that it will work with MySQL strict mode on
146
        foreach ($request->input() as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $request->input() of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
147
            if (empty($value)) {
148
                $request->request->set($key, null);
149
            }
150
        }
151
152
        // update the row in the db
153
        $this->crud->update($request->get($this->crud->model->getKeyName()),
0 ignored issues
show
Bug introduced by
The method getKeyName cannot be called on $this->crud->model (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
154
                            $request->except('redirect_after_save'));
155
156
        // show a success message
157
        \Alert::success(trans('backpack::crud.update_success'))->flash();
158
159
        return \Redirect::to($this->crud->route);
160
    }
161
162
    /**
163
     * Display the specified resource.
164
     *
165
     * @param int $id
166
     *
167
     * @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
168
     */
169 View Code Duplication
    public function show($id)
0 ignored issues
show
Duplication introduced by
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...
170
    {
171
        $this->crud->hasAccessOrFail('show');
172
173
        // get the info for that entry
174
        $this->data['entry'] = $this->crud->getEntry($id);
175
        $this->data['crud'] = $this->crud;
176
        $this->data['title'] = trans('backpack::crud.preview').' '.$this->crud->entity_name;
177
178
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
179
        return view('crud::show', $this->data);
180
    }
181
182
    /**
183
     * Display the revisions for specified resource.
184
     *
185
     * @param int $id
186
     *
187
     * @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
188
     */
189 View Code Duplication
    public function listRevisions($id)
0 ignored issues
show
Duplication introduced by
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...
190
    {
191
        $this->crud->hasAccessOrFail('revisions');
192
193
        // get the info for that entry
194
        $this->data['entry'] = $this->crud->getEntry($id);
195
        $this->data['crud'] = $this->crud;
196
        $this->data['title'] = trans('backpack::crud.revisions').' '.$this->crud->entity_name;
197
        $this->data['id'] = $id;
198
        $this->data['revisions'] = $this->crud->listRevisions($id);
199
200
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
201
        return view('crud::revisions', $this->data);
202
    }
203
204
    /**
205
     * Restore a specific revision for the specified resource.
206
     *
207
     * Used via AJAX in the revisions view
208
     *
209
     * @param int $id
210
     *
211
     * @return JSON Response containing the new revision that was created from the update
212
     * @return HTTP 500 if the request did not contain the revision ID
0 ignored issues
show
Documentation introduced by
Should the return type not be null|\Illuminate\View\Vi...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
213
     */
214
    public function restoreRevision($id)
215
    {
216
217
        $this->crud->hasAccessOrFail('revisions');
218
219
        // @TODO: Currently the route already contains the revision ID, so passing it as a POST param
220
        // is somewhat superfluous.. however if we are POSTing, it makes sense to actually have data to post.
221
        // Perhaps the route shoud be better named to reflect this (e.g. just /model/{id}/revisions) (??)
222
        $revisionId = \Request::input('revision_id', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string|array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
223
        if(!$revisionId) {
224
            abort(500, 'Can\'t restore revision without revision_id');
225
        } else {
226
            $this->crud->restoreRevision($id, $revisionId); // do the update
227
228
            $this->data['entry'] = $this->crud->getEntry($id);
229
            $this->data['crud'] = $this->crud;
230
            $this->data['revisions'] = $this->crud->listRevisions($id); // Reload revisions as they have changed
231
232
            // Rebuild the revision timeline HTML and return it to the AJAX call
233
            // @TODO: Return only the latest revision to save bandwidth - 15/9/16 @se1exin
234
            return view('crud::inc.revision_timeline', $this->data);
235
        }
236
    }
237
238
    /**
239
     * Remove the specified resource from storage.
240
     *
241
     * @param int $id
242
     *
243
     * @return string
244
     */
245
    public function destroy($id)
246
    {
247
        $this->crud->hasAccessOrFail('delete');
248
249
        return $this->crud->delete($id);
250
    }
251
252
    /**
253
     *  Reorder the items in the database using the Nested Set pattern.
254
     *
255
     *	Database columns needed: id, parent_id, lft, rgt, depth, name/title
256
     *
257
     *  @return Response
0 ignored issues
show
Documentation introduced by
Should the return type not be \Illuminate\View\View|\I...\Contracts\View\Factory?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
258
     */
259
    public function reorder()
260
    {
261
        $this->crud->hasAccessOrFail('reorder');
262
263
        if (! $this->crud->isReorderEnabled()) {
264
            abort(403, 'Reorder is disabled.');
265
        }
266
267
        // get all results for that entity
268
        $this->data['entries'] = $this->crud->getEntries();
269
        $this->data['crud'] = $this->crud;
270
        $this->data['title'] = trans('backpack::crud.reorder').' '.$this->crud->entity_name;
271
272
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
273
        return view('crud::reorder', $this->data);
274
    }
275
276
    /**
277
     * Save the new order, using the Nested Set pattern.
278
     *
279
     * Database columns needed: id, parent_id, lft, rgt, depth, name/title
280
     *
281
     * @return
282
     */
283
    public function saveReorder()
284
    {
285
        $this->crud->hasAccessOrFail('reorder');
286
287
        $all_entries = \Request::input('tree');
288
289
        if (count($all_entries)) {
290
            $count = $this->crud->updateTreeOrder($all_entries);
291
        } else {
292
            return false;
293
        }
294
295
        return 'success for '.$count.' items';
296
    }
297
298
    /**
299
     * Used with AJAX in the list view (datatables) to show extra information about that row that didn't fit in the table.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
300
     * It defaults to showing some dummy text.
301
     *
302
     * It's enabled by:
303
     * - setting: $crud->details_row = true;
304
     * - adding the details route for the entity; ex: Route::get('page/{id}/details', 'PageCrudController@showDetailsRow');
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
305
     * - adding a view with the following name to change what the row actually contains: app/resources/views/vendor/backpack/crud/details_row.blade.php
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 151 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
306
     */
307
    public function showDetailsRow($id)
308
    {
309
        $this->crud->hasAccessOrFail('details_row');
310
311
        $this->data['entry'] = $this->crud->getEntry($id);
312
        $this->data['crud'] = $this->crud;
313
314
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
315
        return view('crud::details_row', $this->data);
316
    }
317
318
    /**
319
     * Respond with the JSON of one or more rows, depending on the POST parameters.
320
     * @return JSON Array of cells in HTML form.
0 ignored issues
show
Documentation introduced by
Should the return type not be array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
321
     */
322
    public function search()
323
    {
324
        $this->crud->hasAccessOrFail('list');
325
326
        // add the primary key, even though you don't show it,
327
        // otherwise the buttons won't work
328
        $columns = collect($this->crud->columns)->pluck('name')->merge($this->crud->model->getKeyName())->toArray();
0 ignored issues
show
Bug introduced by
The method getKeyName cannot be called on $this->crud->model (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
329
330
        // structure the response in a DataTable-friendly way
331
        $dataTable = new DataTable($this->crud->query, $columns);
332
333
        // make the datatable use the column types instead of just echoing the text
334
        $dataTable->setFormatRowFunction(function ($entry) {
335
            // get the actual HTML for each row's cell
336
            $row_items = $this->crud->getRowViews($entry, $this->crud);
0 ignored issues
show
Unused Code introduced by
The call to CrudPanel::getRowViews() has too many arguments starting with $this->crud.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
337
338
            // add the buttons as the last column
339
            if ($this->crud->buttons->where('stack', 'line')->count()) {
340
                $row_items[] = \View::make('crud::inc.button_stack', ['stack' => 'line'])
341
                                ->with('crud', $this->crud)
342
                                ->with('entry', $entry)
343
                                ->render();
344
            }
345
346
            // add the details_row buttons as the first column
347
            if ($this->crud->details_row) {
348
                array_unshift($row_items, \View::make('crud::columns.details_row_button')
349
                                ->with('crud', $this->crud)
350
                                ->with('entry', $entry)
351
                                ->render());
352
            }
353
354
            return $row_items;
355
        });
356
357
        return $dataTable->make();
358
    }
359
}
360