<?php
/**
 * Data access support
 *
 * granst common operations on DB via PDO
 *
 * @author ba - Advantis Solutions
 * @version 1.0.1
 * @package Base
 */
class DataAccess {
	private $configkey = "DEFAULT";
	private $handle;
	const TYPE_INTEGER = 'integer';
	const TYPE_TEXT = 'text';
	const TYPE_DATE = 'date';
	
	/**
	 * constructor
	 *
	 * @param string $configkey        	
	 */
	function DataAccess($configkey = null) {
		if ($configkey)
			$this->configkey = $configkey;
	}
	
	/**
	 * connect
	 */
	function connect() {
		$configDB = new ConfigDB ();
		
		$configkey = $this->configkey;
		
		$this->host = $configDB->connections [$configkey] ["DBHOST"];
		if (isset ( $configDB->connections [$configkey] ["PORT"] )) {
			$this->port = $configDB->connections [$configkey] ["PORT"];
		}
		$this->dbname = $configDB->connections [$configkey] ["DBNAME"];
		$this->user = $configDB->connections [$configkey] ["DBUSER"];
		$this->pass = $configDB->connections [$configkey] ["DBPASS"];
		$this->schema = $configDB->connections [$configkey] ["DBSCHEMA"];
		
		if (Transaction::getHandle () != null && Transaction::isOn ()) {
			
			// echo "<br>->getting.handle<br>";
			
			$this->handle = Transaction::getHandle ();
			// echo "<pre>";
			// print_r($this->handle);
			// echo "</pre>";
			
			return;
		} else {
			
			$handle = null;
			
			$connectstr = "pgsql:dbname=" . $this->dbname . ";host=" . $this->host;
			
			if (isset ( $this->port )) {
				$connectstr .= ";port=" . $this->port;
			}
			
			try {
				$handle = new PDO ( $connectstr, $this->user, $this->pass );
				$handle->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
			} catch ( PDOException $e ) {
				error_log ( "MoSy error (DA->connect) : " . $e->getMessage (), 0 );
			}
			
			if (Transaction::isOn ()) {
				
				Transaction::set_handle ( $handle );
				$handle->beginTransaction ();
				// echo "<br>->creating transaction handle<br>";
			} else {
				// echo "<br>->creating NON transaction handle<br>";
			}
			
			$this->handle = $handle;
		}
	}
	
	/**
	 * create entry
	 *
	 * @param unknown $args        	
	 * @return unknown
	 */
	function create($args) {
		if (! $this->handle) {
			// echo "<br>->lets get handle...<br>";
			$this->connect ();
		}
		
		// echo "<br>->inserting<br>";
		
		$fields = array ();
		$values = array ();
		
		foreach ( $args ['obj'] as $key => $value ) {
			if (! in_array ( $key, $this->excluded_fields () )) {
				array_push ( $fields, $key );
				if ($value === false)
					$value = "false";
				
				if ($value!==null)  
					$value = html_entity_decode($value);
				
				array_push ( $values, $value );
			}
		}
		
		$fieldlist = implode ( ',', $fields );
		$qs = str_repeat ( "	?,", count ( $fields ) - 1 );
		$sql = "INSERT INTO " . $this->schema . "." . $args ['entity'] . " ($fieldlist) VALUES(${qs}?)";
		
		// //echo $sql;
		// print_r($values);
		
		try {
			$sth = $this->handle->prepare ( $sql );
			$sth->execute ( $values );
			$newid = $this->handle->lastInsertId ( $this->schema . "." . $args ['entity'] . '_id_seq' );
			$this->handle = null;
			// //echo "newid:".$newid;
			return $newid;
		} catch ( PDOException $e ) {
			error_log ( "MoSy error (DA->create) : " . $e->getMessage (), 0 );
		}
		
		$this->end ();
	}
	
	/**
	 * update entry
	 *
	 * @param unknown $args        	
	 */
	function update($args) {
		if (! $this->handle) {
			
			$this->connect ();
		}
		
		$fields = array ();
		$values = array ();
		
		foreach ( $args ['obj'] as $key => $value ) {
			
			if (! in_array ( $key, $this->excluded_fields () )) {
				array_push ( $fields, $key );
				if ($value === false)
					$value = "false";
				
				if ($value!==null)
					$value = html_entity_decode($value);
				
				array_push ( $values, $value );
			}
		}
		
		$setliststr = '';
		
		if (count ( $fields ) == 1) {
			$setliststr = $fields [0] . "=?";
		} else {
			$setliststr = implode ( "=?,", $fields );
			$setliststr .= "=?";
		}
		
		$sql = "UPDATE " . $this->schema . "." . $args ['entity'] . " SET " . $setliststr . " WHERE id=?";
		
		debug ( $sql );
		
		try {
			$sth = $this->handle->prepare ( $sql );
			
			array_push ( $values, $args ['obj']->id );
			
			$sth->execute ( $values );
		} catch ( PDOException $e ) {
			error_log ( "MoSy error (DA->update) : " . $e->getMessage (), 0 );
		}
		
		
		$this->handle = null;
	}
	

	/**
	 * executes prepared query
	 *
	 * @param unknown $sql        	
	 * @return multitype:
	 */
	function query($sql, $args) {
		if (! $this->handle) {
			
			$this->connect ();
		}
		
		$sth = $this->handle->prepare ( $sql );
		
		if($args!=null) {
			$r = $sth->execute ($args);
		}
		else {
			$r = $sth->execute ();
		}
		
		$this->handle = null;
		
		if ($r) {
			
			$rarray = array ();
			
			while ( $r = $sth->fetch ( PDO::FETCH_ASSOC ) ) {
				if (!is_null($r))
					$this->XSSProtect($r);
				
				array_push ( $rarray, $r );
			}
			
			return $rarray;
		}
	}
	
	/**
	 * support for PDO function param definition
	 *
	 * @param unknown $type        	
	 * @param unknown $value        	
	 * @return number
	 */
	private function get_type_PDO($type, $value) {
		if ($value == null || $value = '') {
			return PDO::PARAM_NULL;
		}
		
		switch ($type) {
			case self::TYPE_INTEGER :
				return PDO::PARAM_INT;
				break;
			
			case self::TYPE_TEXT :
				return PDO::PARAM_STR;
				break;
			
			case self::TYPE_DATE :
				return PDO::PARAM_STR;
				break;
			default :
				return PDO::PARAM_NULL;
				;
				break;
		}
	}
	
	/**
	 * helper function to return params as args array
	 *
	 * @param unknown $key        	
	 * @param unknown $value        	
	 * @param unknown $type        	
	 * @param string $size        	
	 * @return multitype:unknown string
	 */
	function helper_args($key, $value, $type, $size = NULL) {
		return array (
				'key' => $key,
				'value' => $value,
				'type' => $type,
				'size' => $size 
		);
	}
	
	/**
	 * executes DB function with args array defined
	 *
	 * @param unknown $sql        	
	 * @param unknown $args        	
	 * @return multitype:
	 */
	function func_get($sql, $args) {
		if (! $this->handle) {
			
			$this->connect ();
		}
		
		try {
			
			debug ( $sql );
			
			$sth = $this->handle->prepare ( $sql );

			foreach ( $args as $arg ) {
				$sth->bindParam ( $arg ['key'], $arg ['value'], $this->get_type_PDO ( $arg ['type'], $arg ['value'] ) );
			}

			$sth->execute ();
			
			$rarray = array ();
			
			while ( $r = $sth->fetch ( PDO::FETCH_OBJ ) ) {
				
				if (!is_null($r))
					$this->XSSProtect($r);
				
				array_push ( $rarray, $r );
			}

		} catch ( PDOException $e ) {
			error_log ( "MoSy error (DA->func_get) : " . $e->getMessage (), 0 );
		}
		
		$this->handle = null;
		
		return $rarray;
	}
	
	/**
	 * query all columns on args entity
	 *
	 * @param unknown $args        	
	 * @return multitype:
	 */
	function query_get($args) {
		if (! $this->handle) {
			
			$this->connect ();
		}
		
		$sql = 'SELECT * FROM ' . $this->schema . '.' . $args ['entity'];
		
		if ($args ['filter']) {
			
			$sql .= ' WHERE ' . $args ['filter'];
		}
		
		try {
			
			debug ( $sql );
			
			$sth = $this->handle->prepare ( $sql );
			
			$sth->execute ( $args ['values'] );
			
			$rarray = array ();
			
			while ( $r = $sth->fetch ( PDO::FETCH_ASSOC ) ) {
				
				if (!is_null($r))
					$this->XSSProtect($r);
				
				array_push ( $rarray, $r );
			}
		} catch ( PDOException $e ) {
			error_log ( "MoSy error (DA->func_get) : " . $e->getMessage (), 0 );
		}
		
		$this->handle = null;
		
		return $rarray;
	}
	
	/**
	 * excludes fields
	 *
	 * @return multitype:string
	 */
	function excluded_fields() {
		return array (
				"Entityinternal_name",
				"id",
				"internal_name" 
		);
	}
	
	/**
	 * Deletes entry from args entity and obj->id
	 *
	 * @param unknown $args        	
	 * @return boolean
	 */
	function delete($args) {
		if (! $this->handle) {
			
			$this->connect ();
		}
		
		$sql = "DELETE FROM " . $this->schema . "." . $args ['entity'] . "  WHERE id=?";
		
		try {
			$sth = $this->handle->prepare ( $sql );
			
			$res = $sth->execute ( array (
					$args ['obj']->id 
			) );
			
			if ($res === false) {
				return false;
			} else {
				return true;
			}
		} catch ( PDOException $e ) {
			error_log ( "MoSy error (DA->delete) : " . $e->getMessage (), 0 );
		}
		
		$this->handle = null;
	}
	
	/**
	 * Closes connection
	 */
	function end() {
		if (! $this->transactionmode) {
			
			$this->handle = null;
		}
	}

	private function XSSProtect(&$array){

    	array_walk_recursive($array, function (&$val) {
    		if (!is_null($val) && is_string($val))
        		$val = htmlentities($val, ENT_QUOTES);
    	});
	}
}

?>