Completed
Push — master ( 7fb6da...ab6536 )
by Jared
05:24
created

WhereStatement   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 18
c 3
b 0
f 0
lcom 1
cbo 1
dl 0
loc 125
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A isHaving() 0 4 1
C addCondition() 0 27 7
A getConditions() 0 4 1
A buildClause() 0 9 4
A build() 0 18 4
1
<?php
2
3
/**
4
 * @author Jared King <[email protected]>
5
 *
6
 * @link http://jaredtking.com
7
 *
8
 * @copyright 2015 Jared King
9
 * @license MIT
10
 */
11
namespace JAQB\Statement;
12
13
class WhereStatement extends Statement
14
{
15
    /**
16
     * @var bool
17
     */
18
    protected $having;
19
20
    /**
21
     * @var array
22
     */
23
    protected $conditions = [];
24
25
    /**
26
     * @param bool $having when true, statement becomes a having statement
27
     */
28
    public function __construct($having = false)
29
    {
30
        $this->having = $having;
31
    }
32
33
    /**
34
     * Tells whether this statement is a HAVING statement.
35
     *
36
     * @return bool true: is HAVING, false: is WHERE
37
     */
38
    public function isHaving()
39
    {
40
        return $this->having;
41
    }
42
43
    /**
44
     * Adds a condition to the statement.
45
     *
46
     * Accepts the following forms:
47
     * 1. Equality comparison:
48
     *      addCondition('username', 'john')
49
     * 2. Comparison with custom operator:
50
     *      addCondition('balance', 100, '>')
51
     * 3. SQL fragment:
52
     *      addCondition('name LIKE "%john%"')
53
     * 4. List of conditions to add:
54
     *      addCondition([['balance', 100, '>'], ['user_id', 5]])
55
     * 5. Map of equality comparisons:
56
     *      addCondition(['username' => 'john', 'user_id' => 5])
57
     * 6. List of SQL fragments:
58
     *      addCondition(['first_name LIKE "%john%"', 'last_name LIKE "%doe%"'])
59
     *
60
     * @param array|string $field
61
     * @param string|bool  $value    condition value (optional)
62
     * @param string       $operator operator (optional)
63
     *
64
     * @return self
65
     */
66
    public function addCondition($field, $value = false, $operator = '=')
67
    {
68
        if (is_array($field) && !$value) {
69
            foreach ($field as $key => $value) {
70
                if (is_array($value)) { // handles #4
71
                    call_user_func_array([$this, 'addCondition'], $value);
72
                } elseif (!is_numeric($key)) { // handles #5
73
                    $this->addCondition($key, $value);
74
                } else { // handles #6
75
                    $this->addCondition($value);
76
                }
77
            }
78
        } else {
79
            // handles #3
80
            $condition = [$field];
81
82
            // handles #1 and #2
83
            if (func_num_args() >= 2) {
84
                $condition[] = $operator;
85
                $condition[] = $value;
86
            }
87
88
            $this->conditions[] = $condition;
89
        }
90
91
        return $this;
92
    }
93
94
    /**
95
     * Gets the conditions for this statement.
96
     *
97
     * @return array
98
     */
99
    public function getConditions()
100
    {
101
        return $this->conditions;
102
    }
103
104
    protected function buildClause(array $clause)
105
    {
106
        // handle NULL values
107
        if (count($clause) === 3 && $clause[1] === '=' && $clause[2] === null) {
108
            return $this->escapeIdentifier($clause[0]).' IS NULL';
109
        }
110
111
        return parent::buildClause($clause);
112
    }
113
114
    /**
115
     * Generates the raw SQL string for the statement.
116
     *
117
     * @return string
118
     */
119
    public function build()
120
    {
121
        $sql = (!$this->having) ? 'WHERE ' : 'HAVING ';
122
123
        $clauses = [];
124
        foreach ($this->conditions as $clause) {
125
            $clauses[] = $this->buildClause($clause);
126
        }
127
128
        // remove empty values
129
        $clauses = array_filter($clauses);
130
131
        if (count($clauses) == 0) {
132
            return '';
133
        }
134
135
        return $sql.implode(' AND ', $clauses);
136
    }
137
}
138