Completed
Pull Request — master (#6)
by Kris
02:53
created

SelectBase::max()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 8
rs 10
1
<?php
2
3
/*
4
 *   ____         _          _
5
 *  |  _ \  __ _ | |_  __ _ | |__    __ _  ___   ___
6
 *  | |_) |/ _` || __|/ _` || '_ \  / _` |/ __| / _ \
7
 *  |  __/| (_| || |_| (_| || |_) || (_| |\__ \|  __/
8
 *  |_|    \__,_| \__|\__,_||_.__/  \__,_||___/ \___|
9
 *  
10
 * This file is part of Kristuff\Patabase.
11
 *
12
 * (c) Kristuff <[email protected]>
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 *
17
 * @version    0.5.0
18
 * @copyright  2017-2020 Kristuff
19
 */
20
21
namespace Kristuff\Patabase\Query;
22
23
use Kristuff\Patabase\Query;
24
use Kristuff\Patabase\Query\QueryBuilder;
25
26
/**
27
 * Class SelectBase
28
 * 
29
 * Abstract base class for Select
30
 */
31
abstract class SelectBase extends QueryBuilder
32
{
33
34
    /**
35
     * Use DISTINCT or not?
36
     *
37
     * @access protected
38
     * @var    boolean
39
     */
40
    protected $distinct = false;
41
42
    /**
43
     * Columns list for SELECT query
44
     *
45
     * @access protected
46
     * @var    array
47
     */
48
    protected $columns = array();
49
50
    /**
51
     * Table source for SELECT query
52
     *
53
     * @access protected
54
     * @var    array
55
     */
56
    protected $fromTable = '';
57
58
    /**
59
     * SQL JOINS internal list
60
     *
61
     * @access protected
62
     * @var    array
63
     */
64
    protected $joins = array();
65
66
    /**
67
     * SQL GROUP BY internal list
68
     *
69
     * @access protected
70
     * @var    array
71
     */
72
    protected $groupBy = array();
73
74
    /**
75
     * SQL ORDER BY internal list
76
     *
77
     * @access protected
78
     * @var    array
79
     */
80
    protected $orderBy = array();
81
82
    /**
83
     * Limit for the SELECT query
84
     *
85
     * @access protected
86
     * @var    int
87
     */
88
    protected $limit = 0;
89
90
    /**
91
     * Offset for the SELECT query
92
     *
93
     * @access protected
94
     * @var    int
95
     */
96
    protected $offset = 0;
97
98
    /**
99
     * The top QueryBuilder instance, in case of subquery
100
     *
101
     * @access protected
102
     * @var    QueryBuilder
103
     */
104
     protected $topQuery = null;
105
106
    /**
107
     * Constructor
108
     *
109
     * @access public
110
     * @param  Driver\DatabaseDriver   $driver   The driver instance
0 ignored issues
show
Bug introduced by
The type Kristuff\Patabase\Query\Driver\DatabaseDriver was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
111
     * @param  Query        $query    The top query parent in case of subquery. Default is NULL
112
     * @param  array        $args     Columns arguments. Default is empty array
113
     */
114
    public function __construct($driver, $query = null, $args = array())
115
    {
116
        parent::__construct($driver);
117
        $this->topQuery = $query;
118
119
        // columns arguments
120
        if (! empty($args)) {
121
            $this->parseColumnsArguments($args);
122
        }
123
    }
124
125
   /**
126
     * Parse the columns arguments for the select query
127
     *
128
     * @access protected
129
     * @param  mixed        $args       The output columns argument
130
     *
131
     * @return void
132
     */
133
    protected function parseColumnsArguments(array $args)
134
    {
135
        // args could be list of name, or one argument indexed array name => alias
136
        $cols = (count($args) === 1 && is_array($args[0])) ? $args[0] : $args;
137
138
        // parse column
139
        foreach ($cols as $key => $value){
140
            
141
            // Each arg could be a non indexed array of name, or 
142
            // an indexed array name => alias
143
            $column = !is_int($key) ? $key : $value;
144
            $columnValue = !is_int($key) ? $value : null;
145
            $this->column($column, $columnValue);
146
        }
147
    }
148
149
    /**
150
     * Define the used of DISTINCT keyword 
151
     *
152
     * @access public
153
     * @return $this
154
     */
155
    public function distinct()
156
    {
157
        $this->distinct = true;
158
        return $this;
159
    }
160
161
    /**
162
     * Add an output column for the select
163
     *
164
     * @access public
165
     * @param  string   $column    The column name, could be Table.ColumnName format
166
     * @param  string   $alias     The alias for this column
167
     * 
168
     * @return $this
169
     */
170
    public function column($column, $alias = null)
171
    {
172
        $this->columns[] = array(
173
            'type'  => 'column',
174
            'name'  => $column, 
175
            'alias' => $alias);
176
        return $this;
177
    }
178
179
    /**
180
     * Define the outputs columns for the select
181
     *
182
     * @access public
183
     * @return $this
184
     */
185
    public function columns()
186
    {
187
        // args could be list of name, of one argument indexed array name => alias
188
        $args = func_get_args();
189
        $this->parseColumnsArguments($args);
190
        return $this;
191
    }
192
193
    /**
194
     * Add a COUNT(*) column for the select
195
     *
196
     * @access public
197
     * @param  string   $alias     The alias for this column
198
     * 
199
     * @return $this
200
     */
201
    public function count($alias)
202
    {
203
         $this->columns[] = array(
204
            'type'  => 'count',
205
            'alias' => $alias
206
        );
207
        return $this;
208
    }
209
210
    /**
211
     * Add a SUM(column) for the select
212
     *
213
     * @access public
214
     * @param  string $column   The column to sum
215
     * @param  string $alias    The alias for this column 
216
     * @return $this
217
     */
218
    public function sum($column, $alias)
219
    {
220
         $this->columns[] = array(
221
            'type'  => 'sum',
222
            'name'  => $column,
223
            'alias' => $alias
224
        );
225
        return $this;
226
    }
227
228
    /**
229
     * Add a MIN(column) for the select
230
     *
231
     * @access public
232
     * @param  string $column   The column to sum
233
     * @param  string $alias    The alias for this column 
234
     * @return $this
235
     */
236
    public function min($column, $alias)
237
    {
238
         $this->columns[] = array(
239
            'type'  => 'min',
240
            'name'  => $column,
241
            'alias' => $alias
242
        );
243
        return $this;
244
    }
245
246
    /**
247
     * Add a MAX(column) for the select
248
     *
249
     * @access public
250
     * @param  string $column   The column to sum
251
     * @param  string $alias    The alias for this column 
252
     * @return $this
253
     */
254
    public function max($column, $alias)
255
    {
256
         $this->columns[] = array(
257
            'type'  => 'max',
258
            'name'  => $column,
259
            'alias' => $alias
260
        );
261
        return $this;
262
    }
263
264
    /**
265
     * Create and returns a new sub Select instance
266
     *
267
     * @access public
268
     * @param  string $alias    The alias for this query 
269
     *
270
     * @return Query\Select 
271
     */
272
    public function select($alias)
273
    {
274
        $query = new Select($this->driver, $this);
275
        $this->columns[] = array(
276
            'type' => 'sub_query',
277
            'query' => $query,
278
            'alias' => $alias,
279
        );
280
        return $query;
281
    }
282
283
    /**
284
     * Define the FROM tableName
285
     *
286
     * @access public
287
     * @param  string   $tableName      The table name
288
     *
289
     * @return $this
290
     */
291
    public function from($tableName)
292
    {
293
        $this->fromTable = $tableName;
0 ignored issues
show
Documentation Bug introduced by
It seems like $tableName of type string is incompatible with the declared type array of property $fromTable.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
294
        return $this;       
295
    }
296
   
297
    /**
298
     * Left join
299
     *
300
     * @access public
301
     * @param  string   $externalTable    Join table
302
     * @param  string   $externalColumn   Foreign key on the join table
303
     * @param  string   $localTable       Local table
304
     * @param  string   $localColumn      Local column
305
     *
306
     * @return $this
307
     */
308
    public function leftJoin($externalTable, $externalColumn, $localTable, $localColumn)
309
    {
310
        $this->joins[] = sprintf(
311
            'LEFT OUTER JOIN %s ON %s=%s',
312
            $this->driver->escape($externalTable),
313
            $this->driver->escape($localTable).'.'.$this->driver->escape($localColumn),
314
            $this->driver->escape($externalTable).'.'.$this->driver->escape($externalColumn)
315
        );
316
        return $this;
317
    }
318
319
    /**
320
     * Right join
321
     *
322
     * @access public
323
     * @param  string   $externalTable    Join table
324
     * @param  string   $externalColumn   Foreign key on the join table
325
     * @param  string   $localTable       Local table
326
     * @param  string   $localColumn      Local column
327
     *
328
     * @return $this
329
     */
330
    public function rightJoin($externalTable, $externalColumn, $localTable, $localColumn)
331
    {
332
        $this->joins[] = sprintf(
333
            'RIGHT OUTER JOIN %s ON %s=%s',
334
            $this->driver->escape($externalTable),
335
            $this->driver->escape($localTable).'.'.$this->driver->escape($localColumn),
336
            $this->driver->escape($externalTable).'.'.$this->driver->escape($externalColumn)
337
        );
338
        return $this;
339
    }
340
341
    /**
342
     * Full join
343
     *
344
     * @access public
345
     * @param  string   $externalTable    Join table
346
     * @param  string   $externalColumn   Foreign key on the join table
347
     * @param  string   $localTable       Local table
348
     * @param  string   $localColumn      Local column
349
     *
350
     * @return $this
351
     */
352
    public function fullJoin($externalTable, $externalColumn, $localTable, $localColumn)
353
    {
354
        $this->joins[] = sprintf(
355
            'FULL OUTER JOIN %s ON %s=%s',
356
            $this->driver->escape($externalTable),
357
            $this->driver->escape($localTable).'.'.$this->driver->escape($localColumn),
358
            $this->driver->escape($externalTable).'.'.$this->driver->escape($externalColumn)
359
        );
360
        return $this;
361
    }       
362
    
363
    /**
364
     * Inner join
365
     *
366
     * @access public
367
     * @param  string   $externalTable    Join table
368
     * @param  string   $externalColumn   Foreign key on the join table
369
     * @param  string   $localTable       Local table
370
     * @param  string   $localColumn      Local column
371
     *
372
     * @return $this
373
     */
374
    public function innerJoin($externalTable, $externalColumn, $localTable, $localColumn)
375
    {
376
        $this->joins[] = sprintf(
377
            'INNER JOIN %s ON %s=%s',
378
            $this->driver->escape($externalTable),
379
            $this->driver->escape($localTable).'.'.$this->driver->escape($localColumn),
380
            $this->driver->escape($externalTable).'.'.$this->driver->escape($externalColumn)
381
        );
382
        return $this;
383
    }
384
385
    /**
386
     * join (alias for innerJoin)
387
     *
388
     * @access public
389
     * @param  string   $externalTable    Join table
390
     * @param  string   $externalColumn   Foreign key on the join table
391
     * @param  string   $localTable       Local table
392
     * @param  string   $localColumn      Local column
393
     *
394
     * @return $this
395
     */
396
    public function join($externalTable, $externalColumn, $localTable, $localColumn)
397
    {
398
        return $this->innerJoin($externalTable, $externalColumn, $localTable, $localColumn);
399
    }
400
401
    /**
402
     * Get a WHERE statement object
403
     *
404
     * @access public
405
     * @return Query\Where
406
     */
407
    public function where()
408
    {
409
        if (!isset($this->where)){
410
            $this->where = new Query\Where($this, $this->driver, $this->topQuery);
411
        }
412
        return $this->where; 
413
    }
414
415
    /**
416
     * Add a WHERE column = value condition
417
     * It's an alias for ->where()->equal($column, $value)
418
     * 
419
     * @access public
420
     * @return Query\Where
421
     */
422
    public function whereEqual($column, $value)
423
    {
424
        $this->where()->equal($column, $value);
425
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Kristuff\Patabase\Query\SelectBase which is incompatible with the documented return type Kristuff\Patabase\Query\Where.
Loading history...
426
    }
427
    
428
    /**
429
     * Get an HAVING statement object
430
     *
431
     * @access public
432
     * @return Query\Having
433
     */
434
    public function having()
435
    {
436
        if (!isset($this->having)){
437
            $this->having = new Query\Having($this, $this->driver, $this->topQuery);
438
        }
439
        return $this->having; 
440
    }
441
442
    /**
443
     * Define the GROUP BY 
444
     *
445
     * @access public
446
     * @param  mixed 
447
     * @return $this
448
     */
449
    public function groupBy()
450
    {
451
        $this->groupBy = func_get_args();
452
        return $this;
453
    }
454
        
455
    /**
456
     * Add an ORDER BY statement
457
     *
458
     * @access public
459
     * @param  string   $column    Column name
460
     * @param  string   $order     Direction ASC or DESC or custom function
461
     *
462
     * @return $this
463
     */
464
    public function orderBy($column, $order = self::SORT_ASC)
465
    {
466
        $this->orderBy[] = array(
467
            'column' => $column,
468
            'order'  => $order
469
        );
470
        return $this;
471
    }
472
        
473
    /**
474
     * Add an ORDER BY [X] ASC statement
475
     *
476
     * @access public
477
     * @param  string   $column    The column name
478
     * @return $this
479
     */
480
    public function orderAsc($column)
481
    {   
482
        $this->orderBy($column, self::SORT_ASC);
483
        return $this;
484
    }
485
486
    /**
487
     * Add an ORDER BY [X] DESC statement
488
     *
489
     * @access public
490
     * @param  string   $column    The column name
491
     * @return $this
492
     */
493
    public function orderDesc($column)
494
    {
495
        $this->orderBy($column, self::SORT_DESC);
496
        return $this;
497
    }
498
499
    /**
500
     * Add an ORDER BY *random function* statement
501
     *
502
     * @access public
503
     * @param  int      $seed    (optional) The random seed.
504
     *
505
     * @return $this
506
     */
507
    public function orderRand($seed = null)
508
    {
509
        $this->orderBy(NULL, $this->driver->sqlRandom($seed));
0 ignored issues
show
Unused Code introduced by
The call to Kristuff\Patabase\Driver...baseDriver::sqlRandom() has too many arguments starting with $seed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

509
        $this->orderBy(NULL, $this->driver->/** @scrutinizer ignore-call */ sqlRandom($seed));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
510
        return $this;
511
    }
512
513
    /**
514
     * Define the query LIMIT
515
     *
516
     * @access public
517
     * @param  int       $value    The limit value
518
     * 
519
     * @return $this
520
     */
521
    public function limit($value)
522
    {
523
        if (! is_null($value)) {
0 ignored issues
show
introduced by
The condition is_null($value) is always false.
Loading history...
524
            $this->limit = (int) $value;
525
        }
526
        return $this;
527
    }
528
529
    /**
530
     * Define the query OFFSET
531
     *
532
     * @access public
533
     * @param  int      $value      The offset value
534
     *
535
     * @return $this
536
     */
537
    public function offset($value)
538
    {
539
        if (! is_null($value)) {
0 ignored issues
show
introduced by
The condition is_null($value) is always false.
Loading history...
540
            $this->offset = (int) $value;
541
        }
542
        return $this;
543
    }
544
}