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 (#4267)
by Pedro
29:16 queued 14:55
created

Read::shouldUseFallbackLocale()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 4
eloc 4
c 1
b 1
f 0
nc 5
nop 0
dl 0
loc 9
rs 10
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Backpack\CRUD\app\Exceptions\BackpackProRequiredException;
6
use Exception;
7
use Illuminate\Support\Facades\Route;
8
9
/**
10
 * Properties and methods used by the List operation.
11
 */
12
trait Read
13
{
14
    /**
15
     * Find and retrieve the id of the current entry.
16
     *
17
     * @return int|bool The id in the db or false.
18
     */
19
    public function getCurrentEntryId()
20
    {
21
        if ($this->entry) {
22
            return $this->entry->getKey();
23
        }
24
25
        $params = Route::current()?->parameters() ?? [];
26
27
        return  // use the entity name to get the current entry
28
                // this makes sure the ID is corrent even for nested resources
29
                $this->getRequest()->input($this->entity_name) ??
0 ignored issues
show
Bug introduced by
It seems like getRequest() 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

29
                $this->/** @scrutinizer ignore-call */ 
30
                       getRequest()->input($this->entity_name) ??
Loading history...
30
                // otherwise use the next to last parameter
31
                array_values($params)[count($params) - 1] ??
32
                // otherwise return false
33
                false;
34
    }
35
36
    /**
37
     * Find and retrieve the current entry.
38
     *
39
     * @return \Illuminate\Database\Eloquent\Model|bool The row in the db or false.
40
     */
41
    public function getCurrentEntry()
42
    {
43
        $id = $this->getCurrentEntryId();
44
45
        if ($id === false) {
46
            return false;
47
        }
48
49
        return $this->getEntry($id);
50
    }
51
52
    public function getCurrentEntryWithLocale()
53
    {
54
        $entry = $this->getCurrentEntry();
55
56
        if (! $entry) {
57
            return false;
58
        }
59
60
        return $this->setLocaleOnModel($entry);
0 ignored issues
show
Bug introduced by
It seems like setLocaleOnModel() 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

60
        return $this->/** @scrutinizer ignore-call */ setLocaleOnModel($entry);
Loading history...
61
    }
62
63
    /**
64
     * Find and retrieve an entry in the database or fail.
65
     *
66
     * @param int The id of the row in the db to fetch.
0 ignored issues
show
Bug introduced by
The type Backpack\CRUD\app\Library\CrudPanel\Traits\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
67
     * @return \Illuminate\Database\Eloquent\Model The row in the db.
68
     */
69
    public function getEntry($id)
70
    {
71
        if (! $this->entry) {
72
            $this->entry = $this->getModelWithCrudPanelQuery()->findOrFail($id);
0 ignored issues
show
Bug Best Practice introduced by
The property entry does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
73
            $this->entry = $this->entry->withFakes();
74
        }
75
76
        return $this->entry;
77
    }
78
79
    private function shouldUseFallbackLocale()
80
    {
81
        if ($this->getOperationSetting('useFallbackLocale') !== null) {
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

81
        if ($this->/** @scrutinizer ignore-call */ getOperationSetting('useFallbackLocale') !== null) {
Loading history...
82
            return $this->getOperationSetting('useFallbackLocale');
83
        }
84
85
        $fallbackRequestValue = $this->getRequest()->get('_use_fallback');
86
87
        return $fallbackRequestValue === 'true' ? true : (in_array($fallbackRequestValue, array_keys(config('backpack.crud.locales'))) ? $fallbackRequestValue : false);
88
    }
89
90
    /**
91
     * Find and retrieve an entry in the database or fail.
92
     * When found, make sure we set the Locale on it.
93
     *
94
     * @param int The id of the row in the db to fetch.
95
     * @return \Illuminate\Database\Eloquent\Model The row in the db.
96
     */
97
    public function getEntryWithLocale($id)
98
    {
99
        if (! $this->entry) {
100
            $this->entry = $this->getEntry($id);
0 ignored issues
show
Bug Best Practice introduced by
The property entry does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
101
        }
102
103
        return $this->setLocaleOnModel($this->entry);
104
    }
105
106
    /**
107
     * Return a Model builder instance with the current crud query applied.
108
     *
109
     * @return \Illuminate\Database\Eloquent\Builder
110
     */
111
    public function getModelWithCrudPanelQuery()
112
    {
113
        return $this->model->setQuery($this->query->getQuery());
114
    }
115
116
    /**
117
     * Find and retrieve an entry in the database or fail.
118
     *
119
     * @param int The id of the row in the db to fetch.
120
     * @return \Illuminate\Database\Eloquent\Model The row in the db.
121
     */
122
    public function getEntryWithoutFakes($id)
123
    {
124
        return $this->getModelWithCrudPanelQuery()->findOrFail($id);
125
    }
126
127
    /**
128
     * Make the query JOIN all relationships used in the columns, too,
129
     * so there will be less database queries overall.
130
     */
131
    public function autoEagerLoadRelationshipColumns()
132
    {
133
        $relationships = $this->getColumnsRelationships();
0 ignored issues
show
Bug introduced by
It seems like getColumnsRelationships() 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

133
        /** @scrutinizer ignore-call */ 
134
        $relationships = $this->getColumnsRelationships();
Loading history...
134
135
        foreach ($relationships as $relation) {
136
            if (strpos($relation, '.') !== false) {
137
                $parts = explode('.', $relation);
138
                $model = $this->model;
139
140
                // Iterate over each relation part to find the valid relations without attributes
141
                // We should eager load the relation but not the attribute
142
                foreach ($parts as $i => $part) {
143
                    try {
144
                        $model = $model->$part()->getRelated();
145
                    } catch (Exception $e) {
146
                        $relation = implode('.', array_slice($parts, 0, $i));
147
                    }
148
                }
149
            }
150
            $this->with($relation);
0 ignored issues
show
Bug introduced by
It seems like with() 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

150
            $this->/** @scrutinizer ignore-call */ 
151
                   with($relation);
Loading history...
151
        }
152
    }
153
154
    /**
155
     * Get all entries from the database.
156
     *
157
     * @return array|\Illuminate\Database\Eloquent\Collection
158
     */
159
    public function getEntries()
160
    {
161
        $this->autoEagerLoadRelationshipColumns();
162
163
        $entries = $this->query->get();
164
165
        // add the fake columns for each entry
166
        foreach ($entries as $key => $entry) {
167
            $entry->addFakes($this->getFakeColumnsAsArray());
0 ignored issues
show
Bug introduced by
It seems like getFakeColumnsAsArray() 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

167
            $entry->addFakes($this->/** @scrutinizer ignore-call */ getFakeColumnsAsArray());
Loading history...
168
        }
169
170
        return $entries;
171
    }
172
173
    /**
174
     * Enable the DETAILS ROW functionality:.
175
     *
176
     * In the table view, show a plus sign next to each entry.
177
     * 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.
178
     */
179
    public function enableDetailsRow()
180
    {
181
        if (! backpack_pro()) {
182
            throw new BackpackProRequiredException('Details row');
183
        }
184
185
        $this->setOperationSetting('detailsRow', true);
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

185
        $this->/** @scrutinizer ignore-call */ 
186
               setOperationSetting('detailsRow', true);
Loading history...
186
    }
187
188
    /**
189
     * Disable the DETAILS ROW functionality:.
190
     */
191
    public function disableDetailsRow()
192
    {
193
        $this->setOperationSetting('detailsRow', false);
194
    }
195
196
    /**
197
     * Add two more columns at the beginning of the ListEntrie table:
198
     * - one shows the checkboxes needed for bulk actions
199
     * - one is blank, in order for evenual detailsRow or expand buttons
200
     * to be in a separate column.
201
     */
202
    public function enableBulkActions()
203
    {
204
        $this->setOperationSetting('bulkActions', true);
205
    }
206
207
    /**
208
     * Remove the two columns needed for bulk actions.
209
     */
210
    public function disableBulkActions()
211
    {
212
        $this->setOperationSetting('bulkActions', false);
213
214
        $this->removeColumn('bulk_actions');
0 ignored issues
show
Bug introduced by
It seems like removeColumn() 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

214
        $this->/** @scrutinizer ignore-call */ 
215
               removeColumn('bulk_actions');
Loading history...
215
    }
216
217
    /**
218
     * Set the number of rows that should be show on the list view.
219
     */
220
    public function setDefaultPageLength($value)
221
    {
222
        $this->abortIfInvalidPageLength($value);
223
224
        $this->setOperationSetting('defaultPageLength', $value);
225
    }
226
227
    /**
228
     * Get the number of rows that should be show on the list view.
229
     *
230
     * @return int
231
     */
232
    public function getDefaultPageLength()
233
    {
234
        return $this->getOperationSetting('defaultPageLength') ?? config('backpack.crud.operations.list.defaultPageLength') ?? 25;
235
    }
236
237
    /**
238
     * If a custom page length was specified as default, make sure it
239
     * also show up in the page length menu.
240
     */
241
    public function addCustomPageLengthToPageLengthMenu()
242
    {
243
        $values = $this->getOperationSetting('pageLengthMenu')[0];
244
        $labels = $this->getOperationSetting('pageLengthMenu')[1];
245
246
        if (array_search($this->getDefaultPageLength(), $values) === false) {
247
            for ($i = 0; $i < count($values); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
248
                if ($values[$i] > $this->getDefaultPageLength() || $values[$i] === -1) {
249
                    array_splice($values, $i, 0, $this->getDefaultPageLength());
250
                    array_splice($labels, $i, 0, $this->getDefaultPageLength());
251
                    break;
252
                }
253
                if ($i === count($values) - 1) {
254
                    $values[] = $this->getDefaultPageLength();
255
                    $labels[] = $this->getDefaultPageLength();
256
                    break;
257
                }
258
            }
259
        }
260
261
        $this->setOperationSetting('pageLengthMenu', [$values, $labels]);
262
    }
263
264
    /**
265
     * Specify array of available page lengths on the list view.
266
     *
267
     * @param  array|int  $menu
268
     *
269
     * https://backpackforlaravel.com/docs/4.1/crud-cheat-sheet#page-length
270
     */
271
    public function setPageLengthMenu($menu)
272
    {
273
        if (is_array($menu)) {
274
            // start checking $menu integrity
275
            if (count($menu) !== count($menu, COUNT_RECURSIVE)) {
276
                // developer defined as setPageLengthMenu([[50, 100, 300]]) or setPageLengthMenu([[50, 100, 300],['f','h','t']])
277
                // we will apply the same labels as the values to the menu if developer didn't
278
                $this->abortIfInvalidPageLength($menu[0]);
279
280
                if (! isset($menu[1]) || ! is_array($menu[1])) {
281
                    $menu[1] = $menu[0];
282
                }
283
            } else {
284
                // developer defined setPageLengthMenu([10 => 'f', 100 => 'h', 300 => 't']) OR setPageLengthMenu([50, 100, 300])
285
                $menu = $this->buildPageLengthMenuFromArray($menu);
286
            }
287
        } else {
288
            // developer added only a single value setPageLengthMenu(10)
289
            $this->abortIfInvalidPageLength($menu);
290
291
            $menu = [[$menu], [$menu]];
292
        }
293
294
        $this->setOperationSetting('pageLengthMenu', $menu);
295
    }
296
297
    /**
298
     * Builds the menu from the given array. It works out with two different types of arrays:
299
     *  [1, 2, 3] AND [1 => 'one', 2 => 'two', 3 => 'three'].
300
     *
301
     * @param  array  $menu
302
     * @return array
303
     */
304
    private function buildPageLengthMenuFromArray($menu)
305
    {
306
        // check if the values of the array are strings, in case developer defined:
307
        // setPageLengthMenu([0 => 'f', 100 => 'h', 300 => 't'])
308
        if (count(array_filter(array_values($menu), 'is_string')) > 0) {
309
            $values = array_keys($menu);
310
            $labels = array_values($menu);
311
312
            $this->abortIfInvalidPageLength($values);
313
314
            return [$values, $labels];
315
        } else {
316
            // developer defined length as setPageLengthMenu([50, 100, 300])
317
            // we will use the same values as labels
318
            $this->abortIfInvalidPageLength($menu);
319
320
            return [$menu, $menu];
321
        }
322
    }
323
324
    /**
325
     * Get page length menu for the list view.
326
     *
327
     * @return array
328
     */
329
    public function getPageLengthMenu()
330
    {
331
        // if we have a 2D array, update all the values in the right hand array to their translated values
332
        if (isset($this->getOperationSetting('pageLengthMenu')[1]) && is_array($this->getOperationSetting('pageLengthMenu')[1])) {
333
            $aux = $this->getOperationSetting('pageLengthMenu');
334
            foreach ($this->getOperationSetting('pageLengthMenu')[1] as $key => $val) {
335
                $aux[1][$key] = trans($val);
336
            }
337
            $this->setOperationSetting('pageLengthMenu', $aux);
338
        }
339
        $this->addCustomPageLengthToPageLengthMenu();
340
341
        return $this->getOperationSetting('pageLengthMenu');
342
    }
343
344
    /**
345
     * Checks if the provided PageLength segment is valid.
346
     *
347
     * @param  array|int  $value
348
     * @return void
349
     */
350
    private function abortIfInvalidPageLength($value)
351
    {
352
        if ($value === 0 || (is_array($value) && in_array(0, $value))) {
353
            abort(500, 'You should not use 0 as a key in paginator. If you are looking for "ALL" option, use -1 instead.');
354
        }
355
    }
356
357
    /*
358
    |--------------------------------------------------------------------------
359
    |                                EXPORT BUTTONS
360
    |--------------------------------------------------------------------------
361
    */
362
363
    /**
364
     * Tell the list view to show the DataTables export buttons.
365
     */
366
    public function enableExportButtons()
367
    {
368
        if (! backpack_pro()) {
369
            throw new BackpackProRequiredException('Export buttons');
370
        }
371
372
        $this->setOperationSetting('exportButtons', true);
373
        $this->setOperationSetting('showTableColumnPicker', true);
374
        $this->setOperationSetting('showExportButton', true);
375
    }
376
377
    /**
378
     * Check if export buttons are enabled for the table view.
379
     *
380
     * @return bool
381
     */
382
    public function exportButtons()
383
    {
384
        return $this->getOperationSetting('exportButtons') ?? false;
385
    }
386
}
387