Completed
Push — master ( fd7b38...04d014 )
by Midori
13:17
created

QueryMaker::checkInitialized()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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