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
Push — master ( b393e2...607f68 )
by Cristian
02:55
created

Crud::setModel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
cc 2
eloc 5
c 5
b 1
f 1
nc 2
nop 1
dl 0
loc 11
rs 9.4285
1
<?php
2
3
namespace Backpack\CRUD;
4
5
class Crud
6
{
7
    // --------------
8
    // CRUD variables
9
    // --------------
10
    // These variables are passed to the CRUD views, inside the $crud variable.
11
    // All variables are public, so they can be modified from your EntityCrudController.
12
    // All functions and methods are also public, so they can be used in your EntityCrudController to modify these variables.
13
14
    // TODO: translate $entity_name and $entity_name_plural by default, with english fallback
15
    // TODO: code logic for using either Laravel Authorization or Entrust (whatever one chooses) for access
16
17
    public $model = "\App\Models\Entity"; // what's the namespace for your entity's model
18
    public $route; // what route have you defined for your entity? used for links.
19
    public $entity_name = 'entry'; // what name will show up on the buttons, in singural (ex: Add entity)
20
    public $entity_name_plural = 'entries'; // what name will show up on the buttons, in plural (ex: Delete 5 entities)
21
22
    public $access = ['list', 'create', 'update', 'delete'/* 'reorder', 'show', 'details_row' */];
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
23
24
    public $reorder = false;
25
    public $reorder_label = false;
26
    public $reorder_max_level = 3;
27
28
    public $details_row = false;
29
30
    public $columns = []; // Define the columns for the table view as an array;
31
    public $create_fields = []; // Define the fields for the "Add new entry" view as an array;
32
    public $update_fields = []; // Define the fields for the "Edit entry" view as an array;
33
34
    public $query;
35
    public $entry;
36
37
    // TONE FIELDS - TODO: find out what he did with them, replicate or delete
38
    public $field_types = [];
39
40
    public $custom_buttons = [];
41
    public $relations = [];
42
    public $sort = [];
43
44
    public $buttons = [''];
45
46
    // The following methods are used in CrudController or your EntityCrudController to manipulate the variables above.
47
48
    /*
49
    |--------------------------------------------------------------------------
50
    |                                   CREATE
51
    |--------------------------------------------------------------------------
52
    */
53
54
    /**
55
     * Insert a row in the database.
56
     *
57
     * @param  [Request] All input values to be inserted.
58
     *
59
     * @return [Eloquent Collection]
0 ignored issues
show
Documentation introduced by
The doc-type Eloquent">[Eloquent could not be parsed: Unknown type name "[" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
60
     */
61
    public function create($data)
62
    {
63
        $values_to_store = $this->compactFakeFields($data, 'create');
64
        $item = $this->model->create($values_to_store);
1 ignored issue
show
Bug introduced by
The method create cannot be called on $this->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...
65
66
        // if there are any relationships available, also sync those
67
        $this->syncPivot($item, $data);
68
69
        return $item;
70
    }
71
72
    /**
73
     * Get all fields needed for the ADD NEW ENTRY form.
74
     *
75
     * @return [array] The fields with attributes and fake attributes.
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
76
     */
77
    public function getCreateFields()
78
    {
79
        return $this->create_fields;
80
    }
81
82
    /**
83
     * Get all fields with relation set (model key set on field).
84
     *
85
     * @param [string: create/update/both]
86
     *
87
     * @return [array] The fields with model key set.
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
88
     */
89
    public function getRelationFields($form = 'create')
90
    {
91
        if ($form == 'create') {
92
            $fields = $this->create_fields;
93
        } else {
94
            $fields = $this->update_fields;
95
        }
96
97
        $relationFields = [];
98
99
        foreach ($fields as $field) {
100
            if (isset($field['model'])) {
101
                array_push($relationFields, $field);
102
            }
103
104
            if (isset($field['subfields']) &&
105
                is_array($field['subfields']) &&
106
                count($field['subfields'])) {
107
                foreach ($field['subfields'] as $subfield) {
108
                    array_push($relationFields, $subfield);
109
                }
110
            }
111
        }
112
113
        return $relationFields;
114
    }
115
116
    public function syncPivot($model, $data, $form = 'create')
117
    {
118
        $fields_with_relationships = $this->getRelationFields($form);
119
120
        foreach ($fields_with_relationships as $key => $field) {
121
            if (isset($field['pivot']) && $field['pivot']) {
122
                $values = isset($data[$field['name']]) ? $data[$field['name']] : [];
123
                $model->{$field['name']}()->sync($values);
124
125
                if (isset($field['pivotFields'])) {
126
                    foreach ($field['pivotFields'] as $pivotField) {
127
                        foreach ($data[$pivotField] as $pivot_id =>  $field) {
128
                            $model->{$field['name']}()->updateExistingPivot($pivot_id, [$pivotField => $field]);
129
                        }
130
                    }
131
                }
132
            }
133
        }
134
    }
135
136
    /**
137
     * Adds a required => true attribute to each field, so that the required asterisc will show up in the create/update forms.
138
     * TODO: make this work, by editing the $this->fields variable and all fields.
139
     *
140
     * @param [string or array of strings]
141
     */
142
    public function setRequiredFields($fields, $form = 'both')
0 ignored issues
show
Unused Code introduced by
The parameter $fields 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...
Unused Code introduced by
The parameter $form 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...
143
    {
144
        // TODO
145
    }
146
147
    /**
148
     * Adds a required => true attribute to this field, so that the required asteris will show up in the create/update forms.
149
     *
150
     * @param [string]
151
     */
152
    public function setRequiredField($field, $form = 'both')
0 ignored issues
show
Unused Code introduced by
The parameter $field 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...
Unused Code introduced by
The parameter $form 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...
153
    {
154
        // TODO
155
    }
156
157
    /**
158
     * Get all fields that have the required attribute.
159
     * TODO: make this work after making setRequiredFields() work.
160
     *
161
     * @return [array]
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
162
     */
163
    public function getRequiredFields($form = 'both')
0 ignored issues
show
Unused Code introduced by
The parameter $form 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...
164
    {
165
        // TODO
166
    }
167
168
   /*
169
    |--------------------------------------------------------------------------
170
    |                                   READ
171
    |--------------------------------------------------------------------------
172
    */
173
174
    /**
175
     * Find and retrieve an entry in the database or fail.
176
     *
177
     * @param  [int] The id of the row in the db to fetch.
178
     *
179
     * @return [Eloquent Collection] The row in the db.
0 ignored issues
show
Documentation introduced by
The doc-type Eloquent">[Eloquent could not be parsed: Unknown type name "[" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
180
     */
181
    public function getEntry($id)
182
    {
183
        $entry = $this->model->findOrFail($id);
1 ignored issue
show
Bug introduced by
The method findOrFail cannot be called on $this->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...
184
185
        return $entry->withFakes();
186
    }
187
188
    /**
189
     * Get all entries from the database.
190
     *
191
     * @return [Collection of your model]
0 ignored issues
show
Documentation introduced by
The doc-type Collection">[Collection could not be parsed: Unknown type name "[" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
192
     */
193
    public function getEntries()
194
    {
195
        $entries = $this->query->get();
196
197
        // add the fake columns for each entry
198
        foreach ($entries as $key => $entry) {
199
            $entry->addFakes($this->getFakeColumnsAsArray());
200
        }
201
202
        return $entries;
203
    }
204
205
    /**
206
     * Get the fields for the create or update forms.
207
     *
208
     * @param  [form] create / update / both - defaults to 'both'
209
     * @param  [integer] the ID of the entity to be edited in the Update form
210
     *
211
     * @return [array] all the fields that need to be shown and their information
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
212
     */
213
    public function getFields($form, $id = false)
214
    {
215
        switch (strtolower($form)) {
216
            case 'create':
217
                return $this->getCreateFields();
218
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
219
220
            case 'update':
221
                return $this->getUpdateFields($id);
222
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
223
224
            default:
225
                return $this->getCreateFields();
226
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
227
        }
228
    }
229
230
    /**
231
     * Enable the DETAILS ROW functionality:.
232
     *
233
     * In the table view, show a plus sign next to each entry.
234
     * When clicking that plus sign, an AJAX call will bring whatever content you want from the EntityCrudController::showDetailsRow($id) and show it to the user.
235
     */
236
    public function enableDetailsRow()
237
    {
238
        $this->details_row = true;
239
    }
240
241
    /**
242
     * Disable the DETAILS ROW functionality:.
243
     */
244
    public function disableDetailsRow()
245
    {
246
        $this->details_row = false;
247
    }
248
249
   /*
250
    |--------------------------------------------------------------------------
251
    |                                   UPDATE
252
    |--------------------------------------------------------------------------
253
    */
254
255
    /**
256
     * Update a row in the database.
257
     *
258
     * @param  [Int] The entity's id
259
     * @param  [Request] All inputs to be updated.
260
     *
261
     * @return [Eloquent Collection]
0 ignored issues
show
Documentation introduced by
The doc-type Eloquent">[Eloquent could not be parsed: Unknown type name "[" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
262
     */
263
    public function update($id, $data)
264
    {
265
        $item = $this->model->findOrFail($id);
1 ignored issue
show
Bug introduced by
The method findOrFail cannot be called on $this->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...
266
        $updated = $item->update($this->compactFakeFields($data, 'update'));
0 ignored issues
show
Unused Code introduced by
$updated 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...
267
268
        /*if ($updated) */$this->syncPivot($item, $data, 'update');
269
270
        return $item;
271
    }
272
273
    /**
274
     * Get all fields needed for the EDIT ENTRY form.
275
     *
276
     * @param  [integer] The id of the entry that is being edited.
277
     *
278
     * @return [array] The fields with attributes, fake attributes and values.
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
279
     */
280
    public function getUpdateFields($id)
281
    {
282
        $fields = $this->update_fields;
283
        $entry = $this->getEntry($id);
284
285
        foreach ($fields as $k => $field) {
286
            // set the value
287
            if (!isset($fields[$k]['value'])) {
288
                if (isset($field['subfields'])) {
289
                    $fields[$k]['value'] = [];
290
                    foreach ($field['subfields'] as $key => $subfield) {
291
                        $fields[$k]['value'][] = $entry->{$subfield['name']};
292
                    }
293
                } else {
294
                    $fields[$k]['value'] = $entry->{$field['name']};
295
                }
296
            }
297
        }
298
299
        // always have a hidden input for the entry id
300
        $fields['id'] = [
301
                        'name'  => 'id',
302
                        'value' => $entry->id,
303
                        'type'  => 'hidden',
304
                    ];
305
306
        return $fields;
307
    }
308
309
   /*
310
    |--------------------------------------------------------------------------
311
    |                                   DELETE
312
    |--------------------------------------------------------------------------
313
    */
314
315
    /**
316
     * Delete a row from the database.
317
     *
318
     * @param  [int] The id of the item to be deleted.
319
     *
320
     * @return [bool] Deletion confirmation.
0 ignored issues
show
Documentation introduced by
The doc-type [bool] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
321
     *
322
     * TODO: should this delete items with relations to it too?
323
     */
324
    public function delete($id)
325
    {
326
        return $this->model->destroy($id);
1 ignored issue
show
Bug introduced by
The method destroy cannot be called on $this->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...
327
    }
328
329
    /*
330
    |--------------------------------------------------------------------------
331
    |                                   REORDER
332
    |--------------------------------------------------------------------------
333
    */
334
335
    /**
336
     * Change the order and parents of the given elements, according to the NestedSortable AJAX call.
337
     *
338
     * @param  [Request] The entire request from the NestedSortable AJAX Call.
339
     *
340
     * @return [integer] The number of items whose position in the tree has been changed.
0 ignored issues
show
Documentation introduced by
The doc-type [integer] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
341
     */
342
    public function updateTreeOrder($request)
343
    {
344
        $count = 0;
345
346
        foreach ($request as $key => $entry) {
347
            if ($entry['item_id'] != '' && $entry['item_id'] != null) {
348
                $item = $this->model->find($entry['item_id']);
1 ignored issue
show
Bug introduced by
The method find cannot be called on $this->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...
349
                $item->parent_id = $entry['parent_id'];
350
                $item->depth = $entry['depth'];
351
                $item->lft = $entry['left'];
352
                $item->rgt = $entry['right'];
353
                $item->save();
354
355
                $count++;
356
            }
357
        }
358
359
        return $count;
360
    }
361
362
    /**
363
     * Enable the Reorder functionality in the CRUD Panel for users that have the been given access to 'reorder' using:
364
     * $this->crud->allowAccess('reorder');.
365
     *
366
     * @param  [string] Column name that will be shown on the labels.
367
     * @param  [integer] Maximum hierarchy level to which the elements can be nested (1 = no nesting, just reordering).
368
     */
369
    public function enableReorder($label = 'name', $max_level = 1)
370
    {
371
        $this->reorder = true;
372
        $this->reorder_label = $label;
0 ignored issues
show
Documentation Bug introduced by
The property $reorder_label was declared of type boolean, but $label is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
373
        $this->reorder_max_level = $max_level;
374
    }
375
376
    /**
377
     * Disable the Reorder functionality in the CRUD Panel for all users.
378
     */
379
    public function disableReorder()
380
    {
381
        $this->reorder = false;
382
    }
383
384
    /**
385
     * Check if the Reorder functionality is enabled or not.
386
     *
387
     * @return bool
388
     */
389
    public function isReorderEnabled()
390
    {
391
        return $this->reorder;
392
    }
393
394
   /*
395
    |--------------------------------------------------------------------------
396
    |                                   CRUD ACCESS
397
    |--------------------------------------------------------------------------
398
    */
399
400
    public function allowAccess($access)
401
    {
402
        // $this->addButtons((array)$access);
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% 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...
403
        return $this->access = array_merge(array_diff((array) $access, $this->access), $this->access);
404
    }
405
406
    public function denyAccess($access)
407
    {
408
        // $this->removeButtons((array)$access);
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% 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...
409
        return $this->access = array_diff($this->access, (array) $access);
410
    }
411
412
    /**
413
     * Check if a permission is enabled for a Crud Panel. Return false if not.
414
     *
415
     * @param  [string] Permission.
416
     *
417
     * @return bool
418
     */
419
    public function hasAccess($permission)
420
    {
421
        if (!in_array($permission, $this->access)) {
422
            return false;
423
        }
424
425
        return true;
426
    }
427
428
    /**
429
     * Check if a permission is enabled for a Crud Panel. Fail if not.
430
     *
431
     * @param  [string] Permission.
432
     *
433
     * @return bool
434
     */
435
    public function hasAccessOrFail($permission)
436
    {
437
        if (!in_array($permission, $this->access)) {
438
            abort(403, trans('backpack::crud.unauthorized_access'));
439
        }
440
    }
441
442
    /*
443
    |--------------------------------------------------------------------------
444
    |                               CRUD MANIPULATION
445
    |--------------------------------------------------------------------------
446
    */
447
448
    // ------------------------------------------------------
449
    // BASICS - model, route, entity_name, entity_name_plural
450
    // ------------------------------------------------------
451
452
    /**
453
     * This function binds the CRUD to its corresponding Model (which extends Eloquent).
454
     * All Create-Read-Update-Delete operations are done using that Eloquent Collection.
455
     *
456
     * @param [string] Full model namespace. Ex: App\Models\Article
457
     */
458
    public function setModel($model_namespace)
459
    {
460
        if (!class_exists($model_namespace)) {
461
            throw new \Exception('This model does not exist.', 404);
462
        }
463
464
        $this->model = new $model_namespace();
0 ignored issues
show
Documentation Bug introduced by
It seems like new $model_namespace() of type object is incompatible with the declared type string of property $model.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
465
        $this->query = $this->model->select('*');
466
467
        // $this->setFromDb(); // i think that, by default, the auto-fields functionality should be disabled; otherwise, the workflow changes from "set the fields i need" to "update this crud with whatever i need"; which i personally don't like, because it's more hacky and it assumes you should see what the default offers you, then adapt; I propose we set wether the auto-fields functionality is run for panels with a config variable; the config file should be backpack/crud.php and the variable name should be "autoSetFromDb".
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
468
    }
469
470
    /**
471
     * Get the corresponding Eloquent Model for the CrudController, as defined with the setModel() function;.
472
     *
473
     * @return [Eloquent Collection]
0 ignored issues
show
Documentation introduced by
The doc-type Eloquent">[Eloquent could not be parsed: Unknown type name "[" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
474
     */
475
    public function getModel()
476
    {
477
        return $this->model;
478
    }
479
480
    /**
481
     * Set the route for this CRUD.
482
     * Ex: admin/article.
483
     *
484
     * @param [string] Route name.
485
     * @param [array] Parameters.
486
     */
487
    public function setRoute($route)
488
    {
489
        $this->route = $route;
490
        $this->initButtons();
491
    }
492
493
    /**
494
     * Set the route for this CRUD using the route name.
495
     * Ex: admin.article.
496
     *
497
     * @param [string] Route name.
498
     * @param [array] Parameters.
499
     */
500
    public function setRouteName($route, $parameters = [])
501
    {
502
        $complete_route = $route.'.index';
503
504
        if (!\Route::has($complete_route)) {
505
            throw new \Exception('There are no routes for this route name.', 404);
506
        }
507
508
        $this->route = route($complete_route, $parameters);
509
        $this->initButtons();
510
    }
511
512
    /**
513
     * Get the current CrudController route.
514
     *
515
     * Can be defined in the CrudController with:
516
     * - $this->crud->setRoute('admin/article')
517
     * - $this->crud->setRouteName('admin.article')
518
     * - $this->crud->route = "admin/article"
519
     *
520
     * @return [string]
0 ignored issues
show
Documentation introduced by
The doc-type [string] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
521
     */
522
    public function getRoute()
523
    {
524
        return $this->route;
525
    }
526
527
    /**
528
     * Set the entity name in singular and plural.
529
     * Used all over the CRUD interface (header, add button, reorder button, breadcrumbs).
530
     *
531
     * @param [string] Entity name, in singular. Ex: article
532
     * @param [string] Entity name, in plural. Ex: articles
533
     */
534
    public function setEntityNameStrings($singular, $plural)
535
    {
536
        $this->entity_name = $singular;
537
        $this->entity_name_plural = $plural;
538
    }
539
540
    // ------------
541
    // COLUMNS
542
    // ------------
543
544
    /**
545
     * Add a bunch of column names and their details to the CRUD object.
546
     *
547
     * @param [array or multi-dimensional array]
548
     */
549
    public function setColumns($columns)
550
    {
551
        // clear any columns already set
552
        $this->columns = [];
553
554
        // if array, add a column for each of the items
555
        if (is_array($columns) && count($columns)) {
556
            foreach ($columns as $key => $column) {
557
                // if label and other details have been defined in the array
558
                if (is_array($columns[0])) {
559
                    $this->addColumn($column);
560
                } else {
561
                    $this->addColumn([
562
                                    'name'  => $column,
563
                                    'label' => ucfirst($column),
564
                                    'type'  => 'text',
565
                                ]);
566
                }
567
            }
568
        }
569
570
        if (is_string($columns)) {
571
            $this->addColumn([
572
                                'name'  => $columns,
573
                                'label' => ucfirst($columns),
574
                                'type'  => 'text',
575
                                ]);
576
        }
577
578
        // This was the old setColumns() function, and it did not work:
579
        // $this->columns = array_filter(array_map([$this, 'addDefaultTypeToColumn'], $columns));
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% 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...
580
    }
581
582
    /**
583
     * Add a column at the end of to the CRUD object's "columns" array.
584
     *
585
     * @param [string or array]
586
     */
587
    public function addColumn($column)
588
    {
589
        // make sure the column has a type
590
        $column_with_details = $this->addDefaultTypeToColumn($column);
0 ignored issues
show
Unused Code introduced by
$column_with_details 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...
591
592
        // make sure the column has a label
593
        $column_with_details = $this->addDefaultLabel($column);
594
595
        return array_filter($this->columns[] = $column_with_details);
596
    }
597
598
    /**
599
     * Add multiple columns at the end of the CRUD object's "columns" array.
600
     *
601
     * @param [array of columns]
602
     */
603
    public function addColumns($columns)
604
    {
605
        if (count($columns)) {
606
            foreach ($columns as $key => $column) {
607
                $this->addColumn($column);
608
            }
609
        }
610
    }
611
612
    /**
613
     * Add the default column type to the given Column, inferring the type from the database column type.
614
     *
615
     * @param [column array]
616
     */
617
    public function addDefaultTypeToColumn($column)
618
    {
619
        if (array_key_exists('name', (array) $column)) {
620
            $default_type = $this->getFieldTypeFromDbColumnType($column['name']);
621
622
            return array_merge(['type' => $default_type], $column);
623
        }
624
625
        return false;
626
    }
627
628
    /**
629
     * If a field or column array is missing the "label" attribute, an ugly error would be show.
630
     * So we add the field Name as a label - it's better than nothing.
631
     *
632
     * @param [field or column]
633
     */
634
    public function addDefaultLabel($array)
635
    {
636
        if (!array_key_exists('label', (array) $array) && array_key_exists('name', (array) $array)) {
637
            $array = array_merge(['label' => ucfirst($this->makeLabel($array['name']))], $array);
638
639
            return $array;
640
        }
641
642
        return $array;
643
    }
644
645
    /**
646
     * Remove multiple columns from the CRUD object using their names.
647
     *
648
     * @param  [column array]
649
     */
650
    public function removeColumns($columns)
651
    {
652
        $this->columns = $this->remove('columns', $columns);
0 ignored issues
show
Bug introduced by
The method remove() does not exist on Backpack\CRUD\Crud. Did you maybe mean removeColumns()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
653
    }
654
655
    /**
656
     * Remove a column from the CRUD object using its name.
657
     *
658
     * @param  [column array]
659
     */
660
    public function removeColumn($column)
661
    {
662
        return $this->removeColumns([$column]);
663
    }
664
665
    /**
666
     * Change attributes for multiple columns.
667
     *
668
     * @param [columns arrays]
669
     * @param [attributes and values array]
670
     */
671
    public function setColumnsDetails($columns, $attributes)
672
    {
673
        $this->sync('columns', $columns, $attributes);
674
    }
675
676
    /**
677
     * Change attributes for a certain column.
678
     *
679
     * @param [string] Column name.
680
     * @param [attributes and values array]
681
     */
682
    public function setColumnDetails($column, $attributes)
683
    {
684
        $this->setColumnsDetails([$column], $attributes);
685
    }
686
687
    /**
688
     * Order the columns in a certain way.
689
     *
690
     * @param [string] Column name.
691
     * @param [attributes and values array]
692
     */
693
    public function setColumnOrder($columns)
0 ignored issues
show
Unused Code introduced by
The parameter $columns 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...
694
    {
695
        // TODO
696
    }
697
698
    // ALIAS of setColumnOrder($columns)
699
    public function setColumnsOrder($columns)
700
    {
701
        $this->setColumnOrder($columns);
702
    }
703
704
    // ------------
705
    // FIELDS
706
    // ------------
707
708
    /**
709
     * Add a field to the create/update form or both.
710
     *
711
     * @param [string] $name    Field name (the column name in the db in most cases)
0 ignored issues
show
Documentation introduced by
The doc-type [string] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
712
     * @param [array]  $options Field-type-specific information.
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
Bug introduced by
There is no parameter named $options. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
713
     * @param string   $form    The form to add the field to (create/update/both)
714
     */
715
    public function addField($field, $form = 'both')
716
    {
717
        // if the field_defition_array array is a string, it means the programmer was lazy and has only passed the name
718
        // set some default values, so the field will still work
719
        if (is_string($field)) {
720
            $complete_field_array['name'] = $field;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$complete_field_array was never initialized. Although not strictly required by PHP, it is generally a good practice to add $complete_field_array = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
721
        } else {
722
            $complete_field_array = $field;
723
        }
724
725
        // if the label is missing, we should set it
726
        if (!isset($complete_field_array['label'])) {
727
            $complete_field_array['label'] = ucfirst($complete_field_array['name']);
728
        }
729
730
        // if the field type is missing, we should set it
731
        if (!isset($complete_field_array['type'])) {
732
            $complete_field_array['type'] = $this->getFieldTypeFromDbColumnType($complete_field_array['name']);
733
        }
734
735
        // store the field information into the correct variable on the CRUD object
736
        switch (strtolower($form)) {
737
            case 'create':
738
                $this->create_fields[$complete_field_array['name']] = $complete_field_array;
739
                break;
740
741
            case 'update':
742
                $this->update_fields[$complete_field_array['name']] = $complete_field_array;
743
                break;
744
745
            default:
746
                $this->create_fields[$complete_field_array['name']] = $complete_field_array;
747
                $this->update_fields[$complete_field_array['name']] = $complete_field_array;
748
                break;
749
        }
750
    }
751
752
    public function addFields($fields, $form = 'both')
753
    {
754
        if (count($fields)) {
755
            foreach ($fields as $field) {
756
                $this->addField($field, $form);
757
            }
758
        }
759
    }
760
761
    /**
762
     * Remove a certain field from the create/update/both forms by its name.
763
     *
764
     * @param string $name Field name (as defined with the addField() procedure)
765
     * @param string $form update/create/both
766
     */
767
    public function removeField($name, $form = 'both')
768
    {
769
        switch (strtolower($form)) {
770
            case 'create':
771
                array_forget($this->create_fields, $name);
772
                break;
773
774
            case 'update':
775
                array_forget($this->update_fields, $name);
776
                break;
777
778
            default:
779
                array_forget($this->create_fields, $name);
780
                array_forget($this->update_fields, $name);
781
                break;
782
        }
783
    }
784
785
    /**
786
     * Remove many fields from the create/update/both forms by their name.
787
     *
788
     * @param array  $array_of_names A simple array of the names of the fields to be removed.
789
     * @param string $form           update/create/both
790
     */
791
    public function removeFields($array_of_names, $form = 'both')
792
    {
793
        if (!empty($array_of_names)) {
794
            foreach ($array_of_names as $name) {
795
                $this->removeField($name, $form);
796
            }
797
        }
798
    }
799
800
    // TODO: $this->crud->replaceField('name', 'update/create/both');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
801
802
    // TODO: $this->crud->setRequiredFields(['field_1', 'field_2'], 'update/create/both');
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% 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...
803
    // TODO: $this->crud->setRequiredField('field_1', 'update/create/both');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
804
    // TODO: $this->crud->getRequiredFields();
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
805
806
    // TODO: $this->crud->setFieldOrder(['field_1', 'field_2', 'field_3'], 'update/create/both');
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% 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...
807
808
    /**
809
     * Check if field is the first of its type in the given fields array.
810
     * It's used in each field_type.blade.php to determine wether to push the css and js content or not (we only need to push the js and css for a field the first time it's loaded in the form, not any subsequent times).
811
     *
812
     * @param array $field        The current field being tested if it's the first of its type.
813
     * @param array $fields_array All the fields in that particular form.
814
     *
815
     * @return bool true/false
816
     */
817
    public function checkIfFieldIsFirstOfItsType($field, $fields_array)
818
    {
819
        if ($field['name'] == $this->getFirstOfItsTypeInArray($field['type'], $fields_array)['name']) {
820
            return true;
821
        }
822
823
        return false;
824
    }
825
826
    /**
827
     * Order the fields in a certain way.
828
     *
829
     * @param [string] Column name.
830
     * @param [attributes and values array]
831
     */
832
    public function setFieldOrder($fields)
0 ignored issues
show
Unused Code introduced by
The parameter $fields 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...
833
    {
834
        // TODO
835
    }
836
837
    // ALIAS of setFieldOrder($fields)
838
    public function setFieldsOrder($fields)
839
    {
840
        $this->setFieldOrder($fields);
841
    }
842
843
    // ----------------
844
    // ADVANCED QUERIES
845
    // ----------------
846
847
    /**
848
     * Add another clause to the query (for ex, a WHERE clause).
849
     *
850
     * Examples:
851
     * // $this->crud->addClause('active');
852
     * $this->crud->addClause('type', 'car');
853
     * $this->crud->addClause('where', 'name', '==', 'car');
854
     * $this->crud->addClause('whereName', 'car');
855
     * $this->crud->addClause('whereHas', 'posts', function($query) {
856
     *     $query->activePosts();
857
     *     });
858
     *
859
     * @param [type]
860
     */
861
    public function addClause($function)
862
    {
863
        return call_user_func_array([$this->query, $function], array_slice(func_get_args(), 1, 3));
864
    }
865
866
    /**
867
     * Order the results of the query in a certain way.
868
     *
869
     * @param  [type]
870
     * @param  string
871
     *
872
     * @return [type]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
873
     */
874
    public function orderBy($field, $order = 'asc')
875
    {
876
        return $this->query->orderBy($field, $order);
877
    }
878
879
    /**
880
     * Group the results of the query in a certain way.
881
     *
882
     * @param  [type]
883
     *
884
     * @return [type]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
885
     */
886
    public function groupBy($field)
887
    {
888
        return $this->query->groupBy($field);
889
    }
890
891
    /**
892
     * Limit the number of results in the query.
893
     *
894
     * @param  [number]
895
     *
896
     * @return [type]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
897
     */
898
    public function limit($number)
899
    {
900
        return $this->query->limit($number);
901
    }
902
903
    // ------------
904
    // BUTTONS
905
    // ------------
906
907
    // TODO: $this->crud->setButtons(); // default includes edit and delete, with their name, icon, permission, link and class (btn-default)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
908
    // TODO: $this->crud->addButton();
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
909
    // TODO: $this->crud->removeButton();
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
910
    // TODO: $this->crud->replaceButton();
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
911
912
    // ------------------------------------------------------
913
    // AUTO-SET-FIELDS-AND-COLUMNS FUNCTIONALITY
914
    // ------------------------------------------------------
915
916
    /**
917
     * For a simple CRUD Panel, there should be no need to add/define the fields.
918
     * The public columns in the database will be converted to be fields.
919
     */
920
    public function setFromDb()
921
    {
922
        $this->getDbColumnTypes();
923
924
        array_map(function ($field) {
925
            // $this->labels[$field] = $this->makeLabel($field);
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% 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...
926
927
            $new_field = [
928
                                'name'       => $field,
929
                                'label'      => ucfirst($field),
930
                                'value'      => '', 'default' => $this->field_types[$field]['default'],
931
                                'type'       => $this->getFieldTypeFromDbColumnType($field),
932
                                'values'     => [],
933
                                'attributes' => [],
934
                                ];
935
            $this->create_fields[] = $new_field;
936
            $this->update_fields[] = $new_field;
937
938
            if (!in_array($field, $this->model->getHidden())) {
1 ignored issue
show
Bug introduced by
The method getHidden cannot be called on $this->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...
939
                $this->columns[] = [
940
                                    'name'  => $field,
941
                                    'label' => ucfirst($field),
942
                                    'type'  => $this->getFieldTypeFromDbColumnType($field),
943
                                    ];
944
            }
945
946
        }, $this->getDbColumnsNames());
947
    }
948
949
    /**
950
     * Get all columns from the database for that table.
951
     *
952
     * @return [array]
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
953
     */
954
    public function getDbColumnTypes()
955
    {
956
        foreach (\DB::select(\DB::raw('SHOW COLUMNS FROM '.$this->model->getTable())) as $column) {
1 ignored issue
show
Bug introduced by
The method getTable cannot be called on $this->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...
957
            $this->field_types[$column->Field] = ['type' => trim(preg_replace('/\(\d+\)(.*)/i', '', $column->Type)), 'default' => $column->Default];
958
        }
959
960
        return $this->field_types;
961
    }
962
963
    /**
964
     * Intuit a field type, judging from the database column type.
965
     *
966
     * @param  [string] Field name.
967
     *
968
     * @return [string] Fielt type.
0 ignored issues
show
Documentation introduced by
The doc-type [string] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
969
     */
970
    public function getFieldTypeFromDbColumnType($field)
971
    {
972
        if (!array_key_exists($field, $this->field_types)) {
973
            return 'text';
974
        }
975
976
        if ($field == 'password') {
977
            return 'password';
978
        }
979
980
        if ($field == 'email') {
981
            return 'email';
982
        }
983
984
        switch ($this->field_types[$field]['type']) {
985
            case 'int':
986
            case 'smallint':
987
            case 'mediumint':
988
            case 'longint':
989
                return 'number';
990
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
991
992
            case 'string':
993
            case 'varchar':
994
            case 'set':
995
                return 'text';
996
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
997
998
            // case 'enum':
999
            //     return 'enum';
1000
            // break;
1001
1002
            case 'tinyint':
1003
                return 'active';
1004
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1005
1006
            case 'text':
1007
            case 'mediumtext':
1008
            case 'longtext':
1009
                return 'textarea';
1010
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1011
1012
            case 'date':
1013
                return 'date';
1014
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1015
1016
            case 'datetime':
1017
            case 'timestamp':
1018
                return 'datetime';
1019
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1020
            case 'time':
1021
                return 'time';
1022
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1023
1024
            default:
1025
                return 'text';
1026
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1027
        }
1028
    }
1029
1030
    /**
1031
     * Turn a database column name or PHP variable into a pretty label to be shown to the user.
1032
     *
1033
     * @param  [string]
1034
     *
1035
     * @return [string]
0 ignored issues
show
Documentation introduced by
The doc-type [string] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1036
     */
1037
    public function makeLabel($value)
1038
    {
1039
        return trim(preg_replace('/(id|at|\[\])$/i', '', ucfirst(str_replace('_', ' ', $value))));
1040
    }
1041
1042
    /**
1043
     * Get the database column names, in order to figure out what fields/columns to show in the auto-fields-and-columns functionality.
1044
     *
1045
     * @return [array] Database column names as an array.
0 ignored issues
show
Documentation introduced by
The doc-type [array] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1046
     */
1047
    public function getDbColumnsNames()
1048
    {
1049
        // Automatically-set columns should be both in the database, and in the $fillable variable on the Eloquent Model
1050
        $columns = \Schema::getColumnListing($this->model->getTable());
1 ignored issue
show
Bug introduced by
The method getTable cannot be called on $this->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...
1051
        $fillable = $this->model->getFillable();
1 ignored issue
show
Bug introduced by
The method getFillable cannot be called on $this->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...
1052
1053
        if (!empty($fillable)) {
1054
            $columns = array_intersect($columns, $fillable);
1055
        }
1056
1057
        // but not updated_at, deleted_at
1058
        return array_values(array_diff($columns, [$this->model->getKeyName(), 'updated_at', 'deleted_at']));
1 ignored issue
show
Bug introduced by
The method getKeyName cannot be called on $this->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...
1059
    }
1060
1061
    // -----------------
1062
    // Commodity methods
1063
    // -----------------
1064
1065
    /**
1066
     * Refactor the request array to something that can be passed to the model's create or update function.
1067
     * The resulting array will only include the fields that are stored in the database and their values,
1068
     * plus the '_token' and 'redirect_after_save' variables.
1069
     *
1070
     * @param Request $request - everything that was sent from the form, usually \Request::all()
1071
     * @param string  $form    - create/update - to determine what fields should be compacted
1072
     *
1073
     * @return array
1074
     */
1075
    public function compactFakeFields($request, $form = 'create')
1076
    {
1077
        $fake_field_columns_to_encode = [];
1078
1079
        // get the right fields according to the form type (create/update)
1080 View Code Duplication
        switch (strtolower($form)) {
0 ignored issues
show
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...
1081
            case 'update':
1082
                $fields = $this->update_fields;
1083
                break;
1084
1085
            default:
1086
                $fields = $this->create_fields;
1087
                break;
1088
        }
1089
1090
        // go through each defined field
1091
        foreach ($fields as $k => $field) {
1092
            // if it's a fake field
1093
            if (isset($fields[$k]['fake']) && $fields[$k]['fake'] == true) {
1094
                // add it to the request in its appropriate variable - the one defined, if defined
1095
                if (isset($fields[$k]['store_in'])) {
1096
                    $request[$fields[$k]['store_in']][$fields[$k]['name']] = $request[$fields[$k]['name']];
1097
1098
                    $remove_fake_field = array_pull($request, $fields[$k]['name']);
0 ignored issues
show
Unused Code introduced by
$remove_fake_field 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...
1099 View Code Duplication
                    if (!in_array($fields[$k]['store_in'], $fake_field_columns_to_encode, true)) {
0 ignored issues
show
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...
1100
                        array_push($fake_field_columns_to_encode, $fields[$k]['store_in']);
1101
                    }
1102
                } else {
1103
                    //otherwise in the one defined in the $crud variable
1104
1105
                    $request['extras'][$fields[$k]['name']] = $request[$fields[$k]['name']];
1106
1107
                    $remove_fake_field = array_pull($request, $fields[$k]['name']);
0 ignored issues
show
Unused Code introduced by
$remove_fake_field 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...
1108
                    if (!in_array('extras', $fake_field_columns_to_encode, true)) {
1109
                        array_push($fake_field_columns_to_encode, 'extras');
1110
                    }
1111
                }
1112
            }
1113
        }
1114
1115
        // json_encode all fake_value columns in the database, so they can be properly stored and interpreted
1116
        if (count($fake_field_columns_to_encode)) {
1117
            foreach ($fake_field_columns_to_encode as $key => $value) {
1118
                $request[$value] = json_encode($request[$value]);
1119
            }
1120
        }
1121
1122
        // if there are no fake fields defined, this will just return the original Request in full
1123
        // since no modifications or additions have been made to $request
1124
        return $request;
1125
    }
1126
1127
    /**
1128
     * Returns an array of database columns names, that are used to store fake values.
1129
     * Returns ['extras'] if no columns have been found.
1130
     */
1131
    public function getFakeColumnsAsArray($form = 'create')
1132
    {
1133
        $fake_field_columns_to_encode = [];
1134
1135
        // get the right fields according to the form type (create/update)
1136 View Code Duplication
        switch (strtolower($form)) {
0 ignored issues
show
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...
1137
            case 'update':
1138
                $fields = $this->update_fields;
1139
                break;
1140
1141
            default:
1142
                $fields = $this->create_fields;
1143
                break;
1144
        }
1145
1146
        foreach ($fields as $k => $field) {
1147
            // if it's a fake field
1148
            if (isset($fields[$k]['fake']) && $fields[$k]['fake'] == true) {
1149
                // add it to the request in its appropriate variable - the one defined, if defined
1150
                if (isset($fields[$k]['store_in'])) {
1151 View Code Duplication
                    if (!in_array($fields[$k]['store_in'], $fake_field_columns_to_encode, true)) {
0 ignored issues
show
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...
1152
                        array_push($fake_field_columns_to_encode, $fields[$k]['store_in']);
1153
                    }
1154
                } else {
1155
                    //otherwise in the one defined in the $crud variable
1156
1157
                    if (!in_array('extras', $fake_field_columns_to_encode, true)) {
1158
                        array_push($fake_field_columns_to_encode, 'extras');
1159
                    }
1160
                }
1161
            }
1162
        }
1163
1164
        if (!count($fake_field_columns_to_encode)) {
1165
            return ['extras'];
1166
        }
1167
1168
        return $fake_field_columns_to_encode;
1169
    }
1170
1171
    // ----------------------------------
1172
    // Miscellaneous functions or methods
1173
    // ----------------------------------
1174
1175
    /**
1176
     * Return the first element in an array that has the given 'type' attribute.
1177
     *
1178
     * @param string $type
1179
     * @param array  $array
1180
     *
1181
     * @return array
1182
     */
1183
    public function getFirstOfItsTypeInArray($type, $array)
1184
    {
1185
        return array_first($array, function ($key, $item) use ($type) {
1186
            return $item['type'] == $type;
1187
        });
1188
    }
1189
1190
    // ------------
1191
    // TONE FUNCTIONS - UNDOCUMENTED, UNTESTED, SOME MAY BE USED IN THIS FILE
1192
    // ------------
1193
    //
1194
    // TODO:
1195
    // - figure out if they are really needed
1196
    // - comments inside the function to explain how they work
1197
    // - write docblock for them
1198
    // - place in the correct section above (CREATE, READ, UPDATE, DELETE, ACCESS, MANIPULATION)
1199
1200
    public function addButton($button)
1201
    {
1202
        array_unshift($this->buttons, $button);
1203
    }
1204
1205
    public function buttons()
1206
    {
1207
        return $this->buttons;
1208
    }
1209
1210
    public function addCustomButton($button)
1211
    {
1212
        array_unshift($this->custom_buttons, $button);
1213
    }
1214
1215
    public function customButtons()
1216
    {
1217
        return $this->custom_buttons;
1218
    }
1219
1220
    public function showButtons()
1221
    {
1222
        return !empty($this->buttons) && !(count($this->buttons) == 1 && array_key_exists('add', $this->buttons));
1223
    }
1224
1225
    public function initButtons()
1226
    {
1227
        $this->buttons = [
1228
            'add'    => ['route' => "{$this->route}/create", 'label' => trans('crud::crud.buttons.add'), 'class' => '', 'hide' => [], 'icon' => 'fa-plus-circle', 'extra' => []],
1229
            'view'   => ['route' => "{$this->route}/%d", 'label' => trans('crud::crud.buttons.view'), 'class' => '', 'hide' => [], 'icon' => 'fa-eye', 'extra' => []],
1230
            'edit'   => ['route' => "{$this->route}/%d/edit", 'label' => trans('crud::crud.buttons.edit'), 'class' => '', 'hide' => [], 'icon' => 'fa-edit', 'extra' => []],
1231
            'delete' => ['route' => "{$this->route}/%d", 'label' => trans('crud::crud.buttons.delete'), 'class' => '', 'hide' => [], 'icon' => 'fa-trash', 'extra' => ['data-confirm' => trans('crud::crud.confirm.delete'), 'data-type' => 'delete']],
1232
        ];
1233
    }
1234
1235
    public function removeButtons($buttons)
1236
    {
1237
        foreach ($buttons as $button) {
1238
            unset($this->buttons[$button]);
1239
        }
1240
1241
        return $this->buttons;
1242
    }
1243
1244
    public function getColumns()
1245
    {
1246
        return $this->sort('columns');
1247
    }
1248
1249
    public function orderColumns($order)
1250
    {
1251
        $this->setSort('columns', (array) $order);
1252
    }
1253
1254
1255
    public function orderFields($order)
1256
    {
1257
        $this->setSort('fields', (array) $order);
1258
    }
1259
1260
    public function sync($type, $fields, $attributes)
1261
    {
1262
        if (!empty($this->{$type})) {
1263
            $this->{$type} = array_map(function ($field) use ($fields, $attributes) {
1264
                if (in_array($field['name'], (array) $fields)) {
1265
                    $field = array_merge($field, $attributes);
1266
                }
1267
1268
                return $field;
1269
            }, $this->{$type});
1270
        }
1271
    }
1272
1273
    public function setSort($items, $order)
1274
    {
1275
        $this->sort[$items] = $order;
1276
    }
1277
1278
    public function sort($items)
1279
    {
1280
        if (array_key_exists($items, $this->sort)) {
1281
            $elements = [];
1282
1283
            foreach ($this->sort[$items] as $item) {
1284
                if (is_numeric($key = array_search($item, array_column($this->{$items}, 'name')))) {
1285
                    $elements[] = $this->{$items}[$key];
1286
                }
1287
            }
1288
1289
            return $this->{$items} = array_merge($elements, array_filter($this->{$items}, function ($item) use ($items) {return !in_array($item['name'], $this->sort[$items]); }));
1290
        }
1291
1292
        return $this->{$items};
1293
    }
1294
1295
}
1296