LEPTON CMS 7.2.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
41 private bool $bXrunInstalled = false;
42
43
49 private string $error = '';
50
56 private PDO $db_handle;
57
64 public bool $bHaltOnError = true;
65
66 public bool $bForceDieOnError = true;
67
75 public static function getInstance(array &$settings = []): object
76 {
77 if (null === static::$instance)
78 {
79 static::$instance = new static();
80
81 static::$instance->bXrunInstalled = class_exists("lib_comp", true);
82
83 static::$instance->connect($settings);
84 }
85
86 return static::$instance;
87 }
88
96 public function __construct(array &$settings = [])
97 {
98 $this->connect($settings);
99 }
100
104 public function __destruct()
105 {
106
107 }
108
114 protected function set_error(string $error = ''): void
115 {
116 $this->error = $error;
117 }
118
124 public function get_error(): string
125 {
126 return $this->error;
127 }
128
134 public function is_error(): bool
135 {
136 return !empty($this->error);
137 }
138
144 public function get_db_handle(): object
145 {
146 return $this->db_handle;
147 }
148
154 public function get_db_key(): string
155 {
156 return self::$db_key;
157 }
158
191 final function connect(array &$settings = []): void
192 {
193 if (!defined("DB_USER"))
194 {
195 $ini_file_name = LEPTON_PATH."/config/lepton.ini.php";
196
197 if (true === file_exists($ini_file_name))
198 {
199 $config = parse_ini_string(";" . file_get_contents($ini_file_name), true);
200
201 // [3.1]
202 if (!isset($settings['host']))
203 {
204 $settings['host'] = $config['database']['host'];
205 }
206 // [3.2]
207 if (!isset($settings['user']))
208 {
209 $settings['user'] = $config['database']['user'];
210 }
211 // [3.3]
212 if (!isset($settings['pass']))
213 {
214 $settings['pass'] = $config['database']['pass'];
215 }
216 // [3.4]
217 if (!isset($settings['name']))
218 {
219 $settings['name'] = $config['database']['name'];
220 }
221 // [3.5]
222 if (!isset($settings['port']))
223 {
224 $settings['port'] = $config['database']['port'];
225 }
226 // [3.6]
227 if ((isset($config['database']['charset'])) && (!isset($settings['charset'])))
228 {
229 $settings['charset'] = $config['database']['charset'];
230 }
231 // [3.7]
232 if (!defined("TABLE_PREFIX"))
233 {
234 define("TABLE_PREFIX", $config['database']['prefix']);
235 }
236
237 // [4] For the new secure methods in L* IV
238 if (isset($config['database']['key']))
239 {
240 self::$db_key = $config['database']['key'];
241 }
242
243 if (isset($config['database']['options']))
244 {
245 self::$default_openssl_options = intval($config['database']['options']);
246 }
247
248 if (isset($config['database']['cipher']))
249 {
250 if ("0" === $config['database']['cipher'])
251 {
252 $config['database']['cipher'] = 0;
253 }
254 self::$default_openssl_method = $config['database']['cipher'];
255 }
256
257 if (isset($config['database']['iv']))
258 {
259 self::$default_openssl_iv = $config['database']['iv'];
260 }
261
262 if (isset($config['database']['ivlen']))
263 {
264 self::$default_openssl_ivlen = $config['database']['ivlen'];
265 }
266
270 if (isset($config['system_const']))
271 {
272 foreach ($config['system_const'] as $key => $value)
273 {
274 if (!defined($key))
275 {
276 define($key, $value);
277 }
278 }
279 }
280
281 } else {
282 // Problem: no lepton.ini.php
283 exit('<p><b>Sorry, but this installation seems to be damaged! Please contact your webmaster!</b></p>');
284 }
285 }
286
287 // [4.1] For the new secure methods in L* IV
288 if (isset($settings['key']))
289 {
290 self::$db_key = $settings['key'];
291 }
292 if (isset($settings['options']))
293 {
294 self::$default_openssl_options = $settings['options'];
295 }
296 if (isset($settings['cipher']))
297 {
298 self::$default_openssl_method = $settings['cipher'];
299 }
300 if (isset($settings['iv']))
301 {
302 self::$default_openssl_iv = $settings['iv'];
303 }
304 if (isset($settings['ivlen']))
305 {
306 self::$default_openssl_ivlen = $settings['ivlen'];
307 }
308
309 $setup = [
310 'host' => array_key_exists('host', $settings) ? $settings['host'] : DB_HOST,
311 'user' => array_key_exists('user', $settings) ? $settings['user'] : DB_USERNAME,
312 'pass' => array_key_exists('pass', $settings) ? $settings['pass'] : DB_PASSWORD,
313 'name' => array_key_exists('name', $settings) ? $settings['name'] : DB_NAME,
314 'port' => array_key_exists('port', $settings) ? $settings['port'] : DB_PORT
315 ];
316
317 if (array_key_exists('charset', $settings))
318 {
319 $setup['charset'] = $settings['charset'];
320 } else {
321 $setup['charset'] = (defined('DB_CHARSET') ? DB_CHARSET : "utf8");
322 }
323
324 // use DB_PORT only if it differs from the standard port 3306
325 if ($setup['port'] !== '3306')
326 {
327 $setup['host'] .= ';port=' . $setup['port'];
328 }
329
330
331 $dsn = "mysql:dbname=".$setup['name'].";host=".$setup['host'].";charset=".$setup['charset'];
332
333 try {
334
335 $this->db_handle = new PDO(
336 $dsn,
337 $setup['user'],
338 $setup['pass'],
339 array(
340 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
341 PDO::ATTR_PERSISTENT => true,
342 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
343 )
344 );
345
349 $this->simple_query("SET NAMES '".$setup['charset']."'");
350
357 if(isset($config)) {
358 if(isset( $config['database']['mode'] ))
359 {
360 $this->simple_query("SET GLOBAL sql_mode='".$config['database']['mode']."'");
361 }
362 unset($config);
363 }
364
365 $this->simple_query("USE `".$setup['name']."`");
366
367 } catch (PDOException $oError) {
368 $this->set_error( $oError->getMessage() );
369 echo LEPTON_tools::display('Connection failed: ' . $oError->getMessage(),'pre','ui message');
370 echo LEPTON_tools::display('Runtime Code: ' . $oError->getCode(),'pre','ui message');
371 }
372
373 }
374
404 public function simple_query(string $sMySQL_Query = "", array $aParams = []): int
405 {
406 $this->error = "";
407 try
408 {
409 $oStatement=$this->db_handle->prepare( $sMySQL_Query );
410 if (!empty($aParams))
411 {
412 if ((isset($aParams[0])) && (is_array($aParams[0])))
413 {
414 foreach ($aParams as $temp_params)
415 {
416 $oStatement->execute($temp_params);
417 }
418 } else {
419 $oStatement->execute($aParams);
420 }
421 } else {
422 $oStatement->execute();
423 }
424 return $oStatement->rowCount();
425 } catch (PDOException $error)
426 {
427 $this->error = $error->getMessage() . "\n<p>Query: " . $sMySQL_Query . "\n</p>\n";
428 $this->HandleDisplayError("301");
429 return -1; // conform to mysql
430 }
431 }
432
441 public function get_one(string $SQL): mixed
442 {
443 $this->error = "";
444
445 try
446 {
447 $oStatement = $this->db_handle->prepare($SQL);
448 $oStatement->execute();
449
450 $data = $oStatement->fetch(PDO::FETCH_ASSOC);
451 if (false === $data)
452 {
453 return null;
454 } else {
455 return array_shift($data);
456 }
457 }
458 catch( Exception $error )
459 {
460 $this->error = $error->getMessage();
461 $this->HandleDisplayError("GO 101");
462 return null;
463 }
464 }
465
466
482 public function list_tables(string $strip = ""): array|bool
483 {
484 $this->error = "";
485 try
486 {
487 $oStatement=$this->db_handle->prepare( "SHOW tables" );
488 $oStatement->execute();
489
490 $data = $oStatement->fetchAll();
491 }
492 catch (Exception $error)
493 {
494 $this->error = $error->getMessage();
495 $this->HandleDisplayError("1");
496 return false;
497 }
498
499 $ret_value = [];
500 foreach($data as &$ref)
501 {
502 $ret_value[] = array_shift( $ref );
503 }
504 unset($ref);
505
506 if ($strip != "")
507 {
508 foreach ($ret_value as &$ref2)
509 {
510 $ref2 = str_replace($strip, "", $ref2);
511 }
512 }
513 unset($ref2);
514
515 return $ret_value;
516 }
517
528 public function describe_table(string $sTableName, array &$aStorage = [], int $iForm = self::DESCRIBE_RAW ): bool
529 {
530 $this->error = "";
531 try
532 {
533 $oStatement=$this->db_handle->prepare( "DESCRIBE `" . $sTableName . "`" );
534 $oStatement->execute();
535
536 $aStorage = $oStatement->fetchAll();
537
538 switch ($iForm)
539 {
540 case (self::DESCRIBE_ASSOC):
541 $aTemp = [];
542 foreach($aStorage as $values)
543 {
544 $aTemp[ $values["Field"] ] = $values;
545 }
546 unset($values);
547 $aStorage = $aTemp;
548 break;
549
550 case (self::DESCRIBE_ONLY_NAMES):
551 $aTemp = [];
552 foreach($aStorage as $values)
553 {
554 $aTemp[] = $values["Field"];
555 }
556 unset($values);
557 $aStorage = $aTemp;
558 break;
559
560 default:
561 // nothing - keep the storage as it is
562 break;
563 }
564
565 return true;
566 }
567 catch (Exception $error)
568 {
569 $this->error = $error->getMessage();
570 $this->HandleDisplayError("2");
571 return false;
572 }
573 }
574
596 public function execute_query(string $aQuery="", bool $bFetch=false, array &$aStorage=[], bool $bFetchAll=true ) : int
597 {
598 $this->error = "";
599 try{
600 $oStatement=$this->db_handle->prepare($aQuery);
601 $oStatement->execute();
602
603 if (($oStatement->rowCount() > 0) && (true === $bFetch))
604 {
605 $aStorage = (true === $bFetchAll)
606 ? $oStatement->fetchAll()
607 : $oStatement->fetch()
608 ;
609
610 }
611 return $oStatement->rowCount();
612 } catch( PDOException $error) {
613 $this->error = $error->getMessage();
614 $this->HandleDisplayError("10");
615 return -1;
616 }
617 }
618
633 public function build_and_execute(string $type, string $table_name, array $table_values, string $condition="", string $key=""): int
634 {
635 $this->error = "";
636 switch( strtolower($type) )
637 {
638 case 'update':
639 $q = "UPDATE `" . $table_name . "` SET ";
640 foreach ($table_values as $field => $value)
641 {
642 $q .= "`" . $field . "`= :" . $field . ", ";
643 }
644 $q = substr($q, 0, -2) . (($condition != "") ? " WHERE " . $condition : "");
645 break;
646
647 case 'insert':
648 $keys = array_keys($table_values);
649 $q = "INSERT into `" . $table_name . "` (`";
650 $q .= implode("`,`", $keys) . "`) VALUES (:";
651 $q .= implode(", :", $keys) . ")";
652 break;
653
654 case 'insert_on_duplicate_key_update':
655 $keys = array_keys($table_values);
656 $q = "INSERT into `" . $table_name . "` (`";
657 $q .= implode("`,`", $keys) . "`) VALUES (:";
658 $q .= implode(", :", $keys) . ")";
659 $q .= "ON DUPLICATE KEY UPDATE";
660 foreach($table_values as $field => $value)
661 {
662 if ($field != $key)
663 {
664 $q .= "`" . $field . "`= :" . $field . ", ";
665 }
666 }
667 $q = substr($q, 0, -2);
668 break;
669
670 default:
671 die(__line__.": build_and_execute-> type unknown!");
672 }
673
674 try
675 {
676
677 $oStatement=$this->db_handle->prepare($q);
678 $oStatement->execute( $table_values );
679 return $oStatement->rowCount();
680 }
681 catch( PDOException $error)
682 {
683 $this->error = $error->getMessage()."\n<p>Query: ".$q."\n</p>\n";
684 $this->HandleDisplayError("12");
685 return -1;
686 }
687
688 }
689
695 private function HandleDisplayError(string $sPrefix = "" ): void
696 {
697 if (true === $this->bHaltOnError)
698 {
699 // [1]
700 $sMessage = LEPTON_tools::display(
701 (($sPrefix != "") ? "[" . $sPrefix . "] " : "") . $this->error,
702 "pre",
703 "ui message red"
704 );
705
706 // [2]
707 ob_start();
708 debug_print_backtrace();
709 $sBugTrace = ob_get_clean();
710
711 $sMessage .= LEPTON_tools::display(
712 $sBugTrace,
713 "pre",
714 "ui message orange"
715 );
716
717 // [3]
718 if (true === $this->bForceDieOnError)
719 {
720 die($sMessage);
721
722 } else {
723 echo $sMessage;
724 }
725 }
726 }
727
728
736 public function query(string $sSqlQuery = ""): object|null
737 {
738 $this->error = "";
739 try{
740 $oStatement = $this->db_handle->prepare($sSqlQuery);
741 $oStatement->execute();
742
743 if ((true === $this->bXrunInstalled) && (true === lib_comp::$bXRunInit))
744 {
745 return new lib_comp_query($oStatement);
746 } else {
747 return $oStatement;
748 }
749
750 } catch( PDOException $error ) {
751 $this->set_error( $error->getMessage() );
752 $this->HandleDisplayError("xRun 101");
753 return null;
754 }
755 }
756
769 public function add_column(string $table = '', string $column = '', string $desc = ''): bool
770 {
771 $result = [];
772 $this->execute_query(
773 "DESCRIBE `" . TABLE_PREFIX . $table . "` `" . $column . "`",
774 true,
775 $result,
776 false
777 );
778
779 if (empty($result)) // no entry
780 {
781 $this->simple_query("ALTER TABLE `" . TABLE_PREFIX . $table . "` ADD `" . $column . "` " . $desc);
782 }
783
784 return true;
785 }
786}
connect(array &$settings=[])
set_error(string $error='')
get_one(string $SQL)
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=[])
build_and_execute(string $type, string $table_name, array $table_values, string $condition="", string $key="")
__construct(array &$settings=[])
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)
trait LEPTON_secure_database