Skip to content

Commit 1e207c7

Browse files
author
Wazabii
committed
Minor changes
1 parent 4bcc5a1 commit 1e207c7

File tree

3 files changed

+312
-3
lines changed

3 files changed

+312
-3
lines changed

AbstractDB.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ final protected function setWhereData(string|AttrInterface $key, string|int|floa
219219
$this->whereProtocol[$key][] = $val;
220220
$this->resetWhere();
221221
}
222-
222+
223223
/**
224224
* Get the Main FK data protocol
225225
* @return array
@@ -411,4 +411,4 @@ final protected function query(string|self $sql, ?string $method = null, array $
411411
}
412412
return $query;
413413
}
414-
}
414+
}

DB.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,4 +790,4 @@ public function insertID(): int|string
790790
{
791791
return Connect::DB()->insert_id;
792792
}
793-
}
793+
}

Utility/Build.php

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
<?php
2+
3+
namespace MaplePHP\Query\Utility;
4+
5+
use MaplePHP\Query\Interfaces\AttrInterface;
6+
use MaplePHP\Query\Connect;
7+
8+
class Build
9+
{
10+
11+
protected const OPERATORS = [">", ">=", "<", "<>", "!=", "<=", "<=>"]; // Comparison operators
12+
protected const JOIN_TYPES = ["INNER", "LEFT", "RIGHT", "CROSS"]; // Join types
13+
protected const VIEW_PREFIX_NAME = "view"; // View prefix
14+
15+
private $select;
16+
17+
protected $table;
18+
protected $join;
19+
protected $joinedTables;
20+
protected $limit;
21+
protected $offset;
22+
23+
protected $fkData;
24+
protected $mig;
25+
26+
protected $attr;
27+
28+
29+
30+
public function __construct(object|array|null $obj = null)
31+
{
32+
33+
$this->attr = new \stdClass();
34+
if (!is_null($obj)) foreach($obj as $key => $value) {
35+
$this->attr->{$key} = $value;
36+
}
37+
}
38+
39+
40+
/**
41+
* Will build where string
42+
* @param string $prefix
43+
* @param array $where
44+
* @return string
45+
*/
46+
public function where(string $prefix, ?array $where): string
47+
{
48+
$out = "";
49+
if (!is_null($where)) {
50+
$out = " {$prefix}";
51+
$index = 0;
52+
foreach ($where as $array) {
53+
$firstAnd = key($array);
54+
$out .= (($index > 0) ? " {$firstAnd}" : "") . " (";
55+
$out .= $this->whereArrToStr($array);
56+
$out .= ")";
57+
$index++;
58+
}
59+
}
60+
return $out;
61+
}
62+
63+
64+
/**
65+
* Build joins
66+
* @return string
67+
*/
68+
public function join(
69+
string|array|MigrateInterface $table,
70+
string|array $where = null,
71+
array $sprint = array(),
72+
string $type = "INNER"
73+
): string
74+
{
75+
if ($table instanceof MigrateInterface) {
76+
$this->join = array_merge($this->join, $this->buildJoinFromMig($table, $type));
77+
} else {
78+
$this->buildJoinFromArgs($table, $where, $sprint, $type);
79+
}
80+
return (is_array($this->join)) ? " " . implode(" ", $this->join) : "";
81+
}
82+
83+
/**
84+
* Build limit
85+
* @return string
86+
*/
87+
public function limit(): string
88+
{
89+
if (is_null($this->attr->limit) && !is_null($this->attr->offset)) {
90+
$this->attr->limit = 1;
91+
}
92+
$offset = (!is_null($this->attr->offset)) ? ",{$this->attr->offset}" : "";
93+
return (!is_null($this->attr->limit)) ? " LIMIT {$this->attr->limit}{$offset}" : "";
94+
}
95+
96+
97+
/**
98+
* Build Where data
99+
* @param array $array
100+
* @return string
101+
*/
102+
final protected function whereArrToStr(array $array): string
103+
{
104+
$out = "";
105+
$count = 0;
106+
foreach ($array as $key => $arr) {
107+
foreach ($arr as $operator => $a) {
108+
if (is_array($a)) {
109+
foreach ($a as $col => $b) {
110+
foreach ($b as $val) {
111+
if ($count > 0) {
112+
$out .= "{$key} ";
113+
}
114+
$out .= "{$col} {$operator} {$val} ";
115+
$count++;
116+
}
117+
}
118+
} else {
119+
$out .= "{$key} {$a} ";
120+
$count++;
121+
}
122+
}
123+
}
124+
125+
return $out;
126+
}
127+
128+
/**
129+
* Build join data from Migrate data
130+
* @param MigrateInterface $mig
131+
* @param string $type Join type (INNER, LEFT, ...)
132+
* @return array
133+
*/
134+
final protected function buildJoinFromMig(MigrateInterface $mig, string $type): array
135+
{
136+
$joinArr = array();
137+
$prefix = Connect::prefix();
138+
$main = $this->getMainFKData();
139+
$data = $mig->getData();
140+
$this->mig->mergeData($data);
141+
$migTable = $mig->getTable();
142+
143+
foreach ($data as $col => $row) {
144+
if (isset($row['fk'])) {
145+
foreach ($row['fk'] as $a) {
146+
if ($a['table'] === (string)$this->attr->table) {
147+
$joinArr[] = "{$type} JOIN " . $prefix . $migTable . " " . $migTable .
148+
" ON (" . $migTable . ".{$col} = {$a['table']}.{$a['column']})";
149+
}
150+
}
151+
} else {
152+
foreach ($main as $c => $a) {
153+
foreach ($a as $t => $d) {
154+
if (in_array($col, $d)) {
155+
$joinArr[] = "{$type} JOIN " . $prefix . $migTable . " " . $migTable .
156+
" ON ({$t}.{$col} = {$this->attr->alias}.{$c})";
157+
}
158+
}
159+
}
160+
}
161+
162+
$this->joinedTables[$migTable] = $prefix . $migTable;
163+
}
164+
return $joinArr;
165+
}
166+
167+
168+
protected function buildJoinFromArgs(
169+
string|array $table,
170+
string|array $where,
171+
array $sprint = array(),
172+
string $type = "INNER"
173+
): void
174+
{
175+
if (is_null($where)) {
176+
throw new \InvalidArgumentException("You need to specify the argumnet 2 (where) value!", 1);
177+
}
178+
179+
$prefix = Connect::prefix();
180+
$arr = $this->sperateAlias($table);
181+
$table = (string)$this->prep($arr['table'], false);
182+
$alias = (!is_null($arr['alias'])) ? " {$arr['alias']}" : " {$table}";
183+
184+
if (is_array($where)) {
185+
$data = array();
186+
foreach ($where as $key => $val) {
187+
if (is_array($val)) {
188+
foreach ($val as $k => $v) {
189+
$this->setWhereData($k, $v, $data);
190+
}
191+
} else {
192+
$this->setWhereData($key, $val, $data);
193+
}
194+
}
195+
$out = $this->buildWhere("", $data);
196+
} else {
197+
$out = $this->sprint($where, $sprint);
198+
}
199+
$type = $this->joinTypes(strtoupper($type)); // Whitelist
200+
$this->join[] = "{$type} JOIN {$prefix}{$table}{$alias} ON " . $out;
201+
$this->joinedTables[$table] = "{$prefix}{$table}";
202+
}
203+
204+
/**
205+
* Get the Main FK data protocol
206+
* @return array
207+
*/
208+
final protected function getMainFKData(): array
209+
{
210+
if (is_null($this->fkData)) {
211+
$this->fkData = array();
212+
foreach ($this->mig->getMig()->getData() as $col => $row) {
213+
if (isset($row['fk'])) {
214+
foreach ($row['fk'] as $a) {
215+
$this->fkData[$col][$a['table']][] = $a['column'];
216+
}
217+
}
218+
}
219+
}
220+
return $this->fkData;
221+
}
222+
223+
224+
/**
225+
* Sperate Alias
226+
* @param string|array $data
227+
* @return array
228+
*/
229+
final protected function sperateAlias(string|array|DBInterface $data): array
230+
{
231+
$alias = null;
232+
$table = $data;
233+
if (is_array($data)) {
234+
if (count($data) !== 2) {
235+
throw new DBQueryException("If you specify Table as array then it should look " .
236+
"like this [TABLE_NAME, ALIAS]", 1);
237+
}
238+
$alias = array_pop($data);
239+
$table = reset($data);
240+
}
241+
return ["alias" => $alias, "table" => $table];
242+
}
243+
244+
/**
245+
* Mysql Prep/protect string
246+
* @param mixed $val
247+
* @return AttrInterface
248+
*/
249+
final protected function prep(mixed $val, bool $enclose = true): AttrInterface
250+
{
251+
if ($val instanceof AttrInterface) {
252+
return $val;
253+
}
254+
$val = $this->getAttr($val);
255+
$val->enclose($enclose);
256+
return $val;
257+
}
258+
259+
/**
260+
* Mysql Prep/protect array items
261+
* @param array $arr
262+
* @param bool $enclose
263+
* @return array
264+
*/
265+
final protected function prepArr(array $arr, bool $enclose = true): array
266+
{
267+
$new = array();
268+
foreach ($arr as $pKey => $pVal) {
269+
$key = (string)$this->prep($pKey, false);
270+
$new[$key] = (string)$this->prep($pVal, $enclose);
271+
}
272+
return $new;
273+
}
274+
275+
/**
276+
* Get new Attr instance
277+
* @param array|string|int|float $value
278+
* @return AttrInterface
279+
*/
280+
protected function getAttr(array|string|int|float $value): AttrInterface
281+
{
282+
return new Attr($value);
283+
}
284+
285+
/**
286+
* Use vsprintf to mysql prep/protect input in string. Prep string values needs to be eclosed manually
287+
* @param string $str SQL string example: (id = %d AND permalink = '%s')
288+
* @param array $arr Mysql prep values
289+
* @return string
290+
*/
291+
final protected function sprint(string $str, array $arr = array()): string
292+
{
293+
return vsprintf($str, $this->prepArr($arr, false));
294+
}
295+
296+
/**
297+
* Whitelist mysql join types
298+
* @param string $val
299+
* @return string
300+
*/
301+
protected function joinTypes(string $val): string
302+
{
303+
$val = trim($val);
304+
if (in_array($val, $this::JOIN_TYPES)) {
305+
return $val;
306+
}
307+
return "INNER";
308+
}
309+
}

0 commit comments

Comments
 (0)