Passed
Push — master ( 00bef5...064b0e )
by Jonas
02:59
created

withRecursiveExpressionAndCycleDetection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 10
cc 1
nc 1
nop 6
crap 1
1
<?php
2
3
namespace Staudenmeir\LaravelCte\Query\Traits;
4
5
use Illuminate\Database\Connection;
6
use Illuminate\Database\Query\Grammars\Grammar;
7
use Illuminate\Database\Query\Processors\Processor;
8
use RuntimeException;
9
use Staudenmeir\LaravelCte\Query\Grammars\MySqlGrammar;
10
use Staudenmeir\LaravelCte\Query\Grammars\PostgresGrammar;
11
use Staudenmeir\LaravelCte\Query\Grammars\SQLiteGrammar;
12
use Staudenmeir\LaravelCte\Query\Grammars\SqlServerGrammar;
13
14
trait BuildsExpressionQueries
15
{
16
    /**
17
     * The common table expressions.
18
     *
19
     * @var array
20
     */
21
    public $expressions = [];
22
23
    /**
24
     * The common table expressions for union queries.
25
     *
26
     * @var array
27
     */
28
    public $unionExpressions = [];
29
30
    /**
31
     * The recursion limit.
32
     *
33
     * @var int
34
     */
35
    public $recursionLimit;
36
37
    /**
38
     * The recursion limit for union queries.
39
     *
40
     * @var int
41
     */
42
    public $unionRecursionLimit;
43
44
    /**
45
     * Create a new query builder instance.
46
     *
47
     * @param \Illuminate\Database\Connection $connection
48
     * @param \Illuminate\Database\Query\Grammars\Grammar|null $grammar
49
     * @param \Illuminate\Database\Query\Processors\Processor|null $processor
50
     * @return void
51
     */
52 175
    public function __construct(Connection $connection, Grammar $grammar = null, Processor $processor = null)
53
    {
54 175
        $grammar = $grammar ?: $connection->withTablePrefix($this->getQueryGrammar($connection));
55 175
        $processor = $processor ?: $connection->getPostProcessor();
56
57 175
        parent::__construct($connection, $grammar, $processor);
58
59 175
        $this->bindings = ['expressions' => []] + $this->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...
60
    }
61
62
    /**
63
     * Get the query grammar.
64
     *
65
     * @param \Illuminate\Database\Connection $connection
66
     * @return \Illuminate\Database\Query\Grammars\Grammar
67
     */
68 175
    protected function getQueryGrammar(Connection $connection)
69
    {
70 175
        $driver = $connection->getDriverName();
71
72 175
        switch ($driver) {
73 175
            case 'mysql':
74 64
                return new MySqlGrammar();
75 111
            case 'pgsql':
76 41
                return new PostgresGrammar();
77 70
            case 'sqlite':
78 37
                return new SQLiteGrammar();
79 33
            case 'sqlsrv':
80 33
                return new SqlServerGrammar();
81
        }
82
83
        throw new RuntimeException('This database is not supported.'); // @codeCoverageIgnore
84
    }
85
86
    /**
87
     * Add a common table expression to the query.
88
     *
89
     * @param string $name
90
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
91
     * @param array|null $columns
92
     * @param bool $recursive
93
     * @param bool|null $materialized
94
     * @param array|null $cycle
95
     * @return $this
96
     */
97 160
    public function withExpression($name, $query, array $columns = null, $recursive = false, $materialized = null, array $cycle = null)
98
    {
99 160
        [$query, $bindings] = $this->createSub($query);
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

99
        /** @scrutinizer ignore-call */ 
100
        [$query, $bindings] = $this->createSub($query);
Loading history...
100
101 160
        $this->{$this->unions ? 'unionExpressions' : 'expressions'}[] = compact('name', 'query', 'columns', 'recursive', 'materialized', 'cycle');
102
103 160
        $this->addBinding($bindings, 'expressions');
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

103
        $this->/** @scrutinizer ignore-call */ 
104
               addBinding($bindings, 'expressions');
Loading history...
104
105 160
        return $this;
106
    }
107
108
    /**
109
     * Add a recursive common table expression to the query.
110
     *
111
     * @param string $name
112
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
113
     * @param array|null $columns
114
     * @param array|null $cycle
115
     * @return $this
116
     */
117 34
    public function withRecursiveExpression($name, $query, $columns = null, array $cycle = null)
118
    {
119 34
        return $this->withExpression($name, $query, $columns, true, null, $cycle);
120
    }
121
122
    /**
123
     * Add a recursive common table expression with cycle detection to the query.
124
     *
125
     * @param string $name
126
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
127
     * @param array|string $cycleColumns
128
     * @param string $markColumn
129
     * @param string $pathColumn
130
     * @param array|null $columns
131
     * @return $this
132
     */
133 4
    public function withRecursiveExpressionAndCycleDetection($name, $query, $cycleColumns, $markColumn = 'is_cycle', $pathColumn = 'path', $columns = null)
134
    {
135 4
        $cycleColumns = (array) $cycleColumns;
136
137 4
        $cycle = [
138
            'columns' => $cycleColumns
139 4
        ] + compact('markColumn', 'pathColumn');
140
141 4
        return $this->withRecursiveExpression($name, $query, $columns, $cycle);
142
    }
143
144
    /**
145
     * Add a materialized common table expression to the query.
146
     *
147
     * @param string $name
148
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
149
     * @param array|null $columns
150
     * @return $this
151
     */
152 11
    public function withMaterializedExpression($name, $query, $columns = null)
153
    {
154 11
        return $this->withExpression($name, $query, $columns, false, true);
155
    }
156
157
    /**
158
     * Add a non-materialized common table expression to the query.
159
     *
160
     * @param string $name
161
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
162
     * @param array|null $columns
163
     * @return $this
164
     */
165 11
    public function withNonMaterializedExpression($name, $query, $columns = null)
166
    {
167 11
        return $this->withExpression($name, $query, $columns, false, false);
168
    }
169
170
    /**
171
     * Set the recursion limit of the query.
172
     *
173
     * @param int $value
174
     * @return $this
175
     */
176 15
    public function recursionLimit($value)
177
    {
178 15
        $this->{$this->unions ? 'unionRecursionLimit' : 'recursionLimit'} = $value;
179
180 15
        return $this;
181
    }
182
183
    /**
184
     * Insert new records into the table using a subquery.
185
     *
186
     * @param array $columns
187
     * @param \Closure|\Illuminate\Database\Query\Builder|string $query
188
     * @return int
189
     */
190 15
    public function insertUsing(array $columns, $query)
191
    {
192 15
        $this->applyBeforeQueryCallbacks();
0 ignored issues
show
Bug introduced by
It seems like applyBeforeQueryCallbacks() 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

192
        $this->/** @scrutinizer ignore-call */ 
193
               applyBeforeQueryCallbacks();
Loading history...
193
194 15
        [$sql, $bindings] = $this->createSub($query);
195
196 15
        $bindings = array_merge($this->bindings['expressions'], $bindings);
197
198 15
        return $this->connection->affectingStatement(
199 15
            $this->grammar->compileInsertUsing($this, $columns, $sql),
200 15
            $this->cleanBindings($bindings)
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

200
            $this->/** @scrutinizer ignore-call */ 
201
                   cleanBindings($bindings)
Loading history...
201
        );
202
    }
203
204
    /**
205
     * Update records in the database.
206
     *
207
     * @param  array  $values
208
     * @return int
209
     */
210 24
    public function update(array $values)
211
    {
212 24
        $this->applyBeforeQueryCallbacks();
213
214 24
        $sql = $this->grammar->compileUpdate($this, $values);
215
216 24
        return $this->connection->update($sql, $this->cleanBindings(
217 24
            $this->grammar->getBindingsForUpdate($this, $this->bindings, $values)
218
        ));
219
    }
220
}
221