Passed
Push — next ( 9707a2...aa8376 )
by Bas
03:34
created

Grammar::compileDelete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 2
dl 0
loc 20
ccs 10
cts 10
cp 1
crap 2
rs 9.9666
c 0
b 0
f 0
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 91
    public function getDateFormat()
87
    {
88 91
        return 'Y-m-d\TH:i:s.v\Z';
89
    }
90
91
    /**
92
     * Get the grammar specific operators.
93
     *
94
     * @return array
95
     */
96 11
    public function getOperators()
97
    {
98 11
        return $this->comparisonOperators;
99
    }
100
101 116
    protected function prefixTable($table)
102
    {
103 116
        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 91
    public function compileInsert(Builder $builder, array $values)
117
    {
118 91
        if (Arr::isAssoc($values)) {
119 1
            $values = [$values];
120
        }
121 91
        $table = $this->prefixTable($builder->from);
122
123 91
        if (empty($values)) {
124
            $builder->aqb = $builder->aqb->insert('{}', $table);
125
126
            return $builder;
127
        }
128
129 91
        $builder->aqb = $builder->aqb->let('values', $values)
130 91
            ->for('value', 'values')
131 91
            ->insert('value', $table)
132 91
            ->return('NEW._id');
133
134 91
        return $builder;
135
    }
136
137
    /**
138
     * Compile an insert and get ID statement into SQL.
139
     *
140
     * @param array<mixed> $values
141
     */
142 8
    public function compileInsertGetId(Builder $builder, $values, $sequence = "_id"): Builder
143
    {
144 8
        if (Arr::isAssoc($values)) {
145 8
            $values = [$values];
146
        }
147 8
        $table = $this->prefixTable($builder->from);
148
149 8
        if (empty($values)) {
150
            $builder->aqb = $builder->aqb->insert('{}', $table)
151
                ->return('NEW.' . $sequence);
152
153
            return $builder;
154
        }
155
156 8
        $builder->aqb = $builder->aqb->let('values', $values)
157 8
            ->for('value', 'values')
158 8
            ->insert('value', $table)
159 8
            ->return('NEW.' . $sequence);
160
161 8
        return $builder;
162
    }
163
164
    /**
165
     * Compile an insert statement into AQL.
166
     *
167
     * @param Builder $builder
168
     * @param array<mixed> $values
169
     * @return Builder
170
     */
171 2
    public function compileInsertOrIgnore(Builder $builder, array $values)
172
    {
173 2
        if (Arr::isAssoc($values)) {
174 2
            $values = [$values];
175
        }
176 2
        $table = $this->prefixTable($builder->from);
177
178 2
        if (empty($values)) {
179
            $builder->aqb = $builder->aqb->insert('{}', $table);
180
181
            return $builder;
182
        }
183
184 2
        $builder->aqb = $builder->aqb->let('values', $values)
185 2
            ->for('value', 'values')
186 2
            ->insert('value', $table)
187 2
            ->options(["ignoreErrors" => true])
188 2
            ->return('NEW._id');
189
190 2
        return $builder;
191
    }
192
193
194
    /**
195
     * Compile a select query into AQL.
196
     *
197
     * @param Builder $builder
198
     *
199
     * @return Builder
200
     */
201 102
    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
211 102
        $builder = $this->compileComponents($builder);
212
213
//        if ($builder->unions) {
214
//            $sql = $this->wrapUnion($sql).' '.$this->compileUnions($builder);
215
//        }
216
217 102
        return $builder;
218
    }
219
220
    /**
221
     * Compile the components necessary for a select clause.
222
     *
223
     * @param Builder $builder
224
     *
225
     * @return Builder
226
     */
227 102
    protected function compileComponents(Builder $builder)
228
    {
229 102
        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
234 102
            if (isset($builder->$component) && !is_null($builder->$component)) {
235 102
                $method = 'compile' . ucfirst($component);
236
237 102
                $builder = $this->$method($builder, $builder->$component);
238
            }
239
        }
240
241 102
        return $builder;
242
    }
243
244
    /**
245
     * Compile the "from" portion of the query -> FOR in AQL.
246
     *
247
     * @param Builder $builder
248
     * @param string  $table
249
     *
250
     * @return Builder
251
     */
252 102
    protected function compileFrom(Builder $builder, $table)
253
    {
254 102
        $table = $this->prefixTable($table);
255 102
        $alias = $this->registerTableAlias($table);
256
257 102
        $builder->aqb = $builder->aqb->for($alias, $table);
258
259 102
        return $builder;
260
    }
261
262
    /**
263
     * @param  Builder  $builder
264
     * @param  array $variables
265
     * @return Builder
266
     */
267 102
    protected function compileVariables(Builder $builder, array $variables)
268
    {
269 102
        if (! empty($variables)) {
270 1
            foreach ($variables as $variable => $data) {
271 1
                $builder->aqb = $builder->aqb->let($variable, $data);
272
            }
273
        }
274
275 102
        return $builder;
276
    }
277
278
    /**
279
     * Compile the "order by" portions of the query.
280
     *
281
     * @param Builder $builder
282
     * @param array   $orders
283
     *
284
     * @return Builder
285
     */
286 2
    protected function compileOrders(Builder $builder, $orders)
287
    {
288 2
        if (!empty($orders)) {
289 2
            $orders = $this->compileOrdersToFlatArray($builder, $orders);
290 2
            $builder->aqb = $builder->aqb->sort(...$orders);
291
292 2
            return $builder;
293
        }
294
295
        return $builder;
296
    }
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 2
    protected function compileOrdersToFlatArray(Builder $builder, $orders)
307
    {
308 2
        $flatOrders = [];
309
310 2
        foreach ($orders as $order) {
311 2
            if (!isset($order['type']) || $order['type'] != 'Raw') {
312 1
                $order['column'] = $this->normalizeColumn($builder, $order['column']);
313
            }
314
315 2
            $flatOrders[] = $order['column'];
316
317 2
            if (isset($order['direction'])) {
318 1
                $flatOrders[] = $order['direction'];
319
            }
320
        }
321
322 2
        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
     *
329
     * @param Builder $builder
330
     * @param int     $offset
331
     *
332
     * @return Builder
333
     */
334 2
    protected function compileOffset(Builder $builder, $offset)
335
    {
336 2
        $this->offset = (int) $offset;
337
338 2
        return $builder;
339
    }
340
341
    /**
342
     * Compile the "limit" portions of the query.
343
     *
344
     * @param Builder $builder
345
     * @param int     $limit
346
     *
347
     * @return Builder
348
     */
349 48
    protected function compileLimit(Builder $builder, $limit)
350
    {
351 48
        if ($this->offset !== null) {
352 2
            $builder->aqb = $builder->aqb->limit((int) $this->offset, (int) $limit);
353
354 2
            return $builder;
355
        }
356 46
        $builder->aqb = $builder->aqb->limit((int) $limit);
357
358 46
        return $builder;
359
    }
360
361
362
    /**
363
     * Compile an update statement into SQL.
364
     *
365
     * @param Builder $builder
366
     * @param array   $values
367
     *
368
     * @return Builder
369
     */
370 14
    public function compileUpdate(Builder $builder, array $values)
371
    {
372
373 14
        $table = $this->prefixTable($builder->from);
374 14
        $tableAlias = $this->generateTableAlias($table);
375
376 14
        $builder->aqb = $builder->aqb->for($tableAlias, $table);
377
378
        //Fixme: joins?
379 14
        $builder = $this->compileWheres($builder);
380
381 14
        $builder->aqb = $builder->aqb->update($tableAlias, $values, $table);
382
383 14
        return $builder;
384
    }
385
386
    /**
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
     * @return Builder
396
     */
397 6
    public function compileDelete(Builder $builder, $id = null)
398
    {
399 6
        $table = $this->prefixTable($builder->from);
400 6
        $tableAlias = $this->generateTableAlias($table);
401
402
403 6
        if (!is_null($id)) {
0 ignored issues
show
introduced by
The condition is_null($id) is always true.
Loading history...
404 1
            $builder->aqb = $builder->aqb->remove((string) $id, $table);
405
406 1
            return $builder;
407
        }
408
409 6
        $builder->aqb = $builder->aqb->for($tableAlias, $table);
410
411
        //Fixme: joins?
412 6
        $builder = $this->compileWheres($builder);
413
414 6
        $builder->aqb = $builder->aqb->remove($tableAlias, $table);
415
416 6
        return $builder;
417
    }
418
419
    /**
420
     * Compile the random statement into SQL.
421
     *
422
     * @param Builder $builder
423
     *
424
     * @return FunctionExpression;
425
     */
426 1
    public function compileRandom(Builder $builder)
427
    {
428 1
        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 1
    public function getValue($expression)
438
    {
439 1
        return $expression->getValue();
440
    }
441
}
442