Passed
Push — refactor/improve-static-analys... ( 9f92f2...5cc94f )
by Bas
13:59
created

BuildsSelects::from()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 13
ccs 5
cts 6
cp 0.8333
crap 3.0416
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 255
    public function from($table, $as = null)
24
    {
25 255
        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 255
        $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 255
        $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 255
        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 columns to be selected.
40
     *
41
     * @param array<mixed>|mixed $columns
42
     * @return IlluminateQueryBuilder
43
     * @throws Exception
44
     */
45 75
    public function select($columns = ['*']): IlluminateQueryBuilder
46
    {
47 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...
48 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...
49
50 75
        $columns = is_array($columns) ? $columns : func_get_args();
51
52 75
        foreach ($columns as $as => $column) {
53 75
            if (is_string($as) && $this->isQueryable($column)) {
54 1
                $this->selectSub($column, $as);
55 1
                continue;
56
            }
57
58 75
            $this->addColumns([$as => $column]);
59
        }
60
61 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...
62
    }
63
64
    /**
65
     * Add a subselect expression to the query.
66
     *
67
     * @param \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder|string $query
68
     * @param string $as
69
     * @return $this
70
     *
71
     * @throws \InvalidArgumentException
72
     * @throws Exception
73
     */
74 1
    public function selectSub($query, $as)
75
    {
76 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

76
        /** @scrutinizer ignore-call */ 
77
        [$query] = $this->createSub($query, true);
Loading history...
77
78 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

78
        $this->/** @scrutinizer ignore-call */ 
79
               set($as, new Expression($query), 'postIterationVariables');
Loading history...
79
80 1
        $this->addColumns([$as]);
81
82 1
        return $this;
83
    }
84
85
    /**
86
     * Add a new select column to the query.
87
     *
88
     * @param array|mixed $column
89
     * @return $this
90
     */
91 18
    public function addSelect($column)
92
    {
93 18
        $columns = is_array($column) ? $column : func_get_args();
94
95 18
        $this->addColumns($columns);
96
97 18
        return $this;
98
    }
99
100
    /**
101
     * @param array<mixed> $columns
102
     */
103 88
    protected function addColumns(array $columns): void
104
    {
105 88
        foreach ($columns as $as => $column) {
106 88
            if (is_string($as) && $this->isQueryable($column)) {
107
                if (empty($this->columns)) {
108
                    $this->select($this->from . '.*');
109
                }
110
111
                $this->selectSub($column, $as);
112
113
                continue;
114
            }
115
116 88
            if (is_string($as)) {
117 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...
118
119 2
                continue;
120
            }
121
122 88
            $this->columns[] = $column;
123
        }
124
    }
125
126
    /**
127
     * Add an "order by" clause to the query.
128
     *
129
     * @param \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder|Expression|string $column
130
     * @param string $direction
131
     * @return $this
132
     *
133
     * @throws \InvalidArgumentException
134
     */
135 31
    public function orderBy($column, $direction = 'asc')
136
    {
137 31
        if ($this->isQueryable($column)) {
138
            assert(!$column instanceof Expression);
139
            [$query, $bindings] = $this->createSub($column);
140
141
            $column = new Expression('(' . $query . ')');
142
143
            $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

143
            $this->/** @scrutinizer ignore-call */ 
144
                   addBinding($bindings, $this->unions ? 'unionOrder' : 'order');
Loading history...
144
        }
145
146 31
        $direction = strtoupper($direction);
147
148 31
        if (!in_array($direction, ['ASC', 'DESC'], true)) {
149
            throw new InvalidArgumentException('Order direction must be "asc" or "desc".');
150
        }
151
152 31
        $this->{$this->unions ? 'unionOrders' : 'orders'}[] = [
153 31
            'column' => $column,
154 31
            'direction' => $direction,
155 31
        ];
156
157 31
        return $this;
158
    }
159
160
    /**
161
     * @param string $aql
162
     * @param array<mixed> $bindings
163
     * @return $this
164
     */
165 3
    public function orderByRaw($aql, $bindings = [])
166
    {
167 3
        $type = 'Raw';
168
169 3
        $sql = new Expression($aql);
170
171 3
        $this->{$this->unions ? 'unionOrders' : 'orders'}[] = compact('type', 'sql');
172
173 3
        if (!isset($this->bindings[$this->unions ? 'unionOrders' : 'orders'])) {
174 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...
175
176 3
            return $this;
177
        }
178
179
        $this->bindings[$this->unions ? 'unionOrders' : 'orders'] = array_merge(
180
            $this->bindings[$this->unions ? 'unionOrders' : 'orders'],
181
            $bindings
182
        );
183
184
        return $this;
185
    }
186
187
    /**
188
     * Put the query's results in random order.
189
     *
190
     * @param string $seed
191
     * @return $this
192
     */
193 1
    public function inRandomOrder($seed = '')
194
    {
195
        assert($this->grammar instanceof Grammar);
196
197
        // ArangoDB's random function doesn't accept a seed.
198 1
        unset($seed);
199
200 1
        return $this->orderByRaw($this->grammar->compileRandom());
201
    }
202
203
    /**
204
     * Add a union statement to the query.
205
     *
206
     * @param  \Closure|IlluminateQueryBuilder|IlluminateEloquentBuilder $query
207
     * @param  bool  $all
208
     * @return $this
209
     *
210
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
211
     */
212 5
    public function union($query, $all = false)
213
    {
214 5
        if ($query instanceof \Closure) {
215
            $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

215
            $query($query = $this->/** @scrutinizer ignore-call */ newQuery());
Loading history...
216
        }
217
218 5
        if ($query instanceof IlluminateEloquentBuilder) {
219
            $query = $query->getQuery();
220
        }
221
222 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

222
        $this->/** @scrutinizer ignore-call */ 
223
               importBindings($query);
Loading history...
223 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...
224
225 5
        return $this;
226
    }
227
}
228