Completed
Push — master ( 62f14b...fe397a )
by Arjay
02:01
created

QueryDataTable::columnSearch()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 4
nop 0
dl 0
loc 23
rs 8.9297
c 0
b 0
f 0
1
<?php
2
3
namespace Yajra\DataTables;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Database\Query\Builder;
7
use Yajra\DataTables\Utilities\Helper;
8
use Illuminate\Database\Query\Expression;
9
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
10
11
class QueryDataTable extends DataTableAbstract
12
{
13
    /**
14
     * Builder object.
15
     *
16
     * @var \Illuminate\Database\Query\Builder
17
     */
18
    protected $query;
19
20
    /**
21
     * Database connection used.
22
     *
23
     * @var \Illuminate\Database\Connection
24
     */
25
    protected $connection;
26
27
    /**
28
     * Flag for ordering NULLS LAST option.
29
     *
30
     * @var bool
31
     */
32
    protected $nullsLast = false;
33
34
    /**
35
     * Flag to check if query preparation was already done.
36
     *
37
     * @var bool
38
     */
39
    protected $prepared = false;
40
41
    /**
42
     * Query callback for custom pagination using limit without offset.
43
     *
44
     * @var callable
45
     */
46
    protected $limitCallback;
47
48
    /**
49
     * Flag to skip total records count query.
50
     *
51
     * @var bool
52
     */
53
    protected $skipTotalRecords = false;
54
55
    /**
56
     * Flag to keep the select bindings.
57
     *
58
     * @var bool
59
     */
60
    protected $keepSelectBindings = false;
61
62
    /**
63
     * Can the DataTable engine be created with these parameters.
64
     *
65
     * @param mixed $source
66
     * @return bool
67
     */
68
    public static function canCreate($source)
69
    {
70
        return $source instanceof Builder;
0 ignored issues
show
Bug introduced by
The class Illuminate\Database\Query\Builder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
71
    }
72
73
    /**
74
     * @param \Illuminate\Database\Query\Builder $builder
75
     */
76
    public function __construct(Builder $builder)
77
    {
78
        $this->query      = $builder;
79
        $this->request    = app('datatables.request');
80
        $this->config     = app('datatables.config');
81
        $this->columns    = $builder->columns;
82
        $this->connection = $builder->getConnection();
83
        if ($this->config->isDebugging()) {
84
            $this->connection->enableQueryLog();
85
        }
86
    }
87
88
    /**
89
     * Organizes works.
90
     *
91
     * @param bool $mDataSupport
92
     * @return \Illuminate\Http\JsonResponse
93
     * @throws \Exception
94
     */
95
    public function make($mDataSupport = true)
96
    {
97
        try {
98
            $this->prepareQuery();
99
100
            $results   = $this->results();
101
            $processed = $this->processResults($results, $mDataSupport);
102
            $data      = $this->transform($results, $processed);
103
104
            return $this->render($data);
105
        } catch (\Exception $exception) {
106
            return $this->errorResponse($exception);
107
        }
108
    }
109
110
    /**
111
     * Prepare query by executing count, filter, order and paginate.
112
     */
113
    protected function prepareQuery()
114
    {
115
        if (! $this->prepared) {
116
            $this->totalRecords = $this->totalCount();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->totalCount() can also be of type boolean. However, the property $totalRecords is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
117
118
            if ($this->totalRecords) {
119
                $this->filterRecords();
120
                $this->ordering();
121
                $this->paginate();
122
            }
123
        }
124
125
        $this->prepared = true;
126
    }
127
128
    /**
129
     * Skip total records and set the recordsTotal equals to recordsFiltered.
130
     * This will improve the performance by skipping the total count query.
131
     *
132
     * @return $this
133
     */
134
    public function skipTotalRecords()
135
    {
136
        $this->skipTotalRecords = true;
137
138
        return $this;
139
    }
140
141
    /**
142
     * Keep the select bindings.
143
     *
144
     * @return $this
145
     */
146
    public function keepSelectBindings()
147
    {
148
        $this->keepSelectBindings = true;
149
150
        return $this;
151
    }
152
153
    /**
154
     * Count total items.
155
     *
156
     * @return int
157
     */
158
    public function totalCount()
159
    {
160
        if ($this->skipTotalRecords) {
161
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type declared by the interface Yajra\DataTables\Contracts\DataTable::totalCount of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
162
        }
163
164
        return $this->totalRecords ? $this->totalRecords : $this->count();
165
    }
166
167
    /**
168
     * Count filtered items.
169
     *
170
     * @return int
171
     */
172
    protected function filteredCount()
173
    {
174
        $this->filteredRecords = $this->filteredRecords ?: $this->count();
175
        if ($this->skipTotalRecords) {
176
            $this->totalRecords = $this->filteredRecords;
177
        }
178
179
        return $this->filteredRecords;
180
    }
181
182
    /**
183
     * Counts current query.
184
     *
185
     * @return int
186
     */
187
    public function count()
188
    {
189
        $builder = $this->prepareCountQuery();
190
        $table   = $this->connection->raw('(' . $builder->toSql() . ') count_row_table');
191
192
        return $this->connection->table($table)
193
                                ->setBindings($builder->getBindings())
194
                                ->count();
195
    }
196
197
    /**
198
     * Prepare count query builder.
199
     *
200
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
201
     */
202
    protected function prepareCountQuery()
203
    {
204
        $builder = clone $this->query;
205
206
        if (! $this->isComplexQuery($builder)) {
207
            $row_count = $this->wrap('row_count');
208
            $builder->select($this->connection->raw("'1' as {$row_count}"));
209
            if (! $this->keepSelectBindings) {
210
                $builder->setBindings([], 'select');
211
            }
212
        }
213
214
        return $builder;
215
    }
216
217
    /**
218
     * Check if builder query uses complex sql.
219
     *
220
     * @param \Illuminate\Database\Query\Builder $builder
221
     * @return bool
222
     */
223
    protected function isComplexQuery($builder)
224
    {
225
        return Str::contains(Str::lower($builder->toSql()), ['union', 'having', 'distinct', 'order by', 'group by']);
226
    }
227
228
    /**
229
     * Wrap column with DB grammar.
230
     *
231
     * @param string $column
232
     * @return string
233
     */
234
    protected function wrap($column)
235
    {
236
        return $this->connection->getQueryGrammar()->wrap($column);
237
    }
238
239
    /**
240
     * Get paginated results.
241
     *
242
     * @return \Illuminate\Support\Collection
243
     */
244
    public function results()
245
    {
246
        return $this->query->get();
247
    }
248
249
    /**
250
     * Get filtered, ordered and paginated query.
251
     *
252
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
253
     */
254
    public function getFilteredQuery()
255
    {
256
        $this->prepareQuery();
257
258
        return $this->getQuery();
259
    }
260
261
    /**
262
     * Get query builder instance.
263
     *
264
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
265
     */
266
    public function getQuery()
267
    {
268
        return $this->query;
269
    }
270
271
    /**
272
     * Perform column search.
273
     *
274
     * @return void
275
     */
276
    public function columnSearch()
277
    {
278
        $columns = $this->request->columns();
279
280
        foreach ($columns as $index => $column) {
281
            $column = $this->getColumnName($index);
282
283
            if (! $this->request->isColumnSearchable($index) || $this->isBlacklisted($column) && ! $this->hasFilterColumn($column)) {
284
                continue;
285
            }
286
287
            if ($this->hasFilterColumn($column)) {
288
                $keyword = $this->getColumnSearchKeyword($index, $raw = true);
289
                $this->applyFilterColumn($this->getBaseQueryBuilder(), $column, $keyword);
290
            } else {
291
                $column  = $this->resolveRelationColumn($column);
292
                $keyword = $this->getColumnSearchKeyword($index);
293
                $this->compileColumnSearch($index, $column, $keyword);
294
            }
295
296
            $this->isFilterApplied = true;
297
        }
298
    }
299
300
    /**
301
     * Check if column has custom filter handler.
302
     *
303
     * @param  string $columnName
304
     * @return bool
305
     */
306
    public function hasFilterColumn($columnName)
307
    {
308
        return isset($this->columnDef['filter'][$columnName]);
309
    }
310
311
    /**
312
     * Get column keyword to use for search.
313
     *
314
     * @param int  $i
315
     * @param bool $raw
316
     * @return string
317
     */
318
    protected function getColumnSearchKeyword($i, $raw = false)
319
    {
320
        $keyword = $this->request->columnKeyword($i);
321
        if ($raw || $this->request->isRegex($i)) {
322
            return $keyword;
323
        }
324
325
        return $this->setupKeyword($keyword);
326
    }
327
328
    /**
329
     * Apply filterColumn api search.
330
     *
331
     * @param mixed  $query
332
     * @param string $columnName
333
     * @param string $keyword
334
     * @param string $boolean
335
     */
336
    protected function applyFilterColumn($query, $columnName, $keyword, $boolean = 'and')
337
    {
338
        $query    = $this->getBaseQueryBuilder($query);
339
        $callback = $this->columnDef['filter'][$columnName]['method'];
340
341
        if ($this->query instanceof EloquentBuilder) {
0 ignored issues
show
Bug introduced by
The class Illuminate\Database\Eloquent\Builder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
342
            $builder = $this->query->newModelInstance()->newQuery();
343
        } else {
344
            $builder = $this->query->newQuery();
345
        }
346
347
        $callback($builder, $keyword);
348
349
        $query->addNestedWhereQuery($this->getBaseQueryBuilder($builder), $boolean);
350
    }
351
352
    /**
353
     * Get the base query builder instance.
354
     *
355
     * @param mixed $instance
356
     * @return \Illuminate\Database\Query\Builder
357
     */
358
    protected function getBaseQueryBuilder($instance = null)
359
    {
360
        if (! $instance) {
361
            $instance = $this->query;
362
        }
363
364
        if ($instance instanceof EloquentBuilder) {
0 ignored issues
show
Bug introduced by
The class Illuminate\Database\Eloquent\Builder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
365
            return $instance->getQuery();
366
        }
367
368
        return $instance;
369
    }
370
371
    /**
372
     * Resolve the proper column name be used.
373
     *
374
     * @param string $column
375
     * @return string
376
     */
377
    protected function resolveRelationColumn($column)
378
    {
379
        return $column;
380
    }
381
382
    /**
383
     * Compile queries for column search.
384
     *
385
     * @param int    $i
386
     * @param string $column
387
     * @param string $keyword
388
     */
389
    protected function compileColumnSearch($i, $column, $keyword)
390
    {
391
        if ($this->request->isRegex($i)) {
392
            $column = strstr($column, '(') ? $this->connection->raw($column) : $column;
393
            $this->regexColumnSearch($column, $keyword);
394
        } else {
395
            $this->compileQuerySearch($this->query, $column, $keyword, '');
396
        }
397
    }
398
399
    /**
400
     * Compile regex query column search.
401
     *
402
     * @param mixed  $column
403
     * @param string $keyword
404
     */
405
    protected function regexColumnSearch($column, $keyword)
406
    {
407
        switch ($this->connection->getDriverName()) {
408
            case 'oracle':
409
                $sql = ! $this->config->isCaseInsensitive()
410
                    ? 'REGEXP_LIKE( ' . $column . ' , ? )'
411
                    : 'REGEXP_LIKE( LOWER(' . $column . ') , ?, \'i\' )';
412
                break;
413
414
            case 'pgsql':
415
                $column = $this->castColumn($column);
416
                $sql    = ! $this->config->isCaseInsensitive() ? $column . ' ~ ?' : $column . ' ~* ? ';
417
                break;
418
419
            default:
420
                $sql = ! $this->config->isCaseInsensitive()
421
                    ? $column . ' REGEXP ?'
422
                    : 'LOWER(' . $column . ') REGEXP ?';
423
                $keyword = Str::lower($keyword);
424
        }
425
426
        $this->query->whereRaw($sql, [$keyword]);
427
    }
428
429
    /**
430
     * Wrap a column and cast based on database driver.
431
     *
432
     * @param  string $column
433
     * @return string
434
     */
435
    protected function castColumn($column)
436
    {
437
        switch ($this->connection->getDriverName()) {
438
            case 'pgsql':
439
                return 'CAST(' . $column . ' as TEXT)';
440
            case 'firebird':
441
                return 'CAST(' . $column . ' as VARCHAR(255))';
442
            default:
443
                return $column;
444
        }
445
    }
446
447
    /**
448
     * Compile query builder where clause depending on configurations.
449
     *
450
     * @param mixed  $query
451
     * @param string $column
452
     * @param string $keyword
453
     * @param string $boolean
454
     */
455
    protected function compileQuerySearch($query, $column, $keyword, $boolean = 'or')
456
    {
457
        $column = $this->addTablePrefix($query, $column);
458
        $column = $this->castColumn($column);
459
        $sql    = $column . ' LIKE ?';
460
461
        if ($this->config->isCaseInsensitive()) {
462
            $sql = 'LOWER(' . $column . ') LIKE ?';
463
        }
464
465
        $query->{$boolean . 'WhereRaw'}($sql, [$this->prepareKeyword($keyword)]);
466
    }
467
468
    /**
469
     * Patch for fix about ambiguous field.
470
     * Ambiguous field error will appear when query use join table and search with keyword.
471
     *
472
     * @param mixed  $query
473
     * @param string $column
474
     * @return string
475
     */
476
    protected function addTablePrefix($query, $column)
477
    {
478
        if (strpos($column, '.') === false) {
479
            $q = $this->getBaseQueryBuilder($query);
480
            if (! $q->from instanceof Expression) {
0 ignored issues
show
Bug introduced by
The class Illuminate\Database\Query\Expression does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
481
                $column = $q->from . '.' . $column;
482
            }
483
        }
484
485
        return $this->wrap($column);
486
    }
487
488
    /**
489
     * Prepare search keyword based on configurations.
490
     *
491
     * @param string $keyword
492
     * @return string
493
     */
494
    protected function prepareKeyword($keyword)
495
    {
496
        if ($this->config->isCaseInsensitive()) {
497
            $keyword = Str::lower($keyword);
498
        }
499
500
        if ($this->config->isWildcard()) {
501
            $keyword = Helper::wildcardLikeString($keyword);
502
        }
503
504
        if ($this->config->isSmartSearch()) {
505
            $keyword = "%$keyword%";
506
        }
507
508
        return $keyword;
509
    }
510
511
    /**
512
     * Add custom filter handler for the give column.
513
     *
514
     * @param string   $column
515
     * @param callable $callback
516
     * @return $this
517
     */
518
    public function filterColumn($column, callable $callback)
519
    {
520
        $this->columnDef['filter'][$column] = ['method' => $callback];
521
522
        return $this;
523
    }
524
525
    /**
526
     * Order each given columns versus the given custom sql.
527
     *
528
     * @param array  $columns
529
     * @param string $sql
530
     * @param array  $bindings
531
     * @return $this
532
     */
533
    public function orderColumns(array $columns, $sql, $bindings = [])
534
    {
535
        foreach ($columns as $column) {
536
            $this->orderColumn($column, str_replace(':column', $column, $sql), $bindings);
537
        }
538
539
        return $this;
540
    }
541
542
    /**
543
     * Override default column ordering.
544
     *
545
     * @param string $column
546
     * @param string $sql
547
     * @param array  $bindings
548
     * @return $this
549
     * @internal string $1 Special variable that returns the requested order direction of the column.
550
     */
551
    public function orderColumn($column, $sql, $bindings = [])
552
    {
553
        $this->columnDef['order'][$column] = compact('sql', 'bindings');
554
555
        return $this;
556
    }
557
558
    /**
559
     * Set datatables to do ordering with NULLS LAST option.
560
     *
561
     * @return $this
562
     */
563
    public function orderByNullsLast()
564
    {
565
        $this->nullsLast = true;
566
567
        return $this;
568
    }
569
570
    /**
571
     * Paginate dataTable using limit without offset
572
     * with additional where clause via callback.
573
     *
574
     * @param callable $callback
575
     * @return $this
576
     */
577
    public function limit(callable $callback)
578
    {
579
        $this->limitCallback = $callback;
580
581
        return $this;
582
    }
583
584
    /**
585
     * Perform pagination.
586
     *
587
     * @return void
588
     */
589
    public function paging()
590
    {
591
        $limit = (int) $this->request->input('length') > 0 ? $this->request->input('length') : 10;
592
        if (is_callable($this->limitCallback)) {
593
            $this->query->limit($limit);
594
            call_user_func_array($this->limitCallback, [$this->query]);
595
        } else {
596
            $this->query->skip($this->request->input('start'))->take($limit);
597
        }
598
    }
599
600
    /**
601
     * Add column in collection.
602
     *
603
     * @param string          $name
604
     * @param string|callable $content
605
     * @param bool|int        $order
606
     * @return $this
607
     */
608
    public function addColumn($name, $content, $order = false)
609
    {
610
        $this->pushToBlacklist($name);
611
612
        return parent::addColumn($name, $content, $order);
613
    }
614
615
    /**
616
     * Resolve callback parameter instance.
617
     *
618
     * @return \Illuminate\Database\Query\Builder
619
     */
620
    protected function resolveCallbackParameter()
621
    {
622
        return $this->query;
623
    }
624
625
    /**
626
     * Perform default query orderBy clause.
627
     */
628
    protected function defaultOrdering()
629
    {
630
        collect($this->request->orderableColumns())
631
            ->map(function ($orderable) {
632
                $orderable['name'] = $this->getColumnName($orderable['column'], true);
633
634
                return $orderable;
635
            })
636
            ->reject(function ($orderable) {
637
                return $this->isBlacklisted($orderable['name']) && ! $this->hasOrderColumn($orderable['name']);
638
            })
639
            ->each(function ($orderable) {
640
                $column = $this->resolveRelationColumn($orderable['name']);
641
642
                if ($this->hasOrderColumn($column)) {
643
                    $this->applyOrderColumn($column, $orderable);
644
                } else {
645
                    $nullsLastSql = $this->getNullsLastSql($column, $orderable['direction']);
646
                    $normalSql = $this->wrap($column) . ' ' . $orderable['direction'];
647
                    $sql = $this->nullsLast ? $nullsLastSql : $normalSql;
648
                    $this->query->orderByRaw($sql);
649
                }
650
            });
651
    }
652
653
    /**
654
     * Check if column has custom sort handler.
655
     *
656
     * @param string $column
657
     * @return bool
658
     */
659
    protected function hasOrderColumn($column)
660
    {
661
        return isset($this->columnDef['order'][$column]);
662
    }
663
664
    /**
665
     * Apply orderColumn custom query.
666
     *
667
     * @param string $column
668
     * @param array  $orderable
669
     */
670
    protected function applyOrderColumn($column, $orderable)
671
    {
672
        $sql      = $this->columnDef['order'][$column]['sql'];
673
        $sql      = str_replace('$1', $orderable['direction'], $sql);
674
        $bindings = $this->columnDef['order'][$column]['bindings'];
675
        $this->query->orderByRaw($sql, $bindings);
676
    }
677
678
    /**
679
     * Get NULLS LAST SQL.
680
     *
681
     * @param  string $column
682
     * @param  string $direction
683
     * @return string
684
     */
685
    protected function getNullsLastSql($column, $direction)
686
    {
687
        $sql = $this->config->get('datatables.nulls_last_sql', '%s %s NULLS LAST');
688
689
        return sprintf($sql, $column, $direction);
690
    }
691
692
    /**
693
     * Perform global search for the given keyword.
694
     *
695
     * @param string $keyword
696
     */
697
    protected function globalSearch($keyword)
698
    {
699
        $this->query->where(function ($query) use ($keyword) {
700
            collect($this->request->searchableColumnIndex())
701
                ->map(function ($index) {
702
                    return $this->getColumnName($index);
703
                })
704
                ->reject(function ($column) {
705
                    return $this->isBlacklisted($column) && ! $this->hasFilterColumn($column);
706
                })
707
                ->each(function ($column) use ($keyword, $query) {
708
                    if ($this->hasFilterColumn($column)) {
709
                        $this->applyFilterColumn($query, $column, $keyword, 'or');
710
                    } else {
711
                        $this->compileQuerySearch($query, $column, $keyword);
712
                    }
713
714
                    $this->isFilterApplied = true;
715
                });
716
        });
717
    }
718
719
    /**
720
     * Append debug parameters on output.
721
     *
722
     * @param  array $output
723
     * @return array
724
     */
725
    protected function showDebugger(array $output)
726
    {
727
        $query_log = $this->connection->getQueryLog();
728
        array_walk_recursive($query_log, function (&$item, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

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

Loading history...
729
            $item = utf8_encode($item);
730
        });
731
732
        $output['queries'] = $query_log;
733
        $output['input']   = $this->request->all();
734
735
        return $output;
736
    }
737
738
    /**
739
     * Attach custom with meta on response.
740
     *
741
     * @param array $data
742
     * @return array
743
     */
744
    protected function attachAppends(array $data)
745
    {
746
        $appends = [];
747
        foreach ($this->appends as $key => $value) {
748
            if (is_callable($value)) {
749
                $appends[$key] = value($value($this->getFilteredQuery()));
750
            } else {
751
                $appends[$key] = $value;
752
            }
753
        }
754
755
        return array_merge($data, $appends);
756
    }
757
}
758