BuildsGroups::forNestedWhere()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 10
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...
Bug introduced by
$aql of type string is incompatible with the type Illuminate\Database\Query\TValue expected by parameter $value of Illuminate\Database\Quer...pression::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

48
        $this->groups[] = new Expression(/** @scrutinizer ignore-type */ $aql);
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
        // FIXME: check for possible expressions instead of strings.
60
        /* @phpstan-ignore-next-line */
61 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...
62 10
        $this->groupVariables = null;
63
    }
64
65
    /**
66
     * @param ConditionExpression|string $column
67
     * @param null|string $operator
68
     * @param $value
69
     * @param $boolean
70
     * @return $this|\LaravelFreelancerNL\Aranguent\Query\Builder
71
     */
72 3
    public function having($column, $operator = null, $value = null, $boolean = 'and')
73
    {
74 3
        $type = 'Basic';
75
76 3
        if ($column instanceof ConditionExpression) {
77
            $type = 'Expression';
78
79
            $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...
80
81
            return $this;
82
        }
83
84
        // Here we will make some assumptions about the operator. If only 2 values are
85
        // passed to the method, we will assume that the operator is an equals sign
86
        // and keep going. Otherwise, we'll require the operator to be passed in.
87 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

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

101
        if ($this->/** @scrutinizer ignore-call */ invalidOperator($operator)) {
Loading history...
102
            [$value, $operator] = [$operator, '='];
103
        }
104
105 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

105
        if ($this->/** @scrutinizer ignore-call */ isBitwiseOperator($operator)) {
Loading history...
106
            $type = 'Bitwise';
107
        }
108
109 3
        if (!$value instanceof Expression) {
110 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

110
            $this->addBinding($this->/** @scrutinizer ignore-call */ flattenValue($value), 'having');
Loading history...
111 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

111
            $value = '@' . array_key_last($this->/** @scrutinizer ignore-call */ getBindings());
Loading history...
112
        }
113
114 3
        $this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean');
115
116 3
        return $this;
117
    }
118
119
    /**
120
     * Add a raw having clause to the query.
121
     *
122
     * @param  string  $sql
123
     * @param  array<mixed>  $bindings
124
     * @param  string  $boolean
125
     * @return $this
126
     */
127 1
    public function havingRaw($sql, array $bindings = [], $boolean = 'and')
128
    {
129 1
        $type = 'Raw';
130
131 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...
132
133 1
        if (!empty($bindings)) {
134
            $this->addBinding($bindings, 'having');
135
        }
136
137 1
        return $this;
138
    }
139
140
    /**
141
     * Create a new query instance for nested where condition.
142
     *
143
     * @param array<mixed> $aliases
144
     * @return Builder
145
     */
146 40
    public function forNestedWhere($aliases = [])
147
    {
148 40
        $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

148
        /** @scrutinizer ignore-call */ 
149
        $query = $this->newQuery();
Loading history...
149 40
        foreach ($aliases as $alias) {
150 1
            $query->groups[] = $alias;
151
152
        }
153 40
        return $query->from((string) $this->grammar->getValue($this->from));
154
    }
155
156
    /**
157
     * Add a nested having statement to the query.
158
     *
159
     * @param  \Closure  $callback
160
     * @param  string  $boolean
161
     * @return $this
162
     */
163 1
    public function havingNested(Closure $callback, $boolean = 'and')
164
    {
165 1
        $callback($query = $this->forNestedWhere($this->groups ?? []));
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