1 | <?php |
||
2 | namespace Godsgood33\Php_Db; |
||
3 | |||
4 | use mysqli; |
||
5 | use stdClass; |
||
6 | use Exception; |
||
7 | use InvalidArgumentException; |
||
8 | |||
9 | use Monolog\Logger; |
||
10 | use Monolog\Formatter\LineFormatter; |
||
11 | use Monolog\Handler\StreamHandler; |
||
12 | |||
13 | use Godsgood33\Php_Db\Exceptions\MissingParams; |
||
14 | use Godsgood33\Php_Db\Exceptions\ConnectError; |
||
15 | use Godsgood33\Php_Db\Exceptions\MissingInterfaceAndMethods; |
||
16 | use Godsgood33\Php_Db\Exceptions\QueryError; |
||
17 | |||
18 | /** |
||
19 | * Constant to define that we want to return an object |
||
20 | * |
||
21 | * @var int |
||
22 | */ |
||
23 | define('MYSQLI_OBJECT', 4); |
||
24 | |||
25 | /** |
||
26 | * Constant to return consistent date format |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | define('MYSQL_DATE', 'Y-m-d'); |
||
31 | |||
32 | /** |
||
33 | * Constant to return consistent datetime format |
||
34 | * |
||
35 | * @var string |
||
36 | */ |
||
37 | define('MYSQL_DATETIME', 'Y-m-d H:i:s'); |
||
38 | |||
39 | /** |
||
40 | * A generic database class |
||
41 | * |
||
42 | * @author Ryan Prather <[email protected]> |
||
43 | */ |
||
44 | class Database |
||
45 | { |
||
46 | |||
47 | /** |
||
48 | * Constant defining a SELECT query |
||
49 | * |
||
50 | * @var integer |
||
51 | */ |
||
52 | private const SELECT = 1; |
||
53 | |||
54 | /** |
||
55 | * Constant defining a SELECT COUNT query |
||
56 | * |
||
57 | * @var integer |
||
58 | */ |
||
59 | private const SELECT_COUNT = 2; |
||
60 | |||
61 | /** |
||
62 | * Constant defining a CREATE TABLE query |
||
63 | * |
||
64 | * @var integer |
||
65 | */ |
||
66 | private const CREATE_TABLE = 3; |
||
67 | |||
68 | /** |
||
69 | * Constant defining DROP query |
||
70 | * |
||
71 | * @var integer |
||
72 | */ |
||
73 | private const DROP = 4; |
||
74 | |||
75 | /** |
||
76 | * Constant defining DELETE query |
||
77 | * |
||
78 | * @var integer |
||
79 | */ |
||
80 | private const DELETE = 5; |
||
81 | |||
82 | /** |
||
83 | * Constant defining INSERT query |
||
84 | * |
||
85 | * @var integer |
||
86 | */ |
||
87 | private const INSERT = 6; |
||
88 | |||
89 | /** |
||
90 | * Constant defining REPLACE query |
||
91 | * |
||
92 | * @var integer |
||
93 | */ |
||
94 | private const REPLACE = 7; |
||
95 | |||
96 | /** |
||
97 | * Constant defining UPDATE query |
||
98 | * |
||
99 | * @var integer |
||
100 | */ |
||
101 | private const UPDATE = 8; |
||
102 | |||
103 | /** |
||
104 | * Constant defining EXTENDED INSERT query |
||
105 | * |
||
106 | * @var integer |
||
107 | */ |
||
108 | private const EXTENDED_INSERT = 9; |
||
109 | |||
110 | /** |
||
111 | * Constant defining EXTENDED REPLACE query |
||
112 | * |
||
113 | * @var integer |
||
114 | */ |
||
115 | private const EXTENDED_REPLACE = 10; |
||
116 | |||
117 | /** |
||
118 | * Constant defining EXTENDED UPDATE query |
||
119 | * |
||
120 | * @var integer |
||
121 | */ |
||
122 | private const EXTENDED_UPDATE = 11; |
||
123 | |||
124 | /** |
||
125 | * Constant defining ALTER TABLE query |
||
126 | * |
||
127 | * @var integer |
||
128 | */ |
||
129 | private const ALTER_TABLE = 12; |
||
130 | |||
131 | /** |
||
132 | * Constant defining action for alter table statement |
||
133 | * |
||
134 | * @var integer |
||
135 | */ |
||
136 | private const ADD_COLUMN = 1; |
||
137 | |||
138 | /** |
||
139 | * Constant defining action for alter table statement |
||
140 | * |
||
141 | * @var integer |
||
142 | */ |
||
143 | private const DROP_COLUMN = 2; |
||
144 | |||
145 | /** |
||
146 | * Constant defining action for alter table statement |
||
147 | * |
||
148 | * @var integer |
||
149 | */ |
||
150 | private const MODIFY_COLUMN = 3; |
||
151 | |||
152 | /** |
||
153 | * Constant defining action to add a constraint |
||
154 | * |
||
155 | * @var integer |
||
156 | */ |
||
157 | private const ADD_CONSTRAINT = 4; |
||
158 | |||
159 | /** |
||
160 | * Constant defining a TRUNCATE TABLE query |
||
161 | * |
||
162 | * @var integer |
||
163 | */ |
||
164 | private const TRUNCATE = 13; |
||
165 | |||
166 | /** |
||
167 | * The mysqli connection |
||
168 | * |
||
169 | * @access protected |
||
170 | * @var mysqli |
||
171 | */ |
||
172 | protected $_c; |
||
173 | |||
174 | /** |
||
175 | * To store the SQL statement |
||
176 | * |
||
177 | * @access private |
||
178 | * @var string |
||
179 | */ |
||
180 | private $_sql = null; |
||
181 | |||
182 | /** |
||
183 | * A variable to store the type of query that is being run |
||
184 | * |
||
185 | * @access private |
||
186 | * @var int |
||
187 | */ |
||
188 | private $_queryType = null; |
||
189 | |||
190 | /** |
||
191 | * The result of the query |
||
192 | * |
||
193 | * @access protected |
||
194 | * @var mixed |
||
195 | */ |
||
196 | protected $_result = null; |
||
197 | |||
198 | /** |
||
199 | * Log level |
||
200 | * |
||
201 | * @access private |
||
202 | * @var string |
||
203 | */ |
||
204 | private $_logLevel = Logger::ERROR; |
||
205 | |||
206 | /** |
||
207 | * Variable to store the logger |
||
208 | * |
||
209 | * @access private |
||
210 | * @var \Monolog\Logger |
||
211 | */ |
||
212 | private $_logger = null; |
||
213 | |||
214 | /** |
||
215 | * Path for the logger to log the file |
||
216 | * |
||
217 | * @access private |
||
218 | * @var string |
||
219 | */ |
||
220 | private $_logPath = null; |
||
221 | |||
222 | /** |
||
223 | * Variable to store the most recent insert ID from an insert query |
||
224 | * |
||
225 | * @access protected |
||
226 | * @var mixed |
||
227 | */ |
||
228 | protected $_insertId = null; |
||
229 | |||
230 | /** |
||
231 | * Constructor |
||
232 | * |
||
233 | * @param string $strLogPath |
||
234 | * [optional] absolute log path for the log file |
||
235 | * @param mysqli $dbh |
||
236 | * [optional] |
||
237 | * [by ref] |
||
238 | * mysqli object to perform queries. |
||
239 | * @param int $intLogLevel |
||
240 | * [optional] Level of the log file to output |
||
241 | * |
||
242 | * @uses PHP_DB_ENCRYPT bool to define if the password is encrypted |
||
243 | * @uses PHP_DB_PWD string to store the password |
||
244 | * @uses PHP_DB_SERVER string to store the database server name or IP |
||
245 | * @uses PHP_DB_USER string to store the name of the user used to connect to the server |
||
246 | * @uses PHP_DB_SCHEMA string to store the default schema to connect to |
||
247 | * @uses PHP_DB_LOG_LEVEL int to store the PSR-4 log level for the library |
||
248 | * @uses PHP_DB_CLI_LOG bool to store if logs should be echoed to STDOUT |
||
249 | */ |
||
250 | 130 | public function __construct($strLogPath = __DIR__, mysqli &$dbh = null, $intLogLevel = null) |
|
251 | { |
||
252 | // set the log file path |
||
253 | 130 | $this->_logPath = $strLogPath; |
|
254 | 130 | if (!file_exists($this->_logPath)) { |
|
255 | touch($this->_logPath . "/db.log"); |
||
256 | } |
||
257 | |||
258 | // set the log level |
||
259 | 130 | if (!defined("PHP_DB_LOG_LEVEL") && is_null($intLogLevel)) { |
|
260 | $this->_logLevel = Logger::ERROR; |
||
261 | 130 | } elseif (!is_null($intLogLevel)) { |
|
262 | $this->_logLevel = $intLogLevel; |
||
263 | 130 | } elseif (defined('PHP_DB_LOG_LEVEL')) { |
|
264 | 130 | $this->_logLevel = PHP_DB_LOG_LEVEL; |
|
265 | } |
||
266 | |||
267 | // open the log handler |
||
268 | 130 | $this->_logger = new Logger('db', [ |
|
269 | 130 | new StreamHandler(realpath($this->_logPath . "/db.log"), $this->_logLevel) |
|
270 | ]); |
||
271 | |||
272 | // check to see if we are operating in a CLI and if the user wants log data output to the terminal |
||
273 | 130 | if (PHP_SAPI == 'cli' && defined('PHP_DB_CLI_LOG') && PHP_DB_CLI_LOG) { |
|
274 | $stream = new StreamHandler(STDOUT, $this->_logLevel); |
||
275 | $stream->setFormatter(new LineFormatter("%datetime% %level_name% %message%" . PHP_EOL, "H:i:s.u")); |
||
276 | $this->_logger->pushHandler($stream); |
||
277 | } |
||
278 | |||
279 | // check to see if a connection was passed and all defined constants are present to establish a connection |
||
280 | 130 | if (! is_null($dbh) && is_a($dbh, 'mysqli')) { |
|
281 | 1 | $this->_logger->debug("Connecting through existing connection"); |
|
282 | 1 | $this->_c = $dbh; |
|
283 | 130 | } elseif (!defined('PHP_DB_SERVER') || !defined('PHP_DB_USER') || !defined('PHP_DB_PWD') || !defined('PHP_DB_SCHEMA')) { |
|
284 | $this->_logger->critical("Missing essential defined constants"); |
||
285 | throw new MissingParams("Please create and include a constant file with the following constants defining your DB connection (PHP_DB_SERVER, PHP_DB_USER, PHP_DB_PWD, PHP_DB_SCHEMA)", E_USER_ERROR); |
||
286 | 130 | } elseif (defined('PHP_DB_ENCRYPT') && (!defined('PHP_DB_ENCRYPT_ALGORITHM') || !defined('PHP_DB_ENCRYPT_SALT'))) { |
|
287 | $this->_logger->critical("Missing essential encryption constants"); |
||
288 | throw new MissingParams("Missing required PHP_DB_ENCRYPT_ALGORITHM or PHP_DB_ENCRYPT_SALT constants"); |
||
289 | } |
||
290 | |||
291 | // check to see if the password is encrypted and decrypt if it is |
||
292 | 130 | if (defined('PHP_DB_ENCRYPT') && PHP_DB_ENCRYPT) { |
|
293 | 130 | $this->_logger->debug("Decrypting password"); |
|
294 | 130 | $pwd = $this->decrypt(PHP_DB_PWD); |
|
295 | } else { |
||
296 | $pwd = PHP_DB_PWD; |
||
297 | } |
||
298 | |||
299 | // open the connection |
||
300 | 130 | $this->_c = new mysqli(PHP_DB_SERVER, PHP_DB_USER, $pwd, PHP_DB_SCHEMA); |
|
301 | |||
302 | // check for a connection error and throw an error if there is one |
||
303 | 130 | if ($this->_c->connect_errno) { |
|
304 | $this->_logger->error("Error connecting to database {$this->_c->connect_error}"); |
||
305 | throw new ConnectError("Could not create database class due to error {$this->_c->connect_error}", E_ERROR); |
||
306 | } |
||
307 | |||
308 | // update the logger with the connection details |
||
309 | 130 | $this->_logger->info("Database connected"); |
|
310 | 130 | $this->_logger->debug("Connection details:", [ |
|
311 | 130 | 'Server' => PHP_DB_SERVER, |
|
312 | 130 | 'User' => PHP_DB_USER, |
|
313 | 130 | 'Schema' => PHP_DB_SCHEMA |
|
314 | ]); |
||
315 | |||
316 | 130 | $this->setVar("time_zone", "+00:00"); |
|
317 | 130 | $this->setVar("sql_mode", ""); |
|
318 | 130 | } |
|
319 | |||
320 | /** |
||
321 | * Function to make sure that the database is connected |
||
322 | * |
||
323 | * @return bool |
||
324 | * |
||
325 | * @throws ConnectError |
||
326 | */ |
||
327 | 17 | public function isConnected(): bool |
|
328 | { |
||
329 | 17 | $this->_logger->info("Checking for live connection"); |
|
330 | |||
331 | 17 | if (is_a($this->_c, 'mysqli')) { |
|
332 | 16 | $ret = $this->_c->ping(); |
|
333 | } else { |
||
334 | 1 | throw new ConnectError("Connection lost"); |
|
335 | } |
||
336 | |||
337 | 16 | return $ret; |
|
338 | } |
||
339 | |||
340 | /** |
||
341 | * Setter function for _logger |
||
342 | * |
||
343 | * @param Logger $log |
||
344 | * |
||
345 | * @return bool |
||
346 | */ |
||
347 | 1 | public function setLogger(Logger $log): bool |
|
348 | { |
||
349 | // set the logger |
||
350 | 1 | $this->_logger->debug("Setting logger"); |
|
351 | 1 | $this->_logger = $log; |
|
352 | 1 | return true; |
|
353 | } |
||
354 | |||
355 | /** |
||
356 | * Getter function for _logLevel |
||
357 | * |
||
358 | * @return int |
||
359 | */ |
||
360 | 1 | public function getLogLevel(): int |
|
361 | { |
||
362 | 1 | $level = $this->_logLevel; |
|
363 | |||
364 | 1 | $this->_logger->debug("Getting log level ({$level})"); |
|
365 | 1 | return $level; |
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
366 | } |
||
367 | |||
368 | /** |
||
369 | * Getter function for _queryType |
||
370 | * |
||
371 | * @return int |
||
372 | */ |
||
373 | 1 | public function getQueryType(): int |
|
374 | { |
||
375 | 1 | $this->_logger->debug("Getting query type"); |
|
376 | 1 | return $this->_queryType; |
|
377 | } |
||
378 | |||
379 | /** |
||
380 | * Setter function for _queryType |
||
381 | * |
||
382 | * @param int $qt |
||
383 | * Class constants that store query type |
||
384 | * |
||
385 | * @return Database |
||
386 | */ |
||
387 | 100 | private function setQueryType(int $qt): Database |
|
388 | { |
||
389 | 100 | $this->_logger->debug("Setting query type"); |
|
390 | 100 | $this->_queryType = $qt; |
|
391 | |||
392 | 100 | return $this; |
|
393 | } |
||
394 | |||
395 | /** |
||
396 | * Magic method to convert the class to a string represented by the SQL query |
||
397 | * |
||
398 | * @return string|null |
||
399 | */ |
||
400 | 66 | public function __toString(): ?string |
|
401 | { |
||
402 | 66 | $this->_logger->notice("__toString"); |
|
403 | 66 | $this->_logger->debug($this->_sql); |
|
404 | 66 | return $this->_sql; |
|
405 | } |
||
406 | |||
407 | /** |
||
408 | * Function to return the currently selected database schema |
||
409 | * |
||
410 | * @return string|bool |
||
411 | * Returns the string name of the selected schema or FALSE if none selected |
||
412 | */ |
||
413 | 1 | public function getSchema() |
|
414 | { |
||
415 | 1 | if ($res = $this->_c->query("SELECT DATABASE()")) { |
|
416 | 1 | $row = $res->fetch_row(); |
|
417 | |||
418 | 1 | $this->_logger->debug("Getting schema {$row[0]}"); |
|
419 | 1 | return $row[0]; |
|
420 | } |
||
421 | |||
422 | return false; |
||
423 | } |
||
424 | |||
425 | /** |
||
426 | * Function to set schema |
||
427 | * |
||
428 | * @param string $strSchema |
||
429 | * |
||
430 | * @return bool |
||
431 | * |
||
432 | * @throws QueryError |
||
433 | */ |
||
434 | 2 | public function setSchema(string $strSchema): bool |
|
435 | { |
||
436 | 2 | $this->_logger->info("Setting schema to {$strSchema}"); |
|
437 | 2 | if (! $this->_c->select_db($strSchema)) { |
|
438 | 1 | $this->_logger->error("Unknown schema {$strSchema}"); |
|
439 | 1 | throw new QueryError("Unknown database schema $strSchema"); |
|
440 | } |
||
441 | 1 | return true; |
|
442 | } |
||
443 | |||
444 | /** |
||
445 | * Method to set a MYSQL variable |
||
446 | * |
||
447 | * @param string $strName |
||
448 | * Name of the SQL variable to set |
||
449 | * @param string $strVal |
||
450 | * Value for the variable |
||
451 | * |
||
452 | * @return bool |
||
453 | */ |
||
454 | 130 | public function setVar(string $strName, ?string $strVal): bool |
|
455 | { |
||
456 | 130 | if (empty($strName)) { |
|
457 | 1 | $this->_logger->debug("name is blank", [ |
|
458 | 1 | 'name' => $strName |
|
459 | ]); |
||
460 | 1 | return false; |
|
461 | } |
||
462 | |||
463 | 130 | $this->_logger->debug("Setting {$strName} = '{$strVal}'"); |
|
464 | |||
465 | 130 | if ($this->_c->real_query("SET $strName = {$this->_escape($strVal)}")) { |
|
466 | 130 | $this->_logger->info("Var set"); |
|
467 | 130 | return true; |
|
468 | } else { |
||
469 | 1 | $this->_logger->error("Failed to set variable {$this->_c->error}"); |
|
470 | 1 | return false; |
|
471 | } |
||
472 | } |
||
473 | |||
474 | /** |
||
475 | * Function to execute the statement |
||
476 | * |
||
477 | * @param int $return |
||
478 | * [optional] |
||
479 | * MYSQLI constant to control what is returned from the mysqli_result object |
||
480 | * @param string $strSql |
||
481 | * [optional] |
||
482 | * Optional SQL query |
||
483 | * |
||
484 | * @throws QueryError |
||
485 | * @throws ConnectError |
||
486 | * |
||
487 | * @return mixed |
||
488 | */ |
||
489 | 15 | public function execute(int $return = MYSQLI_OBJECT, ?string $strSql = null) |
|
490 | { |
||
491 | 15 | if (! is_null($strSql)) { |
|
492 | 2 | $this->_sql = $strSql; |
|
493 | } |
||
494 | |||
495 | 15 | $this->_result = false; |
|
496 | 15 | $this->_insertId = null; |
|
497 | |||
498 | 15 | $this->isConnected(); |
|
499 | |||
500 | 15 | $this->_logger->info("Executing {$this->_queryType} query"); |
|
501 | 15 | $this->_logger->debug($this->_sql); |
|
502 | |||
503 | try { |
||
504 | 15 | if (in_array($this->_queryType, [ |
|
505 | 15 | self::SELECT, |
|
506 | 15 | self::SELECT_COUNT |
|
507 | ])) { |
||
508 | 6 | $this->_result = $this->_c->query($this->_sql); |
|
509 | 6 | if ($this->_c->error) { |
|
510 | $this->_logger->error("There is an error {$this->_c->error}"); |
||
511 | $this->_logger->debug("Errored on query", [$this->_sql]); |
||
512 | throw new QueryError("There was an error {$this->_c->error}", E_ERROR); |
||
513 | } |
||
514 | } else { |
||
515 | 9 | $this->_result = $this->_c->real_query($this->_sql); |
|
516 | 9 | if ($this->_c->errno) { |
|
517 | 1 | $this->_logger->error("There was an error {$this->_c->error}"); |
|
518 | 1 | $this->_logger->debug("Errored on query", [$this->_sql]); |
|
519 | 1 | throw new QueryError("There was an error {$this->_c->error}", E_ERROR); |
|
520 | } |
||
521 | } |
||
522 | |||
523 | 14 | $this->_logger->debug("Checking for query results"); |
|
524 | 14 | $this->_result = $this->checkResults($return); |
|
525 | 1 | } catch (QueryError $e) { |
|
526 | 1 | $this->_logger->error($e); |
|
527 | } |
||
528 | |||
529 | 15 | return $this->_result; |
|
530 | } |
||
531 | |||
532 | /** |
||
533 | * Function to check the results and return what is expected |
||
534 | * |
||
535 | * @param mixed $returnType |
||
536 | * [optional] |
||
537 | * Optional return mysqli_result return type |
||
538 | * |
||
539 | * @return mixed |
||
540 | */ |
||
541 | 14 | protected function checkResults(int $returnType) |
|
542 | { |
||
543 | 14 | $res = null; |
|
544 | |||
545 | // check the sql results and process appropriately |
||
546 | 14 | if (in_array($this->_queryType, [Database::CREATE_TABLE, Database::ALTER_TABLE, Database::TRUNCATE, Database::DROP])) { |
|
547 | 5 | $res = $this->_result; |
|
548 | 9 | } elseif (in_array($this->_queryType, [Database::INSERT, Database::EXTENDED_INSERT, Database::DELETE, Database::UPDATE, Database::EXTENDED_UPDATE, Database::REPLACE, Database::EXTENDED_REPLACE, Database::DELETE])) { |
|
549 | 2 | $res = $this->_c->affected_rows; |
|
550 | |||
551 | 2 | if (in_array($this->_queryType, [Database::INSERT, Database::REPLACE, Database::EXTENDED_INSERT])) { |
|
552 | 2 | $this->_insertId = $this->_c->insert_id; |
|
553 | } |
||
554 | 7 | } elseif ($this->_queryType == Database::SELECT_COUNT) { |
|
555 | 1 | if (! is_a($this->_result, 'mysqli_result')) { |
|
556 | $this->_logger->error("Error with return on query"); |
||
557 | return null; |
||
558 | } |
||
559 | |||
560 | 1 | if ($this->_result->num_rows == 1) { |
|
561 | 1 | $row = $this->_result->fetch_assoc(); |
|
562 | 1 | if (isset($row['count'])) { |
|
563 | 1 | $this->_logger->debug("Returning SELECT_COUNT query", [ |
|
564 | 1 | 'count' => $row['count'] |
|
565 | ]); |
||
566 | 1 | $res = $row['count']; |
|
567 | } |
||
568 | } elseif ($this->_result->num_rows > 1) { |
||
569 | $this->_logger->debug("Returning SELECT_COUNT query", [ |
||
570 | 'count' => $this->_result->num_rows |
||
571 | ]); |
||
572 | $res = $this->_result->num_rows; |
||
573 | } |
||
574 | |||
575 | 1 | mysqli_free_result($this->_result); |
|
576 | } else { |
||
577 | 6 | $method = "mysqli_fetch_object"; |
|
578 | 6 | if ($returnType == MYSQLI_ASSOC) { |
|
579 | 1 | $method = "mysqli_fetch_assoc"; |
|
580 | 5 | } elseif ($returnType == MYSQLI_NUM) { |
|
581 | 1 | $method = "mysqli_fetch_array"; |
|
582 | } |
||
583 | |||
584 | 6 | if (is_a($this->_result, 'mysqli_result')) { |
|
585 | 5 | if ($this->_result->num_rows > 1) { |
|
586 | 3 | $res = []; |
|
587 | 3 | while ($row = call_user_func($method, $this->_result)) { |
|
588 | 3 | $res[] = $row; |
|
589 | } |
||
590 | } else { |
||
591 | 2 | $res = call_user_func($method, $this->_result); |
|
592 | } |
||
593 | } else { |
||
594 | 1 | $this->_logger->error("Error with return on query"); |
|
595 | 1 | return null; |
|
596 | } |
||
597 | } |
||
598 | |||
599 | 13 | if ($this->_c->error) { |
|
600 | $this->_logger->error("Encountered a SQL error", ['error' => $this->_c->error, 'list' => $this->_c->error_list]); |
||
601 | $this->_logger->debug("Debug", ['debug' => debug_backtrace()]); |
||
602 | return null; |
||
603 | } |
||
604 | |||
605 | 13 | return $res; |
|
606 | } |
||
607 | |||
608 | /** |
||
609 | * Function to pass through calling the query function (used for backwards compatibility and for more complex queries that aren't currently supported) |
||
610 | * Nothing is escaped |
||
611 | * |
||
612 | * @param string $strSql |
||
613 | * [optional] |
||
614 | * Optional query to pass in and execute |
||
615 | * |
||
616 | * @return mysqli_result|bool |
||
0 ignored issues
–
show
|
|||
617 | */ |
||
618 | 2 | public function query(?string $strSql = null) |
|
619 | { |
||
620 | 2 | return is_null($strSql) ? $this->_c->query($this->_sql) : $this->_c->query($strSql); |
|
0 ignored issues
–
show
|
|||
621 | } |
||
622 | |||
623 | /** |
||
624 | * A function to build a select query |
||
625 | * |
||
626 | * @param string $strTableName |
||
627 | * The table to query |
||
628 | * @param array|string $fields |
||
629 | * [optional] |
||
630 | * Optional array of fields to return (defaults to '*') |
||
631 | * @param array:DBWhere|DBWhere $arrWhere |
||
632 | * [optional] Where clause data |
||
633 | * @param array $arrFlags |
||
634 | * [optional] |
||
635 | * Optional 2-dimensional array to allow other flags |
||
636 | * |
||
637 | * @see Database::flags() |
||
638 | * |
||
639 | * @throws Exception |
||
640 | * @throws InvalidArgumentException |
||
641 | * |
||
642 | * @return mixed |
||
643 | * |
||
644 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
645 | */ |
||
646 | 37 | public function select(string $strTableName, $fields = null, $arrWhere = [], ?array $arrFlags = []) |
|
647 | { |
||
648 | 37 | $this->_sql = null; |
|
649 | 37 | $this->setQueryType(self::SELECT); |
|
650 | |||
651 | // starting building the query |
||
652 | 37 | if ($this->checkTableName($strTableName)) { |
|
653 | 37 | $this->_logger->debug("Starting SELECT query of {$strTableName}", [ |
|
654 | 37 | 'fields' => $this->fields($fields) |
|
655 | ]); |
||
656 | 36 | $this->_sql = "SELECT " . $this->fields($fields) . " FROM $strTableName"; |
|
657 | } |
||
658 | |||
659 | // add in any joins |
||
660 | 36 | if (isset($arrFlags['joins']) && is_array($arrFlags['joins']) && count($arrFlags['joins'])) { |
|
661 | 1 | $this->_logger->debug("Adding joins", [ |
|
662 | 1 | 'joins' => implode(' ', $arrFlags['joins']) |
|
663 | ]); |
||
664 | 1 | $this->_sql .= " " . implode(" ", $arrFlags['joins']); |
|
665 | } else { |
||
666 | 35 | $this->_logger->debug("No joins"); |
|
667 | } |
||
668 | |||
669 | // parse the where clauses |
||
670 | 36 | $where = $this->parseClause($arrWhere); |
|
671 | |||
672 | 34 | if (! is_null($where) && is_array($where) && count($where)) { |
|
673 | 8 | $where_str = " WHERE"; |
|
674 | 8 | $this->_logger->debug("Parsing where clause and adding to query"); |
|
675 | 8 | foreach ($where as $x => $w) { |
|
676 | 8 | if ($x > 0) { |
|
677 | 1 | $where_str .= " {$w->sqlOperator}"; |
|
678 | } |
||
679 | 8 | $where_str .= $w; |
|
680 | } |
||
681 | 8 | if (strlen($where_str) > strlen(" WHERE")) { |
|
682 | 8 | $this->_sql .= $where_str; |
|
683 | } |
||
684 | } |
||
685 | |||
686 | // search for any other flags (order, having, group) |
||
687 | 34 | if (is_array($arrFlags) && count($arrFlags)) { |
|
688 | 9 | $this->_logger->debug("Parsing flags and adding to query", $arrFlags); |
|
689 | 9 | $this->_sql .= $this->flags($arrFlags); |
|
690 | } |
||
691 | |||
692 | 32 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
693 | return $this->execute(); |
||
694 | } |
||
695 | |||
696 | 32 | return $this->_sql; |
|
697 | } |
||
698 | |||
699 | /** |
||
700 | * Function to build a query to check the number of rows in a table |
||
701 | * |
||
702 | * @param string $strTableName |
||
703 | * The table to query |
||
704 | * @param array:DBWhere|DBWhere $arrWhere |
||
705 | * [optional] |
||
706 | * Optional 2-dimensional array to build where clause |
||
707 | * @param array $arrFlags |
||
708 | * [optional] |
||
709 | * Optional 2-dimensional array to add flags |
||
710 | * |
||
711 | * @see Database::flags() |
||
712 | * |
||
713 | * @return int|NULL |
||
714 | * |
||
715 | * @throws InvalidArgumentException |
||
716 | * |
||
717 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
718 | */ |
||
719 | 4 | public function selectCount(string $strTableName, $arrWhere = [], ?array $arrFlags = []) |
|
720 | { |
||
721 | 4 | $this->_sql = null; |
|
722 | 4 | $this->setQueryType(self::SELECT_COUNT); |
|
723 | |||
724 | // start building query |
||
725 | 4 | if ($this->checkTableName($strTableName)) { |
|
726 | 4 | $this->_sql = "SELECT COUNT(1) AS 'count' FROM $strTableName"; |
|
727 | } |
||
728 | |||
729 | // add in any joins |
||
730 | 4 | if (isset($arrFlags['joins']) && is_array($arrFlags['joins'])) { |
|
731 | 1 | $this->_sql .= " " . implode(" ", $arrFlags['joins']); |
|
732 | } |
||
733 | |||
734 | // parse where clauses |
||
735 | 4 | $where = $this->parseClause($arrWhere); |
|
736 | |||
737 | 4 | if (! is_null($where) && is_array($where) && count($where)) { |
|
738 | 2 | $where_str = " WHERE"; |
|
739 | 2 | $this->_logger->debug("Parsing where clause and adding to query"); |
|
740 | 2 | foreach ($where as $x => $w) { |
|
741 | 2 | if ($x > 0) { |
|
742 | 1 | $where_str .= " {$w->sqlOperator}"; |
|
743 | } |
||
744 | 2 | $where_str .= $w; |
|
745 | } |
||
746 | 2 | if (strlen($where_str) > strlen(" WHERE")) { |
|
747 | 2 | $this->_sql .= $where_str; |
|
748 | } |
||
749 | } |
||
750 | |||
751 | // add in additional flags (group, having, order) |
||
752 | 4 | if (is_array($arrFlags) && count($arrFlags)) { |
|
753 | 1 | $this->_sql .= $this->flags($arrFlags); |
|
754 | } |
||
755 | |||
756 | 4 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
757 | return $this->execute(); |
||
758 | } |
||
759 | |||
760 | 4 | return $this->_sql; |
|
0 ignored issues
–
show
|
|||
761 | } |
||
762 | |||
763 | /** |
||
764 | * Function to build an insert query statement |
||
765 | * |
||
766 | * @param string $strTableName |
||
767 | * @param array|string $arrParams |
||
768 | * @param bool $blnToIgnore |
||
769 | * |
||
770 | * @return string|NULL |
||
771 | * |
||
772 | * @throws InvalidArgumentException |
||
773 | * @throws MissingInterfaceAndMethods |
||
774 | * |
||
775 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
776 | */ |
||
777 | 7 | public function insert(string $strTableName, $arrParams = null, bool $blnToIgnore = false) |
|
778 | { |
||
779 | 7 | $this->_sql = null; |
|
780 | 7 | $this->setQueryType(self::INSERT); |
|
781 | |||
782 | // start building query |
||
783 | 7 | if ($this->checkTableName($strTableName)) { |
|
784 | 7 | $this->_sql = "INSERT" . ($blnToIgnore ? " IGNORE" : "") . " INTO {$strTableName}"; |
|
785 | } |
||
786 | |||
787 | // add in field parameters and values |
||
788 | 7 | if (is_array($arrParams) && count($arrParams)) { |
|
789 | 3 | if (is_array($arrParams) && count($arrParams)) { |
|
790 | 3 | $this->_sql .= " (`" . implode("`,`", array_keys($arrParams)) . "`)"; |
|
791 | } |
||
792 | 3 | $this->_sql .= " VALUES (" . implode(",", array_map([ |
|
793 | 3 | $this, |
|
794 | 3 | '_escape' |
|
795 | 3 | ], array_values($arrParams))) . ")"; |
|
796 | 4 | } elseif (is_string($arrParams) && stripos($arrParams, 'select') !== false) { |
|
797 | 1 | $this->_sql .= " {$arrParams}"; |
|
798 | 3 | } elseif (is_object($arrParams)) { |
|
799 | 2 | $interfaces = class_implements($arrParams); |
|
800 | 2 | if (in_array("Godsgood33\Php_Db\DBInterface", $interfaces) && is_callable(get_class($arrParams) . "::insert")) { |
|
801 | 1 | $params = call_user_func([$arrParams, "insert"]); |
|
802 | 1 | $this->_sql .= " (`" . implode("`,`", array_keys($params)) . "`) VALUES "; |
|
803 | 1 | $this->_sql .= "(" . implode(",", array_map([$this, '_escape'], array_values($params))) . ")"; |
|
804 | } else { |
||
805 | 1 | throw new MissingInterfaceAndMethods("Object does not implement the DBInterface interface and methods"); |
|
806 | } |
||
807 | } else { |
||
808 | 1 | throw new InvalidArgumentException("Invalid type passed to insert " . gettype($arrParams)); |
|
809 | } |
||
810 | |||
811 | 5 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
812 | return $this->execute(); |
||
813 | } |
||
814 | |||
815 | 5 | return $this->_sql; |
|
816 | } |
||
817 | |||
818 | /** |
||
819 | * Function to create an extended insert query statement |
||
820 | * |
||
821 | * @param string $strTableName |
||
822 | * The table name that the data is going to be inserted on |
||
823 | * @param array $arrFields |
||
824 | * An array of field names that each value represents |
||
825 | * @param array|string $params |
||
826 | * An array of array of values or a string with a SELECT statement to populate the insert with |
||
827 | * @param bool $blnToIgnore |
||
828 | * [optional] |
||
829 | * Boolean to decide if we need to use the INSERT IGNORE INTO syntax |
||
830 | * |
||
831 | * @return NULL|string Returns the SQL if self::$autorun is set to false, else it returns the output from running. |
||
832 | * |
||
833 | * @throws InvalidArgumentException |
||
834 | * @throws MissingParams |
||
835 | * @throws MissingInterfaceAndMethods |
||
836 | * |
||
837 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
838 | */ |
||
839 | 7 | public function extendedInsert(string $strTableName, array $arrFields, $params, bool $blnToIgnore = false) |
|
840 | { |
||
841 | 7 | $this->_sql = null; |
|
842 | 7 | $this->setQueryType(self::EXTENDED_INSERT); |
|
843 | |||
844 | // start building query |
||
845 | 7 | if ($this->checkTableName($strTableName)) { |
|
846 | 7 | $this->_sql = "INSERT " . ($blnToIgnore ? "IGNORE " : "") . "INTO $strTableName " . "(`" . implode("`,`", $arrFields) . "`)"; |
|
847 | } |
||
848 | |||
849 | 7 | if (is_array($params) && count($params)) { |
|
850 | 6 | $this->_sql .= " VALUES "; |
|
851 | 6 | if (isset($params[0]) && is_array($params[0])) { |
|
852 | 4 | foreach ($params as $p) { |
|
853 | 4 | if (count($p) != count($arrFields)) { |
|
854 | 2 | $this->_logger->emergency("Inconsistent number of fields to values in extendedInsert", [ |
|
855 | 2 | $p, |
|
856 | 2 | debug_backtrace() |
|
857 | ]); |
||
858 | 2 | throw new MissingParams("Inconsistent number of fields in fields and values in extendedInsert " . print_r($p, true)); |
|
859 | } |
||
860 | 3 | $this->_sql .= "(" . implode(",", array_map([$this, '_escape'], array_values($p))) . ")"; |
|
861 | |||
862 | 3 | if ($p != end($params)) { |
|
863 | 3 | $this->_sql .= ","; |
|
864 | } |
||
865 | } |
||
866 | 2 | } elseif (isset($params[0]) && is_object($params[0])) { |
|
867 | 2 | $interfaces = class_implements($params[0]); |
|
868 | 2 | if (!in_array("Godsgood33\Php_Db\DBInterface", $interfaces)) { |
|
869 | 1 | throw new MissingInterfaceAndMethods("Object does not implement DBInterface interface and methods"); |
|
870 | } |
||
871 | 1 | foreach ($params as $param) { |
|
872 | 1 | if (!is_callable(get_class($param) . "::insert")) { |
|
873 | throw new MissingInterfaceAndMethods("Cannot call insert method"); |
||
874 | } |
||
875 | 1 | $key_value = call_user_func([$param, "insert"]); |
|
876 | 1 | $this->_sql .= "(" . implode(",", array_map([$this, '_escape'], array_values($key_value))) . "),"; |
|
877 | } |
||
878 | 1 | $this->_sql = substr($this->_sql, 0, -1); |
|
879 | } else { |
||
880 | $this->_sql .= "(" . implode("),(", array_map([$this, '_escape'], array_values($params))) . ")"; |
||
881 | } |
||
882 | } else { |
||
883 | 1 | throw new InvalidArgumentException("Invalid param type"); |
|
884 | } |
||
885 | |||
886 | 3 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
887 | return $this->execute(); |
||
888 | } |
||
889 | |||
890 | 3 | return $this->_sql; |
|
891 | } |
||
892 | |||
893 | /** |
||
894 | * Build a statement to update a table |
||
895 | * |
||
896 | * @param string $strTableName |
||
897 | * The table name to update |
||
898 | * @param array $arrParams |
||
899 | * Name/value pairs of the field name and value |
||
900 | * @param array:DBWhere|DBWhere $arrWhere |
||
901 | * [optional] |
||
902 | * DBWhere clauses |
||
903 | * @param array $arrFlags |
||
904 | * [optional] |
||
905 | * Two-dimensional array to create other flag options (joins, order, and group) |
||
906 | * |
||
907 | * @see Database::flags() |
||
908 | * |
||
909 | * @return NULL|string |
||
910 | * |
||
911 | * @throws InvalidArgumentException |
||
912 | * @throws MissingParams |
||
913 | * @throws MissingInterfaceAndMethods |
||
914 | * |
||
915 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
916 | */ |
||
917 | 9 | public function update(string $strTableName, $arrParams, $arrWhere = [], ?array $arrFlags = []) |
|
918 | { |
||
919 | 9 | $this->_sql = "UPDATE "; |
|
920 | 9 | $this->setQueryType(self::UPDATE); |
|
921 | |||
922 | 9 | if ($this->checkTableName($strTableName)) { |
|
923 | 9 | $this->_sql .= $strTableName; |
|
924 | |||
925 | 9 | if (isset($arrFlags['joins']) && is_array($arrFlags['joins'])) { |
|
926 | 1 | $this->_sql .= " " . implode(" ", $arrFlags['joins']); |
|
927 | 1 | unset($arrFlags['joins']); |
|
928 | } |
||
929 | |||
930 | 9 | $this->_sql .= " SET "; |
|
931 | } |
||
932 | |||
933 | 9 | if (is_array($arrParams) && count($arrParams)) { |
|
934 | 6 | $keys = array_keys($arrParams); |
|
935 | 6 | foreach ($arrParams as $f => $p) { |
|
936 | 6 | $field = $f; |
|
937 | 6 | if ((strpos($f, "`") === false) && (strpos($f, ".") === false) && (strpos($f, "*") === false) && (stripos($f, " as ") === false)) { |
|
938 | 5 | $field = "`{$f}`"; |
|
939 | } |
||
940 | |||
941 | 6 | if (! is_null($p)) { |
|
942 | 5 | $this->_sql .= "$field={$this->_escape($p)}"; |
|
943 | } else { |
||
944 | 1 | $this->_sql .= "$field=NULL"; |
|
945 | } |
||
946 | |||
947 | 6 | if ($f != end($keys)) { |
|
948 | 1 | $this->_sql .= ","; |
|
949 | } |
||
950 | } |
||
951 | 3 | } elseif (is_object($arrParams)) { |
|
952 | 2 | $interfaces = class_implements($arrParams); |
|
953 | 2 | if (in_array("Godsgood33\Php_Db\DBInterface", $interfaces) && is_callable(get_class($arrParams) . "::update")) { |
|
954 | 1 | $params = call_user_func([$arrParams, "update"]); |
|
955 | 1 | $fields = array_keys($params); |
|
956 | 1 | $values = array_map([$this, '_escape'], array_values($params)); |
|
957 | 1 | foreach ($fields as $x => $f) { |
|
958 | 1 | if ($x > 0) { |
|
959 | 1 | $this->_sql .= ","; |
|
960 | } |
||
961 | 1 | $this->_sql .= "`{$f}`={$values[$x]}"; |
|
962 | } |
||
963 | } else { |
||
964 | 1 | throw new MissingInterfaceAndMethods("Params is an object that doesn't implement DBInterface"); |
|
965 | } |
||
966 | } else { |
||
967 | 1 | throw new MissingParams("No fields to update"); |
|
968 | } |
||
969 | |||
970 | 7 | $where = $this->parseClause($arrWhere); |
|
971 | |||
972 | 7 | if (! is_null($where) && is_array($where) && count($where)) { |
|
973 | 3 | $where_str = " WHERE"; |
|
974 | 3 | $this->_logger->debug("Parsing where clause and adding to query"); |
|
975 | 3 | foreach ($where as $x => $w) { |
|
976 | 3 | if ($x > 0) { |
|
977 | 1 | $where_str .= " {$w->sqlOperator}"; |
|
978 | } |
||
979 | 3 | $where_str .= $w; |
|
980 | } |
||
981 | 3 | if (strlen($where_str) > strlen(" WHERE")) { |
|
982 | 3 | $this->_sql .= $where_str; |
|
983 | } |
||
984 | } |
||
985 | |||
986 | 7 | if (! is_null($arrFlags) && is_array($arrFlags) && count($arrFlags)) { |
|
987 | $this->_sql .= $this->flags($arrFlags); |
||
988 | } |
||
989 | |||
990 | 7 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
991 | return $this->execute(); |
||
992 | } |
||
993 | |||
994 | 7 | return $this->_sql; |
|
995 | } |
||
996 | |||
997 | /** |
||
998 | * Function to offer an extended updated functionality by using two different tables. |
||
999 | * |
||
1000 | * @param string $strTableToUpdate |
||
1001 | * The table that you want to update (alias 'tbu' is automatically added) |
||
1002 | * @param string $strOriginalTable |
||
1003 | * The table with the data you want to overwrite to_be_updated table (alias 'o' is automatically added) |
||
1004 | * @param string $strLinkField |
||
1005 | * The common index value between them that will join the fields |
||
1006 | * @param array|string $arrParams |
||
1007 | * If string only a single field is updated (tbu.$params = o.$params) |
||
1008 | * If array each element in the array is a field to be updated (tbu.$param = o.$param) |
||
1009 | * |
||
1010 | * @return mixed |
||
1011 | * |
||
1012 | * @throws InvalidArgumentException |
||
1013 | * |
||
1014 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1015 | */ |
||
1016 | 2 | public function extendedUpdate(string $strTableToUpdate, string $strOriginalTable, string $strLinkField, array $arrParams) |
|
1017 | { |
||
1018 | 2 | $this->_sql = "UPDATE "; |
|
1019 | 2 | $this->setQueryType(self::EXTENDED_UPDATE); |
|
1020 | |||
1021 | 2 | if (! is_null($strTableToUpdate) && ! is_null($strOriginalTable) && ! is_null($strLinkField)) { |
|
1022 | 2 | $this->_sql .= "$strTableToUpdate tbu INNER JOIN $strOriginalTable o USING ($strLinkField) SET "; |
|
1023 | } |
||
1024 | |||
1025 | 2 | if (is_array($arrParams) && count($arrParams)) { |
|
1026 | 2 | foreach ($arrParams as $param) { |
|
1027 | 2 | if ($param != $strLinkField) { |
|
1028 | 2 | $this->_sql .= "tbu.`$param` = o.`$param`,"; |
|
1029 | } |
||
1030 | } |
||
1031 | 2 | $this->_sql = substr($this->_sql, 0, - 1); |
|
1032 | } elseif (is_string($arrParams)) { |
||
1033 | $this->_sql .= "tbu.`$arrParams` = o.`$arrParams`"; |
||
1034 | } else { |
||
1035 | throw new InvalidArgumentException("Do not understand datatype " . gettype($arrParams), E_ERROR); |
||
1036 | } |
||
1037 | |||
1038 | 2 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1039 | return $this->execute(); |
||
1040 | } |
||
1041 | |||
1042 | 2 | return $this->_sql; |
|
1043 | } |
||
1044 | |||
1045 | /** |
||
1046 | * Function to build a replace query |
||
1047 | * |
||
1048 | * @param string $strTableName |
||
1049 | * The table to update |
||
1050 | * @param array $arrParams |
||
1051 | * Name/value pair to insert |
||
1052 | * |
||
1053 | * @return NULL|string |
||
1054 | * |
||
1055 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1056 | */ |
||
1057 | 2 | public function replace(string $strTableName, $arrParams) |
|
1058 | { |
||
1059 | 2 | $this->_sql = null; |
|
1060 | 2 | $this->setQueryType(self::REPLACE); |
|
1061 | |||
1062 | 2 | if ($this->checkTableName($strTableName)) { |
|
1063 | 2 | $this->_sql = "REPLACE INTO $strTableName "; |
|
1064 | } |
||
1065 | |||
1066 | 2 | if (is_array($arrParams) && count($arrParams)) { |
|
1067 | 1 | $keys = array_keys($arrParams); |
|
1068 | 1 | $vals = array_values($arrParams); |
|
1069 | |||
1070 | 1 | $this->_sql .= "(`" . implode("`,`", $keys) . "`)"; |
|
1071 | 1 | $this->_sql .= " VALUES (" . implode(",", array_map([ |
|
1072 | 1 | $this, |
|
1073 | 1 | '_escape' |
|
1074 | 1 | ], array_values($vals))) . ")"; |
|
1075 | 1 | } elseif (is_object($arrParams)) { |
|
1076 | 1 | $interfaces = class_implements($arrParams); |
|
1077 | 1 | if (in_array("Godsgood33\Php_Db\DBInterface", $interfaces) && is_callable(get_class($arrParams) . "::replace")) { |
|
1078 | 1 | $params = call_user_func([$arrParams, "replace"]); |
|
1079 | 1 | $this->_sql .= "(`" . implode("`,`", array_keys($params)) . "`) VALUES "; |
|
1080 | 1 | $this->_sql .= "(" . implode(",", array_map([$this, '_escape'], array_values($params))) . ")"; |
|
1081 | } |
||
1082 | } |
||
1083 | |||
1084 | 2 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1085 | return $this->execute(); |
||
1086 | } |
||
1087 | |||
1088 | 2 | return $this->_sql; |
|
1089 | } |
||
1090 | |||
1091 | /** |
||
1092 | * Function to build an extended replace statement |
||
1093 | * |
||
1094 | * @param string $strTableName |
||
1095 | * Table name to update |
||
1096 | * @param array $arrFields |
||
1097 | * Array of fields |
||
1098 | * @param array $arrParams |
||
1099 | * Two-dimensional array of values |
||
1100 | * |
||
1101 | * @return NULL|string |
||
1102 | * |
||
1103 | * @throws InvalidArgumentException |
||
1104 | * |
||
1105 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1106 | */ |
||
1107 | 1 | public function extendedReplace(string $strTableName, array $arrFields, array $arrParams) |
|
1108 | { |
||
1109 | 1 | $this->_sql = null; |
|
1110 | 1 | $this->setQueryType(self::EXTENDED_REPLACE); |
|
1111 | |||
1112 | 1 | if (! is_array($arrFields) || ! count($arrFields)) { |
|
1113 | throw new InvalidArgumentException("Error with the field type"); |
||
1114 | } |
||
1115 | |||
1116 | 1 | if ($this->checkTableName($strTableName)) { |
|
1117 | 1 | $this->_sql = "REPLACE INTO $strTableName " . "(`" . implode("`,`", $arrFields) . "`)"; |
|
1118 | } |
||
1119 | |||
1120 | 1 | if (is_array($arrParams) && count($arrParams)) { |
|
1121 | 1 | $this->_sql .= " VALUES "; |
|
1122 | 1 | foreach ($arrParams as $p) { |
|
1123 | 1 | $this->_sql .= "(" . implode(",", array_map([ |
|
1124 | 1 | $this, |
|
1125 | 1 | '_escape' |
|
1126 | 1 | ], array_values($p))) . ")"; |
|
1127 | |||
1128 | 1 | if ($p != end($arrParams)) { |
|
1129 | 1 | $this->_sql .= ","; |
|
1130 | } |
||
1131 | } |
||
1132 | } |
||
1133 | |||
1134 | 1 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1135 | return $this->execute(); |
||
1136 | } |
||
1137 | |||
1138 | 1 | return $this->_sql; |
|
1139 | } |
||
1140 | |||
1141 | /** |
||
1142 | * Function to build a delete statement |
||
1143 | * |
||
1144 | * @param string $strTableName |
||
1145 | * Table name to act on |
||
1146 | * @param array $arrFields |
||
1147 | * [optional] |
||
1148 | * Optional list of fields to delete (used when including multiple tables) |
||
1149 | * @param array:DBWhere|DBWhere $arrWhere |
||
1150 | * [optional] |
||
1151 | * Optional where clauses to use |
||
1152 | * @param array $arrJoins |
||
1153 | * [optional] |
||
1154 | * Optional 2-dimensional array to add other flags |
||
1155 | * |
||
1156 | * @see Database::flags() |
||
1157 | * |
||
1158 | * @return string|NULL |
||
1159 | * |
||
1160 | * @throws InvalidArgumentException |
||
1161 | * |
||
1162 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1163 | */ |
||
1164 | 4 | public function delete(string $strTableName, ?array $arrFields = [], $arrWhere = [], ?array $arrJoins = []) |
|
1165 | { |
||
1166 | 4 | $this->_sql = "DELETE"; |
|
1167 | 4 | $this->setQueryType(self::DELETE); |
|
1168 | |||
1169 | 4 | $this->_logger->debug("Deleting table data"); |
|
1170 | |||
1171 | 4 | if (! is_null($arrFields) && is_array($arrFields) && count($arrFields)) { |
|
1172 | 1 | $this->_sql .= " " . implode(",", $arrFields); |
|
1173 | } |
||
1174 | |||
1175 | 4 | if ($this->checkTableName($strTableName)) { |
|
1176 | 4 | $this->_sql .= " FROM $strTableName"; |
|
1177 | } |
||
1178 | |||
1179 | 4 | if (! is_null($arrJoins) && is_array($arrJoins) && count($arrJoins)) { |
|
1180 | 1 | $this->_sql .= " " . implode(" ", $arrJoins); |
|
1181 | } |
||
1182 | |||
1183 | 4 | $where = $this->parseClause($arrWhere); |
|
1184 | |||
1185 | 4 | if (! is_null($where) && is_array($where) && count($where)) { |
|
1186 | 2 | $where_str = " WHERE"; |
|
1187 | 2 | $this->_logger->debug("Parsing where clause and adding to query"); |
|
1188 | 2 | foreach ($where as $x => $w) { |
|
1189 | 2 | if ($x > 0) { |
|
1190 | 1 | $where_str .= " {$w->sqlOperator}"; |
|
1191 | } |
||
1192 | 2 | $where_str .= $w; |
|
1193 | } |
||
1194 | 2 | if (strlen($where_str) > strlen(" WHERE")) { |
|
1195 | 2 | $this->_sql .= $where_str; |
|
1196 | } |
||
1197 | } |
||
1198 | |||
1199 | 4 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1200 | return $this->execute(); |
||
1201 | } |
||
1202 | |||
1203 | 4 | return $this->_sql; |
|
1204 | } |
||
1205 | |||
1206 | /** |
||
1207 | * Function to build a drop table statement (automatically executes) |
||
1208 | * |
||
1209 | * @param string $strTableName |
||
1210 | * Table to drop |
||
1211 | * @param string $strType |
||
1212 | * [optional] |
||
1213 | * Type of item to drop ('table', 'view') (defaulted to 'table') |
||
1214 | * @param bool $blnIsTemp |
||
1215 | * [optional] |
||
1216 | * Optional bool if this is a temporary table |
||
1217 | * |
||
1218 | * @return string|NULL |
||
1219 | * |
||
1220 | * @throws InvalidArgumentException |
||
1221 | * |
||
1222 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1223 | */ |
||
1224 | 5 | public function drop(string $strTableName, string $strType = 'table', bool $blnIsTemp = false) |
|
1225 | { |
||
1226 | 5 | $this->_sql = null; |
|
1227 | 5 | $this->setQueryType(self::DROP); |
|
1228 | |||
1229 | 5 | switch ($strType) { |
|
1230 | 5 | case 'table': |
|
1231 | 4 | $strType = 'TABLE'; |
|
1232 | 4 | break; |
|
1233 | 1 | case 'view': |
|
1234 | 1 | $strType = 'VIEW'; |
|
1235 | 1 | break; |
|
1236 | default: |
||
1237 | throw new InvalidArgumentException("Invalid type " . gettype($strType), E_ERROR); |
||
1238 | } |
||
1239 | |||
1240 | 5 | if ($this->checkTableName($strTableName)) { |
|
1241 | 5 | $this->_sql = "DROP" . ($blnIsTemp ? " TEMPORARY" : "") . " $strType IF EXISTS `{$strTableName}`"; |
|
1242 | } |
||
1243 | |||
1244 | 5 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1245 | return $this->execute(); |
||
1246 | } |
||
1247 | |||
1248 | 5 | return $this->_sql; |
|
1249 | } |
||
1250 | |||
1251 | /** |
||
1252 | * Function to build a truncate table statement (automatically executes) |
||
1253 | * |
||
1254 | * @param string $strTableName |
||
1255 | * Table to truncate |
||
1256 | * |
||
1257 | * @return string|NULL |
||
1258 | * |
||
1259 | * @throws InvalidArgumentException |
||
1260 | * |
||
1261 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1262 | */ |
||
1263 | 1 | public function truncate(string $strTableName) |
|
1264 | { |
||
1265 | 1 | $this->_sql = null; |
|
1266 | 1 | $this->setQueryType(self::TRUNCATE); |
|
1267 | |||
1268 | 1 | if ($this->checkTableName($strTableName)) { |
|
1269 | 1 | $this->_sql = "TRUNCATE TABLE $strTableName"; |
|
1270 | } |
||
1271 | |||
1272 | 1 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1273 | return $this->execute(); |
||
1274 | } |
||
1275 | |||
1276 | 1 | return $this->_sql; |
|
1277 | } |
||
1278 | |||
1279 | /** |
||
1280 | * Function to build a create temporary table statement |
||
1281 | * |
||
1282 | * @param string $strTableName |
||
1283 | * Name to give the table when creating |
||
1284 | * @param bool $blnIsTemp |
||
1285 | * [optional] |
||
1286 | * Optional bool to make the table a temporary table |
||
1287 | * @param mixed $strSelect |
||
1288 | * [optional] |
||
1289 | * Optional parameter if null uses last built statement |
||
1290 | * If string, will be made the SQL statement executed to create the table |
||
1291 | * If array, 2-dimensional array with "field", "datatype" values to build table fields |
||
1292 | * |
||
1293 | * @return NULL|string |
||
1294 | * |
||
1295 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1296 | */ |
||
1297 | 4 | public function createTable(string $strTableName, bool $blnIsTemp = false, $strSelect = null) |
|
1298 | { |
||
1299 | 4 | $this->setQueryType(self::CREATE_TABLE); |
|
1300 | |||
1301 | 4 | if (is_null($strSelect) && ! is_null($this->_sql) && substr($this->_sql, 0, 6) == 'SELECT') { |
|
1302 | 1 | $this->_sql = "CREATE" . ($blnIsTemp ? " TEMPORARY" : "") . " TABLE IF NOT EXISTS $strTableName AS ($this->_sql)"; |
|
1303 | 3 | } elseif ($this->checkTableName($strTableName) && is_string($strSelect)) { |
|
1304 | 1 | $this->_sql = "CREATE" . ($blnIsTemp ? " TEMPORARY" : "") . " TABLE IF NOT EXISTS $strTableName AS ($strSelect)"; |
|
1305 | 2 | } elseif ($this->checkTableName($strTableName) && is_array($strSelect)) { |
|
1306 | 2 | $this->_sql = "CREATE" . ($blnIsTemp ? " TEMPORARY" : "") . " TABLE IF NOT EXISTS $strTableName ("; |
|
1307 | |||
1308 | 2 | foreach ($strSelect as $field) { |
|
1309 | 2 | $default = null; |
|
1310 | 2 | if (is_a($field, 'Godsgood33\Php_Db\DBCreateTable')) { |
|
1311 | 2 | $this->_sql .= (string) $field . ","; |
|
1312 | } elseif (is_array($field)) { |
||
1313 | if (isset($field['default'])) { |
||
1314 | $default = (is_null($field['default']) ? "" : " DEFAULT '{$field['default']}'"); |
||
1315 | } |
||
1316 | $this->_sql .= "`{$field['field']}` {$field['datatype']}" . $default . (isset($field['option']) ? " {$field['option']}" : '') . ","; |
||
1317 | } |
||
1318 | } |
||
1319 | 2 | $this->_sql = substr($this->_sql, 0, - 1) . ")"; |
|
1320 | } |
||
1321 | |||
1322 | 4 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1323 | return $this->execute(); |
||
1324 | } |
||
1325 | |||
1326 | 4 | return $this->_sql; |
|
1327 | } |
||
1328 | |||
1329 | /** |
||
1330 | * Function to create a table using a stdClass object derived from JSON |
||
1331 | * |
||
1332 | * @param stdClass $json |
||
1333 | * @param bool $blnDropFirst bool to decide if you want to drop the table first |
||
1334 | * |
||
1335 | * @example /examples/create_table_json.json |
||
1336 | * |
||
1337 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1338 | */ |
||
1339 | 3 | public function createTableJson($json, bool $blnDropFirst = false) |
|
1340 | { |
||
1341 | 3 | $this->setQueryType(self::CREATE_TABLE); |
|
1342 | 3 | $this->_c->select_db($json->schema); |
|
1343 | |||
1344 | 3 | if ($blnDropFirst) { |
|
1345 | $this->drop($json->name); |
||
1346 | if (!defined('PHP_DB_AUTORUN') || !PHP_DB_AUTORUN) { |
||
1347 | $this->execute(); |
||
1348 | } |
||
1349 | } |
||
1350 | |||
1351 | 3 | $this->_sql = "CREATE TABLE IF NOT EXISTS `{$json->name}` ("; |
|
1352 | 3 | foreach ($json->fields as $field) { |
|
1353 | 3 | $this->_sql .= "`{$field->name}` {$field->dataType}"; |
|
1354 | |||
1355 | 3 | if ($field->dataType == 'enum' && isset($field->values)) { |
|
1356 | 1 | $this->_sql .= "('" . implode("','", $field->values) . "')"; |
|
1357 | } |
||
1358 | |||
1359 | 3 | if (isset($field->ai) && $field->ai) { |
|
1360 | 3 | $this->_sql .= " AUTO_INCREMENT"; |
|
1361 | } |
||
1362 | |||
1363 | 3 | if (isset($field->nn) && $field->nn) { |
|
1364 | 3 | $this->_sql .= " NOT NULL"; |
|
1365 | 2 | } elseif (isset($field->default)) { |
|
1366 | 2 | if (strtolower($field->default) == 'null') { |
|
1367 | 1 | $this->_sql .= " DEFAULT NULL"; |
|
1368 | 1 | } elseif (strlen($field->default)) { |
|
1369 | 1 | $this->_sql .= " DEFAULT '{$field->default}'"; |
|
1370 | } |
||
1371 | } |
||
1372 | |||
1373 | 3 | if ($field != end($json->fields)) { |
|
1374 | 2 | $this->_sql .= ","; |
|
1375 | } |
||
1376 | } |
||
1377 | |||
1378 | 3 | if (isset($json->index) && count($json->index)) { |
|
1379 | 1 | foreach ($json->index as $ind) { |
|
1380 | 1 | $ref = null; |
|
1381 | 1 | if (is_array($ind->ref)) { |
|
1382 | $ref = ""; |
||
1383 | foreach ($ind->ref as $r) { |
||
1384 | $ref .= "`{$r}` ASC,"; |
||
1385 | } |
||
1386 | $ref = substr($ref, 0, -1); |
||
1387 | 1 | } elseif (is_string($ind->ref)) { |
|
1388 | 1 | $ref = $ind->ref; |
|
1389 | } |
||
1390 | 1 | if (!is_null($ref)) { |
|
1391 | 1 | $this->_sql .= ", " . strtoupper($ind->type) . " `{$ind->id}` (`{$ref}`)"; |
|
1392 | } |
||
1393 | } |
||
1394 | } |
||
1395 | |||
1396 | 3 | if (isset($json->constraints) && count($json->constraints)) { |
|
1397 | foreach ($json->constraints as $con) { |
||
1398 | $this->_sql .= ", CONSTRAINT `{$con->id}` " . "FOREIGN KEY (`{$con->local}`) " . "REFERENCES `{$con->schema}`.`{$con->table}` (`{$con->field}`) " . "ON DELETE " . (is_null($con->delete) ? "NO ACTION" : strtoupper($con->delete)) . " " . "ON UPDATE " . (is_null($con->update) ? "NO ACTION" : strtoupper($con->update)); |
||
1399 | } |
||
1400 | } |
||
1401 | |||
1402 | 3 | if (isset($json->unique) && count($json->unique)) { |
|
1403 | 1 | $this->_sql .= ", UNIQUE(`" . implode("`,`", $json->unique) . "`)"; |
|
1404 | } |
||
1405 | |||
1406 | 3 | if (isset($json->primary_key) && count($json->primary_key)) { |
|
1407 | 3 | $this->_sql .= ", PRIMARY KEY(`" . implode("`,`", $json->primary_key) . "`))"; |
|
1408 | } else { |
||
1409 | if (substr($this->_sql, - 1) == ',') { |
||
1410 | $this->_sql = substr($this->_sql, 0, - 1); |
||
1411 | } |
||
1412 | |||
1413 | $this->_sql .= ")"; |
||
1414 | } |
||
1415 | |||
1416 | 3 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1417 | return $this->execute(); |
||
1418 | } |
||
1419 | |||
1420 | 3 | return $this->_sql; |
|
1421 | } |
||
1422 | |||
1423 | /** |
||
1424 | * Method to add a column to the database (only one at a time!) |
||
1425 | * |
||
1426 | * @param string $strTableName |
||
1427 | * @param stdClass $params |
||
1428 | * |
||
1429 | * @return string|mixed |
||
1430 | * |
||
1431 | * @throws InvalidArgumentException |
||
1432 | * |
||
1433 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1434 | */ |
||
1435 | 3 | public function addColumn(string $strTableName, stdClass $params) |
|
1436 | { |
||
1437 | 3 | $this->setQueryType(self::ALTER_TABLE); |
|
1438 | 3 | $this->checkTableName($strTableName); |
|
1439 | |||
1440 | 3 | $this->_sql = "ALTER TABLE {$strTableName} ADD COLUMN"; |
|
1441 | |||
1442 | 3 | if (!self::checkObject($params, ['name', 'dataType'])) { |
|
1443 | 1 | $this->_logger->error("Missing elements for the addColumn method (need 'name', 'dataType')", [$params]); |
|
1444 | 1 | throw new InvalidArgumentException("Missing elements for the addColumn method"); |
|
1445 | } |
||
1446 | |||
1447 | 2 | $nn = (isset($params->nn) && $params->nn ? " NOT NULL" : ""); |
|
1448 | 2 | $default = null; |
|
1449 | 2 | if ($params->default === null) { |
|
1450 | 1 | $default = " DEFAULT NULL"; |
|
1451 | 1 | } elseif (strlen($params->default)) { |
|
1452 | 1 | $default = " DEFAULT {$this->_escape($params->default)}"; |
|
1453 | } |
||
1454 | 2 | $this->_sql .= " `{$params->name}` {$params->dataType}" . $nn . $default; |
|
1455 | |||
1456 | 2 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1457 | return $this->execute(); |
||
1458 | } |
||
1459 | |||
1460 | 2 | return $this->_sql; |
|
1461 | } |
||
1462 | |||
1463 | /** |
||
1464 | * Method to drop a fields from a table |
||
1465 | * |
||
1466 | * @param string $strTableName |
||
1467 | * @param string|array:string $params |
||
1468 | * |
||
1469 | * @return string|mixed |
||
1470 | * |
||
1471 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1472 | */ |
||
1473 | 3 | public function dropColumn(string $strTableName, $params) |
|
1474 | { |
||
1475 | 3 | $this->setQueryType(self::ALTER_TABLE); |
|
1476 | 3 | $this->_sql = "ALTER TABLE {$strTableName} DROP COLUMN"; |
|
1477 | |||
1478 | 3 | if (is_array($params) && count($params)) { |
|
1479 | 2 | foreach ($params as $col) { |
|
1480 | 2 | $this->_sql .= " `{$col->name}`"; |
|
1481 | |||
1482 | 2 | if ($col != end($params)) { |
|
1483 | 1 | $this->_sql .= ","; |
|
1484 | } |
||
1485 | } |
||
1486 | 1 | } elseif (is_string($params)) { |
|
1487 | 1 | $this->_sql .= " `{$params}`"; |
|
1488 | } |
||
1489 | |||
1490 | 3 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1491 | return $this->execute(); |
||
1492 | } |
||
1493 | |||
1494 | 3 | return $this->_sql; |
|
1495 | } |
||
1496 | |||
1497 | /** |
||
1498 | * Method to modify a field to change it's datatype, name, or other parameter |
||
1499 | * |
||
1500 | * @param string $strTableName |
||
1501 | * @param stdClass $params |
||
1502 | * |
||
1503 | * @return string|mixed |
||
1504 | * |
||
1505 | * @throws InvalidArgumentException |
||
1506 | * |
||
1507 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1508 | */ |
||
1509 | 3 | public function modifyColumn($strTableName, $params) |
|
1510 | { |
||
1511 | 3 | $this->setQueryType(self::ALTER_TABLE); |
|
1512 | 3 | $this->_sql = "ALTER TABLE {$strTableName} MODIFY COLUMN"; |
|
1513 | |||
1514 | 3 | if (!self::checkObject($params, ['name', 'dataType'])) { |
|
1515 | 1 | $this->_logger->error("Missing elements to the modifyColumn method (need 'name' and 'dataType')", [$params]); |
|
1516 | 1 | throw new InvalidArgumentException("Missing elements to the modifyColumn method"); |
|
1517 | } |
||
1518 | |||
1519 | 2 | if (!isset($params->new_name)) { |
|
1520 | 1 | $params->new_name = $params->name; |
|
1521 | } |
||
1522 | |||
1523 | 2 | $nn = (isset($params->nn) && $params->nn ? " NOT NULL" : ""); |
|
1524 | 2 | $default = null; |
|
1525 | 2 | if ($params->default === null) { |
|
1526 | 1 | $default = " DEFAULT NULL"; |
|
1527 | 1 | } elseif (strlen($params->default)) { |
|
1528 | 1 | $default = " DEFAULT {$this->_escape($params->default)}"; |
|
1529 | } |
||
1530 | 2 | $this->_sql .= " `{$params->name}` `{$params->new_name}` {$params->dataType}" . $nn . $default; |
|
1531 | |||
1532 | 2 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1533 | return $this->execute(); |
||
1534 | } |
||
1535 | |||
1536 | 2 | return $this->_sql; |
|
1537 | } |
||
1538 | |||
1539 | /** |
||
1540 | * Method to add a constraint to a table |
||
1541 | * |
||
1542 | * @param string $strTableName |
||
1543 | * @param stdClass $params |
||
1544 | * |
||
1545 | * @return string|mixed |
||
1546 | * |
||
1547 | * @throws InvalidArgumentException |
||
1548 | * |
||
1549 | * @uses PHP_DB_AUTORUN bool to decide if the statement should be auto-committed and the results returned instead of the statement |
||
1550 | */ |
||
1551 | 7 | public function addConstraint($strTableName, $params) |
|
1552 | { |
||
1553 | 7 | $this->setQueryType(self::ALTER_TABLE); |
|
1554 | 7 | $this->_sql = "ALTER TABLE {$strTableName} ADD CONSTRAINT"; |
|
1555 | |||
1556 | 7 | if (!is_a($params, 'stdClass')) { |
|
1557 | 1 | $this->_logger->critical("Error in reading constraint field"); |
|
1558 | 1 | throw new InvalidArgumentException("Error in reading constraint field"); |
|
1559 | } |
||
1560 | |||
1561 | 6 | if (!self::checkObject($params, ['id', 'local', 'schema', 'table', 'field', 'delete', 'update'])) { |
|
1562 | 1 | $this->_logger->error("Missing elements in the addConstraint method (need 'id', 'local', 'schema', 'table', 'field', 'delete', 'update')", [$params]); |
|
1563 | 1 | throw new InvalidArgumentException("There are some missing elements for the addConstraint action"); |
|
1564 | } |
||
1565 | |||
1566 | 5 | if (!in_array(strtoupper($params->delete), ['CASCADE', 'SET NULL', 'RESTRICT', 'NO ACTION'])) { |
|
1567 | 1 | $this->_logger->error("Invalid action for deletion on addConstraint"); |
|
1568 | 1 | throw new InvalidArgumentException("Invalid action for deletion on addConstraint"); |
|
1569 | } |
||
1570 | |||
1571 | 4 | if (!in_array(strtoupper($params->update), ['CASCADE', 'SET NULL', 'RESTRICT', 'NO ACTION'])) { |
|
1572 | 1 | $this->_logger->error("Invalid action for update on addConstraint"); |
|
1573 | 1 | throw new InvalidArgumentException("Invalid action for update on addConstraint"); |
|
1574 | } |
||
1575 | |||
1576 | 3 | if (is_array($params->field) && is_array($params->local)) { |
|
1577 | 1 | $field = "`" . implode("`,`", $params->field) . "`"; |
|
1578 | 1 | $local = "`" . implode("`,`", $params->local) . "`"; |
|
1579 | 2 | } elseif (is_string($params->field) && is_string($params->local)) { |
|
1580 | 1 | $field = "`{$params->field}`"; |
|
1581 | 1 | $local = "`{$params->local}`"; |
|
1582 | } else { |
||
1583 | 1 | throw new InvalidArgumentException("Invalid type for the field and local values both must be an array or string"); |
|
1584 | } |
||
1585 | 2 | $this->_sql .= " `{$params->id}` FOREIGN KEY ({$local}) REFERENCES `{$params->schema}`.`{$params->table}` ({$field}) ON DELETE {$params->delete} ON UPDATE {$params->update}"; |
|
1586 | |||
1587 | 2 | if (defined("PHP_DB_AUTORUN") && PHP_DB_AUTORUN) { |
|
1588 | return $this->execute(); |
||
1589 | } |
||
1590 | |||
1591 | 2 | return $this->_sql; |
|
1592 | } |
||
1593 | |||
1594 | /** |
||
1595 | * Check to see if a field in a table exists |
||
1596 | * |
||
1597 | * @param string $strTableName |
||
1598 | * Table to check |
||
1599 | * @param string $strFieldName |
||
1600 | * Field name to find |
||
1601 | * |
||
1602 | * @return bool Returns TRUE if field is found in that schema and table, otherwise FALSE |
||
1603 | */ |
||
1604 | 2 | public function fieldExists(string $strTableName, string $strFieldName): bool |
|
1605 | { |
||
1606 | 2 | $fdata = $this->fieldData($strTableName); |
|
1607 | |||
1608 | 2 | if (is_array($fdata) && count($fdata)) { |
|
1609 | 2 | foreach ($fdata as $field) { |
|
1610 | 2 | if ($field->name == $strFieldName) { |
|
1611 | 1 | return true; |
|
1612 | } |
||
1613 | } |
||
1614 | } |
||
1615 | |||
1616 | 1 | return false; |
|
1617 | } |
||
1618 | |||
1619 | /** |
||
1620 | * Function to get the column data (datatype, flags, defaults, etc) |
||
1621 | * |
||
1622 | * @param string $strTableName |
||
1623 | * Table to query |
||
1624 | * @param mixed $field |
||
1625 | * [optional] |
||
1626 | * Optional field to retrieve data (if null, returns data from all fields) |
||
1627 | * |
||
1628 | * @return mixed |
||
1629 | */ |
||
1630 | 7 | public function fieldData(string $strTableName, $field = null) |
|
1631 | { |
||
1632 | 7 | if (is_null($field)) { |
|
1633 | 3 | $res = $this->_c->query("SELECT * FROM $strTableName LIMIT 1"); |
|
1634 | 5 | } elseif (is_array($field)) { |
|
1635 | 5 | $res = $this->_c->query("SELECT `" . implode("`,`", $field) . "` FROM $strTableName LIMIT 1"); |
|
1636 | 1 | } elseif (is_string($field)) { |
|
1637 | 1 | $res = $this->_c->query("SELECT $field FROM $strTableName LIMIT 1"); |
|
1638 | } else { |
||
1639 | 1 | return null; |
|
1640 | } |
||
1641 | |||
1642 | 7 | $fields = null; |
|
1643 | 7 | if (is_a($res, 'mysqli_result')) { |
|
1644 | 7 | $fields = $res->fetch_fields(); |
|
1645 | 7 | foreach ($fields as $i => $f) { |
|
1646 | 7 | $fields["{$f->name}"] = $f; |
|
1647 | 7 | unset($fields[$i]); |
|
1648 | } |
||
1649 | } |
||
1650 | |||
1651 | 7 | return $fields; |
|
1652 | } |
||
1653 | |||
1654 | /** |
||
1655 | * Function to check that all field parameters are set correctly |
||
1656 | * |
||
1657 | * @param stdClass $field_data |
||
1658 | * @param stdClass $check |
||
1659 | * @param array $pks |
||
1660 | * @param stdClass $index |
||
1661 | * |
||
1662 | * @return array|string |
||
1663 | */ |
||
1664 | 4 | public function fieldCheck(stdClass $field_data, stdClass $check, array $pks, ?array $index) |
|
1665 | { |
||
1666 | 4 | $default = null; |
|
1667 | 4 | $ret = null; |
|
1668 | |||
1669 | 4 | $nn = (isset($check->nn) && $check->nn ? " NOT NULL" : null); |
|
1670 | |||
1671 | 4 | if ($check->default === null) { |
|
1672 | 1 | $default = " DEFAULT NULL"; |
|
1673 | 3 | } elseif (strlen($check->default)) { |
|
1674 | 1 | $default = " DEFAULT '{$check->default}'"; |
|
1675 | } |
||
1676 | |||
1677 | 4 | if ($field_data->type != $check->type && $check->type != MYSQLI_TYPE_ENUM) { |
|
1678 | 3 | $this->_logger->notice("Wrong datatype", [ |
|
1679 | 3 | 'name' => $field_data->name, |
|
1680 | 3 | 'datatype' => $check->dataType |
|
1681 | ]); |
||
1682 | 3 | $ret = " CHANGE COLUMN `{$field_data->name}` `{$check->name}` {$check->dataType}" . "{$nn}{$default}"; |
|
1683 | 1 | } elseif (! is_null($check->length) && $field_data->length != $check->length) { |
|
1684 | 1 | $this->_logger->notice("Incorrect size", [ |
|
1685 | 1 | 'name' => $field_data->name, |
|
1686 | 1 | 'current' => $field_data->length, |
|
1687 | 1 | 'new_size' => $check->length |
|
1688 | ]); |
||
1689 | 1 | $ret = " CHANGE COLUMN `{$field_data->name}` `{$check->name}` {$check->dataType}" . "{$nn}{$default}"; |
|
1690 | } elseif ($check->type == MYSQLI_TYPE_ENUM && ! ($field_data->flags & MYSQLI_ENUM_FLAG)) { |
||
1691 | $this->_logger->notice("Setting ENUM type", [ |
||
1692 | 'name' => $field_data->name, |
||
1693 | 'values' => implode(",", $check->values) |
||
1694 | ]); |
||
1695 | $ret = " CHANGE COLUMN `{$field_data->name}` `{$check->name}` {$check->dataType}('" . implode("','", $check->values) . "')" . "{$nn}{$default}"; |
||
1696 | } |
||
1697 | |||
1698 | 4 | if (! is_null($index) && count($index)) { |
|
1699 | foreach ($index as $ind) { |
||
1700 | if ($check->name == $ind->ref && ! ($field_data->flags & MYSQLI_MULTIPLE_KEY_FLAG)) { |
||
1701 | $this->_logger->debug("Missing index", [ |
||
1702 | 'name' => $field_data->name |
||
1703 | ]); |
||
1704 | $ret .= ($ret ? "," : "") . " ADD INDEX `{$ind->id}` (`{$ind->ref}` ASC)"; |
||
1705 | } |
||
1706 | } |
||
1707 | } |
||
1708 | |||
1709 | 4 | if (in_array($check->name, $pks) && ! ($field_data->flags & MYSQLI_PRI_KEY_FLAG)) { |
|
1710 | $this->_logger->debug("Setting PKs", [ |
||
1711 | 'keys' => implode(',', $pks) |
||
1712 | ]); |
||
1713 | $ret .= ($ret ? "," : "") . " DROP PRIMARY KEY, ADD PRIMARY KEY(`" . implode("`,`", $pks) . "`)"; |
||
1714 | } |
||
1715 | |||
1716 | 4 | return $ret; |
|
1717 | } |
||
1718 | |||
1719 | /** |
||
1720 | * Function to check for the existence of a table within a schema |
||
1721 | * |
||
1722 | * @param string $strSchema |
||
1723 | * The schema to search in |
||
1724 | * @param string $strTableName |
||
1725 | * Table to search for |
||
1726 | * |
||
1727 | * @return int|bool Returns number of tables that match if table is found in that schema, otherwise FALSE |
||
1728 | * |
||
1729 | * @throws InvalidArgumentException |
||
1730 | */ |
||
1731 | 5 | public function tableExists($strSchema, $strTableName) |
|
1732 | { |
||
1733 | 5 | if (! $this->_c->select_db($strSchema)) { |
|
1734 | 1 | $this->_logger->error("Schema {$strSchema} not found", [$this->_c->error]); |
|
1735 | 1 | throw new InvalidArgumentException("Error connecting to schema {$strSchema}"); |
|
1736 | } |
||
1737 | |||
1738 | 4 | if (preg_match("/[^0-9a-zA-Z\%\?\_]/", $strTableName)) { |
|
1739 | 1 | $this->_logger->warning("Invalid table name {$strTableName}"); |
|
1740 | 1 | return false; |
|
1741 | } |
||
1742 | |||
1743 | 3 | $sql = "SHOW TABLES LIKE '{$strTableName}'"; |
|
1744 | |||
1745 | 3 | if ($res = $this->_c->query($sql)) { |
|
1746 | 3 | if (gettype($res) == 'object' && is_a($res, 'mysqli_result') && $res->num_rows) { |
|
1747 | 2 | return $res->num_rows; |
|
1748 | } |
||
1749 | } elseif ($this->_c->errno) { |
||
1750 | $this->_logger->error($this->_c->error); |
||
1751 | } |
||
1752 | |||
1753 | 1 | return false; |
|
1754 | } |
||
1755 | |||
1756 | /** |
||
1757 | * Function to detect if string is a JSON object or not |
||
1758 | * |
||
1759 | * @param string $strVal |
||
1760 | * |
||
1761 | * @return bool |
||
1762 | */ |
||
1763 | 1 | public function isJson($strVal): bool |
|
1764 | { |
||
1765 | 1 | json_decode($strVal); |
|
1766 | 1 | return (json_last_error() == JSON_ERROR_NONE); |
|
1767 | } |
||
1768 | |||
1769 | /** |
||
1770 | * Function to escape SQL characters to prevent SQL injection |
||
1771 | * |
||
1772 | * @param mixed $val |
||
1773 | * Value to escape |
||
1774 | * @param bool $blnEscape |
||
1775 | * Decide if we should escape or not |
||
1776 | * |
||
1777 | * @throws Exception |
||
1778 | * @throws InvalidArgumentException |
||
1779 | * |
||
1780 | * @return string Escaped value |
||
1781 | */ |
||
1782 | 130 | public function _escape($val, bool $blnEscape = true): string |
|
1783 | { |
||
1784 | 130 | if (is_null($val) || (is_string($val) && strtolower($val) == 'null')) { |
|
1785 | 1 | return 'NULL'; |
|
1786 | 130 | } elseif (is_numeric($val) || is_string($val)) { |
|
1787 | 130 | if ($blnEscape) { |
|
1788 | 130 | return "'{$this->_c->real_escape_string($val)}'"; |
|
1789 | } |
||
1790 | 1 | return $val; |
|
1791 | 6 | } elseif (is_a($val, 'DateTime')) { |
|
1792 | 1 | return "'{$val->format(MYSQL_DATETIME)}'"; |
|
1793 | 5 | } elseif (is_bool($val)) { |
|
1794 | 1 | return $val ? "'1'" : "'0'"; |
|
1795 | 4 | } elseif (is_array($val)) { |
|
1796 | 1 | $ret = []; |
|
1797 | 1 | foreach ($val as $v) { |
|
1798 | 1 | $ret[] = $this->_escape($v); |
|
1799 | } |
||
1800 | 1 | return "(" . implode(",", $ret) . ")"; |
|
1801 | 3 | } elseif (is_object($val) && method_exists($val, '_escape')) { |
|
1802 | 2 | $ret = call_user_func([ |
|
1803 | 2 | $val, |
|
1804 | 2 | '_escape' |
|
1805 | ]); |
||
1806 | 2 | if ($ret !== false && is_string($ret)) { |
|
1807 | 1 | return $ret; |
|
1808 | } else { |
||
1809 | 1 | throw new Exception("Error in return from _escape method in " . get_class($val), E_ERROR); |
|
1810 | } |
||
1811 | } |
||
1812 | |||
1813 | 1 | throw new InvalidArgumentException("Unknown datatype to escape in SQL string {$this->_sql} " . gettype($val), E_ERROR); |
|
1814 | } |
||
1815 | |||
1816 | /** |
||
1817 | * Function to populate the fields for the SQL |
||
1818 | * |
||
1819 | * @param array|string $fields |
||
1820 | * [optional] |
||
1821 | * Optional array of fields to string together to create a field list |
||
1822 | * |
||
1823 | * @return string |
||
1824 | * |
||
1825 | * @throws InvalidArgumentException |
||
1826 | */ |
||
1827 | 37 | protected function fields($fields = null): string |
|
1828 | { |
||
1829 | 37 | $ret = null; |
|
1830 | |||
1831 | 37 | if (is_array($fields) && count($fields) && isset($fields[0]) && is_string($fields[0])) { |
|
1832 | 3 | foreach ($fields as $field) { |
|
1833 | 3 | if ((strpos($field, '`') === false) && (strpos($field, '.') === false) && (strpos($field, '*') === false) && (strpos($field, 'JSON_') === false) && (stripos($field, ' as ') === false) && stripos($field, 'IF(') === false) { |
|
1834 | 2 | $ret .= "`$field`,"; |
|
1835 | } else { |
||
1836 | 1 | $ret .= "$field,"; |
|
1837 | } |
||
1838 | } |
||
1839 | 3 | $ret = substr($ret, -1) == ',' ? substr($ret, 0, -1) : $ret; |
|
1840 | 34 | } elseif (is_string($fields)) { |
|
1841 | 4 | $ret = $fields; |
|
1842 | 30 | } elseif (is_null($fields)) { |
|
1843 | 29 | $ret = "*"; |
|
1844 | } else { |
||
1845 | 1 | throw new InvalidArgumentException("Invalid field type"); |
|
1846 | } |
||
1847 | |||
1848 | 36 | return $ret; |
|
0 ignored issues
–
show
|
|||
1849 | } |
||
1850 | |||
1851 | /** |
||
1852 | * Function to parse the flags |
||
1853 | * |
||
1854 | * @param array $flags |
||
1855 | * Two-dimensional array to added flags |
||
1856 | * |
||
1857 | * <code> |
||
1858 | * [ |
||
1859 | * 'group' => 'field', |
||
1860 | * 'having' => 'field', |
||
1861 | * 'order' => 'field', |
||
1862 | * 'start' => 0, |
||
1863 | * 'limit' => 0 |
||
1864 | * ] |
||
1865 | * </code> |
||
1866 | * |
||
1867 | * @see Database::groups() |
||
1868 | * @see Database::having() |
||
1869 | * @see Database::order() |
||
1870 | * |
||
1871 | * @return string |
||
1872 | */ |
||
1873 | 10 | protected function flags(array $arrFlags) |
|
1874 | { |
||
1875 | 10 | $ret = ''; |
|
1876 | |||
1877 | 10 | if (isset($arrFlags['group'])) { |
|
1878 | 3 | $ret .= $this->groups($arrFlags['group']); |
|
1879 | } |
||
1880 | |||
1881 | 9 | if (isset($arrFlags['having']) && is_array($arrFlags['having'])) { |
|
1882 | 1 | $having = " HAVING"; |
|
1883 | 1 | $this->_logger->debug("Parsing where clause and adding to query"); |
|
1884 | 1 | foreach ($arrFlags['having'] as $x => $h) { |
|
1885 | 1 | if ($x > 0) { |
|
1886 | 1 | $having .= " {$h->sqlOperator}"; |
|
1887 | } |
||
1888 | 1 | $having .= $h; |
|
1889 | } |
||
1890 | 1 | if (strlen($having) > strlen(" HAVING")) { |
|
1891 | 1 | $ret .= $having; |
|
1892 | } |
||
1893 | } |
||
1894 | |||
1895 | 9 | if (isset($arrFlags['order'])) { |
|
1896 | 3 | $ret .= $this->order($arrFlags['order']); |
|
1897 | } |
||
1898 | |||
1899 | 8 | if (isset($arrFlags['limit']) && (is_string($arrFlags['limit']) || is_numeric($arrFlags['limit']))) { |
|
1900 | 1 | $ret .= " LIMIT "; |
|
1901 | 1 | if (isset($arrFlags['start']) && (is_string($arrFlags['start']) || is_numeric($arrFlags['start']))) { |
|
1902 | 1 | $ret .= "{$arrFlags['start']},"; |
|
1903 | } |
||
1904 | 1 | $ret .= "{$arrFlags['limit']}"; |
|
1905 | } |
||
1906 | |||
1907 | 8 | return $ret; |
|
1908 | } |
||
1909 | |||
1910 | /** |
||
1911 | * Function to parse SQL GROUP BY statements |
||
1912 | * |
||
1913 | * @param mixed $groups |
||
1914 | * |
||
1915 | * @return string |
||
1916 | * |
||
1917 | * @throws InvalidArgumentException |
||
1918 | */ |
||
1919 | 3 | protected function groups($groups): string |
|
1920 | { |
||
1921 | 3 | $ret = ''; |
|
1922 | 3 | if (is_array($groups) && count($groups)) { |
|
1923 | 1 | $ret .= " GROUP BY"; |
|
1924 | |||
1925 | 1 | foreach ($groups as $grp) { |
|
1926 | 1 | $ret .= " $grp"; |
|
1927 | |||
1928 | 1 | if ($grp != end($groups)) { |
|
1929 | 1 | $ret .= ","; |
|
1930 | } |
||
1931 | } |
||
1932 | 2 | } elseif (is_string($groups)) { |
|
1933 | 1 | $ret .= " GROUP BY {$groups}"; |
|
1934 | } else { |
||
1935 | 1 | throw new InvalidArgumentException("Error in datatype for groups " . gettype($groups), E_ERROR); |
|
1936 | } |
||
1937 | |||
1938 | 2 | return $ret; |
|
1939 | } |
||
1940 | |||
1941 | /** |
||
1942 | * Function to parse SQL ORDER BY statements |
||
1943 | * |
||
1944 | * @param mixed $order |
||
1945 | * |
||
1946 | * @return string |
||
1947 | * |
||
1948 | * @throws InvalidArgumentException |
||
1949 | */ |
||
1950 | 3 | protected function order($order): string |
|
1951 | { |
||
1952 | 3 | $ret = ''; |
|
1953 | 3 | if (is_array($order)) { |
|
1954 | 1 | $ret .= " ORDER BY"; |
|
1955 | |||
1956 | 1 | foreach ($order as $ord) { |
|
1957 | 1 | $ret .= " {$ord['field']} {$ord['sort']}"; |
|
1958 | |||
1959 | 1 | if ($ord != end($order)) { |
|
1960 | 1 | $ret .= ","; |
|
1961 | } |
||
1962 | } |
||
1963 | 2 | } elseif (is_string($order)) { |
|
1964 | 1 | $ret .= " ORDER BY {$order}"; |
|
1965 | } else { |
||
1966 | 1 | throw new InvalidArgumentException("Error in datatype for order method ".gettype($order), E_ERROR); |
|
1967 | } |
||
1968 | |||
1969 | 2 | return $ret; |
|
1970 | } |
||
1971 | |||
1972 | /** |
||
1973 | * Method to check if there are any invalid characters in the table name |
||
1974 | * |
||
1975 | * @param string $strTableName |
||
1976 | * Table name passed in |
||
1977 | * |
||
1978 | * @return bool |
||
1979 | * Returns FALSE if table name contains any characters that will be problematic (0-9, a-z, A-Z, $, _), TRUE otherwise |
||
1980 | */ |
||
1981 | 82 | private function checkTableName(string $strTableName): bool |
|
1982 | { |
||
1983 | 82 | return !strlen($strTableName) || preg_match("/[^0-9a-zA-Z\$\_\ ]/", $strTableName) ? false : true; |
|
1984 | } |
||
1985 | |||
1986 | /** |
||
1987 | * Function to see if a constraint exists |
||
1988 | * |
||
1989 | * |
||
1990 | * |
||
1991 | * @param string $strConstraintId |
||
1992 | * |
||
1993 | * @return bool |
||
1994 | */ |
||
1995 | public function isConstraint($strConstraintId): bool |
||
1996 | { |
||
1997 | $res = $this->_c->query("SELECT * FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_NAME = '{$strConstraintId}'"); |
||
1998 | |||
1999 | if ($res->num_rows) { |
||
2000 | return true; |
||
2001 | } |
||
2002 | |||
2003 | return false; |
||
2004 | } |
||
2005 | |||
2006 | /** |
||
2007 | * Method to add a where clause |
||
2008 | * |
||
2009 | * @param DBWhere|array:DBWhere $where |
||
2010 | * |
||
2011 | * @return bool|array:DBWhere |
||
2012 | */ |
||
2013 | 51 | public function parseClause($where) |
|
2014 | { |
||
2015 | 51 | $ret = []; |
|
2016 | 51 | $interfaces = []; |
|
2017 | 51 | if (is_object($where)) { |
|
2018 | 8 | $interfaces = class_implements($where); |
|
2019 | } |
||
2020 | 51 | if (is_array($where)) { |
|
2021 | 42 | foreach ($where as $k => $w) { |
|
2022 | 10 | if (!is_a($w, 'Godsgood33\Php_Db\DBWhere')) { |
|
2023 | 1 | return false; |
|
2024 | } |
||
2025 | 9 | $v = $this->_escape($w->value, $w->escape); |
|
2026 | 9 | $where[$k]->value = $v; |
|
2027 | |||
2028 | 9 | $ret[] = $where[$k]; |
|
2029 | } |
||
2030 | 9 | } elseif (is_a($where, 'Godsgood33\Php_Db\DBWhere')) { |
|
2031 | 8 | $v = $this->_escape($where->value, $where->escape); |
|
2032 | 6 | $where->value = $v; |
|
2033 | 6 | $ret[] = $where; |
|
2034 | 2 | } elseif (in_array("Godsgood33\Php_Db\DBInterface", $interfaces) && is_callable(get_class($where) . "::where")) { |
|
2035 | 1 | $params = call_user_func([$where, "where"]); |
|
2036 | 1 | $ret = $this->parseClause($params); |
|
2037 | } else { |
||
2038 | 1 | $this->_logger->warning("Failed to get where", [$where]); |
|
2039 | } |
||
2040 | |||
2041 | 48 | return $ret; |
|
2042 | } |
||
2043 | |||
2044 | /** |
||
2045 | * Encryption algorithm |
||
2046 | * |
||
2047 | * @param string $data |
||
2048 | * @param string $salt |
||
2049 | * |
||
2050 | * @return string |
||
2051 | * |
||
2052 | * @throws Exception |
||
2053 | * |
||
2054 | * @uses PHP_DB_ENCRYPT_SALT string the salt used in the encryption algorithm |
||
2055 | * @uses PHP_DB_ENCRYPT_ALGORITHM string the encryption algorithm used |
||
2056 | */ |
||
2057 | 1 | public static function encrypt(string $data, ?string $salt = null) |
|
2058 | { |
||
2059 | 1 | if (!defined('PHP_DB_ENCRYPT_SALT') || !defined('PHP_DB_ENCRYPT_ALGORITHM')) { |
|
2060 | throw new Exception("Need to declare and populate PHP_DB_ENCRYPT_SALT and PHP_DB_ENCRYPT_ALGORITHM"); |
||
2061 | } |
||
2062 | |||
2063 | // Remove the base64 encoding from our key |
||
2064 | 1 | if (is_null($salt)) { |
|
2065 | 1 | $encryption_key = base64_decode(PHP_DB_ENCRYPT_SALT); |
|
2066 | } else { |
||
2067 | $encryption_key = base64_decode($salt); |
||
2068 | } |
||
2069 | // Generate an initialization vector |
||
2070 | 1 | $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(PHP_DB_ENCRYPT_ALGORITHM)); |
|
2071 | // Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector. |
||
2072 | 1 | $encrypted = openssl_encrypt($data, PHP_DB_ENCRYPT_ALGORITHM, $encryption_key, 0, $iv); |
|
2073 | // The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::) |
||
2074 | 1 | return base64_encode($encrypted . '::' . $iv); |
|
2075 | } |
||
2076 | |||
2077 | /** |
||
2078 | * Decryption algorithm |
||
2079 | * |
||
2080 | * @param string $data |
||
2081 | * |
||
2082 | * @return string |
||
2083 | * |
||
2084 | * @throws Exception |
||
2085 | * |
||
2086 | * @uses PHP_DB_ENCRYPT_SALT string the salt used in the encryption algorithm |
||
2087 | * @uses PHP_DB_ENCRYPT_ALGORITHM string the encryption algorithm used |
||
2088 | */ |
||
2089 | 130 | public static function decrypt(string $data) |
|
2090 | { |
||
2091 | 130 | if (!defined('PHP_DB_ENCRYPT_SALT') || !defined('PHP_DB_ENCRYPT_ALGORITHM')) { |
|
2092 | throw new Exception("Need to declare and populate PHP_DB_ENCRYPT_SALT and PHP_DB_ENCRYPT_ALGORITHM"); |
||
2093 | } |
||
2094 | |||
2095 | // Remove the base64 encoding from our key |
||
2096 | 130 | $encryption_key = base64_decode(PHP_DB_ENCRYPT_SALT); |
|
2097 | |||
2098 | // To decrypt, split the encrypted data from our IV - our unique separator used was "::" |
||
2099 | 130 | list($encrypted_data, $iv) = explode('::', base64_decode($data), 2); |
|
2100 | 130 | $plaintext = openssl_decrypt($encrypted_data, PHP_DB_ENCRYPT_ALGORITHM, $encryption_key, 0, $iv); |
|
2101 | 130 | return $plaintext; |
|
2102 | } |
||
2103 | |||
2104 | /** |
||
2105 | * Method to check if all required fields are available in the object |
||
2106 | * |
||
2107 | * @param object $object |
||
2108 | * @param array:string $requiredFields |
||
2109 | * |
||
2110 | * @return bool |
||
2111 | */ |
||
2112 | 12 | public static function checkObject($object, $requiredFields): bool |
|
2113 | { |
||
2114 | 12 | $haystack = array_keys(json_decode(json_encode($object), true)); |
|
2115 | 12 | foreach ($requiredFields as $r) { |
|
2116 | 12 | if (!in_array($r, $haystack)) { |
|
2117 | 3 | return false; |
|
2118 | } |
||
2119 | } |
||
2120 | |||
2121 | 9 | return true; |
|
2122 | } |
||
2123 | |||
2124 | /** |
||
2125 | * Method to retrieve the error data |
||
2126 | * |
||
2127 | * @return string |
||
2128 | */ |
||
2129 | 1 | public function error(): string |
|
2130 | { |
||
2131 | 1 | return $this->_c->error; |
|
2132 | } |
||
2133 | } |
||
2134 |