Completed
Push — master ( c04073...0079ad )
by Ron
16:11
created

Insert::formatExtraArgs()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
namespace Kir\MySQL\Builder;
3
4
use Kir\MySQL\Tools\AliasReplacer;
5
use UnexpectedValueException;
6
7
class Insert extends InsertUpdateStatement {
8
	/** @var array */
9
	private $fields = array();
10
	/** @var array */
11
	private $update = array();
12
	/** @var string */
13
	private $table = null;
14
	/** @var string */
15
	private $keyField = null;
16
	/** @var bool */
17
	private $ignore = false;
18
	/** @var Select */
19
	private $from = null;
20
21
	/**
22
	 * @param string $table
23
	 * @return $this
24
	 */
25
	public function into($table) {
26
		$this->table = $table;
27
		return $this;
28
	}
29
30
	/**
31
	 * @param bool $value
32
	 * @return $this
33
	 */
34
	public function setIgnore($value = true) {
35
		$this->ignore = $value;
36
		return $this;
37
	}
38
39
	/**
40
	 * Legt den Primaerschluessel fest.
41
	 * Wenn bei einem Insert der Primaerschluessel mitgegeben wird, dann wird dieser statt der LastInsertId zurueckgegeben
42
	 *
43
	 * @param string $field
44
	 * @return $this
45
	 */
46
	public function setKey($field) {
47
		$this->keyField = $field;
48
		return $this;
49
	}
50
51
	/**
52
	 * @param string $field
53
	 * @param bool|int|float|string $value
54
	 * @throws UnexpectedValueException
55
	 * @return $this
56
	 */
57
	public function add($field, $value) {
58
		$this->fields = $this->addTo($this->fields, $field, $value);
59
		return $this;
60
	}
61
62
	/**
63
	 * @param string $field
64
	 * @param bool|int|float|string $value
65
	 * @throws UnexpectedValueException
66
	 * @return $this
67
	 */
68
	public function update($field, $value) {
69
		$this->update = $this->addTo($this->update, $field, $value);
70
		return $this;
71
	}
72
73
	/**
74
	 * @param string $field
75
	 * @param bool|int|float|string $value
76
	 * @throws UnexpectedValueException
77
	 * @return $this
78
	 */
79
	public function addOrUpdate($field, $value) {
80
		$this->add($field, $value);
81
		$this->update($field, $value);
82
		return $this;
83
	}
84
85
	/**
86
	 * @param string $str
87
	 * @param string ...$params
88
	 * @return $this
89
	 */
90
	public function addExpr($str) {
0 ignored issues
show
Unused Code introduced by
The parameter $str is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
91
		$this->fields[] = func_get_args();
92
		return $this;
93
	}
94
95
	/**
96
	 * @param string $str
97
	 * @param string ...$params
98
	 * @return $this
99
	 */
100
	public function updateExpr($str) {
0 ignored issues
show
Unused Code introduced by
The parameter $str is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
101
		$this->update[] = func_get_args();
102
		return $this;
103
	}
104
105
	/**
106
	 * @param string $str
107
	 * @return $this
108
	 */
109
	public function addOrUpdateExpr($str) {
0 ignored issues
show
Unused Code introduced by
The parameter $str is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
110
		$this->fields[] = func_get_args();
111
		$this->update[] = func_get_args();
112
		return $this;
113
	}
114
115
	/**
116
	 * @param array $data
117
	 * @param array $mask
118
	 * @param array $excludeFields
119
	 * @return $this
120
	 */
121
	public function addAll(array $data, array $mask = null, array $excludeFields = null) {
122
		$this->addAllTo($data, $mask, $excludeFields, function ($field, $value) {
123
			$this->add($field, $value);
124
		});
125
		return $this;
126
	}
127
128
	/**
129
	 * @param array $data
130
	 * @param array $mask
131
	 * @param array $excludeFields
132
	 * @return $this
133
	 */
134
	public function updateAll(array $data, array $mask = null, array $excludeFields = null) {
135
		$this->addAllTo($data, $mask, $excludeFields, function ($field, $value) {
136
			if ($field !== $this->keyField) {
137
				$this->update($field, $value);
138
			}
139
		});
140
		return $this;
141
	}
142
143
	/**
144
	 * @param array $data
145
	 * @param array $mask
146
	 * @param array $excludeFields
147
	 * @return $this
148
	 */
149
	public function addOrUpdateAll(array $data, array $mask = null, array $excludeFields = null) {
150
		$this->addAll($data, $mask, $excludeFields);
151
		$this->updateAll($data, $mask, $excludeFields);
152
		return $this;
153
	}
154
155
	/**
156
	 * @param Select $select
157
	 * @return $this
158
	 */
159
	public function from(Select $select) {
160
		$this->from = $select;
161
		return $this;
162
	}
163
164
	/**
165
	 * @throws Exception
166
	 * @return string
167
	 */
168
	public function __toString() {
169
		if ($this->table === null) {
170
			throw new Exception('Specify a table-name');
171
		}
172
173
		$tableName = (new AliasReplacer($this->db()->getAliasRegistry()))->replace($this->table);
174
175
		$queryArr = array();
176
		$ignoreStr = $this->ignore ? ' IGNORE' : '';
177
		$queryArr[] = "INSERT{$ignoreStr} INTO\n\t{$tableName}\n";
178
179
		if($this->from !== null) {
180
			$fields = $this->from->getFields();
181
			$queryArr[] = sprintf("\t(%s)\n", join(', ', array_keys($fields)));
182
			$queryArr[] = $this->from;
183
		} else {
184
			$fields = $this->fields;
185
			$insertData = $this->buildFieldList($fields);
186
			if (!count($insertData)) {
187
				throw new Exception('No field-data found');
188
			}
189
			$queryArr[] = sprintf("SET\n%s\n", join(",\n", $insertData));
190
		}
191
192
		$updateData = $this->buildUpdate();
193
		if($updateData) {
194
			$queryArr[] = "{$updateData}\n";
195
		}
196
197
		$query = join('', $queryArr);
198
199
		return $query;
200
	}
201
202
	/**
203
	 * @param array $fields
204
	 * @param string $field
205
	 * @param bool|int|float|string $value
206
	 * @return array
207
	 */
208
	private function addTo(array $fields, $field, $value) {
209
		if ($this->isFieldNameValid($field)) {
210
			throw new UnexpectedValueException('Field name is invalid');
211
		}
212
		$sqlField = $field;
213
		$sqlValue = $this->db()->quote($value);
214
		$fields[$sqlField] = $sqlValue;
215
		return $fields;
216
	}
217
218
	/**
219
	 * @param array $data
220
	 * @param array $mask
221
	 * @param array $excludeFields
222
	 * @param callable $fn
223
	 * @return $this
224
	 */
225
	private function addAllTo(array $data, array $mask = null, array $excludeFields = null, $fn) {
226
		if($mask !== null) {
227
			$data = array_intersect_key($data, array_combine($mask, $mask));
228
		}
229
		if($excludeFields !== null) {
230
			foreach($excludeFields as $excludeField) {
231
				if(array_key_exists($excludeField, $data)) {
232
					unset($data[$excludeField]);
233
				}
234
			}
235
		}
236
		$data = $this->clearValues($data);
237
		foreach ($data as $field => $value) {
238
			call_user_func($fn, $field, $value);
239
		}
240
	}
241
242
	/**
243
	 * @return string
244
	 */
245
	private function buildUpdate() {
246
		$queryArr = array();
247
		if(!empty($this->update)) {
248
			$queryArr[] = "ON DUPLICATE KEY UPDATE\n";
249
			$updateArr = array();
250
			if($this->keyField !== null) {
251
				$updateArr[] = "\t`{$this->keyField}` = LAST_INSERT_ID({$this->keyField})";
252
			}
253
			$updateArr = $this->buildFieldList($this->update, $updateArr);
254
255
			$queryArr[] = join(",\n", $updateArr);
256
		}
257
		return join('', $queryArr);
258
	}
259
260
	/**
261
	 * @param string $fieldName
262
	 * @return bool
263
	 */
264
	private function isFieldNameValid($fieldName) {
265
		return is_numeric($fieldName) || !is_scalar($fieldName);
266
	}
267
268
	/**
269
	 * @param array $values
270
	 * @return array
271
	 * @throws Exception
272
	 */
273
	private function clearValues(array $values) {
274
		if(!count($values)) {
275
			return [];
276
		}
277
278
		$tableName = (new AliasReplacer($this->db()->getAliasRegistry()))->replace($this->table);
279
		$fields = $this->db()->getTableFields($tableName);
280
		$result = array();
281
282
		foreach ($values as $fieldName => $fieldValue) {
283
			if(in_array($fieldName, $fields)) {
284
				$result[$fieldName] = $fieldValue;
285
			}
286
		}
287
288
		return $result;
289
	}
290
291
	/**
292
	 * @param string $expression
293
	 * @param array $args
294
	 * @return string
295
	 */
296
	private function formatExtraArgs($expression, $args) {
297
		if(count($args) > 1) {
298
			$args = array_slice($args, 1);
299
			$expression = $this->db()->quoteExpression($expression, $args);
300
		}
301
		return $expression;
302
	}
303
}
304