LEPTON CMS 7.3.0
feel free to keep it strictly simple...
Loading...
Searching...
No Matches
lepton_database.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
25{
27
28 const DESCRIBE_RAW = 0;
29 const DESCRIBE_ASSOC = 1;
31
36 private static LEPTON_database|null $instance = null;
37
38
42 private bool $bXrunInstalled = false;
43
44
50 private string $error = '';
51
57 private PDO $db_handle;
58
65 public bool $bHaltOnError = true;
66
67 public bool $bForceDieOnError = true;
68
76 public static function getInstance(array &$settings = []): object
77 {
78 if (null === static::$instance)
79 {
80 static::$instance = new static();
81
82 static::$instance->bXrunInstalled = class_exists("lib_comp", true);
83
84 static::$instance->bOpenSslInstalled = defined('OPENSSL_VERSION_NUMBER');
85
86 static::$instance->connect($settings);
87 }
88
89 return static::$instance;
90 }
91
99 public function __construct(array &$settings = [])
100 {
101 $this->connect($settings);
102 }
103
107 public function __destruct()
108 {
109
110 }
111
117 protected function set_error(string $error = ''): void
118 {
119 $this->error = $error;
120 }
121
127 public function get_error(): string
128 {
129 return $this->error;
130 }
131
137 public function is_error(): bool
138 {
139 return !empty($this->error);
140 }
141
147 public function get_db_handle(): object
148 {
149 return $this->db_handle;
150 }
151
157 public function get_db_key(): string
158 {
159 return self::$db_key;
160 }
161
194 final function connect(array &$settings = []): void
195 {
196 if (!defined("DB_USER"))
197 {
198 $ini_file_name = LEPTON_PATH."/config/lepton.ini.php";
199
200 if (true === file_exists($ini_file_name))
201 {
202 $config = parse_ini_string(";" . file_get_contents($ini_file_name), true);
203
204 // [3.1]
205 if (!isset($settings['host']))
206 {
207 $settings['host'] = $config['database']['host'];
208 }
209 // [3.2]
210 if (!isset($settings['user']))
211 {
212 $settings['user'] = $config['database']['user'];
213 }
214 // [3.3]
215 if (!isset($settings['pass']))
216 {
217 $settings['pass'] = $config['database']['pass'];
218 }
219 // [3.4]
220 if (!isset($settings['name']))
221 {
222 $settings['name'] = $config['database']['name'];
223 }
224 // [3.5]
225 if (!isset($settings['port']))
226 {
227 $settings['port'] = $config['database']['port'];
228 }
229 // [3.6]
230 if ((isset($config['database']['charset'])) && (!isset($settings['charset'])))
231 {
232 $settings['charset'] = $config['database']['charset'];
233 }
234 // [3.7]
235 if (!defined("TABLE_PREFIX"))
236 {
237 define("TABLE_PREFIX", $config['database']['prefix']);
238 }
239
240 // [4] For the new secure methods in L* IV
241 if (isset($config['database']['key']))
242 {
243 self::$db_key = $config['database']['key'];
244 }
245
246 if (isset($config['database']['options']))
247 {
248 self::$default_openssl_options = intval($config['database']['options']);
249 }
250
251 if (isset($config['database']['cipher']))
252 {
253 if ("0" === $config['database']['cipher'])
254 {
255 $config['database']['cipher'] = 0;
256 }
257 self::$default_openssl_method = $config['database']['cipher'];
258 }
259
260 if (isset($config['database']['iv']))
261 {
262 self::$default_openssl_iv = $config['database']['iv'];
263 }
264
265 if (isset($config['database']['ivlen']))
266 {
267 self::$default_openssl_ivlen = $config['database']['ivlen'];
268 }
269
273 if (isset($config['system_const']))
274 {
275 foreach ($config['system_const'] as $key => $value)
276 {
277 if (!defined($key))
278 {
279 define($key, $value);
280 }
281 }
282 }
283
284 } else {
285 // Problem: no lepton.ini.php
286 exit('<p><b>Sorry, but this installation seems to be damaged! Please contact your webmaster!</b></p>');
287 }
288 }
289
290 // [4.1] For the new secure methods in L* IV
291 if (isset($settings['key']))
292 {
293 self::$db_key = $settings['key'];
294 }
295 if (isset($settings['options']))
296 {
297 self::$default_openssl_options = $settings['options'];
298 }
299 if (isset($settings['cipher']))
300 {
301 self::$default_openssl_method = $settings['cipher'];
302 }
303 if (isset($settings['iv']))
304 {
305 self::$default_openssl_iv = $settings['iv'];
306 }
307 if (isset($settings['ivlen']))
308 {
309 self::$default_openssl_ivlen = $settings['ivlen'];
310 }
311
312 $setup = [
313 'host' => array_key_exists('host', $settings) ? $settings['host'] : DB_HOST,
314 'user' => array_key_exists('user', $settings) ? $settings['user'] : DB_USERNAME,
315 'pass' => array_key_exists('pass', $settings) ? $settings['pass'] : DB_PASSWORD,
316 'name' => array_key_exists('name', $settings) ? $settings['name'] : DB_NAME,
317 'port' => array_key_exists('port', $settings) ? $settings['port'] : DB_PORT
318 ];
319
320 if (array_key_exists('charset', $settings))
321 {
322 $setup['charset'] = $settings['charset'];
323 } else {
324 $setup['charset'] = (defined('DB_CHARSET') ? DB_CHARSET : "utf8");
325 }
326
327 // use DB_PORT only if it differs from the standard port 3306
328 if ($setup['port'] !== '3306')
329 {
330 $setup['host'] .= ';port=' . $setup['port'];
331 }
332
333
334 $dsn = "mysql:dbname=".$setup['name'].";host=".$setup['host'].";charset=".$setup['charset'];
335
336 try {
337
338 $this->db_handle = new PDO(
339 $dsn,
340 $setup['user'],
341 $setup['pass'],
342 array(
343 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
344 PDO::ATTR_PERSISTENT => true,
345 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
346 )
347 );
348
352 $this->simple_query("SET NAMES '".$setup['charset']."'");
353
360 if(isset($config)) {
361 if(isset( $config['database']['mode'] ))
362 {
363 $this->simple_query("SET GLOBAL sql_mode='".$config['database']['mode']."'");
364 }
365 unset($config);
366 }
367
368 $this->simple_query("USE `".$setup['name']."`");
369
370 } catch (PDOException $oError) {
371 $this->set_error( $oError->getMessage() );
372 echo LEPTON_tools::display('Connection failed: ' . $oError->getMessage(),'pre','ui message');
373 echo LEPTON_tools::display('Runtime Code: ' . $oError->getCode(),'pre','ui message');
374 }
375
376 }
377
407 public function simple_query(string $sMySQL_Query = "", array $aParams = []): int
408 {
409 $this->error = "";
410 try
411 {
412 $oStatement=$this->db_handle->prepare( $sMySQL_Query );
413 if (!empty($aParams))
414 {
415 if ((isset($aParams[0])) && (is_array($aParams[0])))
416 {
417 foreach ($aParams as $temp_params)
418 {
419 $oStatement->execute($temp_params);
420 }
421 } else {
422 $oStatement->execute($aParams);
423 }
424 } else {
425 $oStatement->execute();
426 }
427 return $oStatement->rowCount();
428 } catch (PDOException $error)
429 {
430 $this->error = $error->getMessage() . "\n<p>Query: " . $sMySQL_Query . "\n</p>\n";
431 $this->HandleDisplayError("301");
432 return -1; // conform to mysql
433 }
434 }
435
444 public function get_one(string $SQL): mixed
445 {
446 $this->error = "";
447
448 try
449 {
450 $oStatement = $this->db_handle->prepare($SQL);
451 $oStatement->execute();
452
453 $data = $oStatement->fetch(PDO::FETCH_ASSOC);
454 if (false === $data)
455 {
456 return null;
457 } else {
458 return array_shift($data);
459 }
460 }
461 catch( Exception $error )
462 {
463 $this->error = $error->getMessage();
464 $this->HandleDisplayError("GO 101");
465 return null;
466 }
467 }
468
469
485 public function list_tables(string $strip = ""): array|bool
486 {
487 $this->error = "";
488 try
489 {
490 $oStatement=$this->db_handle->prepare( "SHOW tables" );
491 $oStatement->execute();
492
493 $data = $oStatement->fetchAll();
494 }
495 catch (Exception $error)
496 {
497 $this->error = $error->getMessage();
498 $this->HandleDisplayError("1");
499 return false;
500 }
501
502 $ret_value = [];
503 foreach($data as &$ref)
504 {
505 $ret_value[] = array_shift( $ref );
506 }
507 unset($ref);
508
509 if ($strip != "")
510 {
511 foreach ($ret_value as &$ref2)
512 {
513 $ref2 = str_replace($strip, "", $ref2);
514 }
515 }
516 unset($ref2);
517
518 return $ret_value;
519 }
520
531 public function describe_table(string $sTableName, array &$aStorage = [], int $iForm = self::DESCRIBE_RAW ): bool
532 {
533 $this->error = "";
534 try
535 {
536 $oStatement=$this->db_handle->prepare( "DESCRIBE `" . $sTableName . "`" );
537 $oStatement->execute();
538
539 $aStorage = $oStatement->fetchAll();
540
541 switch ($iForm)
542 {
543 case (self::DESCRIBE_ASSOC):
544 $aTemp = [];
545 foreach($aStorage as $values)
546 {
547 $aTemp[ $values["Field"] ] = $values;
548 }
549 unset($values);
550 $aStorage = $aTemp;
551 break;
552
553 case (self::DESCRIBE_ONLY_NAMES):
554 $aTemp = [];
555 foreach($aStorage as $values)
556 {
557 $aTemp[] = $values["Field"];
558 }
559 unset($values);
560 $aStorage = $aTemp;
561 break;
562
563 default:
564 // nothing - keep the storage as it is
565 break;
566 }
567
568 return true;
569 }
570 catch (Exception $error)
571 {
572 $this->error = $error->getMessage();
573 $this->HandleDisplayError("2");
574 return false;
575 }
576 }
577
599 public function execute_query(string $aQuery="", bool $bFetch=false, array &$aStorage=[], bool $bFetchAll=true ) : int
600 {
601 $this->error = "";
602 try{
603 $oStatement=$this->db_handle->prepare($aQuery);
604 $oStatement->execute();
605
606 if (($oStatement->rowCount() > 0) && (true === $bFetch))
607 {
608 $aStorage = (true === $bFetchAll)
609 ? $oStatement->fetchAll()
610 : $oStatement->fetch()
611 ;
612
613 }
614 return $oStatement->rowCount();
615 } catch( PDOException $error) {
616 $this->error = $error->getMessage();
617 $this->HandleDisplayError("10");
618 return -1;
619 }
620 }
621
636 public function build_and_execute(string $type, string $table_name, array $table_values, string $condition="", bool $display_query=false): int
637 {
638 $this->error = "";
639 switch( strtolower($type) )
640 {
641 case 'update':
642 $q = "UPDATE `" . $table_name . "` SET ";
643 foreach ($table_values as $field => $value)
644 {
645 $q .= "`" . $field . "`= :" . $field . ", ";
646 }
647 $q = substr($q, 0, -2) . (($condition != "") ? " WHERE " . $condition : "");
648 break;
649
650 case 'insert':
651 $keys = array_keys($table_values);
652 $q = "INSERT into `" . $table_name . "` (`";
653 $q .= implode("`,`", $keys) . "`) VALUES (:";
654 $q .= implode(", :", $keys) . ")";
655 break;
656
657 default:
658 die(__line__.": build_and_execute-> type unknown!");
659 }
660
661 if($display_query === true)
662 {
663 die(LEPTON_tools::display_dev($q, 'pre','ui orange message'));
664 }
665
666 try
667 {
668
669 $oStatement=$this->db_handle->prepare($q);
670 $oStatement->execute( $table_values );
671 return $oStatement->rowCount();
672 }
673 catch( PDOException $error)
674 {
675 $this->error = $error->getMessage()."\n<p>Query: ".$q."\n</p>\n";
676 $this->HandleDisplayError("12");
677 return -1;
678 }
679
680 }
681
687 private function HandleDisplayError(string $sPrefix = "" ): void
688 {
689 if (true === $this->bHaltOnError)
690 {
691 // [1]
692 $sMessage = LEPTON_tools::display(
693 (($sPrefix != "") ? "[" . $sPrefix . "] " : "") . $this->error,
694 "pre",
695 "ui message red"
696 );
697
698 // [2]
699 ob_start();
700 debug_print_backtrace();
701 $sBugTrace = ob_get_clean();
702
703 $sMessage .= LEPTON_tools::display(
704 $sBugTrace,
705 "pre",
706 "ui message orange"
707 );
708
709 // [3]
710 if (true === $this->bForceDieOnError)
711 {
712 die($sMessage);
713
714 } else {
715 echo $sMessage;
716 }
717 }
718 }
719
720
728 public function query(string $sSqlQuery = ""): object|null
729 {
730 $this->error = "";
731 try{
732 $oStatement = $this->db_handle->prepare($sSqlQuery);
733 $oStatement->execute();
734
735 if ((true === $this->bXrunInstalled) && (true === lib_comp::$bXRunInit))
736 {
737 return new lib_comp_query($oStatement);
738 } else {
739 return $oStatement;
740 }
741
742 } catch( PDOException $error ) {
743 $this->set_error( $error->getMessage() );
744 $this->HandleDisplayError("xRun 101");
745 return null;
746 }
747 }
748
761 public function add_column(string $table = '', string $column = '', string $desc = ''): bool
762 {
763 $result = [];
764 $this->execute_query(
765 "DESCRIBE `" . TABLE_PREFIX . $table . "` `" . $column . "`",
766 true,
767 $result,
768 false
769 );
770
771 if (empty($result)) // no entry
772 {
773 $this->simple_query("ALTER TABLE `" . TABLE_PREFIX . $table . "` ADD `" . $column . "` " . $desc);
774 }
775
776 return true;
777 }
778
798 public function select_addon_tables(string $sAddonName = ""): array
799 {
800 $ret_value = [];
801
802 $aAllTables = $this->list_tables(TABLE_PREFIX);
803
804 foreach ($aAllTables as $sTempTablename)
805 {
806 if ($sTempTablename == $sAddonName)
807 {
808 $ret_value[] = $sAddonName;
809 }
810
811 if (str_starts_with($sTempTablename, $sAddonName."_"))
812 {
813 $ret_value[] = $sTempTablename;
814 }
815 }
816
817 return $ret_value;
818 }
819}
connect(array &$settings=[])
set_error(string $error='')
get_one(string $SQL)
select_addon_tables(string $sAddonName="")
describe_table(string $sTableName, array &$aStorage=[], int $iForm=self::DESCRIBE_RAW)
execute_query(string $aQuery="", bool $bFetch=false, array &$aStorage=[], bool $bFetchAll=true)
simple_query(string $sMySQL_Query="", array $aParams=[])
__construct(array &$settings=[])
build_and_execute(string $type, string $table_name, array $table_values, string $condition="", bool $display_query=false)
list_tables(string $strip="")
static getInstance(array &$settings=[])
add_column(string $table='', string $column='', string $desc='')
query(string $sSqlQuery="")
static display(mixed $something_to_display="", string $tag="pre", string|null $css_class=null, bool|null $useVarDump=null)
static display_dev(mixed $something_to_display="", string $tag="pre", string|null $css_class=null, bool|null $useVarDump=null)
trait LEPTON_secure_database