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

Passed
Push — crud-column-support-array ( c4d6a0 )
by Pedro
19:29
created

Columns::makeSureColumnHasNeededAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 15
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 22
rs 9.7666
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Backpack\CRUD\app\Library\CrudPanel\CrudColumn;
6
use Illuminate\Support\Arr;
7
8
trait Columns
9
{
10
    use ColumnsProtectedMethods;
11
12
    // ------------
13
    // COLUMNS
14
    // ------------
15
16
    /**
17
     * Get the CRUD columns for the current operation.
18
     *
19
     * @return array CRUD columns.
20
     */
21
    public function columns()
22
    {
23
        return $this->getOperationSetting('columns') ?? [];
0 ignored issues
show
Bug introduced by
It seems like getOperationSetting() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

23
        return $this->/** @scrutinizer ignore-call */ getOperationSetting('columns') ?? [];
Loading history...
24
    }
25
26
    /**
27
     * Add a bunch of column names and their details to the CRUD object.
28
     *
29
     * @param  array|string  $columns
30
     */
31
    public function setColumns($columns)
32
    {
33
        // clear any columns already set
34
        $this->removeAllColumns();
35
36
        // if array, add a column for each of the items
37
        if (is_array($columns) && count($columns)) {
38
            foreach ($columns as $key => $column) {
39
                // if label and other details have been defined in the array
40
                if (is_array($column)) {
41
                    $this->addColumn($column);
42
                } else {
43
                    $this->addColumn([
44
                        'name'  => $column,
45
                        'label' => mb_ucfirst($column),
46
                        'type'  => 'text',
47
                    ]);
48
                }
49
            }
50
        }
51
52
        if (is_string($columns)) {
53
            $this->addColumn([
54
                'name'  => $columns,
55
                'label' => mb_ucfirst($columns),
56
                'type'  => 'text',
57
            ]);
58
        }
59
    }
60
61
    /**
62
     * Add a column at the end of to the CRUD object's "columns" array.
63
     *
64
     * @param  array|string  $column
65
     * @return self
66
     */
67
    public function addColumn($column)
68
    {
69
        $column = $this->makeSureColumnHasNeededAttributes($column);
70
        $this->addColumnToOperationSettings($column);
71
72
        (new CrudColumn($column['name']))->callRegisteredAttributeMacros();
73
74
        return $this;
75
    }
76
77
    /**
78
     * Add a column at the end of to the CRUD object's "columns" array and return it
79
     *
80
     * @param  array|string  $column
81
     * @return self
82
     */
83
    public function addAndReturnColumn($column)
84
    {
85
        $column = $this->makeSureColumnHasNeededAttributes($column);
86
        $this->addColumnToOperationSettings($column);
87
88
        $column = (new CrudColumn($column['name']))->callRegisteredAttributeMacros();
89
90
        return $column;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $column returns the type Backpack\CRUD\app\Library\CrudPanel\CrudColumn which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\Traits\Columns.
Loading history...
91
    }
92
93
    /**
94
     * Add multiple columns at the end of the CRUD object's "columns" array.
95
     *
96
     * @param  array  $columns
97
     */
98
    public function addColumns($columns)
99
    {
100
        if (count($columns)) {
101
            foreach ($columns as $key => $column) {
102
                $this->addColumn($column);
103
            }
104
        }
105
    }
106
107
    /**
108
     * Move the most recently added column after the given target column.
109
     *
110
     * @param  string|array  $targetColumn  The target column name or array.
111
     */
112
    public function afterColumn($targetColumn)
113
    {
114
        $this->moveColumn($targetColumn, false);
115
    }
116
117
    /**
118
     * Move the most recently added column before the given target column.
119
     *
120
     * @param  string|array  $targetColumn  The target column name or array.
121
     */
122
    public function beforeColumn($targetColumn)
123
    {
124
        $this->moveColumn($targetColumn);
125
    }
126
127
    /**
128
     * Move this column to be first in the columns list.
129
     *
130
     * @return bool|null
131
     */
132
    public function makeFirstColumn()
133
    {
134
        if (! $this->columns()) {
135
            return false;
136
        }
137
138
        $firstColumn = array_keys(array_slice($this->columns(), 0, 1))[0];
139
        $this->beforeColumn($firstColumn);
140
    }
141
142
    /**
143
     * Add the default column type to the given Column, inferring the type from the database column type.
144
     *
145
     * @param  array  $column
146
     * @return array|bool
147
     */
148
    public function addDefaultTypeToColumn($column)
149
    {
150
        if (array_key_exists('name', (array) $column)) {
151
            $default_type = $this->inferFieldTypeFromDbColumnType($column['name']);
0 ignored issues
show
Bug introduced by
It seems like inferFieldTypeFromDbColumnType() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
            /** @scrutinizer ignore-call */ 
152
            $default_type = $this->inferFieldTypeFromDbColumnType($column['name']);
Loading history...
152
153
            return array_merge(['type' => $default_type], $column);
154
        }
155
156
        return false;
157
    }
158
159
    /**
160
     * Remove a column from the CRUD panel by name.
161
     *
162
     * @param  string  $columnKey  The column key.
163
     */
164
    public function removeColumn($columnKey)
165
    {
166
        $columnsArray = $this->columns();
167
        Arr::forget($columnsArray, $columnKey);
168
        $this->setOperationSetting('columns', $columnsArray);
0 ignored issues
show
Bug introduced by
It seems like setOperationSetting() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

168
        $this->/** @scrutinizer ignore-call */ 
169
               setOperationSetting('columns', $columnsArray);
Loading history...
169
    }
170
171
    /**
172
     * Remove multiple columns from the CRUD panel by name.
173
     *
174
     * @param  array  $columns  Array of column names.
175
     */
176
    public function removeColumns($columns)
177
    {
178
        if (! empty($columns)) {
179
            foreach ($columns as $columnKey) {
180
                $this->removeColumn($columnKey);
181
            }
182
        }
183
    }
184
185
    /**
186
     * Remove all columns from the CRUD panel.
187
     */
188
    public function removeAllColumns()
189
    {
190
        $this->setOperationSetting('columns', []);
191
    }
192
193
    /**
194
     * Remove an attribute from one column's definition array.
195
     *
196
     * @param  string  $column  The name of the column.
197
     * @param  string  $attribute  The name of the attribute being removed.
198
     */
199
    public function removeColumnAttribute($column, $attribute)
200
    {
201
        $columns = $this->columns();
202
203
        unset($columns[$column][$attribute]);
204
205
        $this->setOperationSetting('columns', $columns);
206
    }
207
208
    /**
209
     * Change attributes for multiple columns.
210
     *
211
     * @param  array  $columns
212
     * @param  array  $attributes
213
     */
214
    public function setColumnsDetails($columns, $attributes)
215
    {
216
        foreach ($columns as $columnKey) {
217
            $this->setColumnDetails($columnKey, $attributes);
218
        }
219
    }
220
221
    /**
222
     * Change attributes for a certain column.
223
     *
224
     * @param  string  $columnKey  Column key.
225
     * @param  array  $attributesAndValues
226
     */
227
    public function setColumnDetails($columnKey, $attributesAndValues)
228
    {
229
        $columnsArray = $this->columns();
230
231
        if (isset($columnsArray[$columnKey])) {
232
            foreach ($attributesAndValues as $attributeName => $attributeValue) {
233
                $columnsArray[$columnKey][$attributeName] = $attributeValue;
234
            }
235
        }
236
237
        $this->setOperationSetting('columns', $columnsArray);
238
    }
239
240
    /**
241
     * Alias for setColumnDetails().
242
     * Provides a consistent syntax with Fields, Buttons, Filters modify functionality.
243
     *
244
     * @param  string  $column  Column name.
245
     * @param  array  $attributes
246
     */
247
    public function modifyColumn($column, $attributes)
248
    {
249
        $this->setColumnDetails($column, $attributes);
250
    }
251
252
    /**
253
     * Set label for a specific column.
254
     *
255
     * @param  string  $column
256
     * @param  string  $label
257
     */
258
    public function setColumnLabel($column, $label)
259
    {
260
        $this->setColumnDetails($column, ['label' => $label]);
261
    }
262
263
    /**
264
     * Get the relationships used in the CRUD columns.
265
     *
266
     * @return array Relationship names
267
     */
268
    public function getColumnsRelationships()
269
    {
270
        $columns = $this->columns();
271
272
        return collect($columns)->pluck('entity')->reject(function ($value, $key) {
0 ignored issues
show
Bug introduced by
$columns of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

272
        return collect(/** @scrutinizer ignore-type */ $columns)->pluck('entity')->reject(function ($value, $key) {
Loading history...
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

272
        return collect($columns)->pluck('entity')->reject(function ($value, /** @scrutinizer ignore-unused */ $key) {

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

Loading history...
273
            return ! $value;
274
        })->toArray();
275
    }
276
277
    /**
278
     * Order the CRUD columns. If certain columns are missing from the given order array, they will be pushed to the
279
     * new columns array in the original order.
280
     *
281
     * @param  array  $order  An array of column names in the desired order.
282
     */
283
    public function orderColumns($order)
284
    {
285
        $orderedColumns = [];
286
        foreach ($order as $columnName) {
287
            if (array_key_exists($columnName, $this->columns())) {
288
                $orderedColumns[$columnName] = $this->columns()[$columnName];
289
            }
290
        }
291
292
        if (empty($orderedColumns)) {
293
            return;
294
        }
295
296
        $remaining = array_diff_key($this->columns(), $orderedColumns);
297
        $this->setOperationSetting('columns', array_merge($orderedColumns, $remaining));
298
    }
299
300
    /**
301
     * Get a column by the id, from the associative array.
302
     *
303
     * @param  int  $column_number  Placement inside the columns array.
304
     * @return array Column details.
305
     */
306
    public function findColumnById($column_number)
307
    {
308
        $result = array_slice($this->columns(), $column_number, 1);
309
310
        return reset($result);
311
    }
312
313
    /**
314
     * Get the visibility priority for the actions column
315
     * in the CRUD table view.
316
     *
317
     * @return int The priority, from 1 to infinity. Lower is better.
318
     */
319
    public function getActionsColumnPriority()
320
    {
321
        return (int) $this->getOperationSetting('actionsColumnPriority') ?? 1;
322
    }
323
324
    /**
325
     * Set a certain priority for the actions column
326
     * in the CRUD table view. Usually set to 10000 in order to hide it.
327
     *
328
     * @param  int  $number  The priority, from 1 to infinity. Lower is better.
329
     * @return self
330
     */
331
    public function setActionsColumnPriority($number)
332
    {
333
        $this->setOperationSetting('actionsColumnPriority', (int) $number);
334
335
        return $this;
336
    }
337
338
    /**
339
     * Check if a column exists, by any given attribute.
340
     *
341
     * @param  string  $attribute  Attribute name on that column definition array.
342
     * @param  string  $value  Value of that attribute on that column definition array.
343
     * @return bool
344
     */
345
    public function hasColumnWhere($attribute, $value)
346
    {
347
        $match = Arr::first($this->columns(), function ($column, $columnKey) use ($attribute, $value) {
0 ignored issues
show
Unused Code introduced by
The parameter $columnKey is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

347
        $match = Arr::first($this->columns(), function ($column, /** @scrutinizer ignore-unused */ $columnKey) use ($attribute, $value) {

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

Loading history...
348
            return isset($column[$attribute]) && $column[$attribute] == $value;
349
        });
350
351
        return (bool) $match;
352
    }
353
354
    /**
355
     * Get the first column where a given attribute has the given value.
356
     *
357
     * @param  string  $attribute  Attribute name on that column definition array.
358
     * @param  string  $value  Value of that attribute on that column definition array.
359
     * @return bool
360
     */
361
    public function firstColumnWhere($attribute, $value)
362
    {
363
        return Arr::first($this->columns(), function ($column, $columnKey) use ($attribute, $value) {
0 ignored issues
show
Unused Code introduced by
The parameter $columnKey is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

363
        return Arr::first($this->columns(), function ($column, /** @scrutinizer ignore-unused */ $columnKey) use ($attribute, $value) {

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

Loading history...
364
            return isset($column[$attribute]) && $column[$attribute] == $value;
365
        });
366
    }
367
368
    /**
369
     * The only REALLY MANDATORY attribute for a column is the 'name'.
370
     * Everything else, Backpack can probably guess.
371
     *
372
     * This method checks that all necessary attributes are set.
373
     * If not, it tries to guess them.
374
     *
375
     * @param  string|array  $column  The column definition array OR column name as string.
376
     * @return array Proper column definition array.
377
     */
378
    public function makeSureColumnHasNeededAttributes($column)
379
    {
380
        $column = $this->makeSureColumnHasName($column);
0 ignored issues
show
Bug introduced by
It seems like $column can also be of type string; however, parameter $column of Backpack\CRUD\app\Librar...makeSureColumnHasName() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

380
        $column = $this->makeSureColumnHasName(/** @scrutinizer ignore-type */ $column);
Loading history...
381
        $column = $this->makeSureColumnHasKey($column);
382
        $column = $this->makeSureColumnHasLabel($column);
383
        $column = $this->makeSureColumnHasEntity($column);
384
        $column = $this->makeSureColumnHasModel($column);
385
        $column = $this->makeSureColumnHasAttribute($column);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $column is correct as $this->makeSureColumnHasAttribute($column) targeting Backpack\CRUD\app\Librar...ureColumnHasAttribute() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
386
        $column = $this->makeSureColumnHasRelationType($column);
0 ignored issues
show
Bug introduced by
$column of type void is incompatible with the type array expected by parameter $column of Backpack\CRUD\app\Librar...ColumnHasRelationType(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

386
        $column = $this->makeSureColumnHasRelationType(/** @scrutinizer ignore-type */ $column);
Loading history...
387
        $column = $this->makeSureColumnHasType($column);
388
        $column = $this->makeSureColumnHasPriority($column);
389
        $column = $this->makeSureSubfieldsHaveNecessaryAttributes($column);
0 ignored issues
show
Bug introduced by
It seems like makeSureSubfieldsHaveNecessaryAttributes() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

389
        /** @scrutinizer ignore-call */ 
390
        $column = $this->makeSureSubfieldsHaveNecessaryAttributes($column);
Loading history...
390
391
        // check if the column exists in the database (as a db column)
392
        $column_exists_in_db = $this->hasDatabaseColumn($this->model->getTable(), $column['name']);
393
394
        // make sure column has tableColumn, orderable and searchLogic
395
        $column['tableColumn'] = $column['tableColumn'] ?? $column_exists_in_db;
396
        $column['orderable'] = $column['orderable'] ?? $column_exists_in_db;
397
        $column['searchLogic'] = $column['searchLogic'] ?? $column_exists_in_db;
398
399
        return $column;
400
    }
401
402
    /**
403
     * Count the number of columns added so far.
404
     *
405
     * It will not take into account the action
406
     * columns (columns with buttons, checkbox).
407
     *
408
     * @return int
409
     */
410
    public function countColumnsWithoutActions()
411
    {
412
        return collect($this->columns())->filter(function ($column, $key) {
0 ignored issues
show
Bug introduced by
$this->columns() of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

412
        return collect(/** @scrutinizer ignore-type */ $this->columns())->filter(function ($column, $key) {
Loading history...
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

412
        return collect($this->columns())->filter(function ($column, /** @scrutinizer ignore-unused */ $key) {

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

Loading history...
413
            return ! isset($column['hasActions']) || $column['hasActions'] == false;
414
        })->count();
415
    }
416
417
    /**
418
     * Create and return a CrudColumn object for that column name.
419
     *
420
     * Enables developers to use a fluent syntax to declare their columns,
421
     * in addition to the existing options:
422
     * - CRUD::addColumn(['name' => 'price', 'type' => 'number']);
423
     * - CRUD::column('price')->type('number');
424
     * - CRUD::column(['name' => 'price', 'type' => 'number']);
425
     *
426
     * And if the developer uses the CrudColumn object as Column in their CrudController:
427
     * - Column::name('price')->type('number');
428
     *
429
     * @param  string|array  $name  The name of the column in the db, or model attribute.
430
     * @return CrudColumn
431
     */
432
    public function column($nameOrDefinition)
433
    {
434
        return new CrudColumn($nameOrDefinition);
435
    }
436
}
437