Passed
Push — next ( 4a2827...9707a2 )
by Bas
07:22
created

Grammar::compileInsertGetId()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 20
ccs 3
cts 3
cp 1
rs 9.8666
cc 3
nc 4
nop 3
crap 3
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Traits\Macroable;
7
use LaravelFreelancerNL\Aranguent\Query\Concerns\CompilesAggregates;
8
use LaravelFreelancerNL\Aranguent\Query\Concerns\CompilesColumns;
9
use LaravelFreelancerNL\Aranguent\Query\Concerns\CompilesGroups;
10
use LaravelFreelancerNL\Aranguent\Query\Concerns\CompilesJoins;
11
use LaravelFreelancerNL\Aranguent\Query\Concerns\CompilesWhereClauses;
12
use LaravelFreelancerNL\Aranguent\Query\Concerns\HasAliases;
13
use LaravelFreelancerNL\FluentAQL\Exceptions\BindException as BindException;
14
use LaravelFreelancerNL\FluentAQL\Expressions\FunctionExpression;
15
use LaravelFreelancerNL\FluentAQL\Grammar as FluentAqlGrammar;
16
17
/*
18
 * Provides AQL syntax functions
19
 */
20
21
class Grammar extends FluentAqlGrammar
22
{
23
    use CompilesAggregates;
24
    use CompilesColumns;
0 ignored issues
show
introduced by
The trait LaravelFreelancerNL\Aran...oncerns\CompilesColumns requires some properties which are not provided by LaravelFreelancerNL\Aranguent\Query\Grammar: $aggregate, $groups, $distinct, $from, $joins, $table
Loading history...
25
    use CompilesJoins;
0 ignored issues
show
introduced by
The trait LaravelFreelancerNL\Aran...\Concerns\CompilesJoins requires some properties which are not provided by LaravelFreelancerNL\Aranguent\Query\Grammar: $type, $table
Loading history...
26
    use CompilesGroups;
27
    use CompilesWhereClauses;
28
    use HasAliases;
0 ignored issues
show
introduced by
The trait LaravelFreelancerNL\Aran...ery\Concerns\HasAliases requires some properties which are not provided by LaravelFreelancerNL\Aranguent\Query\Grammar: $variables, $groups, $from
Loading history...
29
    use Macroable;
30
31
    public $name;
32
33
    /**
34
     * The grammar table prefix.
35
     *
36
     * @var string
37
     */
38
    protected $tablePrefix = '';
39
40
    /**
41
     * The grammar table prefix.
42
     *
43
     * @var null|int
44
     */
45
    protected $offset = null;
46
47
    /**
48
     * The components that make up a select clause.
49
     *
50
     * @var array
51
     */
52
    protected $selectComponents = [
53
        'from',
54
        'variables',
55
        'joins',
56
        'wheres',
57
        'groups',
58
        'aggregate',
59
        'havings',
60
        'orders',
61
        'offset',
62
        'limit',
63
        'columns',
64
    ];
65
66
    protected $operatorTranslations = [
67
        '='          => '==',
68
        '<>'         => '!=',
69
        '<=>'        => '==',
70
        'rlike'      => '=~',
71
        'not rlike'  => '!~',
72
        'regexp'     => '=~',
73
        'not regexp' => '!~',
74
    ];
75
76
    protected $whereTypeOperators = [
77
        'In'    => 'IN',
78
        'NotIn' => 'NOT IN',
79
    ];
80
81
    /**
82
     * Get the format for database stored dates.
83
     *
84
     * @return string
85
     */
86 82
    public function getDateFormat()
87
    {
88 82
        return 'Y-m-d\TH:i:s.v\Z';
89
    }
90
91
    /**
92
     * Get the grammar specific operators.
93
     *
94
     * @return array
95
     */
96 9
    public function getOperators()
97
    {
98 9
        return $this->comparisonOperators;
99
    }
100
101 108
    protected function prefixTable($table)
102
    {
103 108
        return $this->tablePrefix . $table;
104
    }
105
106
    /**
107
     * Compile an insert statement into AQL.
108
     *
109
     * @param Builder $builder
110
     * @param array   $values
111
     *
112
     * @throws BindException
113
     *
114
     * @return Builder
115
     */
116 82
    public function compileInsert(Builder $builder, array $values)
117
    {
118 82
        if (Arr::isAssoc($values)) {
119 10
            $values = [$values];
120
        }
121 82
        $table = $this->prefixTable($builder->from);
122
123 82
        if (empty($values)) {
124
            $builder->aqb = $builder->aqb->insert('{}', $table);
125
126
            return $builder;
127
        }
128
129 82
        $builder->aqb = $builder->aqb->let('values', $values)
130 82
            ->for('value', 'values')
131 82
            ->insert('value', $table)
132 82
            ->return('NEW._id');
133
134 82
        return $builder;
135
    }
136
137
    /**
138
     * Compile an insert and get ID statement into SQL.
139
     *
140
     * @param array<mixed> $values
141
     */
142
    public function compileInsertGetId(Builder $builder, $values, $sequence = "_id"): Builder
143
    {
144
        if (Arr::isAssoc($values)) {
145
            $values = [$values];
146
        }
147 10
        $table = $this->prefixTable($builder->from);
148
149 10
        if (empty($values)) {
150
            $builder->aqb = $builder->aqb->insert('{}', $table)
151
                ->return('NEW.' . $sequence);
152
153
            return $builder;
154
        }
155
156
        $builder->aqb = $builder->aqb->let('values', $values)
157
            ->for('value', 'values')
158
            ->insert('value', $table)
159 103
            ->return('NEW.' . $sequence);
160
161
        return $builder;
162
    }
163
164
    /**
165
     * Compile an insert statement into AQL.
166
     *
167
     * @param Builder $builder
168
     * @param array<mixed> $values
169 103
     * @return Builder
170
     */
171
    public function compileInsertOrIgnore(Builder $builder, array $values)
172
    {
173
        if (Arr::isAssoc($values)) {
174
            $values = [$values];
175 103
        }
176
        $table = $this->prefixTable($builder->from);
177
178
        if (empty($values)) {
179
            $builder->aqb = $builder->aqb->insert('{}', $table);
180
181
            return $builder;
182
        }
183
184
        $builder->aqb = $builder->aqb->let('values', $values)
185 103
            ->for('value', 'values')
186
            ->insert('value', $table)
187 103
            ->options(["ignoreErrors" => true])
188
            ->return('NEW._id');
189
190
        return $builder;
191
    }
192 103
193 103
194
    /**
195 103
     * Compile a select query into AQL.
196
     *
197
     * @param Builder $builder
198
     *
199 103
     * @return Builder
200
     */
201
    public function compileSelect(Builder $builder)
202
    {
203
//        if ($builder->unions && $builder->aggregate) {
204
//            return $this->compileUnionAggregate($builder);
205
//        }
206
207
        // To compile the query, we'll spin through each component of the query and
208
        // see if that component exists. If it does we'll just call the compiler
209
        // function for the component which is responsible for making the SQL.
210 103
211
        $builder = $this->compileComponents($builder);
212 103
213 103
//        if ($builder->unions) {
214
//            $sql = $this->wrapUnion($sql).' '.$this->compileUnions($builder);
215 103
//        }
216
217 103
        return $builder;
218
    }
219
220
    /**
221
     * Compile the components necessary for a select clause.
222
     *
223
     * @param Builder $builder
224
     *
225 103
     * @return Builder
226
     */
227 103
    protected function compileComponents(Builder $builder)
228 1
    {
229 1
        foreach ($this->selectComponents as $component) {
230
            // To compile the query, we'll spin through each component of the query and
231
            // see if that component exists. If it does we'll just call the compiler
232
            // function for the component which is responsible for making the SQL.
233 103
234
            if (isset($builder->$component) && !is_null($builder->$component)) {
235
                $method = 'compile' . ucfirst($component);
236
237
                $builder = $this->$method($builder, $builder->$component);
238
            }
239
        }
240
241
        return $builder;
242
    }
243
244 2
    /**
245
     * Compile the "from" portion of the query -> FOR in AQL.
246 2
     *
247 2
     * @param Builder $builder
248 2
     * @param string  $table
249
     *
250 2
     * @return Builder
251
     */
252
    protected function compileFrom(Builder $builder, $table)
253
    {
254
        $table = $this->prefixTable($table);
255
        $alias = $this->registerTableAlias($table);
256
257
        $builder->aqb = $builder->aqb->for($alias, $table);
258
259
        return $builder;
260
    }
261
262
    /**
263
     * @param  Builder  $builder
264 2
     * @param  array $variables
265
     * @return Builder
266 2
     */
267
    protected function compileVariables(Builder $builder, array $variables)
268 2
    {
269 2
        if (! empty($variables)) {
270 1
            foreach ($variables as $variable => $data) {
271
                $builder->aqb = $builder->aqb->let($variable, $data);
272
            }
273 2
        }
274
275 2
        return $builder;
276 1
    }
277
278
    /**
279
     * Compile the "order by" portions of the query.
280 2
     *
281
     * @param Builder $builder
282
     * @param array   $orders
283
     *
284
     * @return Builder
285
     */
286
    protected function compileOrders(Builder $builder, $orders)
287
    {
288
        if (!empty($orders)) {
289
            $orders = $this->compileOrdersToFlatArray($builder, $orders);
290
            $builder->aqb = $builder->aqb->sort(...$orders);
291
292 2
            return $builder;
293
        }
294 2
295
        return $builder;
296 2
    }
297
298
    /**
299
     * Compile the query orders to an array.
300
     *
301
     * @param Builder $builder
302
     * @param array   $orders
303
     *
304
     * @return array
305
     */
306
    protected function compileOrdersToFlatArray(Builder $builder, $orders)
307 48
    {
308
        $flatOrders = [];
309 48
310 2
        foreach ($orders as $order) {
311
            if (!isset($order['type']) || $order['type'] != 'Raw') {
312 2
                $order['column'] = $this->normalizeColumn($builder, $order['column']);
313
            }
314 46
315
            $flatOrders[] = $order['column'];
316 46
317
            if (isset($order['direction'])) {
318
                $flatOrders[] = $order['direction'];
319
            }
320
        }
321
322
        return $flatOrders;
323
    }
324
325
    /**
326
     * Compile the "offset" portions of the query.
327
     * We are handling this first by saving the offset which will be used by the FluentAQL's limit function.
328 16
     *
329
     * @param Builder $builder
330
     * @param int     $offset
331 16
     *
332 16
     * @return Builder
333
     */
334 16
    protected function compileOffset(Builder $builder, $offset)
335
    {
336
        $this->offset = (int) $offset;
337 16
338
        return $builder;
339 16
    }
340
341 16
    /**
342
     * Compile the "limit" portions of the query.
343
     *
344
     * @param Builder $builder
345
     * @param int     $limit
346
     *
347
     * @return Builder
348
     */
349
    protected function compileLimit(Builder $builder, $limit)
350
    {
351
        if ($this->offset !== null) {
352
            $builder->aqb = $builder->aqb->limit((int) $this->offset, (int) $limit);
353
354
            return $builder;
355 6
        }
356
        $builder->aqb = $builder->aqb->limit((int) $limit);
357 6
358 6
        return $builder;
359
    }
360
361 6
362 1
    /**
363
     * Compile an update statement into SQL.
364 1
     *
365
     * @param Builder $builder
366
     * @param array   $values
367 6
     *
368
     * @return Builder
369
     */
370 6
    public function compileUpdate(Builder $builder, array $values)
371
    {
372 6
373
        $table = $this->prefixTable($builder->from);
374 6
        $tableAlias = $this->generateTableAlias($table);
375
376
        $builder->aqb = $builder->aqb->for($tableAlias, $table);
377
378
        //Fixme: joins?
379
        $builder = $this->compileWheres($builder);
380
381
        $builder->aqb = $builder->aqb->update($tableAlias, $values, $table);
382
383
        return $builder;
384 1
    }
385
386 1
    /**
387
     * Compile a delete statement into SQL.
388
     *
389
     * @SuppressWarnings(PHPMD.CamelCaseParameterName)
390
     * @SuppressWarnings(PHPMD.CamelCaseVariableName)
391
     *
392
     * @param Builder $builder
393
     * @param null    $id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $id is correct as it would always require null to be passed?
Loading history...
394
     *
395 1
     * @return Builder
396
     */
397 1
    public function compileDelete(Builder $builder, $id = null)
398
    {
399
        $table = $this->prefixTable($builder->from);
400
        $tableAlias = $this->generateTableAlias($table);
401
402
403
        if (!is_null($id)) {
0 ignored issues
show
introduced by
The condition is_null($id) is always true.
Loading history...
404
            $builder->aqb = $builder->aqb->remove((string) $id, $table);
405
406
            return $builder;
407
        }
408
409
        $builder->aqb = $builder->aqb->for($tableAlias, $table);
410
411
        //Fixme: joins?
412
        $builder = $this->compileWheres($builder);
413
414
        $builder->aqb = $builder->aqb->remove($tableAlias, $table);
415
416
        return $builder;
417
    }
418
419
    /**
420
     * Compile the random statement into SQL.
421
     *
422
     * @param Builder $builder
423
     *
424
     * @return FunctionExpression;
425
     */
426
    public function compileRandom(Builder $builder)
427
    {
428
        return $builder->aqb->rand();
429
    }
430
431
    /**
432
     * Get the value of a raw expression.
433
     *
434
     * @param  \Illuminate\Database\Query\Expression  $expression
435
     * @return string
436
     */
437
    public function getValue($expression)
438
    {
439
        return $expression->getValue();
440
    }
441
}
442