Failed Conditions
Push — refactor/improve-static-analys... ( ba8000...c6edde )
by Bas
14:06
created

mergeConstraintsFrom()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 11
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 18
rs 9.9
ccs 8
cts 8
cp 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Eloquent\Concerns;
6
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Database\Eloquent\Builder as IlluminateBuilder;
9
use Illuminate\Database\Eloquent\Builder as IlluminateEloquentBuilder;
10
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
11
use Illuminate\Database\Query\Expression;
12
use Illuminate\Support\Str;
13
use LaravelFreelancerNL\Aranguent\Query\Builder as QueryBuilder;
14
use LaravelFreelancerNL\FluentAQL\Expressions\FunctionExpression;
15
use LaravelFreelancerNL\FluentAQL\QueryBuilder as ArangoQueryBuilder;
16
17
trait QueriesAranguentRelationships
18
{
19
    /**
20
     * Add a sub-query count clause to this query.
21
     *
22
     * @param  \Illuminate\Database\Query\Builder  $query
23
     * @param  string  $operator
24 1
     * @param  int  $count
25
     * @param  string  $boolean
26
     * @return $this
27
     */
28
    protected function addWhereCountQuery(IlluminateQueryBuilder $query, $operator = '>=', $count = 1, $boolean = 'and')
29
    {
30
31 1
        $this->getQuery()->exchangeTableAliases($query);
0 ignored issues
show
Bug introduced by
It seems like getQuery() 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
        $this->/** @scrutinizer ignore-call */ 
32
               getQuery()->exchangeTableAliases($query);
Loading history...
32
33 1
        $this->getQuery()->importBindings($query);
34 1
35
        return $this->where(
0 ignored issues
show
Bug introduced by
It seems like where() 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

35
        return $this->/** @scrutinizer ignore-call */ where(
Loading history...
36 1
            new Expression('LENGTH(('.$query->toSql().'))'),
37
            $operator,
38
            is_numeric($count) ? new Expression($count) : $count,
0 ignored issues
show
introduced by
The condition is_numeric($count) is always true.
Loading history...
39
            $boolean
40
        );
41
    }
42
43
    /**
44
     * Merge the where constraints from another query to the current query.
45
     *
46
     * @param IlluminateEloquentBuilder $from
47
     * @return IlluminateEloquentBuilder|static
48
     */
49
    public function mergeConstraintsFrom(Builder $from)
50
    {
51 137
        $whereBindings = $this->getQuery()->getBindings() ?? [];
52
53 137
        $wheres = $from->getQuery()->from !== $this->getQuery()->from
54
            ? $this->requalifyWhereTables(
0 ignored issues
show
Bug introduced by
It seems like requalifyWhereTables() 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

54
            ? $this->/** @scrutinizer ignore-call */ requalifyWhereTables(
Loading history...
55 137
                $from->getQuery()->wheres,
56 137
                $from->getQuery()->grammar->getValue($from->getQuery()->from),
57
                $this->getModel()->getTable()
0 ignored issues
show
Bug introduced by
It seems like getModel() 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

57
                $this->/** @scrutinizer ignore-call */ 
58
                       getModel()->getTable()
Loading history...
58
            ) : $from->getQuery()->wheres;
59 1
60 1
        // Here we have some other query that we want to merge the where constraints from. We will
61
        // copy over any where constraints on the query as well as remove any global scopes the
62
        // query might have removed. Then we will return ourselves with the finished merging.
63 1
        return $this->withoutGlobalScopes(
0 ignored issues
show
Bug introduced by
It seems like withoutGlobalScopes() 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

63
        return $this->/** @scrutinizer ignore-call */ withoutGlobalScopes(
Loading history...
64
            $from->removedScopes()
65 1
        )->mergeWheres(
66
            $wheres, $whereBindings
67
        );
68
    }
69 1
70
    /**
71 1
     * Add subselect queries to include an aggregate value for a relationship.
72
     *
73 1
     * @param  mixed  $relations
74
     * @param  string  $column
75
     * @param  string  $function
76
     * @return $this
77 1
     */
78
    public function withAggregate($relations, $column, $function = null)
79
    {
80
        if (empty($relations)) {
81
            return $this;
82 1
        }
83 1
84
        if (is_null($this->query->columns)) {
85
            $this->query->select([$this->query->from.'.*']);
86
        }
87 1
88
        $relations = is_array($relations) ? $relations : [$relations];
89 1
90
        foreach ($this->parseWithRelations($relations) as $name => $constraints) {
0 ignored issues
show
Bug introduced by
It seems like parseWithRelations() 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
        foreach ($this->/** @scrutinizer ignore-call */ parseWithRelations($relations) as $name => $constraints) {
Loading history...
91
            // First we will determine if the name has been aliased using an "as" clause on the name
92
            // and if it has we will extract the actual relationship name and the desired name of
93
            // the resulting column. This allows multiple aggregates on the same relationships.
94 1
            $segments = explode(' ', $name);
95
96 1
            unset($alias);
97
98
            if (count($segments) === 3 && Str::lower($segments[1]) === 'as') {
99
                [$name, $alias] = [$segments[0], $segments[2]];
100
            }
101 1
102
            $relation = $this->getRelationWithoutConstraints($name);
0 ignored issues
show
Bug introduced by
It seems like getRelationWithoutConstraints() 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

102
            /** @scrutinizer ignore-call */ 
103
            $relation = $this->getRelationWithoutConstraints($name);
Loading history...
103
104
            if ($function) {
105
                $hashedColumn = $this->getRelationHashedColumn($column, $relation);
0 ignored issues
show
Bug introduced by
It seems like getRelationHashedColumn() 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

105
                /** @scrutinizer ignore-call */ 
106
                $hashedColumn = $this->getRelationHashedColumn($column, $relation);
Loading history...
106 1
107 1
                $wrappedColumn = $this->getQuery()->getGrammar()->wrap(
108
                    $column === '*' ? $column : $relation->getRelated()->qualifyColumn($hashedColumn)
109
                );
110
111 1
                $expression = $function === 'exists' ? $wrappedColumn : sprintf('%s(%s)', $function, $wrappedColumn);
112 1
            } else {
113
                $expression = $column;
114
            }
115
116
            // Here, we will grab the relationship sub-query and prepare to add it to the main query
117 1
            // as a sub-select. First, we'll get the "has" query and use that to get the relation
118
            // sub-query. We'll format this relationship name and append this column if needed.
119
            $query = $relation->getRelationExistenceQuery(
120 1
                $relation->getRelated()->newQuery(), $this, new Expression($expression)
121
            )->setBindings([], 'select');
122 1
123 1
            $query->callScope($constraints);
124 1
125
            $query = $query->mergeConstraintsFrom($relation->getQuery())->toBase();
126 1
127
            // If the query contains certain elements like orderings / more than one column selected
128
            // then we will remove those elements from the query so that it will execute properly
129
            // when given to the database. Otherwise, we may receive SQL errors or poor syntax.
130
            $query->orders = null;
131 1
            $query->setBindings([], 'order');
132
133
            if (count($query->columns) > 1) {
134
                $query->columns = [$query->columns[0]];
135
                $query->bindings['select'] = [];
136
            }
137
138
            // Finally, we will make the proper column alias to the query and run this sub-select on
139
            // the query builder. Then, we will return the builder instance back to the developer
140
            // for further constraint chaining that needs to take place on the query as needed.
141
            $alias ??= Str::snake(
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $alias seems to be defined later in this foreach loop on line 99. Are you sure it is defined here?
Loading history...
142
                preg_replace('/[^[:alnum:][:space:]_]/u', '', "$name $function $column")
143
            );
144
145
            if ($function === 'exists') {
146
                //FIXME: test for results from the subquery -> whereHas?
147
                $this->selectRaw(
0 ignored issues
show
Bug introduced by
It seems like selectRaw() 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

147
                $this->/** @scrutinizer ignore-call */ 
148
                       selectRaw(
Loading history...
148
                    sprintf('exists(%s) as %s', $query->toSql(), $this->getQuery()->grammar->wrap($alias)),
149
                    $query->getBindings()
150
                )->withCasts([$alias => 'bool']);
151
            } else {
152
                if ($function === null) {
153
                    $query->limit(1);
154
                }
155
156
                $this->getQuery()->exchangeTableAliases($query);
157
                $this->getQuery()->importBindings($query);
158
159
                $this->set($alias, new Expression(strtoupper($function).'(('.$query->toSql().'))'), 'postIterationVariables');
0 ignored issues
show
Bug introduced by
It seems like set() 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

159
                $this->/** @scrutinizer ignore-call */ 
160
                       set($alias, new Expression(strtoupper($function).'(('.$query->toSql().'))'), 'postIterationVariables');
Loading history...
160
                $this->addSelect($alias);
0 ignored issues
show
Bug introduced by
It seems like addSelect() 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

160
                $this->/** @scrutinizer ignore-call */ 
161
                       addSelect($alias);
Loading history...
161
            }
162
        }
163
164
        return $this;
165
    }
166
}
167