|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace voku\db; |
|
4
|
|
|
|
|
5
|
|
|
use voku\helper\Phonetic; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* Helper: this handles extra functions that use the "DB"-Class |
|
9
|
|
|
* |
|
10
|
|
|
* @package voku\db |
|
11
|
|
|
*/ |
|
12
|
|
|
class Helper |
|
13
|
|
|
{ |
|
14
|
|
|
/** |
|
15
|
|
|
* Check if "mysqlnd"-driver is used. |
|
16
|
|
|
* |
|
17
|
34 |
|
* @return bool |
|
18
|
|
|
*/ |
|
19
|
34 |
|
public static function isMysqlndIsUsed() |
|
20
|
|
|
{ |
|
21
|
34 |
|
static $_mysqlnd_is_used = null; |
|
22
|
1 |
|
|
|
23
|
1 |
|
if ($_mysqlnd_is_used === null) { |
|
24
|
|
|
$_mysqlnd_is_used = (extension_loaded('mysqlnd') && function_exists('mysqli_fetch_all')); |
|
25
|
34 |
|
} |
|
26
|
|
|
|
|
27
|
|
|
return $_mysqlnd_is_used; |
|
28
|
|
|
} |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* Check if the current environment supports "utf8mb4". |
|
32
|
|
|
* |
|
33
|
|
|
* @param DB $dbConnection |
|
34
|
|
|
* |
|
35
|
7 |
|
* @return bool |
|
36
|
|
|
*/ |
|
37
|
|
|
public static function isUtf8mb4Supported(DB $dbConnection = null) |
|
38
|
|
|
{ |
|
39
|
|
|
/** |
|
40
|
|
|
* https://make.wordpress.org/core/2015/04/02/the-utf8mb4-upgrade/ |
|
41
|
|
|
* |
|
42
|
|
|
* - You’re currently using the utf8 character set. |
|
43
|
|
|
* - Your MySQL server is version 5.5.3 or higher (including all 10.x versions of MariaDB). |
|
44
|
|
|
* - Your MySQL client libraries are version 5.5.3 or higher. If you’re using mysqlnd, 5.0.9 or higher. |
|
45
|
|
|
* |
|
46
|
|
|
* INFO: utf8mb4 is 100% backwards compatible with utf8. |
|
47
|
7 |
|
*/ |
|
48
|
7 |
|
|
|
49
|
|
|
if ($dbConnection === null) { |
|
50
|
|
|
$dbConnection = DB::getInstance(); |
|
51
|
|
|
} |
|
52
|
7 |
|
|
|
53
|
|
|
$server_version = self::get_mysql_server_version($dbConnection); |
|
54
|
|
|
$client_version = self::get_mysql_client_version($dbConnection); |
|
55
|
7 |
|
|
|
56
|
7 |
|
if ( |
|
57
|
|
|
$server_version >= 50503 |
|
58
|
7 |
|
&& |
|
59
|
|
|
( |
|
60
|
|
|
( |
|
61
|
7 |
|
self::isMysqlndIsUsed() === true |
|
62
|
7 |
|
&& |
|
63
|
|
|
$client_version >= 50009 |
|
64
|
|
|
) |
|
65
|
7 |
|
|| |
|
66
|
|
|
( |
|
67
|
7 |
|
self::isMysqlndIsUsed() === false |
|
68
|
|
|
&& |
|
69
|
|
|
$client_version >= 50503 |
|
70
|
|
|
) |
|
71
|
7 |
|
) |
|
72
|
|
|
|
|
73
|
|
|
) { |
|
74
|
|
|
return true; |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
return false; |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
7 |
|
* A phonetic search algorithms for different languages. |
|
82
|
|
|
* |
|
83
|
7 |
|
* @param string $searchString |
|
84
|
|
|
* @param string $searchFieldName |
|
85
|
7 |
|
* @param string $idFieldName |
|
86
|
1 |
|
* @param string $language <p>en, de, fr</p> |
|
87
|
1 |
|
* @param string $table |
|
88
|
|
|
* @param array $whereArray |
|
89
|
7 |
|
* @param DB|null $dbConnection <p>use <strong>null</strong> if you will use the current database-connection</p> |
|
90
|
|
|
* @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p> |
|
91
|
|
|
* |
|
92
|
|
|
* @return array |
|
93
|
|
|
*/ |
|
94
|
|
|
public static function phoneticSearch($searchString, $searchFieldName, $idFieldName = null, $language = 'de', $table, array $whereArray = null, DB $dbConnection = null, $databaseName = null) |
|
95
|
|
|
{ |
|
96
|
|
|
// init |
|
97
|
|
|
$searchString = (string)$searchString; |
|
98
|
|
|
$searchFieldName = (string)$searchFieldName; |
|
99
|
|
|
|
|
100
|
7 |
|
if ($dbConnection === null) { |
|
101
|
|
|
$dbConnection = DB::getInstance(); |
|
102
|
7 |
|
} |
|
103
|
|
|
|
|
104
|
7 |
|
if ($table === '') { |
|
105
|
1 |
|
$debug = new Debug($dbConnection); |
|
106
|
1 |
|
$debug->displayError('invalid table name'); |
|
107
|
|
|
|
|
108
|
7 |
|
return array(); |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
if ($idFieldName === null) { |
|
112
|
|
|
$idFieldName = 'id'; |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
$whereSQL = $dbConnection->_parseArrayPair($whereArray, 'AND'); |
|
|
|
|
|
|
116
|
|
|
if ($whereSQL) { |
|
117
|
|
|
$whereSQL = 'AND ' . $whereSQL; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
if ($databaseName) { |
|
|
|
|
|
|
121
|
1 |
|
$databaseName = $dbConnection->quote_string(trim($databaseName)) . '.'; |
|
122
|
|
|
} |
|
123
|
1 |
|
|
|
124
|
|
|
// get the row |
|
125
|
|
|
$query = 'SELECT ' . $dbConnection->quote_string($searchFieldName) . ', ' . $dbConnection->quote_string($idFieldName) . ' |
|
126
|
|
|
FROM ' . $databaseName . $dbConnection->quote_string($table) . ' |
|
127
|
|
|
WHERE 1 = 1 |
|
128
|
1 |
|
' . $whereSQL . ' |
|
129
|
1 |
|
'; |
|
130
|
1 |
|
$result = $dbConnection->query($query); |
|
131
|
1 |
|
|
|
132
|
|
|
// make sure the row exists |
|
133
|
|
|
if ($result->num_rows <= 0) { |
|
134
|
|
|
return array(); |
|
135
|
1 |
|
} |
|
136
|
|
|
|
|
137
|
1 |
|
$dataToSearchIn = array(); |
|
138
|
1 |
|
/** @noinspection LoopWhichDoesNotLoopInspection */ |
|
139
|
1 |
|
/** @noinspection PhpAssignmentInConditionInspection */ |
|
140
|
|
|
while ($tmpArray = $result->fetchArray()) { |
|
141
|
1 |
|
$dataToSearchIn[$tmpArray[$idFieldName]] = $tmpArray[$searchFieldName]; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
$phonetic = new Phonetic($language); |
|
145
|
|
|
return $phonetic->phonetic_matches($searchString, $dataToSearchIn); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
1 |
|
/** |
|
149
|
|
|
* A string that represents the MySQL client library version. |
|
150
|
|
|
* |
|
151
|
|
|
* @param DB $dbConnection |
|
152
|
1 |
|
* |
|
153
|
1 |
|
* @return string |
|
154
|
|
|
*/ |
|
155
|
1 |
View Code Duplication |
public static function get_mysql_client_version(DB $dbConnection = null) |
|
|
|
|
|
|
156
|
1 |
|
{ |
|
157
|
1 |
|
static $_mysqli_client_version = null; |
|
158
|
1 |
|
|
|
159
|
1 |
|
if ($dbConnection === null) { |
|
160
|
|
|
$dbConnection = DB::getInstance(); |
|
161
|
|
|
} |
|
162
|
1 |
|
|
|
163
|
|
|
if ($_mysqli_client_version === null) { |
|
164
|
1 |
|
$_mysqli_client_version = \mysqli_get_client_version($dbConnection->getLink()); |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
return $_mysqli_client_version; |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* Returns a string representing the version of the MySQL server that the MySQLi extension is connected to. |
|
173
|
|
|
* |
|
174
|
|
|
* @param DB $dbConnection |
|
175
|
|
|
* |
|
176
|
|
|
* @return string |
|
177
|
|
|
*/ |
|
178
|
|
View Code Duplication |
public static function get_mysql_server_version(DB $dbConnection = null) |
|
|
|
|
|
|
179
|
|
|
{ |
|
180
|
1 |
|
static $_mysqli_server_version = null; |
|
181
|
|
|
|
|
182
|
|
|
if ($dbConnection === null) { |
|
183
|
1 |
|
$dbConnection = DB::getInstance(); |
|
184
|
|
|
} |
|
185
|
1 |
|
|
|
186
|
1 |
|
if ($_mysqli_server_version === null) { |
|
187
|
1 |
|
$_mysqli_server_version = \mysqli_get_server_version($dbConnection->getLink()); |
|
188
|
|
|
} |
|
189
|
1 |
|
|
|
190
|
|
|
return $_mysqli_server_version; |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
/** |
|
194
|
|
|
* Return all db-fields from a table. |
|
195
|
|
|
* |
|
196
|
1 |
|
* @param string $table |
|
197
|
1 |
|
* @param bool $useStaticCache |
|
198
|
1 |
|
* @param DB|null $dbConnection <p>use <strong>null</strong> if you will use the current database-connection</p> |
|
199
|
1 |
|
* @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p> |
|
200
|
|
|
* |
|
201
|
1 |
|
* @return array |
|
202
|
|
|
*/ |
|
203
|
|
|
public static function getDbFields($table, $useStaticCache = true, DB $dbConnection = null, $databaseName = null) |
|
204
|
|
|
{ |
|
205
|
|
|
static $DB_FIELDS_CACHE = array(); |
|
206
|
1 |
|
|
|
207
|
|
|
// use the static cache |
|
208
|
1 |
|
if ( |
|
209
|
1 |
|
$useStaticCache === true |
|
210
|
1 |
|
&& |
|
211
|
|
|
isset($DB_FIELDS_CACHE[$table]) |
|
212
|
|
|
) { |
|
213
|
1 |
|
return $DB_FIELDS_CACHE[$table]; |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
// init |
|
217
|
1 |
|
$dbFields = array(); |
|
218
|
|
|
|
|
219
|
|
|
if ($dbConnection === null) { |
|
220
|
1 |
|
$dbConnection = DB::getInstance(); |
|
221
|
1 |
|
} |
|
222
|
1 |
|
|
|
223
|
|
|
if ($table === '') { |
|
224
|
1 |
|
$debug = new Debug($dbConnection); |
|
225
|
|
|
$debug->displayError('invalid table name'); |
|
226
|
1 |
|
|
|
227
|
1 |
|
return array(); |
|
228
|
1 |
|
} |
|
229
|
1 |
|
|
|
230
|
1 |
|
if ($databaseName) { |
|
|
|
|
|
|
231
|
1 |
|
$databaseName = $dbConnection->quote_string(trim($databaseName)) . '.'; |
|
232
|
1 |
|
} |
|
233
|
1 |
|
|
|
234
|
1 |
|
$sql = 'SHOW COLUMNS FROM ' . $databaseName . $dbConnection->escape($table); |
|
235
|
|
|
$result = $dbConnection->query($sql); |
|
236
|
1 |
|
|
|
237
|
1 |
|
if ($result && $result->num_rows > 0) { |
|
238
|
|
|
foreach ($result->fetchAllArray() as $tmpResult) { |
|
239
|
1 |
|
$dbFields[] = $tmpResult['Field']; |
|
240
|
1 |
|
} |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
1 |
|
// add to static cache |
|
244
|
1 |
|
$DB_FIELDS_CACHE[$table] = $dbFields; |
|
245
|
|
|
|
|
246
|
1 |
|
return $dbFields; |
|
247
|
1 |
|
} |
|
248
|
1 |
|
|
|
249
|
|
|
/** |
|
250
|
|
|
* Copy row within a DB table and making updates to the columns. |
|
251
|
|
|
* |
|
252
|
|
|
* @param string $table |
|
253
|
|
|
* @param array $whereArray |
|
254
|
|
|
* @param array $updateArray |
|
255
|
|
|
* @param array $ignoreArray |
|
256
|
|
|
* @param DB|null $dbConnection <p>Use <strong>null</strong> to get your first singleton instance.</p> |
|
257
|
|
|
* @param null|string $databaseName <p>use <strong>null</strong> if you will use the current database</p> |
|
258
|
|
|
* |
|
259
|
|
|
* @return bool|int "int" (insert_id) by "<b>INSERT / REPLACE</b>"-queries<br /> |
|
260
|
|
|
* "false" on error |
|
261
|
|
|
*/ |
|
262
|
|
|
public static function copyTableRow($table, array $whereArray, array $updateArray = array(), array $ignoreArray = array(), DB $dbConnection = null, $databaseName = null) |
|
263
|
|
|
{ |
|
264
|
|
|
// init |
|
265
|
|
|
$table = trim($table); |
|
266
|
|
|
|
|
267
|
|
|
if ($dbConnection === null) { |
|
268
|
|
|
$dbConnection = DB::getInstance(); |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
if ($table === '') { |
|
272
|
|
|
$debug = new Debug($dbConnection); |
|
273
|
|
|
$debug->displayError('invalid table name'); |
|
274
|
|
|
|
|
275
|
|
|
return false; |
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
$whereSQL = $dbConnection->_parseArrayPair($whereArray, 'AND'); |
|
279
|
|
|
if ($whereSQL) { |
|
280
|
|
|
$whereSQL = 'AND ' . $whereSQL; |
|
281
|
|
|
} |
|
282
|
|
|
|
|
283
|
|
|
if ($databaseName) { |
|
|
|
|
|
|
284
|
|
|
$databaseName = $dbConnection->quote_string(trim($databaseName)) . '.'; |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
// get the row |
|
288
|
|
|
$query = 'SELECT * FROM ' . $databaseName . $dbConnection->quote_string($table) . ' |
|
289
|
|
|
WHERE 1 = 1 |
|
290
|
|
|
' . $whereSQL . ' |
|
291
|
|
|
'; |
|
292
|
|
|
$result = $dbConnection->query($query); |
|
293
|
|
|
|
|
294
|
|
|
// make sure the row exists |
|
295
|
|
|
if ($result->num_rows > 0) { |
|
296
|
|
|
|
|
297
|
|
|
/** @noinspection LoopWhichDoesNotLoopInspection */ |
|
298
|
|
|
/** @noinspection PhpAssignmentInConditionInspection */ |
|
299
|
|
|
while ($tmpArray = $result->fetchArray()) { |
|
300
|
|
|
|
|
301
|
|
|
// re-build a new DB query and ignore some field-names |
|
302
|
|
|
$bindings = array(); |
|
303
|
|
|
$insert_keys = ''; |
|
304
|
|
|
$insert_values = ''; |
|
305
|
|
|
|
|
306
|
|
|
foreach ($tmpArray as $fieldName => $value) { |
|
307
|
|
|
|
|
308
|
|
|
if (!in_array($fieldName, $ignoreArray, true)) { |
|
309
|
|
|
if (array_key_exists($fieldName, $updateArray)) { |
|
310
|
|
|
$insert_keys .= ',' . $fieldName; |
|
311
|
|
|
$insert_values .= ',?'; |
|
312
|
|
|
$bindings[] = $updateArray[$fieldName]; // INFO: do not escape non selected data |
|
313
|
|
|
} else { |
|
314
|
|
|
$insert_keys .= ',' . $fieldName; |
|
315
|
|
|
$insert_values .= ',?'; |
|
316
|
|
|
$bindings[] = $value; // INFO: do not escape non selected data |
|
317
|
|
|
} |
|
318
|
|
|
} |
|
319
|
|
|
} |
|
320
|
|
|
|
|
321
|
|
|
$insert_keys = ltrim($insert_keys, ','); |
|
322
|
|
|
$insert_values = ltrim($insert_values, ','); |
|
323
|
|
|
|
|
324
|
|
|
// insert the "copied" row |
|
325
|
|
|
$new_query = 'INSERT INTO ' . $databaseName . $dbConnection->quote_string($table) . ' |
|
326
|
|
|
(' . $insert_keys . ') |
|
327
|
|
|
VALUES |
|
328
|
|
|
(' . $insert_values . ') |
|
329
|
|
|
'; |
|
330
|
|
|
return $dbConnection->query($new_query, $bindings); |
|
331
|
|
|
} |
|
332
|
|
|
} |
|
333
|
|
|
|
|
334
|
|
|
return false; |
|
335
|
|
|
} |
|
336
|
|
|
} |
|
337
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.