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 — master ( e0c389...f0dd86 )
by Cristian
01:42 queued 12s
created

Search::getColumnWithTableNamePrefixed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 1
c 2
b 1
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel\Traits;
4
5
use Carbon\Carbon;
6
use Validator;
7
8
trait Search
9
{
10
    /*
11
    |--------------------------------------------------------------------------
12
    |                                   SEARCH
13
    |--------------------------------------------------------------------------
14
    */
15
16
    /**
17
     * Add conditions to the CRUD query for a particular search term.
18
     *
19
     * @param string $searchTerm Whatever string the user types in the search bar.
20
     *
21
     * @return \Illuminate\Database\Eloquent\Builder
22
     */
23
    public function applySearchTerm($searchTerm)
24
    {
25
        return $this->query->where(function ($query) use ($searchTerm) {
26
            foreach ($this->columns() as $column) {
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

26
            foreach ($this->/** @scrutinizer ignore-call */ columns() as $column) {
Loading history...
27
                if (! isset($column['type'])) {
28
                    abort(400, 'Missing column type when trying to apply search term.');
29
                }
30
31
                $this->applySearchLogicForColumn($query, $column, $searchTerm);
32
            }
33
        });
34
    }
35
36
    /**
37
     * Apply the search logic for each CRUD column.
38
     */
39
    public function applySearchLogicForColumn($query, $column, $searchTerm)
40
    {
41
        $columnType = $column['type'];
42
43
        // if there's a particular search logic defined, apply that one
44
        if (isset($column['searchLogic'])) {
45
            $searchLogic = $column['searchLogic'];
46
47
            // if a closure was passed, execute it
48
            if (is_callable($searchLogic)) {
49
                return $searchLogic($query, $column, $searchTerm);
50
            }
51
52
            // if a string was passed, search like it was that column type
53
            if (is_string($searchLogic)) {
54
                $columnType = $searchLogic;
55
            }
56
57
            // if false was passed, don't search this column
58
            if ($searchLogic == false) {
59
                return;
60
            }
61
        }
62
63
        // sensible fallback search logic, if none was explicitly given
64
        if ($column['tableColumn']) {
65
            switch ($columnType) {
66
                case 'email':
67
                case 'text':
68
                case 'textarea':
69
                    $query->orWhere($this->getColumnWithTableNamePrefixed($query, $column['name']), 'like', '%'.$searchTerm.'%');
70
                    break;
71
72
                case 'date':
73
                case 'datetime':
74
                    $validator = Validator::make(['value' => $searchTerm], ['value' => 'date']);
75
76
                    if ($validator->fails()) {
77
                        break;
78
                    }
79
80
                    $query->orWhereDate($this->getColumnWithTableNamePrefixed($query, $column['name']), Carbon::parse($searchTerm));
81
                    break;
82
83
                case 'select':
84
                case 'select_multiple':
85
                    $query->orWhereHas($column['entity'], function ($q) use ($column, $searchTerm) {
86
                        $q->where($this->getColumnWithTableNamePrefixed($q, $column['attribute']), 'like', '%'.$searchTerm.'%');
87
                    });
88
                    break;
89
90
                default:
91
                    return;
92
                    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...
93
            }
94
        }
95
    }
96
97
    // -------------------------
98
    // Responsive Table
99
    // -------------------------
100
101
    /**
102
     * Tell the list view to NOT show a reponsive DataTable.
103
     *
104
     * @param bool $value
105
     */
106
    public function setResponsiveTable($value = true)
107
    {
108
        $this->setOperationSetting('responsiveTable', $value);
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

108
        $this->/** @scrutinizer ignore-call */ 
109
               setOperationSetting('responsiveTable', $value);
Loading history...
109
    }
110
111
    /**
112
     * Check if responsiveness is enabled for the table view.
113
     *
114
     * @return bool
115
     */
116
    public function getResponsiveTable()
117
    {
118
        if ($this->getOperationSetting('responsiveTable') !== 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

118
        if ($this->/** @scrutinizer ignore-call */ getOperationSetting('responsiveTable') !== null) {
Loading history...
119
            return $this->getOperationSetting('responsiveTable');
120
        }
121
122
        return config('backpack.crud.operations.list.responsiveTable');
123
    }
124
125
    /**
126
     * Remember to show a responsive table.
127
     */
128
    public function enableResponsiveTable()
129
    {
130
        $this->setResponsiveTable(true);
131
    }
132
133
    /**
134
     * Remember to show a table with horizontal scrolling.
135
     */
136
    public function disableResponsiveTable()
137
    {
138
        $this->setResponsiveTable(false);
139
    }
140
141
    // -------------------------
142
    // Persistent Table
143
    // -------------------------
144
145
    /**
146
     * Tell the list view to NOT store datatable information in local storage.
147
     *
148
     * @param bool $value
149
     */
150
    public function setPersistentTable($value = true)
151
    {
152
        return $this->setOperationSetting('persistentTable', $value);
153
    }
154
155
    /**
156
     * Check if saved state is enabled for the table view.
157
     *
158
     * @return bool
159
     */
160
    public function getPersistentTable()
161
    {
162
        if ($this->getOperationSetting('persistentTable') !== null) {
163
            return $this->getOperationSetting('persistentTable');
164
        }
165
166
        return config('backpack.crud.operations.list.persistentTable');
167
    }
168
169
    /**
170
     * Get duration for persistent table.
171
     *
172
     * @return bool
173
     */
174
    public function getPersistentTableDuration()
175
    {
176
        if ($this->getOperationSetting('persistentTableDuration') !== null) {
177
            return $this->getOperationSetting('persistentTableDuration');
178
        }
179
180
        return config('backpack.crud.operations.list.persistentTableDuration', false);
181
    }
182
183
    /**
184
     * Remember to show a persistent table.
185
     */
186
    public function enablePersistentTable()
187
    {
188
        return $this->setPersistentTable(true);
189
    }
190
191
    /**
192
     * Remember to show a table that doesn't store URLs and pagination in local storage.
193
     */
194
    public function disablePersistentTable()
195
    {
196
        return $this->setPersistentTable(false);
197
    }
198
199
    /**
200
     * Get the HTML of the cells in a table row, for a certain DB entry.
201
     *
202
     * @param \Illuminate\Database\Eloquent\Model $entry     A db entry of the current entity;
203
     * @param bool|int                            $rowNumber The number shown to the user as row number (index);
204
     *
205
     * @return array Array of HTML cell contents.
206
     */
207
    public function getRowViews($entry, $rowNumber = false)
208
    {
209
        $row_items = [];
210
211
        foreach ($this->columns() as $key => $column) {
212
            $row_items[] = $this->getCellView($column, $entry, $rowNumber);
213
        }
214
215
        // add the buttons as the last column
216
        if ($this->buttons()->where('stack', 'line')->count()) {
0 ignored issues
show
Bug introduced by
It seems like buttons() 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

216
        if ($this->/** @scrutinizer ignore-call */ buttons()->where('stack', 'line')->count()) {
Loading history...
217
            $row_items[] = \View::make('crud::inc.button_stack', ['stack' => 'line'])
218
                                ->with('crud', $this)
219
                                ->with('entry', $entry)
220
                                ->with('row_number', $rowNumber)
221
                                ->render();
222
        }
223
224
        // add the details_row button to the first column
225
        if ($this->getOperationSetting('detailsRow')) {
226
            $details_row_button = \View::make('crud::columns.inc.details_row_button')
227
                                           ->with('crud', $this)
228
                                           ->with('entry', $entry)
229
                                           ->with('row_number', $rowNumber)
230
                                           ->render();
231
            $row_items[0] = $details_row_button.$row_items[0];
0 ignored issues
show
Bug introduced by
Are you sure $details_row_button of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

231
            $row_items[0] = /** @scrutinizer ignore-type */ $details_row_button.$row_items[0];
Loading history...
232
        }
233
234
        return $row_items;
235
    }
236
237
    /**
238
     * Get the HTML of a cell, using the column types.
239
     *
240
     * @param array                               $column
241
     * @param \Illuminate\Database\Eloquent\Model $entry     A db entry of the current entity;
242
     * @param bool|int                            $rowNumber The number shown to the user as row number (index);
243
     *
244
     * @return string
245
     */
246
    public function getCellView($column, $entry, $rowNumber = false)
247
    {
248
        return $this->renderCellView($this->getCellViewName($column), $column, $entry, $rowNumber);
249
    }
250
251
    /**
252
     * Get the name of the view to load for the cell.
253
     *
254
     * @param array $column
255
     *
256
     * @return string
257
     */
258
    private function getCellViewName($column)
259
    {
260
        // return custom column if view_namespace attribute is set
261
        if (isset($column['view_namespace']) && isset($column['type'])) {
262
            return $column['view_namespace'].'.'.$column['type'];
263
        }
264
265
        if (isset($column['type'])) {
266
            // if the column has been overwritten return that one
267
            if (view()->exists('vendor.backpack.crud.columns.'.$column['type'])) {
268
                return 'vendor.backpack.crud.columns.'.$column['type'];
269
            }
270
271
            // return the column from the package
272
            return 'crud::columns.'.$column['type'];
273
        }
274
275
        // fallback to text column
276
        return 'crud::columns.text';
277
    }
278
279
    /**
280
     * Render the given view.
281
     *
282
     * @param string   $view
283
     * @param array    $column
284
     * @param object   $entry
285
     * @param bool|int $rowNumber The number shown to the user as row number (index)
286
     *
287
     * @return string
288
     */
289
    private function renderCellView($view, $column, $entry, $rowNumber = false)
290
    {
291
        if (! view()->exists($view)) {
292
            $view = 'crud::columns.text'; // fallback to text column
293
        }
294
295
        return \View::make($view)
0 ignored issues
show
Bug Best Practice introduced by
The expression return View::make($view)..., $rowNumber)->render() also could return the type array which is incompatible with the documented return type string.
Loading history...
296
            ->with('crud', $this)
297
            ->with('column', $column)
298
            ->with('entry', $entry)
299
            ->with('rowNumber', $rowNumber)
300
            ->render();
301
    }
302
303
    /**
304
     * Created the array to be fed to the data table.
305
     *
306
     * @param array    $entries      Eloquent results.
307
     * @param int      $totalRows
308
     * @param int      $filteredRows
309
     * @param bool|int $startIndex
310
     *
311
     * @return array
312
     */
313
    public function getEntriesAsJsonForDatatables($entries, $totalRows, $filteredRows, $startIndex = false)
314
    {
315
        $rows = [];
316
317
        foreach ($entries as $row) {
318
            $rows[] = $this->getRowViews($row, $startIndex === false ? false : ++$startIndex);
319
        }
320
321
        return [
322
            'draw'            => (isset($this->getRequest()['draw']) ? (int) $this->getRequest()['draw'] : 0),
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

322
            'draw'            => (isset($this->/** @scrutinizer ignore-call */ getRequest()['draw']) ? (int) $this->getRequest()['draw'] : 0),
Loading history...
323
            'recordsTotal'    => $totalRows,
324
            'recordsFiltered' => $filteredRows,
325
            'data'            => $rows,
326
        ];
327
    }
328
329
    /**
330
     * Return the column attribute (column in database) prefixed with table to use in search.
331
     *
332
     * @param \Illuminate\Database\Eloquent\Builder $query
333
     * @param string $column
334
     * @return string
335
     */
336
    public function getColumnWithTableNamePrefixed($query, $column)
337
    {
338
        return $query->getModel()->getTableWithPrefix().'.'.$column;
339
    }
340
}
341