Completed
Push — master ( f40c6a...9a6de3 )
by BENOIT
04:32
created

DeleteQueryBuilder::preview()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace BenTools\Where\DeleteQuery;
4
5
use BenTools\Where\Expression\Expression;
6
use BenTools\Where\Helper\Previewer;
7
use function BenTools\Where\valuesOf;
8
9
/**
10
 * Class SelectQuery
11
 *
12
 * @property $mainKeyword
13
 * @property $flags
14
 * @property $tables
15
 * @property $from
16
 * @property $joins
17
 * @property $partitions
18
 * @property $where
19
 * @property $orderBy
20
 * @property $limit
21
 * @property $end
22
 */
23
final class DeleteQueryBuilder
24
{
25
26
    /**
27
     * @var string
28
     */
29
    private $mainKeyword = 'DELETE';
30
31
    /**
32
     * @var array
33
     */
34
    private $flags = [];
35
36
    /**
37
     * @var array
38
     */
39
    private $tables = [];
40
41
    /**
42
     * @var string
43
     */
44
    private $from;
45
46
    /**
47
     * @var array
48
     */
49
    private $partitions = [];
50
51
    /**
52
     * @var array
53
     */
54
    private $joins = [];
55
56
    /**
57
     * @var Expression
58
     */
59
    private $where;
60
61
    /**
62
     * @var array
63
     */
64
    private $orderBy = [];
65
66
    /**
67
     * @var int
68
     */
69
    private $limit;
70
71
    /**
72
     * @var string
73
     */
74
    private $end = ';';
75
76
    /**
77
     * @param Expression[]|string[] ...$tables
78
     * @return DeleteQueryBuilder
79
     */
80
    public static function make(...$tables): self
81
    {
82
        $query = new self;
83
        if (0 !== \func_num_args()) {
84
            $query->tables = $tables;
85
        }
86
        return $query;
87
    }
88
89
    /**
90
     * @param string $keyword
91
     * @return DeleteQueryBuilder
92
     */
93
    public function withMainKeyword(string $keyword): self
94
    {
95
        $clone = clone $this;
96
        $clone->mainKeyword = $keyword;
97
        return $clone;
98
    }
99
100
    /**
101
     * @param Expression[]|string[] ...$tables
102
     * @return DeleteQueryBuilder
103
     */
104
    public function deleteOnlyFromTables(...$tables): self
105
    {
106
        $clone = clone $this;
107
        $clone->tables = $tables;
108
        return $clone;
109
    }
110
111
    /**
112
     * @param string[] ...$flags
113
     * @return DeleteQueryBuilder
114
     */
115
    public function withFlags(string ...$flags): self
116
    {
117
        $clone = clone $this;
118
        $clone->flags = $flags;
119
        return $clone;
120
    }
121
122
    /**
123
     * @param string[] ...$flags
124
     * @return DeleteQueryBuilder
125
     */
126
    public function withAddedFlags(string ...$flags): self
127
    {
128
        $clone = clone $this;
129
        $existingFlags = \array_map('strtoupper', $clone->flags);
130
        foreach ($flags as $flag) {
131
            if (!\in_array(\strtoupper($flag), $existingFlags, true)) {
132
                $clone->flags[] = $flag;
133
            }
134
        }
135
        return $clone;
136
    }
137
138
    /**
139
     * @param string $table
140
     * @return DeleteQueryBuilder
141
     */
142
    public function from(string $table = null): self
143
    {
144
        $clone = clone $this;
145
        $clone->from = $table;
146
        return $clone;
147
    }
148
149
    /**
150
     * @param string[] ...$partitions
151
     * @return DeleteQueryBuilder
152
     */
153
    public function withPartitions(string ...$partitions): self
154
    {
155
        $clone = clone $this;
156
        $clone->partitions = $partitions;
157
        return $clone;
158
    }
159
160
    /**
161
     * @param string[] ...$partitions
162
     * @return DeleteQueryBuilder
163
     */
164
    public function withAddedPartitions(string ...$partitions): self
165
    {
166
        $clone = clone $this;
167
        foreach ($partitions as $partition) {
168
            if (!in_array($partition, $clone->partitions, true)) {
169
                $clone->partitions[] = $partition;
170
            }
171
        }
172
        return $clone;
173
    }
174
175
    /**
176
     * @param string                 $table
177
     * @param string|Expression|null $expression
178
     * @param array                  ...$values
179
     * @return DeleteQueryBuilder
180
     * @throws \InvalidArgumentException
181
     */
182
    public function join(string $table, $expression = null, ...$values): self
183
    {
184
        $clone = clone $this;
185
        $clone->joins[$table] = [
186
            't' => 'JOIN',
187
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
188
        ];
189
        return $clone;
190
    }
191
192
    /**
193
     * @param string                 $table
194
     * @param string|Expression|null $expression
195
     * @param array                  ...$values
196
     * @return DeleteQueryBuilder
197
     * @throws \InvalidArgumentException
198
     */
199
    public function innerJoin(string $table, $expression = null, ...$values): self
200
    {
201
        $clone = clone $this;
202
        $clone->joins[$table] = [
203
            't' => 'INNER JOIN',
204
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
205
        ];
206
        return $clone;
207
    }
208
209
    /**
210
     * @param string                 $table
211
     * @param string|Expression|null $expression
212
     * @param array                  ...$values
213
     * @return DeleteQueryBuilder
214
     * @throws \InvalidArgumentException
215
     */
216
    public function outerJoin(string $table, $expression = null, ...$values): self
217
    {
218
        $clone = clone $this;
219
        $clone->joins[$table] = [
220
            't' => 'OUTER JOIN',
221
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
222
        ];
223
        return $clone;
224
    }
225
226
    /**
227
     * @param string                 $table
228
     * @param string|Expression|null $expression
229
     * @param array                  ...$values
230
     * @return DeleteQueryBuilder
231
     * @throws \InvalidArgumentException
232
     */
233
    public function leftJoin(string $table, $expression = null, ...$values): self
234
    {
235
        $clone = clone $this;
236
        $clone->joins[$table] = [
237
            't' => 'LEFT JOIN',
238
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
239
        ];
240
        return $clone;
241
    }
242
243
    /**
244
     * @param string                 $table
245
     * @param string|Expression|null $expression
246
     * @param array                  ...$values
247
     * @return DeleteQueryBuilder
248
     * @throws \InvalidArgumentException
249
     */
250
    public function leftOuterJoin(string $table, $expression = null, ...$values): self
251
    {
252
        $clone = clone $this;
253
        $clone->joins[$table] = [
254
            't' => 'LEFT OUTER JOIN',
255
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
256
        ];
257
        return $clone;
258
    }
259
260
    /**
261
     * @param string                 $table
262
     * @param string|Expression|null $expression
263
     * @param array                  ...$values
264
     * @return DeleteQueryBuilder
265
     * @throws \InvalidArgumentException
266
     */
267
    public function rightJoin(string $table, $expression = null, ...$values): self
268
    {
269
        $clone = clone $this;
270
        $clone->joins[$table] = [
271
            't' => 'RIGHT JOIN',
272
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
273
        ];
274
        return $clone;
275
    }
276
277
    /**
278
     * @param string                 $table
279
     * @param string|Expression|null $expression
280
     * @param array                  ...$values
281
     * @return DeleteQueryBuilder
282
     * @throws \InvalidArgumentException
283
     */
284
    public function rightOuterJoin(string $table, $expression = null, ...$values): self
285
    {
286
        $clone = clone $this;
287
        $clone->joins[$table] = [
288
            't' => 'RIGHT OUTER JOIN',
289
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
290
        ];
291
        return $clone;
292
    }
293
294
    /**
295
     * @param string                 $table
296
     * @param string|Expression|null $expression
297
     * @param array                  ...$values
298
     * @return DeleteQueryBuilder
299
     * @throws \InvalidArgumentException
300
     */
301
    public function fullJoin(string $table, $expression = null, ...$values): self
302
    {
303
        $clone = clone $this;
304
        $clone->joins[$table] = [
305
            't' => 'FULL JOIN',
306
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
307
        ];
308
        return $clone;
309
    }
310
311
    /**
312
     * @param string                 $table
313
     * @param string|Expression|null $expression
314
     * @param array                  ...$values
315
     * @return DeleteQueryBuilder
316
     * @throws \InvalidArgumentException
317
     */
318
    public function fullOuterJoin(string $table, $expression = null, ...$values): self
319
    {
320
        $clone = clone $this;
321
        $clone->joins[$table] = [
322
            't' => 'FULL OUTER JOIN',
323
            'c' => null !== $expression ? Expression::where($expression, ...$values) : null,
324
        ];
325
        return $clone;
326
    }
327
328
    /**
329
     * Reset all JOIN clauses.
330
     *
331
     * @return DeleteQueryBuilder
332
     */
333
    public function resetJoins(): self
334
    {
335
        $clone = clone $this;
336
        $clone->joins = [];
337
        return $clone;
338
    }
339
340
    /**
341
     * Remove a specific JOIN clause.
342
     *
343
     * @param string $table
344
     * @return DeleteQueryBuilder
345
     */
346
    public function withoutJoin(string $table)
347
    {
348
        $clone = clone $this;
349
        unset($clone->joins[$table]);
350
        return $clone;
351
    }
352
353
    /**
354
     * @param string|Expression|null $expression
355
     * @param array                  ...$values
356
     * @return DeleteQueryBuilder
357
     * @throws \InvalidArgumentException
358
     */
359
    public function where($expression = null, ...$values): self
360
    {
361
        $clone = clone $this;
362
        $clone->where = null !== $expression ? Expression::where($expression, ...$values) : null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null !== $expression ? \...ion, ...$values) : null can also be of type object<self>. However, the property $where is declared as type object<BenTools\Where\Expression\Expression>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
363
        return $clone;
364
    }
365
366
    /**
367
     * @param string|Expression $expression
368
     * @param array             ...$values
369
     * @return DeleteQueryBuilder
370
     * @throws \InvalidArgumentException
371
     */
372
    public function andWhere($expression, ...$values): self
373
    {
374
        if (null === $this->where) {
375
            return $this->where(Expression::where($expression, ...$values));
376
        }
377
        $clone = clone $this;
378
        $clone->where = $clone->where->and(Expression::where($expression, ...$values));
379
        return $clone;
380
    }
381
382
    /**
383
     * @param string|Expression $expression
384
     * @param array             ...$values
385
     * @return DeleteQueryBuilder
386
     * @throws \InvalidArgumentException
387
     */
388
    public function orWhere($expression, ...$values): self
389
    {
390
        if (null === $this->where) {
391
            return $this->where(Expression::where($expression, ...$values));
392
        }
393
        $clone = clone $this;
394
        $clone->where = $clone->where->or(Expression::where($expression, ...$values));
395
        return $clone;
396
    }
397
398
    /**
399
     * @param string[] ...$groupBy
400
     * @return DeleteQueryBuilder
401
     */
402
    public function orderBy(string ...$orderBy): self
403
    {
404
        $clone = clone $this;
405
        $clone->orderBy = $orderBy;
406
        return $clone;
407
    }
408
409
    /**
410
     * @param string[] ...$groupBy
411
     * @return DeleteQueryBuilder
412
     */
413
    public function andOrderBy(string ...$orderBy): self
414
    {
415
        $clone = clone $this;
416
        $clone->orderBy = \array_merge($clone->orderBy, $orderBy);
417
        return $clone;
418
    }
419
420
    /**
421
     * @param int|null $limit
422
     * @return DeleteQueryBuilder
423
     */
424
    public function limit(int $limit = null): self
425
    {
426
        $clone = clone $this;
427
        $clone->limit = $limit;
428
        return $clone;
429
    }
430
431
    /**
432
     * @param string|null $end
433
     * @return DeleteQueryBuilder
434
     */
435
    public function end(string $end = null): self
436
    {
437
        $clone = clone $this;
438
        $clone->end = $end;
439
        return $clone;
440
    }
441
442
    /**
443
     * @return array
444
     */
445
    public function getValues(): array
446
    {
447
        $expressions = \array_filter(\array_merge(\array_column($this->joins, 'c'), [$this->where]), function ($expression) {
448
            return $expression instanceof Expression;
449
        });
450
        return valuesOf(...$expressions);
451
    }
452
453
    /**
454
     * @return string
455
     */
456
    public function __toString(): string
457
    {
458
        return DeleteQueryStringifier::stringify($this);
459
    }
460
461
    /**
462
     * @return string
463
     */
464
    public function preview(): string
465
    {
466
        return Previewer::preview((string) $this, $this->getValues());
467
    }
468
469
    /**
470
     * Read-only properties.
471
     *
472
     * @param $property
473
     * @return mixed
474
     * @throws \InvalidArgumentException
475
     */
476
    public function __get($property)
477
    {
478
        if (!\property_exists($this, $property)) {
479
            throw new \InvalidArgumentException(\sprintf('Property %s::$%s does not exist.', __CLASS__, $property));
480
        }
481
        return $this->{$property};
482
    }
483
}
484