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 (#1360)
by Ihsan
10:18 queued 02:50
created

CrudController::handleEagerLoad()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 12
nc 1
nop 1
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Http\Controllers;
4
5
use Backpack\CRUD\CrudPanel;
6
use Illuminate\Http\Request;
7
use Illuminate\Support\Facades\Form as Form;
8
use Illuminate\Foundation\Bus\DispatchesJobs;
9
use Illuminate\Routing\Controller as BaseController;
10
use Illuminate\Foundation\Validation\ValidatesRequests;
11
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\Reorder;
12
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\AjaxTable;
13
// CRUD Traits for non-core features
14
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\Revisions;
15
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\SaveActions;
16
use Backpack\CRUD\app\Http\Requests\CrudRequest as StoreRequest;
17
use Backpack\CRUD\app\Http\Requests\CrudRequest as UpdateRequest;
18
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\ShowDetailsRow;
19
20
class CrudController extends BaseController
21
{
22
    use DispatchesJobs, ValidatesRequests;
23
    use AjaxTable, Reorder, Revisions, ShowDetailsRow, SaveActions;
24
25
    public $data = [];
26
27
    /**
28
     * @var CrudPanel
29
     */
30
    public $crud;
31
32
    public $request;
33
34
    public function __construct()
35
    {
36
        if (! $this->crud) {
37
            $this->crud = app()->make(CrudPanel::class);
38
            $this->crud->ajax_table=false;
39
40
            // call the setup function inside this closure to also have the request there
41
            // this way, developers can use things stored in session (auth variables, etc)
42
            $this->middleware(function ($request, $next) {
43
                $this->request = $request;
44
                $this->crud->request = $request;
45
                $this->setup();
46
47
                return $next($request);
48
            });
49
        }
50
    }
51
52
    /**
53
     * Allow developers to set their configuration options for a CrudPanel.
54
     */
55
    public function setup()
56
    {
57
    }
58
59
    /**
60
     * Display all rows in the database for this entity.
61
     *
62
     * @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...
63
     */
64
    public function index()
65
    {
66
        $this->crud->hasAccessOrFail('list');
67
68
        $this->data['crud'] = $this->crud;
69
        $this->data['title'] = ucfirst($this->crud->entity_name_plural);
70
71
        // get all entries if AJAX is not enabled
72
        if (! $this->data['crud']->ajaxTable()) {
73
            $this->data['entries'] = $this->data['crud']->getEntries();
74
        }
75
76
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
77
        return view($this->crud->getListView(), $this->data);
78
    }
79
80
    /**
81
     * Show the form for creating inserting a new row.
82
     *
83
     * @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...
84
     */
85
    public function create()
86
    {
87
        $this->crud->hasAccessOrFail('create');
88
89
        // prepare the fields you need to show
90
        $this->data['crud'] = $this->crud;
91
        $this->data['saveAction'] = $this->getSaveAction();
92
        $this->data['fields'] = $this->crud->getCreateFields();
93
        $this->data['title'] = trans('backpack::crud.add').' '.$this->crud->entity_name;
94
95
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
96
        return view($this->crud->getCreateView(), $this->data);
97
    }
98
99
    /**
100
     * Store a newly created resource in the database.
101
     *
102
     * @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...
103
     *
104
     * @return \Illuminate\Http\RedirectResponse
105
     */
106
    public function storeCrud(StoreRequest $request = null)
107
    {
108
        $this->crud->hasAccessOrFail('create');
109
110
        // fallback to global request instance
111
        if (is_null($request)) {
112
            $request = \Request::instance();
113
        }
114
115
        // replace empty values with NULL, so that it will work with MySQL strict mode on
116 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...
117
            if (empty($value) && $value !== '0') {
118
                $request->request->set($key, null);
119
            }
120
        }
121
122
        // insert item in the db
123
        $item = $this->crud->create($request->except(['save_action', '_token', '_method']));
124
        $this->data['entry'] = $this->crud->entry = $item;
125
126
        // show a success message
127
        if($this->crud->model::find($item->id))
0 ignored issues
show
Bug introduced by
The method find 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...
128
         \Alert::success(trans('backpack::crud.insert_success'))->flash();
129
130
        // save the redirect choice for next time
131
        $this->setSaveAction();
132
133
        return $this->performSaveAction($item->getKey());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->performSaveAction($item->getKey()); of type array|Illuminate\Http\RedirectResponse adds the type array to the return on line 133 which is incompatible with the return type documented by Backpack\CRUD\app\Http\C...udController::storeCrud of type Illuminate\Http\RedirectResponse.
Loading history...
134
    }
135
136
    /**
137
     * Show the form for editing the specified resource.
138
     *
139
     * @param int $id
140
     *
141
     * @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...
142
     */
143
    public function edit($id)
144
    {
145
        $this->crud->hasAccessOrFail('update');
146
147
        // get entry ID from Request (makes sure its the last ID for nested resources)
148
        $id = $this->crud->getCurrentEntryId() ?? $id;
149
150
        // get the info for that entry
151
        $this->data['entry'] = $this->crud->getEntry($id);
152
        $this->data['crud'] = $this->crud;
153
        $this->data['saveAction'] = $this->getSaveAction();
154
        $this->data['fields'] = $fields = $this->crud->getUpdateFields($id);
0 ignored issues
show
Unused Code introduced by
$fields is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
155
        $this->data['title'] = trans('backpack::crud.edit').' '.$this->crud->entity_name;
156
157
        $this->data['id'] = $id;
158
159
        if($this->crud->eagerLoad && !empty($this->crud->eagerLoad))
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->crud->eagerLoad of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
160
        foreach($this->crud->eagerLoad as $relation_name)
161
        {
162
         if($this->data['entry'] && $rel = $this->data['entry']->{$relation_name})
163
         {
164
          foreach($this->data['fields'] as $field_name => $field)
165
          {
166
           if(starts_with($field_name, $relation_name))
167
           {
168
            $column_name = str_replace("{$relation_name}.", '', $field_name);
169
170
            $this->data['fields'][$field_name]['value'] = $rel->{$column_name};
171
           }
172
          }
173
         }
174
        }
175
176
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
177
        return view($this->crud->getEditView(), $this->data);
178
    }
179
180
    /**
181
     * Update the specified resource in the database.
182
     *
183
     * @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...
184
     *
185
     * @return \Illuminate\Http\RedirectResponse
186
     */
187
    public function updateCrud(UpdateRequest $request = null)
188
    {
189
        $this->crud->hasAccessOrFail('update');
190
191
        // fallback to global request instance
192
        if (is_null($request)) {
193
            $request = \Request::instance();
194
        }
195
196
        // replace empty values with NULL, so that it will work with MySQL strict mode on
197 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...
198
            if (empty($value) && $value !== '0') {
199
                $request->request->set($key, null);
200
            }
201
        }
202
203
        // update the row in the db
204
        $item = $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...
205
                            $request->except('save_action', '_token', '_method'));
206
        $this->data['entry'] = $this->crud->entry = $item;
207
208
        // show a success message
209
        \Alert::success(trans('backpack::crud.update_success'))->flash();
210
211
        // save the redirect choice for next time
212
        $this->setSaveAction();
213
214
        return $this->performSaveAction($item->getKey());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->performSaveAction($item->getKey()); of type array|Illuminate\Http\RedirectResponse adds the type array to the return on line 214 which is incompatible with the return type documented by Backpack\CRUD\app\Http\C...dController::updateCrud of type Illuminate\Http\RedirectResponse.
Loading history...
215
    }
216
217
    /**
218
     * Display the specified resource.
219
     *
220
     * @param int $id
221
     *
222
     * @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...
223
     */
224
    public function show($id)
225
    {
226
        $this->crud->hasAccessOrFail('show');
227
228
        // get entry ID from Request (makes sure its the last ID for nested resources)
229
        $id = $this->crud->getCurrentEntryId() ?? $id;
230
231
        // set columns from db
232
        $this->crud->setFromDb();
233
234
        // cycle through columns
235
        foreach ($this->crud->columns as $key => $column) {
236
            // remove any autoset relationship columns
237
            if (array_key_exists('model', $column) && array_key_exists('autoset', $column) && $column['autoset']) {
238
                $this->crud->removeColumn($column['name']);
239
            }
240
        }
241
242
        // get the info for that entry
243
        $this->data['entry'] = $this->crud->getEntry($id);
244
        $this->data['crud'] = $this->crud;
245
        $this->data['title'] = trans('backpack::crud.preview').' '.$this->crud->entity_name;
246
247
        // remove preview button from stack:line
248
        $this->crud->removeButton('preview');
249
        $this->crud->removeButton('delete');
250
251
        // load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
252
        return view($this->crud->getShowView(), $this->data);
253
    }
254
255
    /**
256
     * Remove the specified resource from storage.
257
     *
258
     * @param int $id
259
     *
260
     * @return string
261
     */
262
    public function destroy($id)
263
    {
264
        $this->crud->hasAccessOrFail('delete');
265
266
        // get entry ID from Request (makes sure its the last ID for nested resources)
267
        $id = $this->crud->getCurrentEntryId() ?? $id;
268
269
        return $this->crud->delete($id);
270
    }
271
272
    public function handleEagerLoad($item)
273
    {
274
     collect($this->crud->eagerLoad)->each(function($relation_name, $key) use ($item)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
275
     {
276
      $data = collect(request()->all())
277
      ->filter(function($value, $key) use ($relation_name)
278
      {
279
       return starts_with($key, $relation_name);
280
      })
281
      ->mapWithKeys(function($value, $key) use ($relation_name)
282
      {
283
       return [str_replace("{$relation_name}_", '', $key) => $value ?? ''];
284
      })
285
      ->toArray();
286
287
      if(!$rel = $item->{$relation_name})
288
       $item->{$relation_name}()->create($data);
289
      else
290
       $item->{$relation_name}->update($data);
291
     });
292
    }
293
}
294