sql.class.php 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. namespace Juju;
  3. require_once('SQL/query.class.php');
  4. require_once('Data/securestring.class.php');
  5. use \Juju\{SQL\Query, Data\SecureString};
  6. /**
  7. * SQL class. Used for handling SQL connections
  8. *
  9. * @module sql
  10. * @class SQL
  11. * @constructor
  12. */
  13. class SQL {
  14. /**
  15. * This is the mysqli connection beneath everything
  16. *
  17. * @property sql
  18. * @type {mysqli}
  19. * @private
  20. * @required
  21. */
  22. private $guid;
  23. private $sql;
  24. public $queries = [];
  25. private static $connections = [];
  26. public static function FromDSN(string $dsnstring){
  27. $dsnstring = explode(':', $dsnstring)[1];
  28. $dsn = explode(';', $dsnstring);
  29. $dsn = array_reduce($dsn, function($dsn, $item){
  30. $item = explode('=', $item);
  31. $dsn[$item[0]] = $item[1];
  32. return $dsn;
  33. });
  34. if(!isset($dsn['host'])){
  35. throw new \Exception("DSN '{$dsnstring}' missing host");
  36. }
  37. if(!isset($dsn['dbname'])){
  38. throw new \Exception("DSN '{$dsnstring}' missing dbname");
  39. }
  40. if(!isset($dsn['user'])){
  41. $dsn['user'] = $dsn['dbname'];
  42. }
  43. if(!isset($dsn['pass'])){
  44. $dsn['pass'] = $dsn['user'];
  45. }
  46. $dsn['pass'] = SecureString::from($dsn['pass']);
  47. return new SQL($dsn['host'], $dsn['user'], $dsn['pass'], $dsn['dbname']);
  48. }
  49. public function __construct($server,$user,$pass,$db){
  50. $this->guid = uniqid();
  51. $this->sql = new \mysqli('p:'.$server,$user,"{$pass}",$db);;
  52. if($this->sql->connect_error){
  53. throw new \Exception('Mysqli Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
  54. }
  55. self::$connections[] = $sql;
  56. }
  57. public function __destruct(){
  58. $this->sql->rollback();
  59. $this->sql->close();
  60. foreach($this->queries as $query){
  61. unset($query);
  62. }
  63. self::$connections = array_diff(self::$connections, [$this]);
  64. }
  65. public function __invoke(){
  66. return $this->sql;
  67. }
  68. public function __get($name){
  69. switch($name){
  70. case 'error':
  71. return $this->sql->error;
  72. break;
  73. case 'insert_id':
  74. return $this->sql->insert_id;
  75. break;
  76. }
  77. }
  78. public function __toString(){
  79. return $this->guid;
  80. }
  81. /**
  82. * Returns a Query object based on inputs
  83. *
  84. * @method query
  85. * @param {String} sql The sql expression to run
  86. * @param {String=null} [types] A string containing all the types of arguments being passed
  87. * @param {Mixed} [bindings]* The bindings to use in the sql statement
  88. * @return {Query} Returns the query object
  89. */
  90. public function query(...$args){
  91. return new SQL\Query(...array_merge([$this], $args));
  92. }
  93. public function escape($s){
  94. return $this->sql->escape_string($s);
  95. }
  96. public function charset($charset){
  97. return $this->sql->set_charset($charset);
  98. }
  99. public static function make_referenced(&$arr){
  100. $refs = [];
  101. foreach($arr as $key => $value){
  102. $refs[$key] = &$arr[$key];
  103. }
  104. return $refs;
  105. }
  106. public static function shutdown(){
  107. foreach(self::$connections as $sql){
  108. unset($sql);
  109. }
  110. }
  111. }
  112. register_shutdown_function(function(){
  113. SQL::shutdown();
  114. });
  115. ?>