Passed
Push — master ( acba12...b2f89b )
by 世昌
04:15
created

WriteStatement::prepareWhere()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace suda\database\statement;
4
5
use function implode;
6
use function is_array;
7
use function is_string;
8
use function sprintf;
9
use suda\database\Binder;
10
use suda\database\struct\TableStruct;
11
use suda\database\middleware\Middleware;
12
use suda\database\exception\SQLException;
13
14
class WriteStatement extends Statement
15
{
16
    use PrepareTrait;
17
18
    /**
19
     * 数据
20
     *
21
     * @var array|string
22
     */
23
    protected $data;
24
25
    /**
26
     * 数据表结构
27
     *
28
     * @var TableStruct
29
     */
30
    protected $struct;
31
32
    /**
33
     * 数据原始表名
34
     *
35
     * @var string
36
     */
37
    protected $table;
38
39
    /**
40
     * 模板条件条件
41
     *
42
     * @var string|null
43
     */
44
    protected $whereCondition = null;
45
46
    /**
47
     * 是否为删除
48
     *
49
     * @var bool
50
     */
51
    protected $delete = false;
52
53
54
    /**
55
     * 创建写
56
     *
57
     * @param string $rawTableName
58
     * @param TableStruct $struct
59
     * @param Middleware $middleware
60
     * @throws SQLException
61
     */
62
    public function __construct(string $rawTableName, TableStruct $struct, Middleware $middleware)
63
    {
64
        parent::__construct('');
65
        $this->type = self::WRITE;
66
        $this->struct = $struct;
67
        $this->table = $rawTableName;
68
        $this->middleware = $middleware;
69
    }
70
71
    /**
72
     * 写数据
73
     *
74
     * @param string|array $name
75
     * @param mixed $value
76
     * @return $this
77
     * @throws SQLException
78
     */
79
    public function write($name, $value = null)
80
    {
81
        $argcount = func_num_args();
82
        if (is_array($name)) {
83
            foreach ($name as $key => $value) {
84
                $this->write($key, $value);
85
            }
86
        } elseif (is_string($name) && $argcount >= 2) {
87
            $this->prepareWriteField($name, $value);
88
        } else {
89
            $this->data = $name;
90
        }
91
        return $this;
92
    }
93
94
    /**
95
     * 准备字段
96
     *
97
     * @param string $name
98
     * @param mixed $value
99
     * @return void
100
     * @throws SQLException
101
     */
102
    private function prepareWriteField(string $name, $value) {
103
        $name = $this->middleware->inputName($name);
104
        if ($this->struct->hasField($name)) {
105
            $this->data[$name] = $value;
106
        } else {
107
            throw new SQLException(sprintf('table %s has no field %s', $this->struct->getName(), $name));
108
        }
109
    }
110
111
    /**
112
     * 设置影响行数
113
     *
114
     * @return $this
115
     */
116
    public function wantRows()
117
    {
118
        $this->returnType = WriteStatement::RET_ROWS;
119
        return $this;
120
    }
121
122
    /**
123
     * 设置返回是否成功
124
     *
125
     * @return $this
126
     */
127
    public function wantOk()
128
    {
129
        $this->returnType = WriteStatement::RET_BOOL;
130
        return $this;
131
    }
132
133
    /**
134
     * 设置返回ID
135
     *
136
     * @return $this
137
     */
138
    public function wantId()
139
    {
140
        $this->returnType = WriteStatement::RET_LAST_INSERT_ID;
141
        return $this;
142
    }
143
144
    /**
145
     * 删除
146
     *
147
     * @return $this
148
     */
149
    public function delete()
150
    {
151
        $this->delete = true;
152
        return $this;
153
    }
154
155
    /**
156
     * 条件查询
157
     *
158
     * @param string|array $where
159
     * @param array $args
160
     * @return $this
161
     * @throws SQLException
162
     */
163
    public function where($where, ...$args)
164
    {
165
        if (is_string($where)) {
166
            if (count($args) > 0 && is_array($args[0])) {
167
                $whereParameter = $args[0];
168
                $this->whereCondition($where, $whereParameter);
169
            } else {
170
                list($string, $array) = $this->prepareQueryMark($where, $args);
171
                $this->whereCondition($string, $array);
172
            }
173
        } else {
174
            $this->arrayWhereCondition($where, $args[0] ?? []);
175
        }
176
        return $this;
177
    }
178
179
    /**
180
     * 处理输入的键
181
     *
182
     * @param array $fields
183
     * @return array
184
     */
185
    protected function aliasKeyField(array $fields)
186
    {
187
        $values = [];
188
        foreach ($fields as $value) {
189
            $value[0] = $this->middleware->inputName($value[0]);
190
            $values[] = $value;
191
        }
192
        return $values;
193
    }
194
195
    /**
196
     * 获取字符串
197
     *
198
     * @return Query
199
     */
200
    protected function prepareQuery(): Query
201
    {
202
        if (is_array($this->data) && $this->whereCondition === null) {
203
            return $this->prepareInsert($this->data);
204
        } else {
205
            if ($this->delete === false) {
206
                if (is_string($this->data)) {
207
                    $updateSet = trim($this->data);
208
                } else {
209
                    list($updateSet, $upBinder) = $this->prepareUpdateSet($this->data);
210
                    $this->binder = array_merge($this->binder, $upBinder);
211
                }
212
                $string = "UPDATE " . $this->table . " SET " . $updateSet . " WHERE " . $this->whereCondition;
213
                return new Query($string, $this->binder);
214
            } else {
215
                $string = "DELETE FROM " . $this->table . " WHERE " . $this->whereCondition;
216
                return new Query($string, $this->binder);
217
            }
218
        }
219
    }
220
221
    /**
222
     * 字符串式绑定
223
     *
224
     * @param string $where
225
     * @param array $whereParameter
226
     * @return void
227
     * @throws SQLException
228
     */
229
    protected function whereCondition(string $where, array $whereParameter)
230
    {
231
        list($this->whereCondition, $whereBinder) = $this->prepareWhereString($where, $whereParameter);
232
        $this->binder = array_merge($this->binder, $whereBinder);
233
    }
234
235
    /**
236
     * 数组条件式绑定
237
     *
238
     * @param array $where
239
     * @param array $whereParameter
240
     * @return void
241
     * @throws SQLException
242
     */
243
    protected function arrayWhereCondition(array $where, array $whereParameter)
244
    {
245
        list($this->whereCondition, $whereBinder) = $this->prepareWhere($where);
246
        $this->binder = array_merge($this->binder, $whereBinder);
247
        foreach ($whereParameter as $key => $value) {
248
            $this->binder[] = new Binder($key, $value);
249
        }
250
    }
251
252
    /**
253
     * @param array $where
254
     * @return array
255
     * @throws SQLException
256
     */
257
    public function prepareWhere(array $where)
258
    {
259
        $where = $this->normalizeWhereArray($where);
260
        $where = $this->aliasKeyField($where);
261
        return parent::prepareWhere($where);
262
    }
263
264
    /**
265
     * 准备插入语句
266
     *
267
     * @param array $data
268
     * @return Query
269
     */
270
    public function prepareInsert(array $data): Query
271
    {
272
        $names = [];
273
        $binds = [];
274
        $this->binder;
275
        foreach ($data as $name => $value) {
276
            $_name = Binder::index($name);
277
            $this->binder[] = new Binder($_name, $value, $name);
278
            $names[] = "`{$name}`";
279
            $binds[] = ":{$_name}";
280
        }
281
        $i_name = implode(',', $names);
282
        $i_bind = implode(',', $binds);
283
        return new Query(sprintf('INSERT INTO %s (%s) VALUES (%s)', $this->table, $i_name, $i_bind), $this->binder);
284
    }
285
}
286