Completed
Push — master ( 6b0411...a61b3b )
by Bas
04:04
created

Grammar::generateVariable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query\Grammars;
4
5
use Illuminate\Database\Grammar as IlluminateBaseGrammar;
6
use Illuminate\Database\Query\JoinClause;
7
use Illuminate\Support\Str;
8
use Illuminate\Support\Traits\Macroable;
9
use LaravelFreelancerNL\Aranguent\Query\Builder;
10
use LaravelFreelancerNL\FluentAQL\Exceptions\BindException as BindException;
11
use LaravelFreelancerNL\FluentAQL\Facades\AQB;
12
use LaravelFreelancerNL\FluentAQL\Grammar as FluentAqlGrammar;
13
use LaravelFreelancerNL\FluentAQL\QueryBuilder as FluentAQL;
14
15
/*
16
 * Provides AQL syntax functions
17
 */
18
class Grammar extends FluentAqlGrammar
19
{
20
21
    use Macroable;
0 ignored issues
show
Bug introduced by
The trait Illuminate\Support\Traits\Macroable requires the property $name which is not provided by LaravelFreelancerNL\Aran...\Query\Grammars\Grammar.
Loading history...
22
23
    /**
24
     * The grammar table prefix.
25
     *
26
     * @var string
27
     */
28
    protected $tablePrefix = '';
29
30
31
    /**
32
     * The grammar table prefix.
33
     *
34
     * @var null|int
35
     */
36
    protected $offset = null;
37
38
    /**
39
     * The components that make up a select clause.
40
     *
41
     * @var array
42
     */
43
    protected $selectComponents = [
44
        'lock',
45
        'aggregate',
46
        'from',
47
        'joins',
48
        'wheres',
49
        'groups',
50
        'havings',
51
        'orders',
52
        'offset',
53
        'limit',
54
        'columns',
55
    ];
56
57
    protected function generateVariable($table, $postfix = 'Doc')
58
    {
59
        return Str::singular($table).$postfix;
60
    }
61
62
    protected function prefixTable($table)
63
    {
64
        return $this->tablePrefix.$table;
65
    }
66
67
    /**
68
     * Compile an insert statement into AQL.
69
     *
70
     * @param Builder $query
71
     * @param array $values
72
     * @return string
73
     * @throws BindException
74
     */
75
    public function compileInsert(Builder $query, array $values)
76
    {
77
        $table = $this->prefixTable($query->from);
78
79
        if (empty($values)) {
80
            return AQB::insert('{}', $table);
0 ignored issues
show
Bug Best Practice introduced by
The expression return LaravelFreelancer...B::insert('{}', $table) returns the type LaravelFreelancerNL\Flue...API\hasStatementClauses which is incompatible with the documented return type string.
Loading history...
81
        }
82
83
        $qb = new FluentAQL();
84
        return $qb->insert($qb->bind($values), $table)
85
            ->return('NEW._key')
86
            ->get();
87
    }
88
89
    /**
90
     * Compile an insert and get ID statement into SQL.
91
     *
92
     * @param Builder $query
93
     * @param array $values
94
     * @return string
95
     * @throws BindException
96
     */
97
    public function compileInsertGetId(Builder $query, $values)
98
    {
99
        return $this->compileInsert($query, $values);
100
    }
101
102
    /**
103
     * Compile a select query into AQL.
104
     *
105
     * @param  Builder  $query
106
     * @return string
107
     */
108
    public function compileSelect(Builder $query)
109
    {
110
//        if ($query->unions && $query->aggregate) {
111
//            return $this->compileUnionAggregate($query);
112
//        }
113
114
        // To compile the query, we'll spin through each component of the query and
115
        // see if that component exists. If it does we'll just call the compiler
116
        // function for the component which is responsible for making the SQL.
117
118
        $aqb = new FluentAQL();
119
        $aqb = $this->compileComponents($query, $aqb);
120
121
122
//        if ($query->unions) {
123
//            $sql = $this->wrapUnion($sql).' '.$this->compileUnions($query);
124
//        }
125
126
127
        return $aqb->get();
128
    }
129
130
    /**
131
     * Compile the components necessary for a select clause.
132
     *
133
     * @param Builder $query
134
     * @param FluentAQL $aqb
135
     * @return array
136
     */
137
    protected function compileComponents(Builder $query, FluentAQL $aqb)
138
    {
139
        foreach ($this->selectComponents as $component) {
140
            // To compile the query, we'll spin through each component of the query and
141
            // see if that component exists. If it does we'll just call the compiler
142
            // function for the component which is responsible for making the SQL.
143
144
            if (isset($query->$component) && ! is_null($query->$component)) {
145
                $method = 'compile'.ucfirst($component);
146
147
                $aqb = $this->$method($query, $aqb, $query->$component);
148
            }
149
        }
150
151
        return $aqb;
152
    }
153
154
155
    /**
156
     * Compile the "from" portion of the query -> FOR in AQL.
157
     *
158
     * @param \Illuminate\Database\Query\Builder $query
159
     * @param FluentAQL $aqb
160
     * @param string $table
161
     * @return FluentAQL
162
     */
163
    protected function compileFrom(\Illuminate\Database\Query\Builder $query, FluentAQL $aqb, $table)
164
    {
165
         return $aqb->for($this->generateVariable($table), $this->prefixTable($table));
166
    }
167
168
    /**
169
     * Compile the "where" portions of the query.
170
     *
171
     * @param Builder $query
172
     * @param FluentAQL $aqb
173
     * @param $table
174
     * @return string
175
     */
176
    protected function compileWheres(Builder $query, FluentAQL $aqb)
177
    {
178
        // Each type of where clauses has its own compiler function which is responsible
179
        // for actually creating the where clauses SQL. This helps keep the code nice
180
        // and maintainable since each clause has a very small method that it uses.
181
        if (is_null($query->wheres)) {
0 ignored issues
show
introduced by
The condition is_null($query->wheres) is always false.
Loading history...
182
            return $aqb;
183
        }
184
185
        if (count($predicates = $this->compileWheresToArray($query)) > 0) {
186
            return $aqb->filter($predicates);
0 ignored issues
show
Bug introduced by
$predicates of type array is incompatible with the type string expected by parameter $attribute of LaravelFreelancerNL\Flue...\QueryBuilder::filter(). ( Ignorable by Annotation )

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

186
            return $aqb->filter(/** @scrutinizer ignore-type */ $predicates);
Loading history...
187
        }
188
189
        return $aqb;
190
    }
191
192
    /**
193
     * Get an array of all the where clauses for the query.
194
     *
195
     * @param  \Illuminate\Database\Query\Builder  $query
196
     * @return array
197
     */
198
    protected function compileWheresToArray($query)
199
    {
200
        $result = collect($query->wheres)->map(function ($where) use ($query) {
0 ignored issues
show
Unused Code introduced by
The import $query is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
201
            // ArangoDB uses a double '=' for comparison
202
            if ($where['operator'] == '=') {
203
                $where['operator'] = '==';
204
            }
205
            return [
206
                $where['column'],
207
                $where['operator'],
208
                $where['value'],
209
                $where['boolean']
210
            ];
211
        })->all();
212
        return $result;
213
    }
214
215
    /**
216
     * Compile the "order by" portions of the query.
217
     *
218
     * @param Builder $query
219
     * @param FluentAQL $aqb
220
     * @param array $orders
221
     * @return string
222
     */
223
    protected function compileOrders(Builder $query, FluentAQL $aqb, $orders)
224
    {
225
        if (! empty($orders)) {
226
            return $aqb->sort($this->compileOrdersToArray($query, $orders));
227
        }
228
229
        return $aqb;
230
    }
231
232
    /**
233
     * Compile the query orders to an array.
234
     *
235
     * @param  Builder  $query
236
     * @param  array  $orders
237
     * @return FluentAQL
238
     */
239
    protected function compileOrdersToArray(Builder $query, $orders)
240
    {
241
        return array_map(function ($order) {
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_map(functio...{ /* ... */ }, $orders) returns the type array which is incompatible with the documented return type LaravelFreelancerNL\FluentAQL\QueryBuilder.
Loading history...
242
            return $order['sql'] ?? $this->prefixTable($order['column']).' '.$order['direction'];
243
        }, $orders);
244
    }
245
246
    /**
247
     * Compile the "offset" portions of the query.
248
     * We are handling this first by saving the offset which will be used by the FluentAQL's limit function
249
     *
250
     * @param Builder $query
251
     * @param FluentAQL $aqb
252
     * @param int $offset
253
     * @return string
254
     */
255
    protected function compileOffset(Builder $query, FluentAQL $aqb, $offset)
256
    {
257
        $this->offset = (int) $offset;
258
259
        return $aqb;
260
    }
261
262
    /**
263
     * Compile the "limit" portions of the query.
264
     *
265
     * @param Builder $query
266
     * @param FluentAQL $aqb
267
     * @param int $limit
268
     * @return string
269
     */
270
    protected function compileLimit(Builder $query, FluentAQL $aqb, $limit)
271
    {
272
        if ($this->offset !== null) {
273
            return $aqb->limit((int)$this->offset, (int)$limit);
274
        }
275
        return $aqb->limit((int) $limit);
276
    }
277
278
279
    /**
280
     * Compile the "select *" portion of the query.
281
     *
282
     * @param \Illuminate\Database\Query\Builder $query
283
     * @param FluentAQL $aqb
284
     * @param array $columns
285
     * @return string|null
286
     */
287
    protected function compileColumns(\Illuminate\Database\Query\Builder $query, FluentAQL $aqb, array $columns)
288
    {
289
        // If the query is actually performing an aggregating select, we will let that
290
        // compiler handle the building of the select clauses, as it will need some
291
        // more syntax that is best handled by that function to keep things neat.
292
//        if (! is_null($query->aggregate)) {
293
//            return;
294
//        }
295
296
        $values = [];
297
        $doc = $this->generateVariable($query->from);
298
        foreach ($columns as $column) {
299
            if ($column != null && $column != '*') {
300
                $values[$column] = $doc.'.'.$column;
301
            }
302
        }
303
        if (empty($values)) {
304
            $values = $doc;
305
        }
306
        return $aqb->return($values, (boolean) $query->distinct);
307
    }
308
309
    /**
310
     * Compile an update statement into SQL.
311
     *
312
     * @param Builder $query
313
     * @param FluentAQL $aqb
314
     * @param array $values
315
     * @return string
316
     */
317
    public function compileUpdate(Builder $query, array $values)
318
    {
319
        $aqb =  $query->aqb;
320
        $table = $this->prefixTable($query->from);
321
        $tableVariable = $this->generateVariable($table);
322
        $aqb = $aqb->for($tableVariable, $table);
323
324
        //Fixme: joins?
325
        $aqb = $this->compileWheres($query, $aqb);
326
327
        $aqb = $aqb->update($tableVariable, $values, $table)->get();
328
        return $aqb;
329
    }
330
331
    /**
332
     * Compile a delete statement into SQL.
333
     *
334
     * @param Builder $query
335
     * @param null $_key
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $_key is correct as it would always require null to be passed?
Loading history...
336
     * @return string
337
     */
338
    public function compileDelete(Builder $query, $_key = null)
339
    {
340
        $aqb =  $query->aqb;
341
        $table = $this->prefixTable($query->from);
342
        if (! is_null($_key)) {
0 ignored issues
show
introduced by
The condition is_null($_key) is always true.
Loading history...
343
            return $aqb->remove((string) $_key, $table)->get();
344
        }
345
346
        $tableVariable = $this->generateVariable($table);
347
        $aqb = $aqb->for($tableVariable, $table);
348
349
        //Fixme: joins?
350
        $aqb = $this->compileWheres($query, $aqb);
351
        $aqb = $aqb->remove($tableVariable, $table)->get();
352
        return $aqb;
353
    }
354
355
}
356