Completed
Push — master ( 719094...023adc )
by Midori
10:14
created

QueryMaker::count()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 15
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 24
ccs 14
cts 14
cp 1
crap 5
rs 9.4555
1
<?php
2
3
declare(strict_types=1);
4
5
namespace midorikocak\querymaker;
6
7
use InvalidArgumentException;
8
9
use function array_keys;
10
use function array_map;
11
use function array_values;
12
use function implode;
13
use function in_array;
14
use function preg_replace;
15
use function uniqid;
16
17
class QueryMaker implements QueryInterface
18
{
19
    private string $query;
20 21
    private string $statement;
21
    private array $params;
22 21
    private string $offset;
0 ignored issues
show
introduced by
The private property $offset is not used, and could be removed.
Loading history...
23 21
    private string $limit;
24 21
    private string $orderBy;
25 21
26
    public function __construct()
27 18
    {
28
        $this->reset();
29 18
    }
30 18
31 18
    private function reset(): void
32 18
    {
33
        $this->query = '';
34
        $this->statement = '';
35 3
        $this->params = [];
36
37 3
        $this->limit = '';
38 3
        $this->orderBy = '';
39 3
    }
40 3
41
    public function select($table, array $columns = ['*']): QueryInterface
42
    {
43 15
        $this->reset();
44
        $columnsText = implode(', ', $columns);
45 15
        $this->statement = 'SELECT ' . $columnsText . ' FROM ' . $table;
46 15
        $this->query = 'SELECT ' . $columnsText . ' FROM ' . $table;
47
        return $this;
48
    }
49 15
50
    public function count($table = null): QueryInterface
51
    {
52 15
        if ($table && $this->query === '') {
53 15
            $this->reset();
54 15
            $this->statement = 'SELECT COUNT(*) FROM ' . $table;
55 15
            $this->query = 'SELECT COUNT(*) FROM ' . $table;
56
            return $this;
57
        }
58 6
59
        if (!$table && $this->query === '') {
60 6
            throw new InvalidArgumentException('Cannot count');
61 6
        }
62 6
63 6
        $query = $this->query;
64
        $statement = $this->statement;
65
        $this->query = preg_replace('/SELECT .*? FROM/', 'SELECT COUNT(*) FROM', $this->query);
66 6
        $this->statement = preg_replace('/SELECT .*? FROM/', 'SELECT COUNT(*) FROM', $this->statement);
67
68 6
        $toReturn = clone $this;
69 6
70 6
        $this->query = $query;
71 6
        $this->statement = $statement;
72
73
        return $toReturn;
74
    }
75
76
    public function update($table, array $values): QueryInterface
77
    {
78
        $this->reset();
79
        $this->statement = 'UPDATE ' . $table . ' SET ';
80
        $this->query = 'UPDATE ' . $table . ' SET ';
81
        $this->prepareParams($values, ', ');
82
        return $this;
83
    }
84 21
85
    public function insert($table, array $values): QueryInterface
86 21
    {
87
        $this->reset();
88
        $fields = implode(', ', array_keys($values));
89 21
        $params = implode(', ', array_map(fn($key) => ':' . $key, array_keys($values)));
90
        $queryValues = implode(', ', array_map(fn($value) => "'$value'", array_values($values)));
91 21
92
        $this->statement = "INSERT INTO $table ($fields) VALUES ($params)";
93
        $this->query = "INSERT INTO $table ($fields) VALUES ($queryValues)";
94
        $this->params = $values;
95
96
        return $this;
97
    }
98
99 12
    public function delete($table): QueryInterface
100
    {
101 12
        $this->reset();
102 12
        $this->statement = 'DELETE FROM ' . $table;
103
        $this->query = 'DELETE FROM ' . $table;
104 12
        return $this;
105 12
    }
106 12
107
    public function where($key, $value, string $operator = '='): QueryInterface
108
    {
109
        $this->checkOperator($operator);
110 12
111
        $this->statement .= ' WHERE ' . $key . ' ' . $operator . ' :' . $key;
112
        $this->query .= ' WHERE ' . $key . ' ' . $operator . ' \'' . $value . '\'';
113 12
        $this->params[$key] = $value;
114 12
        return $this;
115 12
    }
116
117 12
    public function and($key, $value, string $operator = '='): QueryInterface
118
    {
119
        $this->checkOperator($operator);
120
121
        $this->query .= ' AND ';
122
        $this->statement .= ' AND ';
123
        $this->prepareParam($key, $value, 'AND', $operator);
124
        return $this;
125
    }
126
127 12
    public function orderBy($key, string $order = 'ASC'): QueryInterface
128 12
    {
129 12
        if ($order !== 'DESC' && $order !== 'ASC') {
130
            throw new InvalidArgumentException('Invalid order value');
131 9
        }
132
133 9
        $this->orderBy .= ' ORDER BY ' . $key . ' ' . $order;
134 9
        return $this;
135
    }
136
137
    public function limit(int $limit): QueryInterface
138
    {
139
        $this->limit .= ' LIMIT ' . $limit;
140
        return $this;
141
    }
142
143
    public function offset(int $offset): QueryInterface
144
    {
145
        $this->limit .= ' OFFSET ' . $offset;
146
        return $this;
147
    }
148
149
    public function or($key, $value, $operator = '='): QueryInterface
150
    {
151
        $this->checkOperator($operator);
152
153
        $this->query .= " OR ";
154
        $this->statement .= " OR ";
155
        $this->prepareParam($key, $value, 'OR');
156
        return $this;
157
    }
158
159
    public function between($key, $before, $after): QueryInterface
160
    {
161
        $this->query .= $key . " BETWEEN $before AND $after";
162
        $this->statement .= $key . ' BETWEEN :before AND :after';
163
164
        $this->params['before'] = $before;
165
        $this->params['after'] = $after;
166
        return $this;
167
    }
168
169
    public function getQuery(): string
170
    {
171
        return $this->query . $this->orderBy . $this->limit;
172
    }
173
174
    public function getStatement(): string
175
    {
176
        return $this->statement . $this->orderBy . $this->limit;
177
    }
178
179
    public function getParams(): array
180
    {
181
        return $this->params;
182
    }
183
184
    private function prepareParams(array $values, string $glue, string $operator = '=')
185
    {
186
        $this->checkOperator($operator);
187
        $params = [];
188
        $queryValues = [];
189
190
        foreach ($values as $key => $value) {
191
            if (!isset($this->params[$key])) {
192
                $queryValues[] = $key . ' ' . $operator . ' \'' . $value . '\'';
193
                $params [] = $key . ' ' . $operator . ' :' . $key;
194
195
                $this->params[$key] = $value;
196
            } else {
197
                $uniqid = uniqid('', true);
198
                $queryValues[] = $key . ' ' . $operator . ' \'' . $value . '\'';
199
                $params [] = $key . ' ' . $operator . ' :' . $key . $uniqid;
200
201
                $this->params[$key . $uniqid] = $value;
202
            }
203
        }
204
205
        $this->query .= implode($glue, $queryValues);
206
        $this->statement .= implode($glue, $params);
207
    }
208
209
    private function prepareParam(string $key, $value, string $glue, $operator = '='): void
210
    {
211
        $this->prepareParams([$key => $value], $glue, $operator);
212
    }
213
214
    private function checkOperator(string $operator): void
215
    {
216
        $operators = ['=', '>', '>=', '<', '<=', 'LIKE'];
217
        if (!in_array($operator, $operators, true)) {
218
            throw new InvalidArgumentException('Invalid Operator');
219
        }
220
    }
221
}
222