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 — v6 ( 279770...4aa68f )
by Cristian
26:51 queued 11:50
created

ColumnsProtectedMethods::makeSureColumnHasModel()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 3
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
8
trait ColumnsProtectedMethods
9
{
10
    /**
11
     * Add a column to the current operation, using the Setting API.
12
     *
13
     * @param  array  $column  Column definition array.
14
     */
15
    protected function addColumnToOperationSettings($column)
16
    {
17
        $allColumns = $this->columns();
0 ignored issues
show
Bug introduced by
It seems like columns() 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

17
        /** @scrutinizer ignore-call */ 
18
        $allColumns = $this->columns();
Loading history...
18
        $allColumns = Arr::add($allColumns, $column['key'], $column);
19
20
        $this->setOperationSetting('columns', $allColumns);
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

20
        $this->/** @scrutinizer ignore-call */ 
21
               setOperationSetting('columns', $allColumns);
Loading history...
21
    }
22
23
    /**
24
     * If a column priority has not been defined, provide a default one.
25
     *
26
     * @param  array  $column  Column definition array.
27
     * @return array Proper array defining the column.
28
     */
29
    protected function makeSureColumnHasPriority($column)
30
    {
31
        $columns_count = $this->countColumnsWithoutActions();
0 ignored issues
show
Bug introduced by
It seems like countColumnsWithoutActions() 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

31
        /** @scrutinizer ignore-call */ 
32
        $columns_count = $this->countColumnsWithoutActions();
Loading history...
32
        $assumed_priority = $columns_count ? $columns_count : 0;
33
34
        $column['priority'] = $column['priority'] ?? $assumed_priority;
35
36
        return $column;
37
    }
38
39
    /**
40
     * If the field definition array is actually a string, it means the programmer was lazy
41
     * and has only passed the name of the column. Turn that into a proper array.
42
     *
43
     * @param  array  $column  Column definition array.
44
     * @return array Proper array defining the column.
45
     */
46
    protected function makeSureColumnHasName($column)
47
    {
48
        if (is_string($column)) {
0 ignored issues
show
introduced by
The condition is_string($column) is always false.
Loading history...
49
            $column = ['name' => $column];
50
        }
51
52
        if (is_array($column) && ! isset($column['name'])) {
53
            $column['name'] = 'anonymous_column_'.Str::random(5);
54
        }
55
56
        return $column;
57
    }
58
59
    /**
60
     * If a column array is missing the "label" attribute, an ugly error would be show.
61
     * So we add the field Name as a label - it's better than nothing.
62
     *
63
     * @param  array  $column  Column definition array.
64
     * @return array Proper array defining the column.
65
     */
66
    protected function makeSureColumnHasLabel($column)
67
    {
68
        if (! isset($column['label'])) {
69
            $column['label'] = mb_ucfirst($this->makeLabel($column['name']));
0 ignored issues
show
Bug introduced by
It seems like makeLabel() 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

69
            $column['label'] = mb_ucfirst($this->/** @scrutinizer ignore-call */ makeLabel($column['name']));
Loading history...
70
        }
71
72
        return $column;
73
    }
74
75
    /**
76
     * If a column definition is missing the type, set a default.
77
     *
78
     * @param  array  $column  Column definition array.
79
     * @return array Column definition array with type.
80
     */
81
    protected function makeSureColumnHasType($column)
82
    {
83
        // Do not alter type if it has been set by developer
84
        if (isset($column['type'])) {
85
            return $column;
86
        }
87
88
        // Set text as default column type
89
        $column['type'] = 'text';
90
91
        if (method_exists($this->model, 'translationEnabledForModel') && $this->model->translationEnabledForModel() && array_key_exists($column['name'], $this->model->getTranslations())) {
92
            return $column;
93
        }
94
95
        $could_be_relation = Arr::get($column, 'entity', false) !== false;
96
97
        if ($could_be_relation) {
98
            $column['type'] = $this->inferFieldTypeFromRelationType($column['relation_type']);
0 ignored issues
show
Bug introduced by
It seems like inferFieldTypeFromRelationType() 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

98
            /** @scrutinizer ignore-call */ 
99
            $column['type'] = $this->inferFieldTypeFromRelationType($column['relation_type']);
Loading history...
99
        }
100
101
        if (in_array($column['name'], $this->model->getDates())) {
102
            $column['type'] = 'datetime';
103
        }
104
105
        if ($this->model->hasCast($column['name'])) {
106
            $attributeType = $this->model->getCasts()[$column['name']];
107
108
            switch ($attributeType) {
109
                case 'array':
110
                case 'encrypted:array':
111
                case 'collection':
112
                case 'encrypted:collection':
113
                    $column['type'] = 'array';
114
                    break;
115
                case 'json':
116
                case 'object':
117
                    $column['type'] = 'json';
118
                    break;
119
                case 'bool':
120
                case 'boolean':
121
                    $column['type'] = 'check';
122
                    break;
123
                case 'date':
124
                    $column['type'] = 'date';
125
                    break;
126
                case 'datetime':
127
                    $column['type'] = 'datetime';
128
                    break;
129
                case 'double':
130
                case 'float':
131
                case 'int':
132
                case 'integer':
133
                case 'real':
134
                case 'timestamp':
135
                    $column['type'] = 'number';
136
                    break;
137
            }
138
        }
139
140
        return $column;
141
    }
142
143
    /**
144
     * If a column definition is missing the key, set the default.
145
     * The key is used when storing all columns using the Settings API,
146
     * it is used as the "key" of the associative array that holds all columns.
147
     *
148
     * @param  array  $column  Column definition array.
149
     * @return array Column definition array with key.
150
     */
151
    protected function makeSureColumnHasKey($column)
152
    {
153
        if (! isset($column['key'])) {
154
            $column['key'] = str_replace('.', '__', $column['name']);
155
        }
156
157
        return $column;
158
    }
159
160
    /**
161
     * If a column definition is missing the wrapper element, set the default (empty).
162
     * The wrapper is the HTML element that wrappes around the column text.
163
     * By defining this array a developer can wrap the text into an anchor (link),
164
     * span, div or whatever they want.
165
     *
166
     * @param  array  $column  Column definition array.
167
     * @return array Column definition array with wrapper.
168
     */
169
    protected function makeSureColumnHasWrapper($column)
170
    {
171
        if (! isset($column['wrapper'])) {
172
            $column['wrapper'] = [];
173
        }
174
175
        return $column;
176
    }
177
178
    protected function makeSureColumnHasEntity($column)
179
    {
180
        if (isset($column['entity'])) {
181
            return $column;
182
        }
183
184
        // if the name is an array it's definitely not a relationship
185
        if (is_array($column['name'])) {
186
            return $column;
187
        }
188
189
        // if the name is dot notation it might be a relationship
190
        if (strpos($column['name'], '.') !== false) {
191
            $possibleMethodName = Str::before($column['name'], '.');
192
193
            // if the first part of the string exists as method in the model
194
            if (method_exists($this->model, $possibleMethodName)) {
195
                // check model method for possibility of being a relationship
196
                $column['entity'] = $this->modelMethodIsRelationship($this->model, $possibleMethodName) ? $column['name'] : false;
0 ignored issues
show
Bug introduced by
It seems like modelMethodIsRelationship() 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

196
                $column['entity'] = $this->/** @scrutinizer ignore-call */ modelMethodIsRelationship($this->model, $possibleMethodName) ? $column['name'] : false;
Loading history...
197
198
                if ($column['entity']) {
199
                    // if the user setup the attribute in relation string, we are not going to infer that attribute from model
200
                    // instead we get the defined attribute by the user.
201
                    if ($this->isAttributeInRelationString($column)) {
0 ignored issues
show
Bug introduced by
It seems like isAttributeInRelationString() 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

201
                    if ($this->/** @scrutinizer ignore-call */ isAttributeInRelationString($column)) {
Loading history...
202
                        $column['attribute'] = $column['attribute'] ?? Str::afterLast($column['entity'], '.');
203
                    }
204
                }
205
206
                return $column;
207
            }
208
        }
209
210
        // if there's a method on the model with this name
211
        if (method_exists($this->model, $column['name'])) {
212
            // check model method for possibility of being a relationship
213
            $column['entity'] = $this->modelMethodIsRelationship($this->model, $column['name']);
214
215
            return $column;
216
        }
217
218
        // if the name ends with _id and that method exists,
219
        // we can probably use it as an entity
220
        if (Str::endsWith($column['name'], '_id')) {
221
            $possibleMethodName = Str::replaceLast('_id', '', $column['name']);
222
223
            if (method_exists($this->model, $possibleMethodName)) {
224
                // check model method for possibility of being a relationship
225
                $column['entity'] = $this->modelMethodIsRelationship($this->model, $possibleMethodName);
226
227
                return $column;
228
            }
229
        }
230
231
        return $column;
232
    }
233
234
    /**
235
     * Infer the attribute for the column when needed.
236
     *
237
     * @param  array  $column
238
     * @return void
239
     */
240
    protected function makeSureColumnHasAttribute(array $column)
241
    {
242
        return $this->makeSureFieldHasAttribute($column);
0 ignored issues
show
Bug introduced by
It seems like makeSureFieldHasAttribute() 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

242
        return $this->/** @scrutinizer ignore-call */ makeSureFieldHasAttribute($column);
Loading history...
243
    }
244
245
    /**
246
     * If an entity has been defined for the column, but no model,
247
     * determine the model from that relationship.
248
     *
249
     * @param  array  $column  Column definition array.
250
     * @return array Column definition array with model.
251
     */
252
    protected function makeSureColumnHasModel($column)
253
    {
254
        // if this is a relation type field and no corresponding model was specified,
255
        // get it from the relation method defined in the main model
256
        if (isset($column['entity']) && $column['entity'] !== false && ! isset($column['model'])) {
257
            $column['model'] = $this->getRelationModel($column['entity']);
0 ignored issues
show
Bug introduced by
It seems like getRelationModel() 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

257
            /** @scrutinizer ignore-call */ 
258
            $column['model'] = $this->getRelationModel($column['entity']);
Loading history...
258
        }
259
260
        return $column;
261
    }
262
263
    /**
264
     * If an entity has been defined for the column, but no relation type,
265
     * determine the relation type from that relationship.
266
     *
267
     * @param  array  $column  Column definition array.
268
     * @return array Column definition array with model.
269
     */
270
    protected function makeSureColumnHasRelationType($column)
271
    {
272
        if (isset($column['entity']) && $column['entity'] !== false) {
273
            $column['relation_type'] = $column['relation_type'] ?? $this->inferRelationTypeFromRelationship($column);
0 ignored issues
show
Bug introduced by
It seems like inferRelationTypeFromRelationship() 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

273
            $column['relation_type'] = $column['relation_type'] ?? $this->/** @scrutinizer ignore-call */ inferRelationTypeFromRelationship($column);
Loading history...
274
        }
275
276
        return $column;
277
    }
278
279
    /**
280
     * Move the most recently added column before or after the given target column. Default is before.
281
     *
282
     * @param  string|array  $targetColumn  The target column name or array.
283
     * @param  bool  $before  If true, the column will be moved before the target column, otherwise it will be moved after it.
284
     */
285
    protected function moveColumn($targetColumn, $before = true)
286
    {
287
        // TODO: this and the moveField method from the Fields trait should be refactored into a single method and moved
288
        //       into a common class
289
        $targetColumnName = is_array($targetColumn) ? $targetColumn['name'] : $targetColumn;
290
        $columnsArray = $this->columns();
291
292
        if (array_key_exists($targetColumnName, $columnsArray)) {
293
            $targetColumnPosition = $before ? array_search($targetColumnName, array_keys($columnsArray)) :
294
                array_search($targetColumnName, array_keys($columnsArray)) + 1;
295
296
            $element = array_pop($columnsArray);
297
            $beginningPart = array_slice($columnsArray, 0, $targetColumnPosition, true);
0 ignored issues
show
Bug introduced by
It seems like $targetColumnPosition can also be of type string; however, parameter $length of array_slice() does only seem to accept integer|null, 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

297
            $beginningPart = array_slice($columnsArray, 0, /** @scrutinizer ignore-type */ $targetColumnPosition, true);
Loading history...
298
            $endingArrayPart = array_slice($columnsArray, $targetColumnPosition, null, true);
0 ignored issues
show
Bug introduced by
It seems like $targetColumnPosition can also be of type string; however, parameter $offset of array_slice() does only seem to accept integer, 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

298
            $endingArrayPart = array_slice($columnsArray, /** @scrutinizer ignore-type */ $targetColumnPosition, null, true);
Loading history...
299
300
            $columnsArray = array_merge($beginningPart, [$element['name'] => $element], $endingArrayPart);
301
            $this->setOperationSetting('columns', $columnsArray);
302
        }
303
    }
304
305
    /**
306
     * Check if the column exists in the database, as a DB column.
307
     *
308
     * @param  string  $table
309
     * @param  string  $name
310
     * @return bool
311
     */
312
    protected function hasDatabaseColumn($table, $name)
313
    {
314
        static $cache = [];
315
316
        if (! $this->driverIsSql()) {
0 ignored issues
show
Bug introduced by
It seems like driverIsSql() 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

316
        if (! $this->/** @scrutinizer ignore-call */ driverIsSql()) {
Loading history...
317
            return true;
318
        }
319
320
        if (isset($cache[$table])) {
321
            $columns = $cache[$table];
322
        } else {
323
            $columns = $cache[$table] = $this->getSchema()->getColumnListing($table);
0 ignored issues
show
Bug introduced by
It seems like getSchema() 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

323
            $columns = $cache[$table] = $this->/** @scrutinizer ignore-call */ getSchema()->getColumnListing($table);
Loading history...
324
        }
325
326
        return in_array($name, $columns);
327
    }
328
}
329