Completed
Push — devops/catch-breaking-changes-... ( 88c9a6 )
by Bas
28s queued 18s
created

addWhereCountQuery()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 6
c 2
b 0
f 0
dl 0
loc 14
ccs 5
cts 5
cp 1
rs 10
cc 2
nc 1
nop 4
crap 2
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Eloquent\Concerns;
4
5
use Illuminate\Database\Eloquent\Builder as IlluminateBuilder;
6
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
7
use Illuminate\Database\Query\Expression;
8
use Illuminate\Support\Str;
9
use LaravelFreelancerNL\Aranguent\Query\Builder as QueryBuilder;
10
use LaravelFreelancerNL\FluentAQL\Expressions\FunctionExpression;
11
use LaravelFreelancerNL\FluentAQL\QueryBuilder as ArangoQueryBuilder;
12
13
trait QueriesAranguentRelationships
14
{
15
    /**
16
     * Add a sub-query count clause to this query.
17
     *
18
     * @param  QueryBuilder  $query
19
     * @param  string  $operator
20
     * @param  int  $count
21
     * @param  string  $boolean
22
     * @return IlluminateBuilder
23
     */
24 1
    protected function addWhereCountQuery(
25
        IlluminateQueryBuilder $query,
26
        $operator = '>=',
27
        $count = 1,
28
        $boolean = 'and'
29
    ): IlluminateBuilder {
30
31 1
        $query->grammar->compileSelect($query);
32
33 1
        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

33
        return $this->/** @scrutinizer ignore-call */ where(
Loading history...
34 1
            $query->aqb->count($query->aqb),
35
            $operator,
36 1
            is_numeric($count) ? new Expression($count) : $count,
0 ignored issues
show
introduced by
The condition is_numeric($count) is always true.
Loading history...
37
            $boolean
38
        );
39
    }
40
41
42
    /**
43
     * Add subselect queries to include an aggregate value for a relationship.
44
     * Overrides method in QueriesRelationships trait
45
     *
46
     * @param  mixed  $relations
47
     * @param  string|null  $column
48
     * @param  string  $function
49
     * @return $this
50
     */
51 90
    public function withAggregate($relations, $column, $function = null)
52
    {
53 90
        $result = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
54
55 90
        if (empty($relations)) {
56 90
            return $this;
57
        }
58
59 1
        if (is_null($this->query->columns)) {
60 1
            $this->query->select([$this->query->from . '.*']);
61
        }
62
63 1
        $relations = is_array($relations) ? $relations : [$relations];
64
65 1
        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

65
        foreach ($this->/** @scrutinizer ignore-call */ parseWithRelations($relations) as $name => $constraints) {
Loading history...
66
            // First we will determine if the name has been aliased using an "as" clause on the name
67
            // and if it has we will extract the actual relationship name and the desired name of
68
            // the resulting column. This allows multiple aggregates on the same relationships.
69 1
            $segments = explode(' ', $name);
70
71 1
            unset($alias);
72
73 1
            if (count($segments) === 3 && Str::lower($segments[1]) === 'as') {
74
                [$name, $alias] = [$segments[0], $segments[2]];
75
            }
76
77 1
            $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

77
            /** @scrutinizer ignore-call */ 
78
            $relation = $this->getRelationWithoutConstraints($name);
Loading history...
78
79
            // Here, we will grab the relationship sub-query and prepare to add it to the main query
80
            // as a sub-select. First, we'll get the "has" query and use that to get the relation
81
            // sub-query. We'll format this relationship name and append this column if needed.
82 1
            $query = $relation->getRelationExistenceQuery(
83 1
                $relation->getRelated()->newQuery(),
84
                $this
85
            );
86
87 1
            $query->callScope($constraints);
88
89 1
            $query = $query->mergeConstraintsFrom($relation->getQuery())->toBase();
90
91
            // If the query contains certain elements like orderings / more than one column selected
92
            // then we will remove those elements from the query so that it will execute properly
93
            // when given to the database. Otherwise, we may receive SQL errors or poor syntax.
94 1
            $query->orders = null;
95
96 1
            if (count($query->columns) > 1) {
97
                $query->columns = [$query->columns[0]];
98
                $query->bindings['select'] = [];
99
            }
100
101 1
            $result = $this->getAggregateResultQuery($query, $function);
0 ignored issues
show
Bug introduced by
It seems like $function can also be of type null; however, parameter $function of LaravelFreelancerNL\Aran...tAggregateResultQuery() 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

101
            $result = $this->getAggregateResultQuery($query, /** @scrutinizer ignore-type */ $function);
Loading history...
102
103
            // Finally, we will make the proper column alias to the query and run this sub-select on
104
            // the query builder. Then, we will return the builder instance back to the developer
105
            // for further constraint chaining that needs to take place on the query as needed.
106 1
            $alias = $alias ?? Str::snake(
107 1
                preg_replace('/[^[:alnum:][:space:]_]/u', '', "$name $function $column")
108
            );
109
110
            /** @phpstan-ignore-next-line */
111 1
            $this->selectSub(
0 ignored issues
show
Bug introduced by
It seems like selectSub() 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

111
            $this->/** @scrutinizer ignore-call */ 
112
                   selectSub(
Loading history...
112
                $result,
113
                $alias
114
            );
115
        }
116
117 1
        return $this;
118
    }
119
120 1
    protected function getAggregateResultQuery(QueryBuilder $query, string $function): QueryBuilder|FunctionExpression
121
    {
122 1
        if ($function) {
123 1
            $query->grammar->compileSelect($query);
124 1
            $result = (new ArangoQueryBuilder())->$function($query->aqb);
125
        }
126 1
        if (! $function) {
127
            $query->limit(1);
128
            $result = $query;
129
        }
130
131 1
        return $result;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.
Loading history...
132
    }
133
}
134