Advertisement
Faguss

UserSpice DB.php (with patch by plb) - custom version

May 20th, 2017
469
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.62 KB | None | 0 0
  1. <?php
  2. /*
  3. UserSpice 4
  4. An Open Source PHP User Management System
  5. by the UserSpice Team at http://UserSpice.com
  6.  
  7. This program is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. class DB {
  21.     private static $_instance = null;
  22.     private $_pdo, $_query, $_error = false, $_errorInfo, $_results, $_resultsArray, $_count = 0, $_lastId, $_queryCount=0;
  23.  
  24.     private function __construct(){
  25.         if (!$opts = Config::get('mysql/options'))
  26.             $opts = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET SESSION sql_mode = ''");
  27.         try{
  28.             $this->_pdo = new PDO('mysql:host=' .
  29.                 Config::get('mysql/host') .';dbname='.
  30.                 Config::get('mysql/db') . ';charset=utf8',
  31.                 Config::get('mysql/username'),
  32.                 Config::get('mysql/password'),
  33.                 $opts);
  34.         } catch(PDOException $e){
  35.             die($e->getMessage());
  36.         }
  37.     }
  38.  
  39.     public static function getInstance(){
  40.         if (!isset(self::$_instance)) {
  41.             self::$_instance = new DB();
  42.         }
  43.         return self::$_instance;
  44.     }
  45.  
  46.     public function query($sql, $params = array()){
  47.         #echo "DEBUG: query(sql=$sql, params=".print_r($params,true).")<br />\n";
  48.         $this->_queryCount++;
  49.         $this->_error = false;
  50.         $this->_errorInfo = array(0, null, null); $this->_resultsArray=[]; $this->_count=0; $this->_lastId=0;
  51.         if ($this->_query = $this->_pdo->prepare($sql)) {
  52.             $x = 1;
  53.             if (count($params)) {
  54.                 foreach ($params as $param) {
  55.                     $this->_query->bindValue($x, $param);
  56.                     $x++;
  57.                 }
  58.             }
  59.  
  60.             if ($this->_query->execute()) {
  61.                 if ($this->_query->columnCount() > 0) {
  62.                     $this->_results = $this->_query->fetchALL(PDO::FETCH_OBJ);
  63.                     $this->_resultsArray = json_decode(json_encode($this->_results),true);
  64.                 }
  65.                 $this->_count = $this->_query->rowCount();
  66.                 $this->_lastId = $this->_pdo->lastInsertId();
  67.             } else{
  68.                 $this->_error = true;
  69.                 $this->_errorInfo = $this->_query->errorInfo();
  70.             }
  71.         }
  72.         return $this;
  73.     }
  74.  
  75.     public function findAll($table){
  76.         return $this->action('SELECT *',$table);
  77.     }
  78.  
  79.     public function findById($id,$table){
  80.         return $this->action('SELECT *',$table,array('id','=',$id));
  81.     }
  82.  
  83.     public function action($action, $table, $where = array()){
  84.         $sql    = "{$action} FROM {$table}";
  85.         $values = array();
  86.         $is_ok  = true;
  87.        
  88.         if ($where_text = $this->_calcWhere($where, $values, "and", $is_ok))
  89.             $sql .= " WHERE $where_text";
  90.        
  91.         if ($is_ok)
  92.             if (!$this->query($sql, $values)->error())
  93.                 return $this;
  94.  
  95.         return false;
  96.     }
  97.  
  98.     private function _calcWhere($w, &$vals, $comboparg='and', &$is_ok=NULL) {
  99.         #echo "DEBUG: Entering _calcwhere(w=".print_r($w,true).",...)<br />\n";
  100.         if (is_array($w)) {
  101.                 #echo "DEBUG: is_array - check<br />\n";
  102.             $comb_ops   = ['and', 'or', 'and not', 'or not'];
  103.             $valid_ops  = ['=', '<', '>', '<=', '>=', '<>', '!=', 'LIKE', 'NOT LIKE', 'ALIKE', 'NOT ALIKE', 'REGEXP', 'NOT REGEXP'];
  104.             $two_args   = ['IS NULL', 'IS NOT NULL'];
  105.             $four_args  = ['BETWEEN', 'NOT BETWEEN'];
  106.             $arr_arg    = ['IN', 'NOT IN'];
  107.             $nested_arg = ['ANY', 'ALL', 'SOME'];
  108.             $nested     = ['EXISTS', 'NOT EXISTS'];
  109.             $nestedIN   = ['IN SELECT', 'NOT IN SELECT'];
  110.             $wcount     = count($w);
  111.  
  112.             if ($wcount == 0)
  113.                 return "";
  114.            
  115.             # believe it or not, this appears to be the fastest way to check
  116.             # sequential vs associative. Particularly with our expected short
  117.             # arrays it shouldn't impact memory usage
  118.             # https://gist.github.com/Thinkscape/1965669
  119.             if (array_values($w) === $w) { // sequential array
  120.                         #echo "DEBUG: Sequential array - check!<br />\n";
  121.                 if (in_array(strtolower($w[0]), $comb_ops)) {
  122.                             #echo "DEBUG: w=".print_r($w,true)."<br />\n";
  123.                     $sql = '';
  124.                     $combop = '';
  125.                     for ($i = 1; $i < $wcount; $i++) {
  126.                         $sql .= ' '. $combop . ' ' . $this->_calcWhere($w[$i], $vals, "and", $is_ok);
  127.                         $combop = $w[0];
  128.                     }
  129.                     return '('.$sql.')';                   
  130.                    
  131.                 } elseif ($wcount==3  &&  in_array($w[1],$valid_ops)) {
  132.                     #echo "DEBUG: normal condition w=".print_r($w,true)."<br />\n";
  133.                     $vals[] = $w[2];
  134.                     return "{$w[0]} {$w[1]} ?";
  135.                    
  136.                 } elseif ($wcount==2  &&  in_array($w[1],$two_args)) { 
  137.                     return "{$w[0]} {$w[1]}";
  138.                    
  139.                 } elseif ($wcount==4  &&  in_array($w[1],$four_args)) {
  140.                     $vals[] = $w[2];
  141.                     $vals[] = $w[3];
  142.                     return "{$w[0]} {$w[1]} ? AND ?";
  143.                    
  144.                 } elseif ($wcount==3  &&  in_array($w[1],$arr_arg)  &&  is_array($w[2])) { 
  145.                     $vals = array_merge($vals,$w[2]);
  146.                     return "{$w[0]} {$w[1]} (" . substr( str_repeat(",?",count($w[2])), 1) . ")";
  147.                    
  148.                 } elseif (($wcount==5 || $wcount==6 && is_array($w[5]))  &&  in_array($w[1],$valid_ops)  &&  in_array($w[2],$nested_arg)) {
  149.                     return  "{$w[0]} {$w[1]} {$w[2]}" . $this->get_subquery_sql($w[4],$w[3],$w[5],$vals,$is_ok);
  150.                    
  151.                 } elseif (($wcount==3 || $wcount==4 && is_array($w[3]))  &&  in_array($w[0],$nested)) {
  152.                     return $w[0] . $this->get_subquery_sql($w[2],$w[1],$w[3],$vals,$is_ok);
  153.                        
  154.                 } elseif (($wcount==4 || $wcount==5 && is_array($w[4]))  &&  in_array($w[1],$nestedIN)) {  
  155.                     return "{$w[0]} " . substr($w[1],0,-7) . $this->get_subquery_sql($w[3],$w[2],$w[4],$vals,$is_ok);
  156.                    
  157.                 } else {
  158.                     echo "ERROR: w=".print_r($w,true)."<br />\n";
  159.                     $is_ok = false;
  160.                 }
  161.             } else { // associative array ['field' => 'value']
  162.                 #echo "DEBUG: Associative<br />\n";
  163.                 $sql = '';
  164.                 $combop = '';
  165.                 foreach ($w as $k=>$v) {
  166.                     if (in_array(strtolower($k), $comb_ops)) {
  167.                         #echo "DEBUG: A<br />\n";
  168.                         #echo "A: k=$k, v=".print_r($v,true)."<br />\n";
  169.                         $sql .= $combop . ' (' . $this->_calcWhere($v, $vals, $k, $is_ok) . ') ';
  170.                         $combop = $comboparg;
  171.                     } else {
  172.                         #echo "DEBUG: B<br />\n";
  173.                         #echo "B: k=$k, v=".print_r($v,true)."<br />\n";
  174.                         $vals[] = $v;
  175.                         if (in_array(substr($k,-1,1), array('=', '<', '>'))) // 'field !='=>'value'
  176.                             $sql .= $combop . ' ' . $k . ' ? ';
  177.                         else // 'field'=>'value'
  178.                             $sql .= $combop . ' ' . $k . ' = ? ';
  179.                         $combop = $comboparg;
  180.                     }
  181.                 }
  182.                 return ' ('.$sql.') ';
  183.             }
  184.         } else {
  185.             echo "ERROR: No array in $w<br />\n";
  186.             $is_ok = false;
  187.         }
  188.     }
  189.  
  190.     public function get($table, $where){
  191.         return $this->action('SELECT *', $table, $where);
  192.     }
  193.  
  194.     public function delete($table, $where){
  195.         return empty($where) ? false : $this->action('DELETE', $table, $where);
  196.     }
  197.  
  198.     public function deleteById($table,$id){
  199.         return $this->action('DELETE',$table,array('id','=',$id));
  200.     }
  201.  
  202.     public function insert($table, $fields=[], $update=false) {
  203.         $keys    = array_keys($fields);
  204.         $values  = [];
  205.         $records = 0;
  206.        
  207.         foreach ($fields as $field) {
  208.             $count = is_array($field) ? count($field) : 1;
  209.            
  210.             if (!isset($first_time)  ||  $count<$records) {
  211.                 $first_time = true;
  212.                 $records    = $count;
  213.             }
  214.         }
  215.  
  216.         for ($i=0; $i<$records; $i++)
  217.             foreach ($fields as $field)
  218.                 $values[] = is_array($field) ? $field[$i] : $field;
  219.  
  220.         $col = ",(" . substr( str_repeat(",?",count($fields)), 1) . ")";
  221.         $sql = "INSERT INTO {$table} (`". implode('`,`', $keys)."`) VALUES ". substr( str_repeat($col,$records), 1);
  222.        
  223.         if ($update) {
  224.             $sql .= " ON DUPLICATE KEY UPDATE";
  225.            
  226.             foreach ($keys as $key)
  227.                 if ($key != "id")
  228.                     $sql .= " `$key` = VALUES(`$key`),";
  229.  
  230.             if (!empty($keys))
  231.                 $sql = substr($sql, 0, -1);
  232.         }
  233.  
  234.         return !$this->query($sql, $values)->error();
  235.     }
  236.  
  237.     public function update($table, $id, $fields){
  238.         $sql   = "UPDATE {$table} SET " . (empty($fields) ? "" : "`") . implode("` = ? , `", array_keys($fields)) . (empty($fields) ? "" : "` = ? ");
  239.         $is_ok = true;
  240.        
  241.         if (!is_array($id)) {
  242.             $sql     .= "WHERE id = ?";
  243.             $fields[] = $id;
  244.         } else {
  245.             if (empty($id))
  246.                 return false;
  247.            
  248.             if ($where_text = $this->_calcWhere($id, $fields, "and", $is_ok))
  249.                 $sql .= "WHERE $where_text";
  250.         }
  251.  
  252.         if ($is_ok)
  253.             if (!$this->query($sql, $fields)->error())
  254.                 return true;
  255.  
  256.         return false;
  257.     }
  258.  
  259.     public function results($assoc = false){
  260.         if($assoc) return $this->_resultsArray;
  261.         return $this->_results;
  262.     }
  263.  
  264.     public function first($assoc = false){
  265.         return (!$assoc || $assoc && $this->count()>0)  ?  $this->results($assoc)[0]  :  [];
  266.     }
  267.  
  268.     public function count(){
  269.         return $this->_count;
  270.     }
  271.  
  272.     public function error(){
  273.         return $this->_error;
  274.     }
  275.  
  276.     public function errorInfo() {
  277.         return $this->_errorInfo;
  278.     }
  279.  
  280.     public function errorString() {
  281.         return 'ERROR #'.$this->_errorInfo[0].': '.$this->_errorInfo[2];
  282.     }
  283.  
  284.     public function lastId(){
  285.         return $this->_lastId;
  286.     }
  287.    
  288.     public function getQueryCount(){
  289.         return $this->_queryCount;
  290.     }  
  291.    
  292.     private function get_subquery_sql($action, $table, $where, &$values, &$is_ok) {
  293.         if (is_array($where))
  294.             if ($where_text = $this->_calcWhere($where, $values, "and", $is_ok))
  295.                 $where_text = " WHERE $where_text";
  296.            
  297.         return " (SELECT $action FROM $table$where_text)";
  298.     }
  299.  
  300.     public function cell($tablecolumn, $id=[]) {   
  301.         $input = explode(".", $tablecolumn, 2);
  302.        
  303.         if (count($input) != 2)
  304.             return null;
  305.  
  306.         $result = $this->action("SELECT {$input[1]}", $input[0], (is_numeric($id) ? ["id","=",$id] : $id));
  307.  
  308.         return ($result && $this->_count>0)  ?  $this->_resultsArray[0][$input[1]]  :  null;
  309.     }
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement