Issues (68)

src/Traits/SearchesQueries.php (5 issues)

1
<?php
2
3
namespace Bakery\Traits;
4
5
use Bakery\Support\Arguments;
6
use Bakery\Eloquent\ModelSchema;
7
use Bakery\Support\TypeRegistry;
8
use Illuminate\Support\Facades\DB;
9
use Illuminate\Database\Connection;
10
use Illuminate\Database\Eloquent\Model;
11
use Illuminate\Database\Query\Grammars;
12
use Illuminate\Database\Eloquent\Builder;
13
14
/**
15
 * @property ModelSchema $modelSchema
16
 * @property TypeRegistry $registry
17
 */
18
trait SearchesQueries
19
{
20
    /**
21
     * Apply search on the query.
22
     *
23
     * @param \Illuminate\Database\Eloquent\Builder $query
24
     * @param Arguments $args
25
     * @return Builder
26
     */
27
    protected function applySearch(Builder $query, Arguments $args)
28
    {
29
        // If the query is empty, we don't need to perform any search.
30
        if (empty($args['query'])) {
31
            return $query;
32
        }
33
34
        /** @var Connection $connection */
35
        $connection = DB::connection();
36
37
        $this->tsFields = [];
0 ignored issues
show
Bug Best Practice introduced by
The property tsFields does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
38
39
        $needle = $args['query'];
40
        $fields = $args['fields'];
41
42
        $relations = $this->modelSchema->getRelationFields();
43
        $qualifiedNeedle = preg_quote($needle);
44
45
        foreach ($fields as $key => $value) {
46
            $field = $this->modelSchema->getFieldByKey($key);
47
            $accessor = $field->getAccessor();
48
            if ($relations->keys()->contains($key)) {
49
                $this->applyRelationalSearch($query, $this->model, $accessor, $needle, $value->toArray());
0 ignored issues
show
The property model does not exist on Bakery\Traits\SearchesQueries. Did you mean modelSchema?
Loading history...
It seems like $needle can also be of type null; however, parameter $needle of Bakery\Traits\SearchesQu...applyRelationalSearch() does only seem to accept string, 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

49
                $this->applyRelationalSearch($query, $this->model, $accessor, /** @scrutinizer ignore-type */ $needle, $value->toArray());
Loading history...
50
            } else {
51
                $this->tsFields[] = $this->model->getTable().'.'.$accessor;
52
            }
53
        }
54
55
        if (empty($needle) || empty($this->tsFields)) {
56
            return $query;
57
        }
58
59
        $grammar = $connection->getQueryGrammar();
60
61
        if ($grammar instanceof Grammars\PostgresGrammar) {
62
            $dictionary = config('bakery.postgresDictionary');
63
            $fields = implode(', ', $this->tsFields);
64
            $query->whereRaw("to_tsvector('${dictionary}', concat_ws(' ', ".$fields.")) @@ to_tsquery('${dictionary}', ?)",
65
                ["'{$qualifiedNeedle}':*"]);
66
        }
67
68
        return $query;
69
    }
70
71
    /**
72
     * Apply a relational search.
73
     *
74
     * @param \Illuminate\Database\Eloquent\Builder $query
75
     * @param \Illuminate\Database\Eloquent\Model $model
76
     * @param string $relation
77
     * @param string $needle
78
     * @param array $fields
79
     */
80
    protected function applyRelationalSearch(
81
        Builder $query,
82
        Model $model,
83
        string $relation,
84
        string $needle,
85
        array $fields
86
    ) {
87
        /** @var \Illuminate\Database\Eloquent\Relations\Relation $relation */
88
        $relation = $model->$relation();
89
        $related = $relation->getRelated();
90
        $this->joinRelation($query, $relation, 'left');
0 ignored issues
show
It seems like joinRelation() 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

90
        $this->/** @scrutinizer ignore-call */ 
91
               joinRelation($query, $relation, 'left');
Loading history...
91
92
        foreach ($fields as $key => $value) {
93
            $schema = $this->registry->getSchemaForModel($related);
94
95
            $relations = $schema->getRelationFields();
96
            if ($relations->keys()->contains($key)) {
97
                $this->applyRelationalSearch($query, $related, $key, $needle, $value);
98
            } else {
99
                $this->tsFields[] = $related->getTable().'.'.$key;
0 ignored issues
show
Bug Best Practice introduced by
The property tsFields does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
100
            }
101
        }
102
    }
103
}
104