Completed
Push — master ( 7528f1...a676a1 )
by Restu
14:16
created

GrammarMySql::limit()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 13
rs 8.8571
1
<?php
2
namespace JayaCode\Framework\Core\Database\Query\Grammar;
3
4
use JayaCode\Framework\Core\Database\Query\Query;
5
use Stringy\Stringy;
6
7
/**
8
 * Class GrammarMySql
9
 * @package JayaCode\Framework\Core\Database\Query\Grammar
10
 */
11
class GrammarMySql extends Grammar
12
{
13
14
    /**
15
     * @return string
16
     */
17
    public function build()
18
    {
19
        switch ($this->query->getType()) {
20
            case Query::TYPE_SELECT:
21
                return $this->select();
22
23
            case Query::TYPE_INSERT:
24
                return $this->insert();
25
26
            case Query::TYPE_UPDATE:
27
                return $this->update();
28
29
            case Query::TYPE_DELETE:
30
                return $this->delete();
31
32
            case Query::TYPE_QUERY:
33
                return $this->query->query;
34
        }
35
        return null;
36
    }
37
38
    /**
39
     * @return string
40
     */
41
    private function select()
42
    {
43
        $this->queryString = "SELECT ";
44
45
        $this->queryString .= $this->selectColumn();
46
47
        $table = $this->query->table;
48
        $this->queryString .= " FROM {$this->getFormattedTableOrColumn($table)}";
49
50
        $this->queryString .= $this->where();
51
        
52
        $this->queryString .= $this->sort();
53
        $this->queryString .= $this->limit();
54
55
        return $this->queryString;
56
    }
57
58
    /**
59
     * @return string
60
     */
61
    private function selectColumn()
62
    {
63
        $columns = $this->query->columns;
64
        if (is_null($columns)) {
65
            $columns = [Query::sql("*")];
66
        }
67
68
        if (is_string($columns)) {
69
            $columns = array($columns);
70
        }
71
72
        foreach ($columns as $key => $val) {
73
            if ($columns[$key] instanceof Query) {
74
                $columns[$key] = $columns[$key]->query;
75
            } else {
76
                $columns[$key] = $this->getFormattedTableOrColumn($val);
77
            }
78
        }
79
80
        return implode(', ', $columns);
81
    }
82
83
    /**
84
     * @return string
85
     */
86
    private function where()
87
    {
88
        if (count($this->query->where) <= 0) {
89
            return "";
90
        }
91
92
        $q = Stringy::create("");
93
94
        foreach ($this->query->where as $where) {
95
            $type = $where[0];
96
            $arr = $where[1];
97
98
            if ($q->count() > 1) {
99
                $q = $q->append(" {$type} ");
100
            }
101
102
            if (is_string($arr)) {
103
                $q = $q->append($arr);
104
            }
105
106
            if (is_array($arr)) {
107
                $q = $q->append($this->buildArrWhere($arr));
108
109
                $this->params[] = $arr[2];
110
            }
111
        }
112
113
        return $q->count()?$q->prepend(" WHERE ")->__toString():"";
114
    }
115
116
    /**
117
     * @return string
118
     */
119
    private function sort()
120
    {
121
        if (empty($this->query->sort)) {
122
            return "";
123
        }
124
125
        $sort = $this->query->sort;
126
127
        if (!isset($sort['column']) || !isset($sort['order'])) {
128
            return "";
129
        }
130
131
        return " ORDER BY {$this->getFormattedTableOrColumn($sort['column'])} {$sort['order']}";
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    private function limit()
138
    {
139
        if (empty($this->query->limit) || !is_numeric($this->query->limit)) {
140
            return "";
141
        }
142
143
        $str = " LIMIT {$this->query->limit}";
144
145
        if ($this->query->offset && is_numeric($this->query->offset)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->query->offset of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
146
            $str .= " OFFSET {$this->query->offset}";
147
        }
148
        return $str;
149
    }
150
151
    /**
152
     * @param $arr
153
     * @return string
154
     */
155
    private function buildArrWhere($arr)
156
    {
157
        if (count($arr) != 3) {
158
            throw new \OutOfBoundsException();
159
        }
160
161
        switch ($arr[1]) {
162
            case "BETWEEN":
163
                return "`{$arr[0]}` {$arr[1]} ? AND ?";
164
            default:
165
                return "`{$arr[0]}` {$arr[1]} ?";
166
        }
167
    }
168
169
    /**
170
     * @return string
171
     */
172
    private function insert()
173
    {
174
175
        $this->params = $this->query->values;
176
177
        $table = $this->query->table;
178
        $this->queryString = "INSERT INTO {$this->getFormattedTableOrColumn($table)}";
179
180
        $this->queryString .= "({$this->selectColumn()})";
181
182
        $this->queryString .= " VALUES(";
183
184
        $params = array();
185
186
        for ($i=0, $c=count($this->query->columns); $i<$c; $i++) {
187
            $params[$i] = "?";
188
        }
189
190
        $this->queryString .= join(', ', $params).")";
191
192
        return $this->queryString;
193
    }
194
195
    /**
196
     * @return string
197
     */
198
    private function update()
199
    {
200
        $this->params = $this->query->values;
201
202
        $table = $this->query->table;
203
        $this->queryString = "UPDATE {$this->getFormattedTableOrColumn($table)} SET ";
204
205
        $arrSet = array();
206
        foreach ($this->query->columns as $column) {
207
            $arrSet[] = "{$this->getFormattedTableOrColumn($column)} = ?";
208
        }
209
        $this->queryString .= join(", ", $arrSet);
210
211
        $this->queryString .= $this->where();
212
213
        return $this->queryString;
214
    }
215
216
    /**
217
     * @return string
218
     */
219
    private function delete()
220
    {
221
        $table = $this->query->table;
222
        $this->queryString = "DELETE FROM {$this->getFormattedTableOrColumn($table)}";
223
        $this->queryString .= $this->where();
224
225
        return $this->queryString;
226
    }
227
228
    /**
229
     * @param null $str
230
     * @return null|string
231
     */
232
    private function getFormattedTableOrColumn($str = null)
233
    {
234
        $tmpStr = $str?$str:$this->query->table;
235
        $strArr = explode(".", $tmpStr);
236
237
        foreach ($strArr as $key => $val) {
238
            $strArr[$key] = "`{$val}`";
239
        }
240
241
        return join(".", $strArr);
242
    }
243
}
244