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 (#136)
by Owen
02:46
created

CrudController::search()   B

Complexity

Conditions 3
Paths 1

Size

Total Lines 37
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 3
eloc 18
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 37
rs 8.8571
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 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated across 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...
85
            if (empty($value) && $value !== '0') {
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', '_token']));
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 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated across 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...
147
            if (empty($value) && $value !== '0') {
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', '_token'));
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'] = ucfirst($this->crud->entity_name).' '.trans('backpack::crud.revisions');
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
        $this->crud->hasAccessOrFail('revisions');
217
218
        // @TODO: Currently the route already contains the revision ID, so passing it as a POST param
219
        // is somewhat superfluous.. however if we are POSTing, it makes sense to actually have data to post.
220
        // Perhaps the route shoud be better named to reflect this (e.g. just /model/{id}/revisions) (??)
221
        $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...
222
        if (! $revisionId) {
223
            abort(500, 'Can\'t restore revision without revision_id');
224
        } else {
225
            $this->crud->restoreRevision($id, $revisionId); // do the update
226
227
            $this->data['entry'] = $this->crud->getEntry($id);
228
            $this->data['crud'] = $this->crud;
229
            $this->data['revisions'] = $this->crud->listRevisions($id); // Reload revisions as they have changed
230
231
            // Rebuild the revision timeline HTML and return it to the AJAX call
232
            // @TODO: Return only the latest revision to save bandwidth - 15/9/16 @se1exin
233
            return view('crud::inc.revision_timeline', $this->data);
234
        }
235
    }
236
237
    /**
238
     * Remove the specified resource from storage.
239
     *
240
     * @param int $id
241
     *
242
     * @return string
243
     */
244
    public function destroy($id)
245
    {
246
        $this->crud->hasAccessOrFail('delete');
247
248
        return $this->crud->delete($id);
249
    }
250
251
    /**
252
     *  Reorder the items in the database using the Nested Set pattern.
253
     *
254
     *	Database columns needed: id, parent_id, lft, rgt, depth, name/title
255
     *
256
     *  @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...
257
     */
258
    public function reorder()
259
    {
260
        $this->crud->hasAccessOrFail('reorder');
261
262
        if (! $this->crud->isReorderEnabled()) {
263
            abort(403, 'Reorder is disabled.');
264
        }
265
266
        // get all results for that entity
267
        $this->data['entries'] = $this->crud->getEntries();
268
        $this->data['crud'] = $this->crud;
269
        $this->data['title'] = trans('backpack::crud.reorder').' '.$this->crud->entity_name;
270
271
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
272
        return view('crud::reorder', $this->data);
273
    }
274
275
    /**
276
     * Save the new order, using the Nested Set pattern.
277
     *
278
     * Database columns needed: id, parent_id, lft, rgt, depth, name/title
279
     *
280
     * @return
281
     */
282
    public function saveReorder()
283
    {
284
        $this->crud->hasAccessOrFail('reorder');
285
286
        $all_entries = \Request::input('tree');
287
288
        if (count($all_entries)) {
289
            $count = $this->crud->updateTreeOrder($all_entries);
290
        } else {
291
            return false;
292
        }
293
294
        return 'success for '.$count.' items';
295
    }
296
297
    /**
298
     * 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...
299
     * It defaults to showing some dummy text.
300
     *
301
     * It's enabled by:
302
     * - setting: $crud->details_row = true;
303
     * - 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...
304
     * - 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...
305
     */
306
    public function showDetailsRow($id)
307
    {
308
        $this->crud->hasAccessOrFail('details_row');
309
310
        $this->data['entry'] = $this->crud->getEntry($id);
311
        $this->data['crud'] = $this->crud;
312
313
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
314
        return view('crud::details_row', $this->data);
315
    }
316
317
    /**
318
     * Respond with the JSON of one or more rows, depending on the POST parameters.
319
     * @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...
320
     */
321
    public function search()
322
    {
323
        $this->crud->hasAccessOrFail('list');
324
325
        // add the primary key, even though you don't show it,
326
        // otherwise the buttons won't work
327
        $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...
328
329
        // structure the response in a DataTable-friendly way
330
        $dataTable = new DataTable($this->crud->query, $columns);
331
332
        // make the datatable use the column types instead of just echoing the text
333
        $dataTable->setFormatRowFunction(function ($entry) {
334
            // get the actual HTML for each row's cell
335
            $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...
336
337
            // add the buttons as the last column
338
            if ($this->crud->buttons->where('stack', 'line')->count()) {
339
                $row_items[] = \View::make('crud::inc.button_stack', ['stack' => 'line'])
340
                                ->with('crud', $this->crud)
341
                                ->with('entry', $entry)
342
                                ->render();
343
            }
344
345
            // add the details_row buttons as the first column
346
            if ($this->crud->details_row) {
347
                array_unshift($row_items, \View::make('crud::columns.details_row_button')
348
                                ->with('crud', $this->crud)
349
                                ->with('entry', $entry)
350
                                ->render());
351
            }
352
353
            return $row_items;
354
        });
355
356
        return $dataTable->make();
357
    }
358
359
     /**
360
      * Checks if the given string is unique, and return existing entity.
361
      * @return JSON containing success, message and data.
0 ignored issues
show
Documentation introduced by
Should the return type not be array?

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...
362
      */
363
     public function unicity()
364
     {
365
         $response = ['success' => false, 'message' => trans('backpack::crud.unique_error'), 'meta' => ['link' => null, 'snippet' => null, 'entity_key' => null]];
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 162 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...
366
367
         $field_name = \Request::input('field_name', null);
368
         $check_value = \Request::input('check_value', null);
369
         $display_name = \Request::input('display_name', null);
370
371
         if (empty($field_name)) {
372
             $response['message'] = trans('backpack::crud.unique_field_name_missing');
373
         } elseif (empty($check_value) && $check_value !== '0') {
374
             $response['message'] = trans('backpack::crud.unique_check_value_missing');
375
         } else {
376
             $existing_entity = $this->crud->model->where([$field_name => $check_value])->first();
0 ignored issues
show
Bug introduced by
The method where 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...
377
378
             if (! $existing_entity) {
379
                 $response['success'] = true;
380
                 $response['message'] = null;
381
             } else {
382
                 $response['message'] = $this->crud->entity_name.' '.trans('backpack::crud.unique_exists');
383
                 $response['meta'] = [
384
                    'link' => url($this->crud->route.'/'.$existing_entity->getKey().'/edit'),
385
                    'snippet' => $display_name ? $existing_entity->{$display_name} : $this->crud->entity_name,
386
                    'entity_key' => $existing_entity->getKey(),
387
                ];
388
             }
389
         }
390
391
         return $response;
392
     }
393
}
394