Passed
Push — feature/improved-search-alias-... ( 5f1fd6...88fb3e )
by Bas
03:32 queued 16s
created

BuildsSelects::selectSub()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
6
7
use Exception;
8
use Illuminate\Database\Eloquent\Builder as IlluminateEloquentBuilder;
9
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
10
use Illuminate\Database\Query\Expression;
11
use InvalidArgumentException;
12
use LaravelFreelancerNL\Aranguent\Query\Grammar;
13
14
trait BuildsSelects
15
{
16
    /**
17
     * Set the table which the query is targeting.
18
     *
19
     * @param \Closure|IlluminateQueryBuilder|string $table
20
     * @param string|null $as
21
     * @return IlluminateQueryBuilder
22
     */
23 258
    public function from($table, $as = null)
24
    {
25 258
        if ($this->isQueryable($table) && $as !== null) {
0 ignored issues
show
Bug introduced by
It seems like isQueryable() 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

25
        if ($this->/** @scrutinizer ignore-call */ isQueryable($table) && $as !== null) {
Loading history...
26
            return $this->fromSub($table, $as);
0 ignored issues
show
Bug introduced by
The method fromSub() does not exist on LaravelFreelancerNL\Aran...\Concerns\BuildsSelects. Did you maybe mean from()? ( Ignorable by Annotation )

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

26
            return $this->/** @scrutinizer ignore-call */ fromSub($table, $as);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
27
        }
28
29
        assert(is_string($table));
30
31 258
        $this->registerTableAlias($table, $as);
0 ignored issues
show
Bug introduced by
It seems like registerTableAlias() 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
               registerTableAlias($table, $as);
Loading history...
32
33 258
        $this->from = $table;
0 ignored issues
show
Bug Best Practice introduced by
The property from does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
34
35 258
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type LaravelFreelancerNL\Aran...\Concerns\BuildsSelects which is incompatible with the documented return type Illuminate\Database\Query\Builder.
Loading history...
36
    }
37
38
    /**
39
     * Set the table which the query is targeting.
40
     *
41
     * @param array<mixed> $options
42
     *
43
     * @return IlluminateQueryBuilder
44
     */
45 1
    public function fromOptions($options)
46
    {
47
48 1
        $boundOptions = [];
49 1
        foreach ($options as $key => $option) {
50 1
            $boundOptions[$key]  = $this->bindValue($option, 'fromOptions');
0 ignored issues
show
Bug introduced by
It seems like bindValue() 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

50
            /** @scrutinizer ignore-call */ 
51
            $boundOptions[$key]  = $this->bindValue($option, 'fromOptions');
Loading history...
51
        }
52
53 1
        $this->fromOptions = $boundOptions;
0 ignored issues
show
Bug Best Practice introduced by
The property fromOptions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
54
55 1
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type LaravelFreelancerNL\Aran...\Concerns\BuildsSelects which is incompatible with the documented return type Illuminate\Database\Query\Builder.
Loading history...
56
    }
57
58
    /**
59
     * Set the columns to be selected.
60
     *
61
     * @param array<mixed>|mixed $columns
62
     * @return IlluminateQueryBuilder
63
     * @throws Exception
64
     */
65 75
    public function select($columns = ['*']): IlluminateQueryBuilder
66
    {
67 75
        $this->columns = [];
0 ignored issues
show
Bug Best Practice introduced by
The property columns does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
68 75
        $this->bindings['select'] = [];
0 ignored issues
show
Bug Best Practice introduced by
The property bindings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
69
70 75
        $columns = is_array($columns) ? $columns : func_get_args();
71
72 75
        foreach ($columns as $as => $column) {
73 75
            if (is_string($as) && $this->isQueryable($column)) {
74 1
                $this->selectSub($column, $as);
75 1
                continue;
76
            }
77
78 75
            $this->addColumns([$as => $column]);
79
        }
80
81 75
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type LaravelFreelancerNL\Aran...\Concerns\BuildsSelects which is incompatible with the type-hinted return Illuminate\Database\Query\Builder.
Loading history...
82
    }
83
84
    /**
85
     * Add a subselect expression to the query.
86
     *
87
     * @param \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder|string $query
88
     * @param string $as
89
     * @return $this
90
     *
91
     * @throws \InvalidArgumentException
92
     * @throws Exception
93
     */
94 1
    public function selectSub($query, $as)
95
    {
96 1
        [$query] = $this->createSub($query, true);
0 ignored issues
show
Bug introduced by
It seems like createSub() 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

96
        /** @scrutinizer ignore-call */ 
97
        [$query] = $this->createSub($query, true);
Loading history...
97
98 1
        $this->set($as, new Expression($query), '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

98
        $this->/** @scrutinizer ignore-call */ 
99
               set($as, new Expression($query), 'postIterationVariables');
Loading history...
99
100 1
        $this->addColumns([$as]);
101
102 1
        return $this;
103
    }
104
105
    /**
106
     * Add a new select column to the query.
107
     *
108
     * @param array|mixed $column
109
     * @return $this
110
     */
111 18
    public function addSelect($column)
112
    {
113 18
        $columns = is_array($column) ? $column : func_get_args();
114
115 18
        $this->addColumns($columns);
116
117 18
        return $this;
118
    }
119
120
    /**
121
     * @param array<mixed> $columns
122
     */
123 88
    protected function addColumns(array $columns): void
124
    {
125 88
        foreach ($columns as $as => $column) {
126 88
            if (is_string($as) && $this->isQueryable($column)) {
127
                if (empty($this->columns)) {
128
                    $this->select($this->from . '.*');
129
                }
130
131
                $this->selectSub($column, $as);
132
133
                continue;
134
            }
135
136 88
            if (is_string($as)) {
137 2
                $this->columns[$as] = $column;
0 ignored issues
show
Bug Best Practice introduced by
The property columns does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
138
139 2
                continue;
140
            }
141
142 88
            $this->columns[] = $column;
143
        }
144
    }
145
146
    /**
147
     * Add an "order by" clause to the query.
148
     *
149
     * @param \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder|Expression|string $column
150
     * @param string $direction
151
     * @return $this
152
     *
153
     * @throws \InvalidArgumentException
154
     */
155 33
    public function orderBy($column, $direction = 'asc')
156
    {
157 33
        if ($this->isQueryable($column)) {
158
            assert(!$column instanceof Expression);
159
            [$query, $bindings] = $this->createSub($column);
160
161
            $column = new Expression('(' . $query . ')');
162
163
            $this->addBinding($bindings, $this->unions ? 'unionOrder' : 'order');
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

163
            $this->/** @scrutinizer ignore-call */ 
164
                   addBinding($bindings, $this->unions ? 'unionOrder' : 'order');
Loading history...
164
        }
165
166 33
        $direction = strtoupper($direction);
167
168 33
        if (!in_array($direction, ['ASC', 'DESC'], true)) {
169
            throw new InvalidArgumentException('Order direction must be "asc" or "desc".');
170
        }
171
172 33
        $this->{$this->unions ? 'unionOrders' : 'orders'}[] = [
173 33
            'column' => $column,
174 33
            'direction' => $direction,
175 33
        ];
176
177 33
        return $this;
178
    }
179
180
    /**
181
     * @param string $aql
182
     * @param array<mixed> $bindings
183
     * @return $this
184
     */
185 3
    public function orderByRaw($aql, $bindings = [])
186
    {
187 3
        $type = 'Raw';
188
189 3
        $sql = new Expression($aql);
190
191 3
        $this->{$this->unions ? 'unionOrders' : 'orders'}[] = compact('type', 'sql');
192
193 3
        if (!isset($this->bindings[$this->unions ? 'unionOrders' : 'orders'])) {
194 3
            $this->bindings[$this->unions ? 'unionOrders' : 'orders'] = $bindings;
0 ignored issues
show
Bug Best Practice introduced by
The property bindings does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
195
196 3
            return $this;
197
        }
198
199
        $this->bindings[$this->unions ? 'unionOrders' : 'orders'] = array_merge(
200
            $this->bindings[$this->unions ? 'unionOrders' : 'orders'],
201
            $bindings
202
        );
203
204
        return $this;
205
    }
206
207
    /**
208
     * Put the query's results in random order.
209
     *
210
     * @param string $seed
211
     * @return $this
212
     */
213 1
    public function inRandomOrder($seed = '')
214
    {
215
        assert($this->grammar instanceof Grammar);
216
217
        // ArangoDB's random function doesn't accept a seed.
218 1
        unset($seed);
219
220 1
        return $this->orderByRaw($this->grammar->compileRandom());
221
    }
222
223
    /**
224
     * Add a union statement to the query.
225
     *
226
     * @param  \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder $query
227
     * @param  bool  $all
228
     * @return $this
229
     *
230
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
231
     */
232 5
    public function union($query, $all = false)
233
    {
234 5
        if ($query instanceof \Closure) {
235
            $query($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

235
            $query($query = $this->/** @scrutinizer ignore-call */ newQuery());
Loading history...
236
        }
237
238 5
        if ($query instanceof IlluminateEloquentBuilder) {
239
            $query = $query->getQuery();
240
        }
241
242 5
        $this->importBindings($query);
0 ignored issues
show
Bug introduced by
It seems like importBindings() 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

242
        $this->/** @scrutinizer ignore-call */ 
243
               importBindings($query);
Loading history...
243 5
        $this->unions[] = compact('query', 'all');
0 ignored issues
show
Bug Best Practice introduced by
The property unions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
244
245 5
        return $this;
246
    }
247
}
248