Passed
Push — master ( 54d8cd...312ae5 )
by RN
01:37
created

Dolphin   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 475
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 215
c 1
b 0
f 1
dl 0
loc 475
rs 4.5599
wmc 58

31 Methods

Rating   Name   Duplication   Size   Complexity  
A whereNotNull() 0 5 1
A buildAllWhereQuery() 0 8 1
A having() 0 5 1
A leftJoin() 0 5 1
A limit() 0 5 1
B buildQuery() 0 54 9
A buildAllJoinQuery() 0 7 1
A selectRaw() 0 15 3
A offset() 0 5 1
A query() 0 19 5
A insert() 0 4 1
A orderBy() 0 5 1
A rightJoin() 0 5 1
A delete() 0 15 2
A whereIn() 0 5 1
A whereNull() 0 5 1
A prepare() 0 30 4
A get() 0 3 1
A count() 0 7 1
A select() 0 16 3
A update() 0 24 3
A find() 0 5 1
A groupBy() 0 5 1
A reset() 0 19 1
A truncate() 0 12 2
A whereNotIn() 0 5 1
A first() 0 11 2
A findOrFail() 0 11 2
A join() 0 5 1
A where() 0 12 3
A crossJoin() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Dolphin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Dolphin, and based on these observations, apply Extract Interface, too.

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