Passed
Push — master ( dd8496...f181bd )
by RN
01:45
created

Dolphin::validateArgsCount()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * The Query builder API.
4
 *
5
 * @author RN Kushwaha <[email protected]>
6
 * @since v0.0.1 <Date: 12th April, 2019>
7
 */
8
9
namespace Dolphin\Mapper;
10
11
use Dolphin\Connections\Connection;
12
use Dolphin\Builders\QueryBuilder;
13
use Dolphin\Builders\WhereQueryBuilder;
14
use Dolphin\Builders\InsertQueryBuilder;
15
use Dolphin\Parsers\WhereQueryParser;
16
use Dolphin\Utils\Utils;
17
use \Exception;
18
19
/**
20
 * This class provides some nice features to interact with the Database
21
 * Elegant Query builder
22
 * Method Chaining
23
 * Prepared Statement using named parameter like status = :status
24
 * Raw Query Option
25
 * Join Clause
26
 * Where Clause
27
 * WhereRaw Clause
28
 * orWhere Clause [TODO]
29
 * WhereIn Clause
30
 * WhereNotIn Clause
31
 * WhereNull Clause
32
 * WhereNotNull Clause
33
 * GroupBy Clause
34
 * Having Clause
35
 * OrderBy Clause.
36
 *
37
 * Aggregations like
38
 * Count()
39
 * Max() [TODO]
40
 * Min() [TODO]
41
 * First()
42
 * Last() [TODO]
43
 * Avg() [TODO]
44
 * fetchColumn [TODO]
45
 * union() [TODO]
46
 * delete()
47
 * update()
48
 * insert()
49
 * truncate()
50
 * havingRaw() [TODO]
51
 * exists() [TODO]
52
 */
53
class Dolphin
54
{
55
    protected $fields = array();
56
    public $table;
57
    public $className;
58
    protected $groupBy;
59
    protected $orderBy;
60
    protected $having;
61
    protected $join = array();
62
    protected $leftJoin = array();
63
    protected $rightJoin = array();
64
    protected $crossJoin = array();
65
    protected $where = array();
66
    protected $whereRaw = array();
67
    protected $whereIn = array();
68
    protected $whereNotIn = array();
69
    protected $whereNull = array();
70
    protected $whereNotNull = array();
71
    protected $limit;
72
    protected $offset;
73
    protected $results;
74
75
    private function getFields(array $args, bool $quote = true){
76
        $fldAr = array();
77
        $qb = new QueryBuilder();
78
79
        foreach ($args as $arg) {
80
            foreach (explode(',', $arg) as $ar) {
81
                $fldAr[] = ($quote === true) ? $qb->quote(trim($ar)) : trim($ar);
82
            }
83
        }
84
85
        return $fldAr;
86
    }
87
88
    private function validateArgsCount($noOfArgs){
89
        if($noOfArgs<2 || $noOfArgs >3){
90
            throw new Exception('Where parameter contains invalid number of parameters', 1);
91
        }
92
    }
93
94
    public function select()
95
    {
96
        $args = func_get_args();
97
        $fldAr = $this->getFields($args, true);
98
        $this->fields = array_merge($this->fields, $fldAr);
99
100
        return $this;
101
    }
102
103
    public function selectRaw()
104
    {
105
        $args = func_get_args();
106
        $fldAr = $this->getFields($args, false);
107
        $this->fields = array_merge($this->fields, $fldAr);
108
109
        return $this;
110
    }
111
112
    public function join($join, $mixedParam, $param3 = null, $param4 = null, $mixedParam2 = null)
113
    {
114
        $this->join = array_merge($this->join, [[$join, $mixedParam, $param3, $param4, $mixedParam2]]);
115
116
        return $this;
117
    }
118
119
    public function leftJoin($leftJoin, $mixedParam, $param3 = null, $param4 = null, $mixedParam2 = null)
120
    {
121
        $this->leftJoin = array_merge($this->leftJoin, [[$leftJoin, $mixedParam, $param3, $param4, $mixedParam2]]);
122
123
        return $this;
124
    }
125
126
    public function rightJoin($rightJoin, $mixedParam, $param3 = null, $param4 = null, $mixedParam2 = null)
127
    {
128
        $this->rightJoin = array_merge($this->rightJoin, [[$rightJoin, $mixedParam, $param3, $param4, $mixedParam2]]);
129
130
        return $this;
131
    }
132
133
    public function crossJoin($crossJoin, $params = null)
134
    {
135
        $this->crossJoin = array_merge($this->crossJoin, [[$crossJoin, $params]]);
136
137
        return $this;
138
    }
139
140
    /**
141
     * @throws Exception
142
     */
143
    public function where()
144
    {
145
        $args = func_get_args();
146
        $noOfArgs = func_num_args();
147
148
        $this->validateArgsCount($noOfArgs);
149
150
        if($noOfArgs===2){
151
            $this->where = array_merge($this->where, [[$args[0], '=', $args[1]]]);
152
            return $this;
153
        }
154
155
        $this->where = array_merge($this->where, [[$args[0], $args[1], $args[2]]]);
156
        return $this;
157
    }
158
159
    public function whereIn($whereIn, $params = array())
160
    {
161
        $this->whereIn = array_merge($this->whereIn, [[$whereIn, $params]]);
162
163
        return $this;
164
    }
165
166
    public function whereNotIn($whereNotIn, $params = array())
167
    {
168
        $this->whereNotIn = array_merge($this->whereNotIn, [[$whereNotIn, $params]]);
169
170
        return $this;
171
    }
172
173
    public function whereNull($whereNull)
174
    {
175
        $this->whereNull = array_merge($this->whereNull, [$whereNull]);
176
177
        return $this;
178
    }
179
180
    public function whereNotNull($whereNotNull)
181
    {
182
        $this->whereNotNull = array_merge($this->whereNotNull, [$whereNotNull]);
183
184
        return $this;
185
    }
186
187
    public function whereRaw($whereConditions)
188
    {
189
        $this->whereRaw = array_merge($this->whereRaw, [$whereConditions]);
190
191
        return $this;
192
    }
193
194
    public function offset($offset)
195
    {
196
        $this->offset = $offset;
197
198
        return $this;
199
    }
200
201
    public function limit($limit)
202
    {
203
        $this->limit = $limit;
204
205
        return $this;
206
    }
207
208
    public function orderBy($orderBy)
209
    {
210
        $this->orderBy = $orderBy;
211
212
        return $this;
213
    }
214
215
    public function groupBy($groupBy)
216
    {
217
        $this->groupBy = $groupBy;
218
219
        return $this;
220
    }
221
222
    public function having($having)
223
    {
224
        $this->having = $having;
225
226
        return $this;
227
    }
228
229
    /**
230
     * Builds Query added by method chaining.
231
     * It has the main logic of ORM
232
     */
233
    protected function buildQuery()
234
    {
235
        $qb     = new QueryBuilder();
236
237
        $query  = $qb->buildQuery([
238
            'table' => $this->table,
239
            'fields' => $this->fields,
240
            'join' => $this->join,
241
            'leftJoin' => $this->leftJoin,
242
            'rightJoin' => $this->rightJoin,
243
            'crossJoin' => $this->crossJoin,
244
            'where' => $this->where,
245
            'whereRaw' => $this->whereRaw,
246
            'whereIn' => $this->whereIn,
247
            'whereNotIn' => $this->whereNotIn,
248
            'whereNull' => $this->whereNull,
249
            'whereNotNull' => $this->whereNotNull,
250
            'groupBy' => $this->groupBy,
251
            'having' => $this->having,
252
            'orderBy' => $this->orderBy,
253
            'limit' => $this->limit,
254
            'offset' => $this->offset
255
        ]);
256
257
        return join(' ', $query);
258
    }
259
260
    protected function reset()
261
    {
262
        $this->fields = array();
263
        $this->table = null;
264
        $this->className = null;
265
        $this->groupBy = null;
266
        $this->orderBy = null;
267
        $this->having = null;
268
        $this->join = array();
269
        $this->leftJoin = array();
270
        $this->rightJoin = array();
271
        $this->crossJoin = array();
272
        $this->where = array();
273
        $this->whereRaw = array();
274
        $this->whereIn = array();
275
        $this->whereNotIn = array();
276
        $this->whereNull = array();
277
        $this->whereNotNull = array();
278
        $this->limit = null;
279
        $this->offset = null;
280
    }
281
282
    public function prepare($query, $fetchRows = 'all')
283
    {
284
        $qb   = new QueryBuilder();
285
        $wqp  = new WhereQueryParser();
286
        $util = new Utils();
287
        $rows = null;
288
289
        try {
290
            $ar = $wqp->parseWhereQuery($this->where);
291
            $stmt = Connection::get()->prepare($qb->queryPrefix($query));
292
            $stmt->execute($ar);
293
294
            if ($fetchRows == 'first') {
295
                $this->results = $stmt->fetch(\PDO::FETCH_OBJ);
296
            } else{
297
                $this->results = $stmt->fetchAll(\PDO::FETCH_ASSOC);
298
            }
299
300
            if(count($this->results) ){
301
              // now turn this stdClass object to the object type of calling model
302
              $rows = $util->turnObjects($this->className, $this->results);
303
            }
304
            // Reset class variables
305
            $this->reset();
306
307
            return $rows;
308
        } catch (\PDOException $ex) {
309
            throw new \PDOException($ex->getMessage(), 1);
310
        } catch (Exception $e) {
311
            throw new Exception($e->getMessage(), 1);
312
        }
313
    }
314
315
    public function query($query, $fetchRows = 'all')
316
    {
317
        $qb = new QueryBuilder();
318
319
        try {
320
            $obj = Connection::get()->query($qb->queryPrefix($query), \PDO::FETCH_OBJ);
321
322
            if ($fetchRows == 'count') {
323
                $obj = $obj->fetchColumn();
324
            }
325
326
            // Reset class variables
327
            $this->reset();
328
329
            return $obj;
330
        } catch (\PDOException $ex) {
331
            throw new \PDOException($ex->getMessage(), 1);
332
        } catch (Exception $e) {
333
            throw new Exception($e->getMessage(), 1);
334
        }
335
    }
336
337
    public function get()
338
    {
339
        return $this->prepare($this->buildQuery());
340
    }
341
342
    public function first()
343
    {
344
        $query = $this->buildQuery();
345
346
        if (!strripos($query, 'LIMIT 1')) {
347
            $query .= ' LIMIT 1';
348
        }
349
350
        return $this->prepare($query, 'first');
351
    }
352
353
    public function all()
354
    {
355
        $query = $this->buildQuery();
356
357
        return $this->prepare($query);
358
    }
359
360
    /**
361
     * It fetches the row by primary key
362
     *
363
     * @since v0.0.5
364
     */
365
    public function find($id)
366
    {
367
        $this->where('id', $id);
368
369
        return $this->first();
370
    }
371
372
    /**
373
     * It fetches the row by primary key
374
     *
375
     * @param int $id
376
     * @return object $row
377
     * @throws Exception
378
     * @since v0.0.5
379
     */
380
    public function findOrFail($id)
381
    {
382
        $this->where('id', $id);
383
384
        $row = $this->first();
385
386
        if($row == null ){
387
            throw new Exception("The record does not exists!");
388
        }
389
390
        return $row;
391
    }
392
393
    public function count()
394
    {
395
        $this->fields = null;
396
        $query = $this->buildQuery();
397
        $query = str_replace('SELECT * ', 'SELECT COUNT(*) as count ', $query);
398
399
        return $this->query($query, 'count');
400
    }
401
402
    /**
403
     * It truncates the table
404
     *
405
     * @return boolean
406
     * @throws Exception
407
     * @since v0.0.5
408
     */
409
    public function truncate()
410
    {
411
        $qb = new QueryBuilder();
412
        $query = "TRUNCATE ".$this->table;
413
414
        try{
415
            Connection::get()->query($qb->queryPrefix($query));
416
        } catch(Exception $e){
417
            throw new Exception($e->getMessage());
418
        }
419
420
        return true;
421
    }
422
423
    /**
424
     * It inserts the new rows
425
     *
426
     * @param array $rows
427
     * @return integer $lastInsertedId
428
     * @throws Exception
429
     * @since v0.0.5
430
     */
431
    public function insert($rows)
432
    {
433
        $iqb = new InsertQueryBuilder();
434
        return $iqb->insert($rows, $this->table);
435
    }
436
437
    /**
438
     * It updates the rows
439
     *
440
     * @param array $row
441
     * @return boolean
442
     * @throws Exception
443
     * @since v0.0.5
444
     */
445
    public function update($row)
446
    {
447
        $qb    = new QueryBuilder();
448
        $wqb   = new WhereQueryBuilder();
449
        $query = "UPDATE ".$this->table." SET ";
450
        $ar    = array();
451
452
        foreach($row as $key => $val){
453
            $ar[':'.$key] = $val;
454
            $query.= $qb->quote($key)." =:".$key.",";
455
        }
456
457
        $query = rtrim($query, ",");
458
459
        try{
460
            $whereQuery = $wqb->buildAllWhereQuery(
461
                                $this->where,
462
                                $this->whereRaw,
463
                                $this->whereIn,
464
                                $this->whereNotIn,
465
                                $this->whereNull,
466
                                $this->whereNotNull
467
                            );
468
            $query.= " ".join(" ", $whereQuery);
469
            $stmt = Connection::get()->prepare($qb->queryPrefix($query));
470
            $stmt->execute($ar);
471
            $this->reset();
472
        } catch(Exception $e){
473
            throw new Exception($e->getMessage());
474
        }
475
476
        return true;
477
    }
478
479
    /**
480
     * It deleted the rows matched by where clause
481
     *
482
     * @return boolean
483
     * @throws Exception
484
     * @since v0.0.5
485
     */
486
    public function delete()
487
    {
488
        $qb = new QueryBuilder();
489
        $wqb = new WhereQueryBuilder();
490
        $query = "DELETE FROM ".$this->table;
491
492
        try{
493
            $whereQuery = $wqb->buildAllWhereQuery(
494
                                    $this->where,
495
                                    $this->whereRaw,
496
                                    $this->whereIn,
497
                                    $this->whereNotIn,
498
                                    $this->whereNull,
499
                                    $this->whereNotNull
500
                                );
501
            $query.= " ".join(" ", $whereQuery);
502
            Connection::get()->query($qb->queryPrefix($query));
503
            $this->reset();
504
        } catch(Exception $e){
505
            throw new Exception($e->getMessage());
506
        }
507
508
        return true;
509
    }
510
511
}
512