1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Lagdo\DbAdmin\DbAdmin; |
4
|
|
|
|
5
|
|
|
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity; |
6
|
|
|
use Lagdo\DbAdmin\Driver\Entity\TableSelectEntity; |
7
|
|
|
|
8
|
|
|
use Exception; |
9
|
|
|
|
10
|
|
|
use function intval; |
11
|
|
|
use function count; |
12
|
|
|
use function str_replace; |
13
|
|
|
use function compact; |
14
|
|
|
use function preg_match; |
15
|
|
|
use function microtime; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Admin table select functions |
19
|
|
|
*/ |
20
|
|
|
class TableSelectAdmin extends AbstractAdmin |
21
|
|
|
{ |
22
|
|
|
/** |
23
|
|
|
* Print columns box in select |
24
|
|
|
* @param array $select Result of processSelectColumns()[0] |
25
|
|
|
* @param array $columns Selectable columns |
26
|
|
|
* @param array $options |
27
|
|
|
* @return array |
28
|
|
|
*/ |
29
|
|
|
private function getColumnsOptions(array $select, array $columns, array $options): array |
30
|
|
|
{ |
31
|
|
|
return [ |
32
|
|
|
'select' => $select, |
33
|
|
|
'values' => (array)$options["columns"], |
34
|
|
|
'columns' => $columns, |
35
|
|
|
'functions' => $this->driver->functions(), |
36
|
|
|
'grouping' => $this->driver->grouping(), |
37
|
|
|
]; |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Print search box in select |
42
|
|
|
* |
43
|
|
|
* @param array $columns Selectable columns |
44
|
|
|
* @param array $indexes |
45
|
|
|
* @param array $options |
46
|
|
|
* |
47
|
|
|
* @return array |
48
|
|
|
*/ |
49
|
|
|
private function getFiltersOptions(array $columns, array $indexes, array $options): array |
50
|
|
|
{ |
51
|
|
|
$fulltexts = []; |
52
|
|
|
foreach ($indexes as $i => $index) { |
53
|
|
|
$fulltexts[$i] = $index->type == "FULLTEXT" ? $this->util->html($options["fulltext"][$i]) : ''; |
54
|
|
|
} |
55
|
|
|
return [ |
56
|
|
|
// 'where' => $where, |
57
|
|
|
'values' => (array)$options["where"], |
58
|
|
|
'columns' => $columns, |
59
|
|
|
'indexes' => $indexes, |
60
|
|
|
'operators' => $this->driver->operators(), |
61
|
|
|
'fulltexts' => $fulltexts, |
62
|
|
|
]; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Print order box in select |
67
|
|
|
* |
68
|
|
|
* @param array $columns Selectable columns |
69
|
|
|
* @param array $options |
70
|
|
|
* |
71
|
|
|
* @return array |
72
|
|
|
*/ |
73
|
|
|
private function getSortingOptions(array $columns, array $options): array |
74
|
|
|
{ |
75
|
|
|
$values = []; |
76
|
|
|
$descs = (array)$options["desc"]; |
77
|
|
|
foreach ((array)$options["order"] as $key => $value) { |
78
|
|
|
$values[] = [ |
79
|
|
|
'col' => $value, |
80
|
|
|
'desc' => $descs[$key] ?? 0, |
81
|
|
|
]; |
82
|
|
|
} |
83
|
|
|
return [ |
84
|
|
|
// 'order' => $order, |
85
|
|
|
'values' => $values, |
86
|
|
|
'columns' => $columns, |
87
|
|
|
]; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Print limit box in select |
92
|
|
|
* |
93
|
|
|
* @param string $limit Result of processSelectLimit() |
94
|
|
|
* |
95
|
|
|
* @return array |
96
|
|
|
*/ |
97
|
|
|
private function getLimitOptions(string $limit): array |
98
|
|
|
{ |
99
|
|
|
return ['value' => $this->util->html($limit)]; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Print text length box in select |
104
|
|
|
* |
105
|
|
|
* @param int $textLength Result of processSelectLength() |
106
|
|
|
* |
107
|
|
|
* @return array |
108
|
|
|
*/ |
109
|
|
|
private function getLengthOptions($textLength): array |
110
|
|
|
{ |
111
|
|
|
return [ |
112
|
|
|
'value' => $textLength === 0 ? 0 : $this->util->html($textLength), |
113
|
|
|
]; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Print action box in select |
118
|
|
|
* |
119
|
|
|
* @param array $indexes |
120
|
|
|
* |
121
|
|
|
* @return array |
122
|
|
|
*/ |
123
|
|
|
// private function getActionOptions(array $indexes) |
124
|
|
|
// { |
125
|
|
|
// $columns = []; |
126
|
|
|
// foreach ($indexes as $index) { |
127
|
|
|
// $current_key = \reset($index->columns); |
128
|
|
|
// if ($index->type != "FULLTEXT" && $current_key) { |
129
|
|
|
// $columns[$current_key] = 1; |
130
|
|
|
// } |
131
|
|
|
// } |
132
|
|
|
// $columns[""] = 1; |
133
|
|
|
// return ['columns' => $columns]; |
134
|
|
|
// } |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Print command box in select |
138
|
|
|
* |
139
|
|
|
* @return bool whether to print default commands |
140
|
|
|
*/ |
141
|
|
|
// private function getCommandOptions() |
142
|
|
|
// { |
143
|
|
|
// return !$this->driver->isInformationSchema($this->driver->database()); |
144
|
|
|
// } |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Print import box in select |
148
|
|
|
* |
149
|
|
|
* @return bool whether to print default import |
150
|
|
|
*/ |
151
|
|
|
// private function getImportOptions() |
152
|
|
|
// { |
153
|
|
|
// return !$this->driver->isInformationSchema($this->driver->database()); |
154
|
|
|
// } |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Print extra text in the end of a select form |
158
|
|
|
* |
159
|
|
|
* @param array $emailFields Fields holding e-mails |
160
|
|
|
* @param array $columns Selectable columns |
161
|
|
|
* |
162
|
|
|
* @return array |
163
|
|
|
*/ |
164
|
|
|
// private function getEmailOptions(array $emailFields, array $columns) |
165
|
|
|
// { |
166
|
|
|
// } |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* @param array $queryOptions |
170
|
|
|
* |
171
|
|
|
* @return int |
172
|
|
|
*/ |
173
|
|
|
private function setDefaultOptions(array &$queryOptions): int |
174
|
|
|
{ |
175
|
|
|
$defaultOptions = [ |
176
|
|
|
'columns' => [], |
177
|
|
|
'where' => [], |
178
|
|
|
'order' => [], |
179
|
|
|
'desc' => [], |
180
|
|
|
'fulltext' => [], |
181
|
|
|
'limit' => '50', |
182
|
|
|
'text_length' => '100', |
183
|
|
|
'page' => '1', |
184
|
|
|
]; |
185
|
|
|
foreach ($defaultOptions as $name => $value) { |
186
|
|
|
if (!isset($queryOptions[$name])) { |
187
|
|
|
$queryOptions[$name] = $value; |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
$page = intval($queryOptions['page']); |
191
|
|
|
if ($page > 0) { |
192
|
|
|
$page -= 1; // Page numbers start at 0 here, instead of 1. |
193
|
|
|
} |
194
|
|
|
$queryOptions['page'] = $page; |
195
|
|
|
return $page; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @param array $fields |
200
|
|
|
* |
201
|
|
|
* @return array |
202
|
|
|
*/ |
203
|
|
|
private function getFieldsOptions(array $fields): array |
204
|
|
|
{ |
205
|
|
|
$rights = []; // privilege => 0 |
206
|
|
|
$columns = []; // selectable columns |
207
|
|
|
$textLength = 0; |
208
|
|
|
foreach ($fields as $key => $field) { |
209
|
|
|
$name = $this->util->fieldName($field); |
210
|
|
|
if (isset($field->privileges["select"]) && $name != "") { |
211
|
|
|
$columns[$key] = \html_entity_decode(\strip_tags($name), ENT_QUOTES); |
212
|
|
|
if ($this->util->isShortable($field)) { |
213
|
|
|
$textLength = $this->util->processSelectLength(); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
$rights[] = $field->privileges; |
217
|
|
|
} |
218
|
|
|
return [$rights, $columns, $textLength]; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* @param array $indexes |
223
|
|
|
* @param array $select |
224
|
|
|
* @param mixed $tableStatus |
225
|
|
|
* |
226
|
|
|
* @return array|null |
227
|
|
|
*/ |
228
|
|
|
private function setPrimaryKey(array &$indexes, array $select, $tableStatus) |
229
|
|
|
{ |
230
|
|
|
$primary = $unselected = null; |
231
|
|
|
foreach ($indexes as $index) { |
232
|
|
|
if ($index->type == "PRIMARY") { |
233
|
|
|
$primary = \array_flip($index->columns); |
234
|
|
|
$unselected = ($select ? $primary : []); |
235
|
|
|
foreach ($unselected as $key => $val) { |
236
|
|
|
if (\in_array($this->driver->escapeId($key), $select)) { |
237
|
|
|
unset($unselected[$key]); |
238
|
|
|
} |
239
|
|
|
} |
240
|
|
|
break; |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
$oid = $tableStatus->oid; |
245
|
|
|
if ($oid && !$primary) { |
246
|
|
|
/*$primary = */$unselected = [$oid => 0]; |
247
|
|
|
$indexes[] = ["type" => "PRIMARY", "columns" => [$oid]]; |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
return $unselected; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/** |
254
|
|
|
* @param array $select |
255
|
|
|
* @param array $columns |
256
|
|
|
* @param array $indexes |
257
|
|
|
* @param int $limit |
258
|
|
|
* @param int $textLength |
259
|
|
|
* @param array $queryOptions |
260
|
|
|
* |
261
|
|
|
* @return array |
262
|
|
|
*/ |
263
|
|
|
private function getAllOptions(array $select, array $columns, array $indexes, |
264
|
|
|
int $limit, int $textLength, array $queryOptions): array |
265
|
|
|
{ |
266
|
|
|
return [ |
267
|
|
|
'columns' => $this->getColumnsOptions($select, $columns, $queryOptions), |
268
|
|
|
'filters' => $this->getFiltersOptions($columns, $indexes, $queryOptions), |
269
|
|
|
'sorting' => $this->getSortingOptions($columns, $queryOptions), |
270
|
|
|
'limit' => $this->getLimitOptions($limit), |
271
|
|
|
'length' => $this->getLengthOptions($textLength), |
272
|
|
|
// 'action' => $this->getActionOptions($indexes), |
273
|
|
|
]; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* @param string $table |
278
|
|
|
* @param array $columns |
279
|
|
|
* @param array $fields |
280
|
|
|
* @param array $select |
281
|
|
|
* @param array $group |
282
|
|
|
* @param array $where |
283
|
|
|
* @param array $order |
284
|
|
|
* @param array $unselected |
285
|
|
|
* @param int $limit |
286
|
|
|
* @param int $page |
287
|
|
|
* |
288
|
|
|
* @return TableSelectEntity |
289
|
|
|
*/ |
290
|
|
|
private function getSelectEntity(string $table, array $columns, array $fields, array $select, |
291
|
|
|
array $group, array $where, array $order, array $unselected, int $limit, int $page): TableSelectEntity |
292
|
|
|
{ |
293
|
|
|
$select2 = $select; |
294
|
|
|
$group2 = $group; |
295
|
|
|
if (!$select2) { |
|
|
|
|
296
|
|
|
$select2[] = "*"; |
297
|
|
|
$convert_fields = $this->driver->convertFields($columns, $fields, $select); |
298
|
|
|
if ($convert_fields) { |
299
|
|
|
$select2[] = \substr($convert_fields, 2); |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
foreach ($select as $key => $val) { |
303
|
|
|
$field = $fields[$this->driver->unescapeId($val)] ?? null; |
304
|
|
|
if ($field && ($as = $this->driver->convertField($field))) { |
305
|
|
|
$select2[$key] = "$as AS $val"; |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
$isGroup = count($group) < count($select); |
309
|
|
|
if (!$isGroup && $unselected) { |
|
|
|
|
310
|
|
|
foreach ($unselected as $key => $val) { |
311
|
|
|
$select2[] = $this->driver->escapeId($key); |
312
|
|
|
if ($group2) { |
|
|
|
|
313
|
|
|
$group2[] = $this->driver->escapeId($key); |
314
|
|
|
} |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
// From driver.inc.php |
319
|
|
|
return new TableSelectEntity($table, $select2, $where, $group2, $order, $limit, $page); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Get required data for create/update on tables |
324
|
|
|
* |
325
|
|
|
* @param string $table The table name |
326
|
|
|
* @param array $queryOptions The query options |
327
|
|
|
* |
328
|
|
|
* @return array |
329
|
|
|
* @throws Exception |
330
|
|
|
*/ |
331
|
|
|
private function prepareSelect(string $table, array &$queryOptions = []): array |
332
|
|
|
{ |
333
|
|
|
$page = $this->setDefaultOptions($queryOptions); |
334
|
|
|
$this->util->input()->setValues($queryOptions); |
|
|
|
|
335
|
|
|
|
336
|
|
|
// From select.inc.php |
337
|
|
|
$fields = $this->driver->fields($table); |
338
|
|
|
list(, $columns, $textLength) = $this->getFieldsOptions($fields); |
339
|
|
|
if (!$columns && $this->driver->support("table")) { |
340
|
|
|
throw new Exception($this->trans->lang('Unable to select the table') . |
341
|
|
|
($fields ? "." : ": " . $this->driver->error())); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
$indexes = $this->driver->indexes($table); |
345
|
|
|
$foreignKeys = $this->admin->columnForeignKeys($table); |
346
|
|
|
list($select, $group) = $this->util->processSelectColumns(); |
347
|
|
|
$where = $this->util->processSelectSearch($fields, $indexes); |
348
|
|
|
$order = $this->util->processSelectOrder(); |
349
|
|
|
$limit = $this->util->processSelectLimit(); |
350
|
|
|
$tableStatus = $this->driver->tableStatusOrName($table); |
351
|
|
|
$unselected = $this->setPrimaryKey($indexes, $select, $tableStatus); |
352
|
|
|
$tableName = $this->util->tableName($tableStatus); |
353
|
|
|
|
354
|
|
|
// $set = null; |
355
|
|
|
// if(isset($rights["insert"]) || !support("table")) { |
356
|
|
|
// $set = ""; |
357
|
|
|
// foreach((array) $queryOptions["where"] as $val) { |
358
|
|
|
// if($foreignKeys[$val["col"]] && count($foreignKeys[$val["col"]]) == 1 && ($val["op"] == "=" |
359
|
|
|
// || (!$val["op"] && !preg_match('~[_%]~', $val["val"])) // LIKE in Editor |
360
|
|
|
// )) { |
361
|
|
|
// $set .= "&set" . urlencode("[" . $this->util->bracketEscape($val["col"]) . "]") . "=" . urlencode($val["val"]); |
362
|
|
|
// } |
363
|
|
|
// } |
364
|
|
|
// } |
365
|
|
|
// $this->util->selectLinks($tableStatus, $set); |
366
|
|
|
|
367
|
|
|
// if($page == "last") |
368
|
|
|
// { |
369
|
|
|
// $isGroup = count($group) < count($select); |
370
|
|
|
// $found_rows = $this->driver->result($this->driver->sqlForRowCount($table, $where, $isGroup, $group)); |
371
|
|
|
// $page = \floor(\max(0, $found_rows - 1) / $limit); |
372
|
|
|
// } |
373
|
|
|
|
374
|
|
|
$options = $this->getAllOptions($select, $columns, $indexes, $limit, $textLength, $queryOptions); |
375
|
|
|
$entity = $this->getSelectEntity($table, $columns, $fields, $select, $group, $where, $order, $unselected, $limit, $page); |
|
|
|
|
376
|
|
|
$query = $this->driver->buildSelectQuery($entity); |
377
|
|
|
// From adminer.inc.php |
378
|
|
|
$query = str_replace("\n", " ", $query); |
379
|
|
|
|
380
|
|
|
return [$options, $query, $select, $fields, $foreignKeys, $columns, $indexes, |
381
|
|
|
$where, $group, $order, $limit, $page, $textLength, $tableName, $unselected]; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Get required data for create/update on tables |
386
|
|
|
* |
387
|
|
|
* @param string $table The table name |
388
|
|
|
* @param array $queryOptions The query options |
389
|
|
|
* |
390
|
|
|
* @return array |
391
|
|
|
* @throws Exception |
392
|
|
|
*/ |
393
|
|
|
public function getSelectData(string $table, array $queryOptions = []): array |
394
|
|
|
{ |
395
|
|
|
list($options, $query) = $this->prepareSelect($table, $queryOptions); |
396
|
|
|
|
397
|
|
|
$query = $this->util->html($query); |
398
|
|
|
$mainActions = [ |
399
|
|
|
'select-exec' => $this->trans->lang('Execute'), |
400
|
|
|
'insert-table' => $this->trans->lang('New item'), |
401
|
|
|
'select-back' => $this->trans->lang('Back'), |
402
|
|
|
]; |
403
|
|
|
|
404
|
|
|
return compact('mainActions', 'options', 'query'); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
/** |
408
|
|
|
* Get required data for create/update on tables |
409
|
|
|
* |
410
|
|
|
* @param string $table The table name |
411
|
|
|
* @param array $queryOptions The query options |
412
|
|
|
* |
413
|
|
|
* @return array |
414
|
|
|
* @throws Exception |
415
|
|
|
*/ |
416
|
|
|
public function execSelect(string $table, array $queryOptions): array |
417
|
|
|
{ |
418
|
|
|
list(, $query, $select, $fields, , , $indexes, $where, $group, , $limit, $page, |
419
|
|
|
$textLength, , $unselected) = $this->prepareSelect($table, $queryOptions); |
420
|
|
|
|
421
|
|
|
$error = null; |
422
|
|
|
// From driver.inc.php |
423
|
|
|
$start = microtime(true); |
424
|
|
|
$statement = $this->driver->execute($query); |
425
|
|
|
// From adminer.inc.php |
426
|
|
|
$duration = $this->trans->formatTime($start); // Compute and format the duration |
427
|
|
|
|
428
|
|
|
if (!$statement) { |
429
|
|
|
return ['error' => $this->driver->error()]; |
430
|
|
|
} |
431
|
|
|
// From select.inc.php |
432
|
|
|
$rows = []; |
433
|
|
|
while (($row = $statement->fetchAssoc())) { |
434
|
|
|
if ($page && $this->driver->jush() == "oracle") { |
435
|
|
|
unset($row["RNUM"]); |
436
|
|
|
} |
437
|
|
|
$rows[] = $row; |
438
|
|
|
} |
439
|
|
|
if (!$rows) { |
440
|
|
|
return ['error' => $this->trans->lang('No rows.')]; |
441
|
|
|
} |
442
|
|
|
// $backward_keys = $this->driver->backwardKeys($table, $tableName); |
443
|
|
|
|
444
|
|
|
// Results headers |
445
|
|
|
$headers = [ |
446
|
|
|
'', // !$group && $select ? '' : lang('Modify'); |
447
|
|
|
]; |
448
|
|
|
$names = []; |
449
|
|
|
// $functions = []; |
450
|
|
|
reset($select); |
451
|
|
|
$rank = 1; |
452
|
|
|
foreach ($rows[0] as $key => $value) { |
453
|
|
|
$header = []; |
454
|
|
|
if (!isset($unselected[$key])) { |
455
|
|
|
$value = $queryOptions["columns"][key($select)] ?? []; |
456
|
|
|
$fun = $value["fun"] ?? ''; |
457
|
|
|
$field = $fields[$select ? ($value ? $value["col"] : current($select)) : $key]; |
458
|
|
|
$name = ($field ? $this->util->fieldName($field, $rank) : ($fun ? "*" : $key)); |
459
|
|
|
$header = compact('value', 'field', 'name'); |
460
|
|
|
if ($name != "") { |
461
|
|
|
$rank++; |
462
|
|
|
$names[$key] = $name; |
463
|
|
|
$column = $this->driver->escapeId($key); |
464
|
|
|
// $href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key); |
465
|
|
|
// $desc = "&desc%5B0%5D=1"; |
466
|
|
|
$header['column'] = $column; |
467
|
|
|
$header['key'] = $this->util->html($this->util->bracketEscape($key)); |
468
|
|
|
$header['sql'] = $this->util->applySqlFunction($fun, $name); //! columns looking like functions |
469
|
|
|
} |
470
|
|
|
// $functions[$key] = $fun; |
471
|
|
|
next($select); |
472
|
|
|
} |
473
|
|
|
$headers[] = $header; |
474
|
|
|
} |
475
|
|
|
|
476
|
|
|
// $lengths = []; |
477
|
|
|
// if($queryOptions["modify"]) |
478
|
|
|
// { |
479
|
|
|
// foreach($rows as $row) |
480
|
|
|
// { |
481
|
|
|
// foreach($row as $key => $value) |
482
|
|
|
// { |
483
|
|
|
// $lengths[$key] = \max($lengths[$key], \min(40, strlen(\utf8_decode($value)))); |
484
|
|
|
// } |
485
|
|
|
// } |
486
|
|
|
// } |
487
|
|
|
|
488
|
|
|
$results = []; |
489
|
|
|
foreach ($rows as $n => $row) { |
490
|
|
|
$uniqueIds = $this->util->uniqueIds($rows[$n], $indexes); |
491
|
|
|
if (empty($uniqueIds)) { |
492
|
|
|
foreach ($row as $key => $value) { |
493
|
|
|
if (!\preg_match('~^(COUNT\((\*|(DISTINCT )?`(?:[^`]|``)+`)\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\(`(?:[^`]|``)+`\))$~', $key)) { |
494
|
|
|
//! columns looking like functions |
495
|
|
|
$uniqueIds[$key] = $value; |
496
|
|
|
} |
497
|
|
|
} |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
// Unique identifier to edit returned data. |
501
|
|
|
// $unique_idf = ""; |
502
|
|
|
$rowIds = [ |
503
|
|
|
'where' => [], |
504
|
|
|
'null' => [], |
505
|
|
|
]; |
506
|
|
|
foreach ($uniqueIds as $key => $value) { |
507
|
|
|
$key = \trim($key); |
508
|
|
|
$type = ''; |
509
|
|
|
$collation = ''; |
510
|
|
|
if (isset($fields[$key])) { |
511
|
|
|
$type = $fields[$key]->type; |
512
|
|
|
$collation = $fields[$key]->collation; |
513
|
|
|
} |
514
|
|
|
if (($this->driver->jush() == "sql" || $this->driver->jush() == "pgsql") && |
515
|
|
|
\preg_match('~char|text|enum|set~', $type) && strlen($value) > 64) { |
516
|
|
|
$key = (\strpos($key, '(') ? $key : $this->driver->escapeId($key)); //! columns looking like functions |
517
|
|
|
$key = "MD5(" . ($this->driver->jush() != 'sql' || \preg_match("~^utf8~", $collation) ? |
518
|
|
|
$key : "CONVERT($key USING " . $this->driver->charset() . ")") . ")"; |
519
|
|
|
$value = \md5($value); |
520
|
|
|
} |
521
|
|
|
if ($value !== null) { |
522
|
|
|
$rowIds['where'][$this->util->bracketEscape($key)] = $value; |
523
|
|
|
} else { |
524
|
|
|
$rowIds['null'][] = $this->util->bracketEscape($key); |
525
|
|
|
} |
526
|
|
|
// $unique_idf .= "&" . ($value !== null ? \urlencode("where[" . $this->util->bracketEscape($key) . "]") . |
527
|
|
|
// "=" . \urlencode($value) : \urlencode("null[]") . "=" . \urlencode($key)); |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
$cols = []; |
531
|
|
|
foreach ($row as $key => $value) { |
532
|
|
|
if (isset($names[$key])) { |
533
|
|
|
$field = $fields[$key] ?? new TableFieldEntity(); |
534
|
|
|
$value = $this->driver->value($value, $field); |
535
|
|
|
if ($value != "" && (!isset($email_fields[$key]) || $email_fields[$key] != "")) { |
536
|
|
|
//! filled e-mails can be contained on other pages |
537
|
|
|
$email_fields[$key] = ($this->util->isMail($value) ? $names[$key] : ""); |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
$link = ""; |
541
|
|
|
|
542
|
|
|
$value = $this->util->selectValue($value, $link, $field, $textLength); |
543
|
|
|
$text = preg_match('~text|lob~', $field->type); |
544
|
|
|
|
545
|
|
|
$cols[] = compact(/*'id', */'text', 'value'/*, 'editable'*/); |
546
|
|
|
} |
547
|
|
|
} |
548
|
|
|
$results[] = ['ids' => $rowIds, 'cols' => $cols]; |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
$isGroup = count($group) < count($select); |
552
|
|
|
$total = $this->driver->result($this->driver->sqlForRowCount($table, $where, $isGroup, $group)); |
553
|
|
|
|
554
|
|
|
$rows = $results; |
555
|
|
|
return compact('duration', 'headers', 'query', 'rows', 'limit', 'total', 'error'); |
556
|
|
|
} |
557
|
|
|
} |
558
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.