<?php
	
/**
 * class db is used for establishing connection to the database
 * 
 * 
 * @copyright solve-x 2015
 * @author Bostjan Kodric <bostjan.kodric@solve-x.net>
 * 
 */

	class db
	{
	
		var $ErrorCode;
		public $SQLconnect;
		private $logging;
		private $DataBaseEngine;
		private $inTransaction = 0;
		private $SQLPrepare;
		public $logFile = "/var/www/warpit/_log/class.db.log";
	
		/**
		 * function establishes connection to mysql database
		 * 
		 *
		 * @return MySQL connection identifier
		 */
		
		function __construct($DatabaseEngine = "mysql")
		{
			$this->DataBaseEngine = $DatabaseEngine;
		}
	
		function ChangeDatabase($database) { 
			mysqli_select_db($database,$this->SQLconnect);
		}

		/**
		 * database Initialization
		 *
		 * @param string $username
		 * @param string $password
		 * @param string $server
		 * @param string $setname
		 */
		function SetDatabaseConnection($username = "", $password = "", $server = "localhost",$setname = "utf8") 
		{ 
			
			switch ($this->DataBaseEngine) {
				case "mysql" : 
					$this->SQLconnect = mysqli_connect($server,$username,$password);
					mysqli_query("SET NAMES '".$setname."'");
					break;
				default :
					$this->SQLconnect = mysqli_connect($server,$username,$password);
					mysqli_query("SET NAMES '".$setname."'");
					break;

			}
		}
			
		/**
		 * function resets error code array
		 *
		 */
		function resetErrorCode() { unset($this->ErrorCode); }
	
		
		/**
		 * runs sql and returns query result object. 
		 * Same functionality as $result = mysql_query in MySql
		 *
		 * @param string $sql
		 * @return query object result
		 */
		
		function SQLexecute($sql)
		{
			//echo $sql."<-<hr>";
			$this->resetErrorCode();
			$this->ErrorCode['code'] = 0;
			$this->LogWrite($sql,true,"DB class (SQLexecute)");
			
			if ($result = mysqli_query($sql,$this->SQLconnect)) 
				return $result;
			else 
			{
					$this->ErrorCode['code'] = mysqli_errno();
					$this->ErrorCode['text'] = mysqli_error();
					$this->ErrorCode['json'] = "{success:false,error:'". addslashes( $this->ErrorCode['text'])."',sql:'".addslashes( $sql)."' }";
					//just in case
					if($this->inTransaction)
						$this->SQLcommit();
					mysqli_query("UNLOCK TABLES",$this->SQLconnect);
					throw new Exception("Error:".$this->GetError().",SQL: $sql");
					
					return 0;
			} 
		}
		
		
		/**
		 * Gets the table, row or column value!
		 *
		 * @param unknown_type $table 
		 * @param unknown_type $row - if specified returns only one row...can be number for int or where statement
		 * @param unknown_type $column - if specified returns value of this column, otherwise row as assoc array!
		 * @param unknown_type $database
		 */
		public function get($table,$row=null,$column=null,$database=null)
		{
			if($database)
				$this->ChangeDatabase($database);

			$sel = $column ? $column : '*';
			if(strpos($sel,',')==0 && trim($sel) != '*' )
			//if column does not contains commas and is not select all
				$oneColumn = true;
			else 
				$oneColumn = false;
			$byId = is_numeric($row);
			$sql = "SELECT $sel FROM $table";
			if($row)
			{
				if(is_numeric($row))
					$sql.= " WHERE id = $row";
				else
					$sql .= " WHERE $row";
			}
			$this->LogWrite($sql,true,"DB class (get)");
			
			$res = $this->SQLexecute($sql);
			if($oneColumn)
				while ($r = $this->fetchAssoc($res))
				{
					$ans[] = $r[$sel];
				}
			else
				while ($r = $this->fetchAssoc($res))
				{
					$ans[] = $r;
				}
			//if only one column is sought and one row is fetched we return the value
			if($byId)
				return $ans[0];
				
			return $ans;
			
		}


		/**
		 * Begins a transactions
		 *
		 */
		function SQLbegin()
		{
			mysqli_query("START TRANSACTION", $this->SQLconnect);
			$this->inTransaction = 1;
			return mysqli_query('BEGIN',$this->SQLconnect);
			
		}
		
		
		/**
		 * Commits a transactions
		 *
		 */
		function SQLcommit()
		{
			$this->inTransaction = 0;
			return mysqli_query('COMMIT',$this->SQLconnect);
			
		}
		
		
		/**
		 * Rolls back a transactions
		 *
		 */
		function SQLrollback()
		{
			return mysqli_query('ROLLBACK',$this->SQLconnect);
			
		}
		
		
		function IsError() 
		{
			return $this->ErrorCode['code']; 
		} 
		
		
		function GetError() 
		{
			return $this->ErrorCode['text']; 
		}
		
		
		function JsonError()
		{
			return $this->ErrorCode['json']; 
		}
		
		
		/**
		 * Function works as $record = mysql_fetch_assoc($result)
		 *
		 * @param database object $result
		 * @return actual record set
		 */
		function fetchAssoc(&$result) 
		{
			return mysqli_fetch_assoc($result); 
		}
		
					
		/**
		 * Function works as $record = mysql_fetch_array($result)
		 *
		 * @param database object $result
		 * @return actual record set
		 */
		function fetchArray(&$result) 
		{
			return mysqli_fetch_array($result); 
		}
		
		
		/**
		 * Function works as $record = mysql_fetch_row($result)
		 *
		 * @param database object $result
		 * @return actual record set
		 */
		function fetchRow(&$result) 
		{
			return mysqli_fetch_row($result); 
		}
		
		
		function affectedRows() 
		{
			return mysqli_affected_rows($this->SQLconnect); 
		}
		
		
		/**
		 * Function reeturns last inserted id in database
		 *
		 * @return id of last inserted id
		 */
		function GetLastInsertId() {
			$sql = "SELECT LAST_INSERT_ID();";
			$result = $this->SQLexecute($sql);
			$zadetek = mysqli_fetch_array($result);
			return $zadetek[0];	
		}
		
		
		/**
		 *  Function returns number on rows in result
		 * 
		 * @param query object $result
		 * @return integer number of records in result
		 */
		function NumRows($result) 
		{
			return mysqli_num_rows($result); 
		}
		
		
		/**
		 *  Function returns number of fields in result
		 * 
		 * @param query object $result
		 * @return integer number of fields in result
		 */
		function NumFields($result) 
		{
			return mysqli_field_count($result); 
		}
		
		
		/**
		 *  Function returns name of field in result
		 *  Borut: to support mysql property, I return only name of the field,
		 *  mysqli_fetch_field_direct function can return also
		 * 	$finfo->name,
		 * 	$finfo->table
		 * 	$finfo->max_length
		 * 	$finfo->flags
		 * 	$finfo->type
		 *  object of all available data is supported in function FieldProperty
		 * 
		 * @param query object $result
		 * @param index of field
		 * @return string name of the field
		 */
		function FieldName($result,$index) {
			 $field_prop = mysqli_fetch_field_direct($result, $index);
			 
			 return $field_prop->name; 
		}
		
		
		/**
		 * We get 5 properties about the filed we fetch inside the query
		 *
		 * @param query object $result
		 * @param index of field
		 * @return object about mysql field
		 */
		function FieldProperty()
		{
			return mysqli_fetch_field_direct($result, $index);
		}
		
		
		/**
		 *  Function returns field type in result
		 *  Borut: to support mysql property, I return only type of the field,
		 *  mysqli_fetch_field_direct function can return also
		 * 	$finfo->name,
		 * 	$finfo->table
		 * 	$finfo->max_length
		 * 	$finfo->flags
		 * 	$finfo->type
		 *  object of all available data is supported in function FieldProperty
		 * 
		 * @param query object $result
		 * @param index of field
		 * @return integer type of the field
		 */
		function FieldType($result,$index) 
		{
			 $field_prop = mysqli_fetch_field_direct($result, $index);
			 
			 return $field_prop->type; 
		}
		
		
		/**
		 *  Function returns name of fields in a table
		 * 	Optionly a filter can be sot to get e.g. only numeric fields!
		 * 
		 * @param query object $result
		 * @param index of field
		 * @return array of fields
		 */
		function GetFields($tableName,$params=null) { 
			if(is_array($params))
			{
				$filters = $params;
			}
			if(is_string($params))
			{
				$filters[] = $params;
			}
			$fields = array();
			$res = $this->SQLexecute("DESCRIBE $tableName");
			while ($row = $this->fetchAssoc($res))
			{ 
				if(is_array($filters))
				{	
					$type = $row['Type'];
					foreach ($filters as $filter)
						switch ($filter) {
							case 'int':
									if(strtoupper(substr($type,0,3)) == 'INT' || strtoupper(substr($type,0,7)) == 'TINYINT' || strtoupper(substr($type,0,8)) == 'SMALLINT' || strtoupper(substr($type,0,9)) == 'MEDIUMINT' || strtoupper(substr($type,0,6)) == 'BIGINT')
									{	$fields[] = $row['Field']; }
							break;
							
							default:
								;
							break;
						}
					
				}
				else
				{
					$fields[] = $row['Field'];
				}
			}
			return $fields;
		}
		
		function RenameTable($oldName,$newName){
			if(!$this->TableExists($oldName)) return true;
			
			$sql = "RENAME TABLE $oldName TO $newName";
			$this->SQLexecute($sql);
			if($this->IsError())
				return false;
			return true;
		}
		public function DropTable($tableName)
		{
			$sql = "DROP TABLE IF EXISTS $tableName";
			$this->SQLexecute($sql);
			
		}
		function getAutoIncVal($table)
		{
			$sql = "SHOW TABLE STATUS LIKE '$table'";
			$result = $this->SQLexecute($sql);
			$zadetek = mysqli_fetch_array($result);
			return $zadetek['Auto_increment'];	
			
		}
		function describe($tableName,$database = null)
		{
			if($database)
				$this->ChangeDatabase($database);
			$res = $this->SQLexecute("DESCRIBE $tableName");
			while ($row = $this->fetchAssoc($res))
			{
				$name = $row['Field'];
				$data['field'] = $name;
				$data['type'] = $row['Type'];
				$data['default'] = $row['default'];
				$arr[$name] = $data;
			}
			return $arr;
		}
		function TableExists($tableName,$database = null)
		{
			if($database)
				$this->ChangeDatabase($database);
			$sql = "SHOW TABLES LIKE '$tableName'";
			$rs = $this->SQLexecute($sql);
			if($this->fetchRow($rs))
				return true;
			return false;
		}
		
		function setLogging($aParam) { $this->logging = $aParam;} 
		
		//setArray returns results in Array
		function getArray($sql){
			 $temp = array();
			
			 $temp_res = $this->SQLexecute($sql);
			 
			 while ($t = $this->fetchArray($temp_res)) {
			 	array_push($temp, $t);
			 }
			 return $temp;
		}


		
		/**
		 * set the time zone and return the date
		 *
		 * @return date in the "H:i:s:u [j.n.Y]" format
		 */
		protected function GetTime() {
			return date("H:i:s:u [j.n.Y]");
		}

		/**
		 * Write debug info to a log file
		 *
		 * @param string $strLog
		 */
		public function LogWrite($strLog,$execute=null,$title=null) {
			if (!$execute) return true;
			//return true;
			
			if ($title) $title = " - ".$title;
			$strLog = $this->GetTime().$title." - ".$strLog."\r\n";
			$str = (isset($_SESSION['id_user'])) ? $_SESSION['id_user'] : 'admin'; 
			if (file_put_contents("/tmp/warpit_db_log_".$str.".txt", $strLog, FILE_APPEND | LOCK_EX)) {
				return true;
			} else {
				return false;
			}
		}
	

		
	}
?>
