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
Pull Request — main (#5270)
by Cristian
27:17 queued 12:20
created

Columns::addAndReturnColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
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
        $this->prepareAttributesAndAddColumn($column);
70
71
        return $this;
72
    }
73
74
    /**
75
     * Add a column at the end of the CRUD object's "columns" array and return it.
76
     */
77
    public function addAndReturnColumn(array|string $column): CrudColumn
78
    {
79
        $column = $this->prepareAttributesAndAddColumn($column);
80
81
        return $column;
82
    }
83
84
    /**
85
     * Add multiple columns at the end of the CRUD object's "columns" array.
86
     *
87
     * @param  array  $columns
88
     */
89
    public function addColumns($columns)
90
    {
91
        if (count($columns)) {
92
            foreach ($columns as $key => $column) {
93
                $this->addColumn($column);
94
            }
95
        }
96
    }
97
98
    /**
99
     * Move the most recently added column after the given target column.
100
     *
101
     * @param  string|array  $targetColumn  The target column name or array.
102
     */
103
    public function afterColumn($targetColumn)
104
    {
105
        $this->moveColumn($targetColumn, false);
106
    }
107
108
    /**
109
     * Move the most recently added column before the given target column.
110
     *
111
     * @param  string|array  $targetColumn  The target column name or array.
112
     */
113
    public function beforeColumn($targetColumn)
114
    {
115
        $this->moveColumn($targetColumn);
116
    }
117
118
    /**
119
     * Move this column to be first in the columns list.
120
     *
121
     * @return bool|null
122
     */
123
    public function makeFirstColumn()
124
    {
125
        if (! $this->columns()) {
126
            return false;
127
        }
128
129
        $firstColumn = array_keys(array_slice($this->columns(), 0, 1))[0];
130
        $this->beforeColumn($firstColumn);
131
    }
132
133
    /**
134
     * Add the default column type to the given Column, inferring the type from the database column type.
135
     *
136
     * @param  array  $column
137
     * @return array|bool
138
     */
139
    public function addDefaultTypeToColumn($column)
140
    {
141
        if (array_key_exists('name', (array) $column)) {
142
            $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

142
            /** @scrutinizer ignore-call */ 
143
            $default_type = $this->inferFieldTypeFromDbColumnType($column['name']);
Loading history...
143
144
            return array_merge(['type' => $default_type], $column);
145
        }
146
147
        return false;
148
    }
149
150
    /**
151
     * Remove a column from the CRUD panel by name.
152
     *
153
     * @param  string  $columnKey  The column key.
154
     */
155
    public function removeColumn($columnKey)
156
    {
157
        $columnsArray = $this->columns();
158
        Arr::forget($columnsArray, $columnKey);
159
        $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

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

263
        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...
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

263
        return collect(/** @scrutinizer ignore-type */ $columns)->pluck('entity')->reject(function ($value, $key) {
Loading history...
264
            return ! $value;
265
        })->toArray();
266
    }
267
268
    /**
269
     * Order the CRUD columns. If certain columns are missing from the given order array, they will be pushed to the
270
     * new columns array in the original order.
271
     *
272
     * @param  array  $order  An array of column names in the desired order.
273
     */
274
    public function orderColumns($order)
275
    {
276
        $orderedColumns = [];
277
        foreach ($order as $columnName) {
278
            if (array_key_exists($columnName, $this->columns())) {
279
                $orderedColumns[$columnName] = $this->columns()[$columnName];
280
            }
281
        }
282
283
        if (empty($orderedColumns)) {
284
            return;
285
        }
286
287
        $remaining = array_diff_key($this->columns(), $orderedColumns);
288
        $this->setOperationSetting('columns', array_merge($orderedColumns, $remaining));
289
    }
290
291
    /**
292
     * Get a column by the id, from the associative array.
293
     *
294
     * @param  int  $column_number  Placement inside the columns array.
295
     * @return array Column details.
296
     */
297
    public function findColumnById($column_number)
298
    {
299
        $result = array_slice($this->columns(), $column_number, 1);
300
301
        return reset($result);
302
    }
303
304
    /**
305
     * Get the visibility priority for the actions column
306
     * in the CRUD table view.
307
     *
308
     * @return int The priority, from 1 to infinity. Lower is better.
309
     */
310
    public function getActionsColumnPriority()
311
    {
312
        return (int) $this->getOperationSetting('actionsColumnPriority') ?? 1;
313
    }
314
315
    /**
316
     * Set a certain priority for the actions column
317
     * in the CRUD table view. Usually set to 10000 in order to hide it.
318
     *
319
     * @param  int  $number  The priority, from 1 to infinity. Lower is better.
320
     * @return self
321
     */
322
    public function setActionsColumnPriority($number)
323
    {
324
        $this->setOperationSetting('actionsColumnPriority', (int) $number);
325
326
        return $this;
327
    }
328
329
    /**
330
     * Check if a column exists, by any given attribute.
331
     *
332
     * @param  string  $attribute  Attribute name on that column definition array.
333
     * @param  string  $value  Value of that attribute on that column definition array.
334
     * @return bool
335
     */
336
    public function hasColumnWhere($attribute, $value)
337
    {
338
        $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

338
        $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...
339
            return isset($column[$attribute]) && $column[$attribute] == $value;
340
        });
341
342
        return (bool) $match;
343
    }
344
345
    /**
346
     * Get the first column where a given attribute has the given value.
347
     *
348
     * @param  string  $attribute  Attribute name on that column definition array.
349
     * @param  string  $value  Value of that attribute on that column definition array.
350
     * @return bool
351
     */
352
    public function firstColumnWhere($attribute, $value)
353
    {
354
        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

354
        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...
355
            return isset($column[$attribute]) && $column[$attribute] == $value;
356
        });
357
    }
358
359
    /**
360
     * The only REALLY MANDATORY attribute for a column is the 'name'.
361
     * Everything else, Backpack can probably guess.
362
     *
363
     * This method checks that all necessary attributes are set.
364
     * If not, it tries to guess them.
365
     *
366
     * @param  string|array  $column  The column definition array OR column name as string.
367
     * @return array Proper column definition array.
368
     */
369
    public function makeSureColumnHasNeededAttributes($column)
370
    {
371
        $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

371
        $column = $this->makeSureColumnHasName(/** @scrutinizer ignore-type */ $column);
Loading history...
372
        $column = $this->makeSureColumnHasKey($column);
373
        $column = $this->makeSureColumnHasLabel($column);
374
        $column = $this->makeSureColumnHasEntity($column);
375
        $column = $this->makeSureColumnHasModel($column);
376
        $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...
377
        $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

377
        $column = $this->makeSureColumnHasRelationType(/** @scrutinizer ignore-type */ $column);
Loading history...
378
        $column = $this->makeSureColumnHasType($column);
379
        $column = $this->makeSureColumnHasPriority($column);
380
        $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

380
        /** @scrutinizer ignore-call */ 
381
        $column = $this->makeSureSubfieldsHaveNecessaryAttributes($column);
Loading history...
381
382
        // check if the column exists in the database (as a db column)
383
        $column_exists_in_db = $this->hasDatabaseColumn($this->model->getTable(), $column['name']);
384
385
        // make sure column has tableColumn, orderable and searchLogic
386
        $column['tableColumn'] = $column['tableColumn'] ?? $column_exists_in_db;
387
        $column['orderable'] = $column['orderable'] ?? $column_exists_in_db;
388
        $column['searchLogic'] = $column['searchLogic'] ?? $column_exists_in_db;
389
390
        return $column;
391
    }
392
393
    /**
394
     * Count the number of columns added so far.
395
     *
396
     * It will not take into account the action
397
     * columns (columns with buttons, checkbox).
398
     *
399
     * @return int
400
     */
401
    public function countColumnsWithoutActions()
402
    {
403
        return collect($this->columns())->filter(function ($column, $key) {
0 ignored issues
show
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

403
        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...
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

403
        return collect(/** @scrutinizer ignore-type */ $this->columns())->filter(function ($column, $key) {
Loading history...
404
            return ! isset($column['hasActions']) || $column['hasActions'] == false;
405
        })->count();
406
    }
407
408
    /**
409
     * Create and return a CrudColumn object for that column name.
410
     *
411
     * Enables developers to use a fluent syntax to declare their columns,
412
     * in addition to the existing options:
413
     * - CRUD::addColumn(['name' => 'price', 'type' => 'number']);
414
     * - CRUD::column('price')->type('number');
415
     * - CRUD::column(['name' => 'price', 'type' => 'number']);
416
     *
417
     * And if the developer uses the CrudColumn object as Column in their CrudController:
418
     * - Column::name('price')->type('number');
419
     *
420
     * @param  string|array  $name  The name of the column in the db, or model attribute.
421
     * @return CrudColumn
422
     */
423
    public function column($nameOrDefinition)
424
    {
425
        return new CrudColumn($nameOrDefinition);
426
    }
427
}
428