-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDatabase.php
More file actions
114 lines (96 loc) · 3.27 KB
/
Copy pathDatabase.php
File metadata and controls
114 lines (96 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?php
namespace FpDbTest;
use Exception;
use mysqli;
class Database implements DatabaseInterface
{
private mysqli $mysqli;
public function __construct(mysqli $mysqli)
{
$this->mysqli = $mysqli;
}
public function buildQuery(string $query, array $args = []): string
{
$argPos = 0;
// replace args
$result = preg_replace_callback(
"/\?[dfa#]?/",
function ($matched) use ($args, &$argPos) {
// echo("!!!matched $argPos:".print_r($matched, true));
switch ($matched[0]) {
case '?':
return $this->formatArg($args[$argPos++], '');
case '?#':
return $this->formatArg($args[$argPos++], '#');
case '?d':
return $this->formatArg($args[$argPos++], 'd');
case '?a':
return $this->formatArg($args[$argPos++], 'a');
}
},
$query,
);
if ($argPos <> count($args)) throw new Exception("Not all the args are consumed");
// replace conditional blocks
$result = preg_replace_callback(
"/\{([^\}]+)\}/",
function ($matched) use ($args, &$argPos) {
if (str_contains($matched[1], $this->skip())) return '';
return $matched[1];
},
$result,
);
return $result;
}
private function formatArg($arg, $type) {
if ($arg == $this->skip()) {
return $arg;
}
if ($type == 'a') {
// format as array
if (!is_array($arg)) throw new Exception("Array expected");
if (!count($arg)) throw new Exception("Empty array");
if (array_is_list($arg)) {
$parts = array_map(
fn ($x) => $this->formatArg($x, ''),
$arg,
);
return implode(", ", $parts);
}
// format as associative array
$parts = [];
foreach ($arg as $k => $v) {
$parts[] = $this->formatArg($k, '#')." = ".$this->formatArg($v, '');
}
return implode(", ", $parts);
}
if ($type == '#') {
// format as identifiers
$arr = is_string($arg) ? [$arg] : $arg;
if (!is_array($arr)) throw new Exception("Array expected");
if (!count($arr)) throw new Exception("Empty array");
return "`". implode("`, `", $arr) . "`"; // TODO: escape?
}
if ($type == '' && is_string($arg)) {
// format as string
return "'$arg'"; // TODO: escape
}
if ($type == 'd' || ($type == '' && is_int($arg))) {
// format as integer
return (int)$arg;
}
if ($type == 'f' || ($type == '' && is_float($arg))) {
// format as float
return (float)$arg;
}
if (in_array($type, ['f','d','']) && is_null($arg)) {
// format as null
return 'NULL';
}
return $arg;
}
public function skip()
{
return '__SKIPPED__8s7dtfgkdhlsfo';
}
}