Advertisement
Guest User

Untitled

a guest
May 12th, 2016
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.73 KB | None | 0 0
  1. <?php
  2. /**
  3. * TSH Ltd
  4. *
  5. * @package    TSH_Db
  6. */
  7.  
  8. class TSH_Db_Exception extends TSH_Exception {}
  9.  
  10.  
  11.  
  12. /**
  13. * @category   TSH
  14. * @package    TSH_Db
  15. */
  16. class TSH_Db
  17. {
  18.  
  19.     static protected $_Instance = null;
  20.    
  21.     static public function Get()
  22.     {
  23.         if (false == (static::$_Instance instanceof static))
  24.         {
  25.             if (!defined('DB_USERNAME') || !defined('DB_PASSWORD') || !defined('DB_HOST') || !defined('DB_NAME'))
  26.             {
  27.                 throw new TSH_Db_Exception('Database configuration not set');
  28.             }
  29.             static::$_Instance = new static(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
  30.         }
  31.         return static::$_Instance;
  32.     }
  33.    
  34.     protected $_host        = false;
  35.     protected $_username    = false;
  36.     protected $_password    = false;
  37.     protected $_name        = false;
  38.     protected $_mysqli      = false;
  39.     protected $_query       = null;
  40.     protected $_numRows     = false;
  41.     protected $_numThisPage = false;
  42.     protected $_insertId    = false;
  43.     protected $_affectRows  = false;
  44.     protected $_error       = 0;
  45.  
  46.     protected function __construct($host, $username, $password, $name)
  47.     {
  48.         $this->_host     = $host;
  49.         $this->_username = $username;
  50.         $this->_password = $password;
  51.         $this->_name     = $name;
  52.     }
  53.    
  54.     protected function __clone()
  55.     {}
  56.  
  57.     /**
  58.     * Open the database connection using parameters from $this->Config
  59.     * Returns false if mysql returns an error
  60.     *
  61.     * @access       protected
  62.     * @return       bool
  63.     *
  64.     */
  65.     protected function connect()
  66.     {
  67.         $this->init();
  68.        
  69.         if (1049 == $this->_mysqli->errno)
  70.         {          
  71.             // initialise the mysqli object
  72.             $this->_mysqli = mysqli_init();
  73.  
  74.             // open connection
  75.             $this->_mysqli->real_connect(   $this->_host,
  76.                                             $this->_username,
  77.                                             $this->_password);
  78.                                            
  79.             $this->_mysqli->query('CREATE DATABASE IF NOT EXISTS ' . $this->_name);
  80.             $this->_mysqli->close();
  81.             $this->init();
  82.         }
  83.        
  84.         if ($this->_mysqli->errno > 0)
  85.         {          
  86.             throw new TSH_Db_Exception('MySQL Connect Failed (' . $this->_mysqli->errno . '): ' . $this->_mysqli->error, $this->_mysqli->errno);
  87.         }
  88.  
  89.        
  90.         $this->_mysqli->set_charset('utf8');
  91.  
  92.     }
  93.  
  94.     public function disconnect()
  95.     {
  96.         if (!$this->isConnected())
  97.         {
  98.             return true;
  99.         }
  100.  
  101.         $result = $this->_mysqli->close();
  102.         $this->_mysqli = false;
  103.     }
  104.  
  105.     /**
  106.     * tries to establish the db connection
  107.     *
  108.     * @access       protected
  109.     *
  110.     */
  111.     protected function init()
  112.     {
  113.         // initialise the mysqli object
  114.         $this->_mysqli = mysqli_init();
  115.  
  116.         // open connection
  117.         $this->_mysqli->real_connect(   $this->_host,
  118.                                         $this->_username,
  119.                                         $this->_password,
  120.                                         $this->_name );
  121.                                        
  122.         // check for major error
  123.         if (false === is_object($this->_mysqli))
  124.         {
  125.             throw new TSH_Db_Exception('MySQL Connect Failed');
  126.         }
  127.     }
  128.  
  129.     /**
  130.     * takes a string and mysql escapes it
  131.     *
  132.     * @access       public
  133.     * @param       string       $value
  134.     * @return       string
  135.     *
  136.     */
  137.     public function escape($value)
  138.     {
  139.         if (false == $this->isConnected())
  140.         {
  141.             $this->connect();
  142.         }
  143.  
  144.         return $this->_mysqli->real_escape_string($value);
  145.     }
  146.  
  147.  
  148.     /**
  149.     * takes a string and mysql escapes it and adds quotes unless it looks like an sql function or os numeric
  150.     *
  151.     * @access       public
  152.     * @param       string       $value
  153.     * @return       string
  154.     *
  155.     */
  156.     public function escapeValue($value)
  157.     {
  158.  
  159.         if (is_numeric($value))
  160.         {
  161.             // Added quotes around number to stop numbers in
  162.             // text fields being inserted as INT
  163.             $value = '\'' . $this->escape($value) . '\'';
  164.         }
  165.         elseif(is_bool($value))
  166.         {
  167.             $value = 0;
  168.             if ($value) $value = 1;
  169.         }
  170.         elseif(is_null($value))
  171.         {
  172.             $value = 'NULL';
  173.         }
  174.         elseif(is_string($value))
  175.         {
  176.             // @todo add code to avoid sql functions such as NOW()
  177.             $value = "'" . $this->escape($value) . "'";
  178.         }
  179.         elseif(is_array($value))
  180.         {
  181.             $newvalue   = array();
  182.             foreach ($value as $subvalue)
  183.             {
  184.                 $newvalue[]   = $this->escapeValue($subvalue);
  185.             }
  186.             $value  = implode(',', $newvalue);
  187.         }
  188.         else
  189.         {
  190.             $value = "''";
  191.         }
  192.  
  193.         return $value;
  194.  
  195.     }
  196.  
  197.     /**
  198.     * takes a string and escapes variables into it from an indexed array
  199.     *
  200.     * @access       public
  201.     * @param       string       $sql
  202.     * @param       array       $params
  203.     * @return       string
  204.     *
  205.     */
  206.     public function escapeInto($sql, $params)
  207.     {
  208.         if (!is_array($params)) return $sql;
  209.  
  210.         $keys = array();
  211.         $values = array();
  212.  
  213.         foreach ($params as $key => $value)
  214.         {
  215.             $keys[] = ':' . $key;
  216.             $values[] = $this->escapeValue($value);
  217.         }
  218.  
  219.         return str_replace($keys, $values, $sql);
  220.     }
  221.  
  222.     /**
  223.     * Check the database connection was made succesfully
  224.     *
  225.     * @access       public
  226.     * @return       bool
  227.     *
  228.     */
  229.     public function isConnected()
  230.     {
  231.         if (is_object($this->_mysqli))
  232.         {
  233.             return $this->_mysqli->ping();
  234.         }
  235.         else
  236.         {
  237.             return false;
  238.         }
  239.     }
  240.  
  241.  
  242.     /**
  243.     * Run a select query on the database
  244.     * Returns false if mysql returns an error
  245.     *
  246.     * @access       public
  247.     * @param        string      $query
  248.     * @return       array|boolean
  249.     *
  250.     */
  251.     public function select($sql, $params = false)
  252.     {
  253.         $output = false;
  254.  
  255.         $this->_queryType = 'select';
  256.  
  257.         $this->_query = $this->escapeInto($sql, $params);
  258.  
  259.         $this->startQuery();
  260.  
  261.         $this->_mysqli->real_query($this->_query);
  262.         $result = $this->_mysqli->use_result();
  263.  
  264.         if ($result)
  265.         {
  266.             $rows = array();
  267.             while($row = $result->fetch_assoc())
  268.             {
  269.                 $rows[] = $row;
  270.             }
  271.             $result->free();
  272.            
  273.             $output = $rows;
  274.             $this->_numRows = count($output);
  275.         }
  276.  
  277.         $this->endQuery();
  278.  
  279.         return $output;
  280.     }
  281.    
  282.    
  283.     /**
  284.     * Run a select query on the database
  285.     * Returns false if mysql returns an error
  286.     *
  287.     * @access       public
  288.     * @param        string      $query
  289.     * @return       mixed
  290.     *
  291.     */
  292.     public function selectPage($page, $sql, $params = false, $numPerPage = 20)
  293.     {
  294.  
  295.         $output = false;
  296.        
  297.         if (!is_numeric($page) || $page < 1)
  298.         {
  299.             $page = 1;
  300.         }
  301.        
  302.         if (false === stripos($sql, 'SQL_CALC_FOUND_ROWS'))
  303.         {
  304.             //check for select
  305.             $selectPosition = stripos($sql, 'SELECT');
  306.  
  307.             // check if we have select and remove
  308.             if (false !== $selectPosition)
  309.             {
  310.                 $sql = substr($sql, $selectPosition + 6);
  311.             }
  312.  
  313.             // add the select to the front of the query
  314.             $sql = 'SELECT SQL_CALC_FOUND_ROWS' . $sql;
  315.         }
  316.        
  317.         // add the limit to the end of the query
  318.         $sql .= ' LIMIT ' . (($page - 1) * $numPerPage) . ', ' . $numPerPage;
  319.  
  320.         $this->_queryType = 'select';
  321.  
  322.         $this->_query = $this->escapeInto($sql, $params);
  323.  
  324.         $this->startQuery();
  325.  
  326.         $this->_mysqli->real_query($this->_query);
  327.         $result = $this->_mysqli->use_result();
  328.  
  329.         if ($result)
  330.         {
  331.             $rows = array();
  332.             while($row = $result->fetch_assoc())
  333.             {
  334.                 $rows[] = $row;
  335.             }
  336.             $result->free();
  337.            
  338.             // get the total number o rows
  339.             $this->_mysqli->real_query('SELECT FOUND_ROWS() AS total');
  340.             $rowResult = $this->_mysqli->use_result();
  341.             $row = $rowResult->fetch_assoc();
  342.             $this->_numRows = $row['total'];
  343.             $rowResult->free();
  344.                
  345.             $output = $rows;
  346.             $this->_numThisPage = count($output);
  347.         }
  348.  
  349.         $this->endQuery();
  350.  
  351.         return $output;
  352.  
  353.     }
  354.  
  355.     /**
  356.     * Run a select query on the database and return first result as and associative array
  357.     *
  358.     * @access       public
  359.     * @param        string      $query
  360.     * @return       mixed
  361.     *
  362.     */
  363.     public function selectFirst($sql, $params = false)
  364.     {
  365.         $output = false;
  366.  
  367.         $this->_queryType = 'select';
  368.  
  369.         $this->_query = $this->escapeInto($sql, $params);
  370.  
  371.         $this->startQuery();
  372.  
  373.         $this->_mysqli->real_query($this->_query);
  374.         $result = $this->_mysqli->use_result();
  375.  
  376.         if ($result)
  377.         {
  378.             $output = $result->fetch_assoc();
  379.             $result->free();
  380.             if ($output)
  381.             {
  382.                 $this->_numRows = 1;
  383.             }
  384.         }
  385.  
  386.         $this->endQuery();
  387.  
  388.         return $output;
  389.     }
  390.  
  391.     /**
  392.     * takes a table name and an associative array and inserts an array of key value pairs
  393.     * from the record array into the table of the given name in the database.
  394.     * The ignore parameter uses insert ignore rather than straight insert.
  395.     *
  396.     * @access       public
  397.     * @param        string      $table
  398.     * @param       array       $records
  399.     * @param       bool        $ignore
  400.     * @return       mixed
  401.     *
  402.     */
  403.     public function insert($table, $records, $ignore = false)
  404.     {
  405.         return $this->_insertOrReplace($table, $records, $ignore);
  406.     }
  407.  
  408.     public function replace($table, $records, $ignore = false)
  409.     {
  410.         return $this->_insertOrReplace($table, $records, $ignore, true);
  411.     }
  412.  
  413.     /**
  414.     * takes a table name and an associative array and inserts an array of key value pairs
  415.     * from the record array into the table of the given name in the database.
  416.     * The ignore parameter uses insert ignore rather than straight insert.
  417.     *
  418.     * @access       protected
  419.     * @param        string      $table
  420.     * @param        array       $records
  421.     * @param        bool        $ignore
  422.     * @param        bool        $replace    Execute an INSERT or a REPLACE statement
  423.     * @return       mixed
  424.     *
  425.     */
  426.     protected function _insertOrReplace($table, $records, $ignore = false, $replace = false)
  427.     {
  428.  
  429.         $this->_queryType = 'insert_multiple';
  430.         if ($replace)
  431.         {
  432.             $this->_queryType = 'replace_multiple';
  433.         }
  434.  
  435.         // handle ignore sql
  436.         $ignoreSql = '';
  437.         if ($ignore && !$replace) $ignoreSql = 'IGNORE';
  438.  
  439.         // escape table name
  440.         $table = $this->escape($table);
  441.  
  442.  
  443.         // check for single record and correct array
  444.         if (!isset($records[0]))
  445.         {
  446.             $record = $records;
  447.             $records = array();
  448.             $records[0] = $record;
  449.             $this->_queryType = ($replace) ? 'replace' : 'insert';
  450.         }
  451.  
  452.         //get field names
  453.         $fields = array_keys($records[0]);
  454.  
  455.  
  456.         // get field sql
  457.         $first = true;
  458.         $fieldSql = '(';
  459.  
  460.         foreach ($fields as $field)
  461.         {
  462.             if(!$first) $fieldSql .= ', ';
  463.  
  464.             $fieldSql .= '`' . $this->escape($field) . '`';
  465.  
  466.             $first = false;
  467.         }
  468.  
  469.         $fieldSql .= ')';
  470.  
  471.  
  472.         // get value sql
  473.  
  474.         $valueSql = '';
  475.         $firstRow = true;
  476.  
  477.         foreach ($records as $record)
  478.         {
  479.             if(!$firstRow) $valueSql .= ",\n";
  480.  
  481.             $valueSql .= '(';
  482.             $first = true;
  483.  
  484.             foreach ($fields as $field)
  485.             {
  486.                 if(!$first) $valueSql .= ', ';
  487.  
  488.                 $valueSql .= $this->escapeValue($record[$field]);
  489.  
  490.                 $first = false;
  491.             }
  492.  
  493.             $valueSql .= ')';
  494.  
  495.             $firstRow = false;  
  496.         }
  497.  
  498.         // col names come from the array keys
  499.         $cols = array_keys($record);
  500.  
  501.         // build the statement
  502.         $verb           = ($replace) ? 'REPLACE' : 'INSERT' ;
  503.         $this->_query   = "$verb $ignoreSql INTO `$table` $fieldSql \nVALUES $valueSql";
  504.         $this->startQuery();
  505.         $result = $this->_mysqli->real_query($this->_query);
  506.         $this->_insertId = $this->_mysqli->insert_id;
  507.         $this->endQuery();
  508.  
  509.         if ($this->_insertId > 0)
  510.         {
  511.             return $this->_insertId;
  512.         }
  513.         else
  514.         {
  515.             if ($ignore)
  516.             {
  517.                 return $result;
  518.             }
  519.             else
  520.             {
  521.                 return false;
  522.             }
  523.         }
  524.     }
  525.  
  526.  
  527.     /**
  528.     * returns last insert id
  529.     *
  530.     * @access       public
  531.     * @return       mixed
  532.     *
  533.     */
  534.     public function getInsertId()
  535.     {
  536.  
  537.         if (is_numeric($this->_insertId) && $this->_insertId > 0)
  538.         {
  539.             return $this->_insertId;
  540.         }
  541.         else
  542.         {
  543.             return false;
  544.         }
  545.     }
  546.  
  547.  
  548.     /**
  549.     * Get the current schema name for this connection
  550.     *
  551.     * @access public
  552.     * @return string
  553.     */
  554.     public function getSchema()
  555.     {
  556.         return $this->_name;
  557.     }
  558.  
  559.  
  560.     /**
  561.     * update the records in the table to have the values from the associative
  562.     * record array using the condition from the where parameter with substitution of the parameters from the params array
  563.     *
  564.     * @access       public
  565.     * @param        string      $table
  566.     * @param       array       $record
  567.     * @param       string      $where
  568.     * @param       array       $params
  569.     * @return       mixed
  570.     *
  571.     */
  572.     public function update($table, $record, $where, $params = array())
  573.     {
  574.         $this->_queryType = 'update';
  575.  
  576.         // escape table name
  577.         $table = $this->escape($table);
  578.  
  579.         // build the statement
  580.         $this->_query = "UPDATE `$table` SET  " . $this->recordToSql($record) . ' WHERE ' . $this->escapeInto($where, $params);
  581.  
  582.         $this->startQuery();
  583.         $result = $this->_mysqli->real_query($this->_query);
  584.         $this->endQuery();
  585.  
  586.         return $result;
  587.     }
  588.  
  589.     /**
  590.     * delete records mathing the where clause from the table
  591.     *
  592.     * @access       public
  593.     * @param        string      $table
  594.     * @param       string      $where
  595.     * @param       array       $params
  596.     * @return       mixed
  597.     *
  598.     */
  599.     public function delete($table, $where, $params = array())
  600.     {
  601.         $this->_queryType = 'delete';
  602.  
  603.         // escape table name
  604.         $table = $this->escape($table);
  605.  
  606.         // build the statement
  607.         $this->_query = "DELETE FROM `$table` WHERE " . $this->escapeInto($where, $params);
  608.  
  609.         $this->startQuery();
  610.         $result = $this->_mysqli->real_query($this->_query);
  611.         $this->endQuery();
  612.  
  613.         return $result;
  614.     }
  615.  
  616.     public function query($sql)
  617.     {
  618.         $this->startQuery();
  619.         $this->_query = $sql;
  620.         $result = $this->_mysqli->query($this->_query);
  621.         $this->endQuery();
  622.         return $result;
  623.     }
  624.  
  625.     /**
  626.     * takes a record as an associative array and returns a string for an insert or
  627.     * update statement.
  628.     *
  629.     * @access       public
  630.     * @param       array       $Record
  631.     * @return       mixed
  632.     *
  633.     */
  634.     public function recordToSql($record)
  635.     {
  636.         // get field sql
  637.         $first = true;
  638.         $sql = '';
  639.  
  640.         foreach ($record as $field => $value)
  641.         {
  642.             if(!$first) $sql .= ', ';
  643.  
  644.             $sql .= '`' . $this->escape($field) . '` = ' . $this->escapeValue($value);
  645.  
  646.             $first = false;
  647.         }
  648.  
  649.         return $sql;
  650.     }
  651.  
  652.     /**
  653.     * takes a string and mysql escapes it
  654.     *
  655.     * @access       public
  656.     * @return       int
  657.     *
  658.     */
  659.     public function affectedRows()
  660.     {
  661.         return $this->_affectedRows;
  662.     }
  663.    
  664.     public function numRows()
  665.     {
  666.         return $this->_numRows;
  667.     }
  668.  
  669.     public function error()
  670.     {
  671.         return $this->_error;
  672.     }
  673.  
  674.     /**
  675.     * run everytime we start a new query, starts the timer and sets the query type
  676.     *
  677.     * @access          public
  678.     * @param  string  $QueryType
  679.     *
  680.     */
  681.     public function startQuery()
  682.     {
  683.         if (false == $this->isConnected())
  684.         {
  685.             $this->connect();
  686.         }
  687.  
  688.         // set the query running variable
  689.         $this->_queryRunning = true;
  690.  
  691.         // set the query type
  692.         if (false === $this->_queryType)
  693.         {
  694.             $this->_queryType = 'run';
  695.         }
  696.  
  697.         // reset number of rows
  698.         $this->_numRows = 0;
  699.  
  700.         // reset number of rows this page
  701.         $this->_numThisPage = 0;
  702.  
  703.         // reset insert id
  704.         $this->_insertId = 0;
  705.  
  706.         //reset affected rows
  707.         $this->_affectedRows = 0;
  708.  
  709.         //reset error
  710.         $this->_error = 0;
  711.     }
  712.  
  713.     /**
  714.     * run at the end of every query
  715.     *
  716.     * @access       public
  717.     *
  718.     */
  719.     public function endQuery()
  720.     {
  721.         // set the query running variable
  722.         $this->_queryRunning = false;
  723.  
  724.         // init the Error and debug vars
  725.         $error = false;
  726.  
  727.         // Clear out last query
  728.         $this->_query = null;
  729.  
  730.         // get affected rows
  731.         $this->_affectedRows = $this->_mysqli->affected_rows;
  732.     }
  733.  
  734. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement