<?php
/*
	DevSaver Web Framework
	Copyright (c) 2013-2016 DevSaver. 
	All rights reserved.
		web:  www.devsaver.com
		mail: support@devsaver.com				
*/

/**
* description
*
* @library	
* @author	
* @since	
*/
class CDatabase{

	var $charset = "utf8";
	var $queries_runtime = 0;
	
	
	
	function __construct($info = array() , $trace = true) {

		$this->trace = $trace;

		$this->DetectConnector();

		if (is_array($info) && count($info))
			$this->Connect($info);
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function DetectConnector() {
		if (class_exists("mysqli")) {

			$this->connector = "mysqli";

		} elseif (function_exists("mysql_connect")) {

			$this->connector = "mysql";

		} else {

			throw new Exception("No MySQL library was found!");

		}	

	}
	
	
	function Connect($info) {
		
		//check what database i have
		switch ($this->connector) {
			case "mysqli":
				$this->conn = new mysqli(
					$info["server"],
					$info["username"] ? $info["username"] : $info["login"],
					$info["password"],
					$info["default"] ? $info["default"] : $info["database"]
				);

				if ($this->conn->connect_errno) {
					throw new Exception($this->conn->connect_error);
				}
				
			break;

			case "mysql":
				$this->conn = @mysql_connect(
					$info["server"],
					$info["username"] ? $info["username"] : $info["login"],
					$info["password"]
				);

				if (!$this->connect_errno()) {
					mysql_select_db( $info["default"] ? $info["default"] : $info["database"] , $this->conn);
				}
				
				if ($this->connect_errno()) {
					throw new Exception($this->connect_error());
				}
				
			break;
		}

				
		//set charset
		$this->set_charset($this->charset);

		//strict mode
		$this->Query("SET @@SESSION.sql_mode = '';");
		//$this->Query("SET @@global.sql_mode= '';");
	}


	function Query($query , $vars = array()) {
		global $_ADMIN , $_SESS;

		$query = $this->statement($query , $vars);		

		if (((constant("STP_ENABLE_DEMO") == 1) && ($_ADMIN ==true)) || (($_SESS["minibase"]["raw"]["acl"] == "viewonly")&& ($_ADMIN ==true))) {

			if (stristr($query , "update") || stristr($query , "insert") || stristr($query , "delete") ) {
				throw new Exception("demo" , 1000);
				return false;
			}
			
		}
		

		$this->queries_cnt ++;

		$start = microtime(true);

		switch ($this->connector) {
			case "mysqli":
				$result = $this->conn->Query($query);
			break;

			case "mysql":
				$result = mysql_query($query , $this->conn);
			break;
		}
		
		$time = microtime(true) - $start;

		$this->queries_runtime += $time;

		global $_ADMIN;

		if (!$_ADMIN) {
			if ($time > 0.05) {
//				debug("<span style='color: red'>" . $time ."ms: ". $query . "</span>");
			} else {		
//		debug($time ."ms: ". $query);
			}

//			debug($time ."ms: ". $query);

		}

		if ($error = $this->connect_error()) {
			throw new Exception( $error . " " .$query  );
		}

		return $result;
		
	}
	
	function QFetchArray($query , $vars = array()) {

		$result = $this->Query($query , $vars);

		if (!$result) {
			return false;
		}
		

		switch ($this->connector) {
			case "mysqli":
				return $result->fetch_array(MYSQLI_ASSOC);
			break;

			case "mysql":
				return mysql_fetch_array($result , MYSQL_ASSOC);
			break;
		}


	}
	

	function QFetchRowArray($query , $vars = array()) {
		$result = $this->Query($query , $vars);

		switch ($this->connector) {
			case "mysqli":
				while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
					$data[] = $row;
				}

				$result->free();		
			break;

			case "mysql":

				while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
					$data[] = $row;
				}

				mysql_free_result($result);
			break;
		}

		return $data;
	}

	function SplitStrQueries($string) {


		$db_file = explode("\n" , $string);

		foreach ($db_file as $key => $val) {

			$val = trim($val);

			if (substr($val, -1) == ";") {

				$last .= $val;

				$queries[] = $last;				

				$last = "";

			} else {
				$last .= $val;
			}

		}

		return $queries;	
	}

	function RowCount($table,$where_clause = "",$what="") {
		$what = $what != "" ? $what : "*" ;
		$data = $this->QFetchArray("SELECT COUNT({$what}) as _counted_rows FROM $table $where_clause;");
		
		return $data["_counted_rows"];
	}

	function GetTables(){
		return $this->Linear($this->QFetchRowArray("SHOW TABLES;"));
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function TableExists($table) {
		$tables = $this->GetTables();

		return in_array($table , $tables);
	}
	function Linear($data) {
		if (is_array($data)) {
			foreach ($data as $key => $val) {
				if (is_array($val)) {
					$_tmp[] = $val[key($val)];
				} else {
					$_tmp[] = $val;
				}
			}			
		}
		
		return $_tmp;
	}

	function QueryDelete($table , $data , $cond = "") {

	}


	function QueryInsert($table , $data = array()) {

		if (!count($data)) {
			return false;
		}
		

		$fields = $this->GetTableFields($table);

		foreach ($data as $key => $val) {

			if ($fields["fields"][$key]) {

				$st_fields[] = $key;
				$st_values[] = $this->prepareValue($val , $fields["fields"][$key]);

			}
			
		}
		
		//build statement 
		$this->Query(
			"INSERT INTO {$table} 
				(`" . implode("`,`" , $st_fields) . "`)
			VALUES
				(" . implode("," , $st_values) . ")			
		");


		return  $this->insert_id();

	}

	function prepareValue($val , $field) {

		switch ($field["Type"]) {
			case "tinyint":
			case "smallint":
			case "mediumint":
			case "bigint":
			case "int":
				return intval($val); 
			break;

			case "double":
			case "double":
			case "float":
				return floatval($val);
			break;

			case "char":
			case "varchar":

			case "text":
			case "tinytext":
			case "mediumtext":
			case "longtext":

			case "blob":
			case "tinyblob":
			case "mediumblob":
			case "longblob":

				return "'" . $this->real_escape_string($val) . "'";
			break;
		}
		
	}
	

	function QueryUpdate($table , $data , $cond = "") {
		if (!count($data)) {
			return false;
		}
		

		$fields = $this->GetTableFields($table);

		foreach ($data as $key => $val) {

			if ($fields["fields"][$key]) {
				$st_fields[] = $key .'=' . $this->prepareValue($val , $fields["fields"][$key]);
			}			
		}


		if (!is_array($st_fields)) {
			return false;
		}
				
		//build statement 
		$this->Query( "UPDATE {$table} SET " . implode(" , " , $st_fields) . ( $cond ? " WHERE {$cond} " : "" ));

		return true;

	}
	
	function QueryUpdateById($table , $data , $id) {
		$fields = $this->GetTableFields($table);

		$this->QueryUpdate(
			$table ,
			$data , 
			"`" . $fields["autoincrement"] . "`="  .$id
		);

		return true;
	}

	function GetTableFields($table){

		if (is_array($this->cache["fields"][$table])) {
			return $this->cache["fields"][$table];
		}
		
		$fields = $this->QFetchRowArray("SHOW FIELDS FROM {$table}");

		foreach ($fields as $key => $val) {

			if ($val["Extra"] == "auto_increment") {
				$autoincrement = $val["Field"];
			}

			//process the type
			$tmp = explode("(" , $val["Type"]);
			$val["Type"] = trim($tmp[0]);
			$val["Size"] = trim(str_replace(")" , "" ,$tmp[1]));

			$_fields[$val["Field"]] = $val;
			
		}

		$this->cache["fields"][$table] = array(
			"fields"	=> $_fields ,
			"autoincrement"	=> $autoincrement
		);

		return $this->cache["fields"][$table];
	}

	function NumRows($result) {
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function statement($query , $params = array()) {

		if (count($params)) {
			foreach ($params as $key => $val) {
				$params[$key] = $this->real_escape_string($val);
			}

			$query = vsprintf($query , $params);
		}

		//debug($query);

		return $query;
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function real_escape_string($val) {

		switch ($this->connector) {
			case "mysqli":
				return $this->conn->real_escape_string($val);
			break;

			case "mysql":
				return mysql_real_escape_string($val , $this->conn);
			break;
		}
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function escapeString($val) {
		return $this->real_escape_string($val);
	}
	
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function set_charset($charset) {

		switch ($this->connector) {
			case "mysqli":
				$this->conn->set_charset($charset);
			break;

			case "mysql":
				mysql_set_charset($charset , $this->conn);
			break;
		}
		
	}

		
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function connect_errno() {

		switch ($this->connector) {
			case "mysqli":
				return $this->conn->connect_errno;
			break;

			case "mysql":

				if (!$this->conn) {
					return 1045;
				}
				
				return mysql_errno($this->conn);
			break;
		}


	}

		
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function insert_id() {

		switch ($this->connector) {
			case "mysqli":
				return $this->conn->insert_id;
			break;

			case "mysql":
				return  mysql_insert_id($this->conn);
			break;
		}


	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function connect_error() {


		switch ($this->connector) {
			case "mysqli":
				return $this->conn->error;
			break;

			case "mysql":
				if ($this->conn) {
					return mysql_error($this->conn);
				} else {
					return mysql_error();	
				}
			break;
		}
		
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function NumQueries() {

		return $this->queries_cnt;
	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function AffectedRows() {
		switch ($this->connector) {
			case "mysqli":
				return $this->conn->affected_rows;
			break;

			case "mysql":
				return $this->mysql_affected_rows($this->conn);
			break;
		}		
	}
	
}


?>
