Passed
Pull Request — next (#84)
by Bas
15:17 queued 11:12
created

BuildsGroups   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Test Coverage

Coverage 88.24%

Importance

Changes 0
Metric Value
eloc 60
c 0
b 0
f 0
dl 0
loc 208
ccs 60
cts 68
cp 0.8824
rs 10
wmc 21

9 Methods

Rating   Name   Duplication   Size   Complexity  
A cleanGroupVariables() 0 4 1
A groupBy() 0 10 2
A groupByRaw() 0 9 2
A forNestedWhere() 0 8 2
A havingRaw() 0 11 2
A addNestedHavingQuery() 0 11 2
A havingNested() 0 7 1
B having() 0 45 7
A havingBetween() 0 20 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
6
7
use Carbon\CarbonPeriod;
8
use Closure;
9
use Illuminate\Contracts\Database\Query\ConditionExpression;
10
use Illuminate\Database\Query\Builder;
11
use Illuminate\Database\Query\Expression;
12
use Illuminate\Support\Arr;
13
14
trait BuildsGroups
15
{
16
    /**
17
     * @var array<string>|null
18
     */
19
    public $groupVariables = null;
20
21
    /**
22
     * Add a "group by" clause to the query.
23
     *
24
     * @param array<mixed>|Expression|string ...$groups
25
     * @return $this
26
     */
27 10
    public function groupBy(...$groups)
28
    {
29 10
        foreach ($groups as $group) {
30 10
            $this->groups = array_merge(
0 ignored issues
show
Bug Best Practice introduced by
The property groups does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
31 10
                (array)$this->groups,
32 10
                Arr::wrap($group)
33 10
            );
34
        }
35
36 10
        return $this;
37
    }
38
39
    /**
40
     * Add a raw groupBy clause to the query.
41
     *
42
     * @param  string  $aql
43
     * @param  array<mixed>  $bindings
44
     * @return $this
45
     */
46 1
    public function groupByRaw($aql, array $bindings = [])
47
    {
48 1
        $this->groups[] = new Expression($aql);
0 ignored issues
show
Bug Best Practice introduced by
The property groups does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
49
50 1
        if (!empty($bindings)) {
51
            $this->addBinding($bindings, 'groupBy');
0 ignored issues
show
Bug introduced by
It seems like addBinding() 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

51
            $this->/** @scrutinizer ignore-call */ 
52
                   addBinding($bindings, 'groupBy');
Loading history...
52
        }
53
54 1
        return $this;
55
    }
56
57 10
    public function cleanGroupVariables(): void
58
    {
59 10
        $this->tableAliases = array_diff($this->tableAliases, $this->groupVariables ?? []);
0 ignored issues
show
Bug Best Practice introduced by
The property tableAliases does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
60 10
        $this->groupVariables = null;
61
    }
62
63
    /**
64
     * @param ConditionExpression|string $column
65
     * @param null|string $operator
66
     * @param $value
67
     * @param $boolean
68
     * @return $this|\LaravelFreelancerNL\Aranguent\Query\Builder
69
     */
70 3
    public function having($column, $operator = null, $value = null, $boolean = 'and')
71
    {
72 3
        $type = 'Basic';
73
74 3
        if ($column instanceof ConditionExpression) {
75
            $type = 'Expression';
76
77
            $this->havings[] = compact('type', 'column', 'boolean');
0 ignored issues
show
Bug Best Practice introduced by
The property havings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
78
79
            return $this;
80
        }
81
82
        // Here we will make some assumptions about the operator. If only 2 values are
83
        // passed to the method, we will assume that the operator is an equals sign
84
        // and keep going. Otherwise, we'll require the operator to be passed in.
85 3
        [$value, $operator] = $this->prepareValueAndOperator(
0 ignored issues
show
Bug introduced by
It seems like prepareValueAndOperator() 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

85
        /** @scrutinizer ignore-call */ 
86
        [$value, $operator] = $this->prepareValueAndOperator(
Loading history...
86 3
            $value,
87 3
            $operator,
88 3
            func_num_args() === 2
89 3
        );
90
91
        /** @phpstan-ignore-next-line  */
92 3
        if ($column instanceof Closure && is_null($operator)) {
0 ignored issues
show
introduced by
$column is never a sub-type of Closure.
Loading history...
93 1
            return $this->havingNested($column, $boolean);
94
        }
95
96
        // If the given operator is not found in the list of valid operators we will
97
        // assume that the developer is just short-cutting the '=' operators and
98
        // we will set the operators to '=' and set the values appropriately.
99 3
        if ($this->invalidOperator($operator)) {
0 ignored issues
show
Bug introduced by
It seems like invalidOperator() 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

99
        if ($this->/** @scrutinizer ignore-call */ invalidOperator($operator)) {
Loading history...
100
            [$value, $operator] = [$operator, '='];
101
        }
102
103 3
        if ($this->isBitwiseOperator($operator)) {
0 ignored issues
show
Bug introduced by
It seems like isBitwiseOperator() 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

103
        if ($this->/** @scrutinizer ignore-call */ isBitwiseOperator($operator)) {
Loading history...
104
            $type = 'Bitwise';
105
        }
106
107 3
        if (!$value instanceof Expression) {
108 3
            $this->addBinding($this->flattenValue($value), 'having');
0 ignored issues
show
Bug introduced by
It seems like flattenValue() 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->addBinding($this->/** @scrutinizer ignore-call */ flattenValue($value), 'having');
Loading history...
109 3
            $value = '@' . array_key_last($this->getBindings());
0 ignored issues
show
Bug introduced by
It seems like getBindings() 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

109
            $value = '@' . array_key_last($this->/** @scrutinizer ignore-call */ getBindings());
Loading history...
110
        }
111
112 3
        $this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean');
113
114 3
        return $this;
115
    }
116
117
    /**
118
     * Add a raw having clause to the query.
119
     *
120
     * @param  string  $sql
121
     * @param  array<mixed>  $bindings
122
     * @param  string  $boolean
123
     * @return $this
124
     */
125 1
    public function havingRaw($sql, array $bindings = [], $boolean = 'and')
126
    {
127 1
        $type = 'Raw';
128
129 1
        $this->havings[] = compact('type', 'sql', 'boolean');
0 ignored issues
show
Bug Best Practice introduced by
The property havings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
130
131 1
        if (!empty($bindings)) {
132
            $this->addBinding($bindings, 'having');
133
        }
134
135 1
        return $this;
136
    }
137
138
    /**
139
     * Create a new query instance for nested where condition.
140
     *
141
     * @param array<mixed> $aliases
142
     * @return Builder
143
     */
144 24
    public function forNestedWhere($aliases = [])
145
    {
146 24
        $query = $this->newQuery();
0 ignored issues
show
Bug introduced by
It seems like newQuery() 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

146
        /** @scrutinizer ignore-call */ 
147
        $query = $this->newQuery();
Loading history...
147 24
        foreach($aliases as $alias) {
148 1
            $query->groups[] = $alias;
149
150
        }
151 24
        return $query->from($this->from);
152
    }
153
154
    /**
155
     * Add a nested having statement to the query.
156
     *
157
     * @param  \Closure  $callback
158
     * @param  string  $boolean
159
     * @return $this
160
     */
161 1
    public function havingNested(Closure $callback, $boolean = 'and')
162
    {
163 1
        $callback($query = $this->forNestedWhere($this->groups));
164
165
166
167 1
        return $this->addNestedHavingQuery($query, $boolean);
168
    }
169
170
    /**
171
     * Add another query builder as a nested having to the query builder.
172
     *
173
     * @param  \Illuminate\Database\Query\Builder  $query
174
     * @param  string  $boolean
175
     * @return $this
176
     */
177 1
    public function addNestedHavingQuery($query, $boolean = 'and')
178
    {
179 1
        if (count($query->havings)) {
180 1
            $type = 'Nested';
181
182 1
            $this->havings[] = compact('type', 'query', 'boolean');
0 ignored issues
show
Bug Best Practice introduced by
The property havings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
183
184 1
            $this->mergeBindings($query);
0 ignored issues
show
Bug introduced by
It seems like mergeBindings() 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

184
            $this->/** @scrutinizer ignore-call */ 
185
                   mergeBindings($query);
Loading history...
185
        }
186
187 1
        return $this;
188
    }
189
190
191
    /**
192
     * Add a "having between " clause to the query.
193
     *
194
     * @param  string  $column
195
     * @param  iterable<mixed>  $values
196
     * @param  string  $boolean
197
     * @param  bool  $not
198
     * @return $this
199
     *
200
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
201
     */
202 1
    public function havingBetween($column, iterable $values, $boolean = 'and', $not = false)
203
    {
204 1
        $type = 'between';
205
206 1
        if ($values instanceof CarbonPeriod) {
207
            $values = [$values->start, $values->end];
208
        }
209
210
        assert(is_array($values));
211
212 1
        $bindings = array_slice($this->cleanBindings(Arr::flatten($values)), 0, 2);
0 ignored issues
show
Bug introduced by
It seems like cleanBindings() 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

212
        $bindings = array_slice($this->/** @scrutinizer ignore-call */ cleanBindings(Arr::flatten($values)), 0, 2);
Loading history...
213 1
        $this->addBinding($bindings[0], 'having');
214 1
        $values[0] = '@' . array_key_last($this->getBindings());
215
216 1
        $this->addBinding($bindings[1], 'having');
217 1
        $values[1] = '@' . array_key_last($this->getBindings());
218
219 1
        $this->havings[] = compact('type', 'column', 'values', 'boolean', 'not');
0 ignored issues
show
Bug Best Practice introduced by
The property havings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
220
221 1
        return $this;
222
    }
223
}
224