<?php
class Model{
	
	static $connections = array(); 

	public $conf = 'default';
	public $table = false; 
	public $db; 
	public $primaryKey = 'id'; 
	public $id; 
	public $errors = array();
	public $form; 
	public $validate = array();

	/**
	* Permet d'initialiser les variables du Model
	**/
	public function __construct(){

		// pour debugger le déroulemnt des appels de modules
//echo "Session active est ".session_id()." - Module model(contruct) at ".microtime(true).' sec'."<br/>"; 

		// Connection à la base ou récupération de la précédente connection
		$conf = Conf::$databases[$this->conf];
		if(isset(Model::$connections[$this->conf])){
			$this->db = Model::$connections[$this->conf];
			return true; 
		}
		try{
			$pdo = new PDO(
				'mysql:host='.$conf['host'].';dbname='.$conf['database'].';',
				$conf['login'],
				$conf['password'],
				array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET SQL_BIG_SELECTS=1')
			);
			$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING); 
			if (Conf::$debug >= 1) {
				$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING); 
			}

			Model::$connections[$this->conf] = $pdo; 
			$this->db = $pdo; 
			}catch(PDOException $e){
			if(Conf::$debug >= 1){
				exit($e->getMessage()); 
			}else{
				die('Impossible de se connecter à la base de donnée'); 
			}
		}	 
	}

	/**
	* Permet de valider des données
	* @param $data données à valider 
	**/
	function validates($data){
		
		//var_dump($this->validate);
		//var_dump($data);
		$errors = array(); 
		foreach($this->validate as $k=>$v){
			//var_dump($this->validate);
				if(!isset($data->$k)){
					$errors[$k] = $v['message']; 
				}
				else{
					foreach($v as $l=>$w) {
						if($w['rule'] == 'Empty'){
							if(empty($data->$k)){
								break; 
							}
						}
						elseif($w['rule'] == 'notEmpty'){
							if(empty($data->$k)){
								$errors[$k] = $w['message'];
								break;									
							}
						}
						elseif(substr($w['rule'],0,4)== 'min_'){
							$len=substr($w['rule'],-(strlen($w['rule'])-4));
							if (strlen($data->$k) < $len) {
								$errors[$k] = $w['message']; 
								echo 'ok'.$errors[$k].'</br>';
							}

						}
						elseif(substr($w['rule'],0,4)== 'max_'){
							$len=substr($w['rule'],-(strlen($w['rule'])-4));
							if (strlen($data->$k) > $len) {
								$errors[$k] = $w['message']; 
								echo 'ok'.$errors[$k].'</br>';
							}
						}
						elseif(substr($w['rule'],0,7)== 'sup-eg_'){
							$val=substr($w['rule'],-(strlen($w['rule'])-7));
							if ($data->$k < $val) {
								$errors[$k] = $w['message']; 
								echo 'ok'.$errors[$k].'</br>';
							}
						}
						elseif(!preg_match('/^'.$w['rule'].'$/',$data->$k)){
							$errors[$k] = $w['message'];
						}
					}
				}
		}
		
		$this->errors = $errors; 
		if(isset($this->Form)){
			$this->Form->errors = $errors; 
		}
		//var_dump($errors);
		
		if(empty($errors)){
			return true;
		}
		return false;
	}



	/**
	* Permet de récupérer plusieurs enregistrements
	* @param $req Tableau contenant les éléments de la requête
	**/
	public function find($req = array()){
		// pour debugger le déroulemnt des appels de modules
//echo "Session active est ".session_id()." - Module  model(find) at ".microtime(true).' sec'."<br/>"; 
		if(isset($req['temp'])){
			$sql = "CREATE TEMPORARY TABLE ".$req['temp']." AS SELECT ";
		}
		else {		
			$sql = 'SELECT ';
		}
		if(isset($req['fields'])){
			if(is_array($req['fields'])){
				$sql .= implode(', ',$$req['fields']);
			}else{
				$sql .= $req['fields']; 
			}
		}else{
			$sql.='*';
		}
		//echo '<br/> table lue ( dans Model): '.$table .' - '.$this->table;
		$sql .= ' FROM '.$this->table;
		//.' as '.get_class($this).' ';

		// Liaison
		if(isset($req['join'])){
			foreach($req['join'] as $k=>$v){
				$sql .= 'LEFT JOIN '.$k.' ON '.$v.' '; 
			}
		}

		// Construction de la condition

		if(isset($req['conditions']) && !empty($req['conditions'])){
			$sql .= ' WHERE ';
			if(!is_array($req['conditions'])){
				$sql .= $req['conditions'];
		
			}else{
				$cond = array(); 
				foreach($req['conditions'] as $k=>$v){
					if(!is_numeric($v)){
					//	$v = '"'.mysql_real_escape_string($v).'"'; 
						$v = $this->db->quote($v); 
					}
					
					$cond[] = "$k=$v";
				}
				$sql .= implode(' AND ',$cond);
			}
	
		}
		
		if(isset($req['group'])){
			$sql .= ' GROUP BY '.$req['group'];
		}

		if(isset($req['order'])){
			$sql .= ' ORDER BY '.$req['order'];
		}

		if(isset($req['limit'])){
			$sql .= ' LIMIT '.$req['limit'];
		}
		if(isset($req['offset'])){$sql .= ' OFFSET '.$req['offset'];
		}
//debug($sql);
		$pre = $this->db->prepare($sql); 
		$_SESSION['s_sql_query']=$sql;
		$pre->execute(); 
//$_SESSION['ind_affiche']=1;
		if ($_SESSION['ind_affiche']==1) { echo $sql.'<br/>'; $_SESSION['ind_affiche']=0; }  

		$_SESSION['Req_Count'] = $pre->rowCount();
		if(!isset($req['temp'])){
			return $pre->fetchAll(PDO::FETCH_OBJ); 
		}
	}

	/**
	* Alias permettant de retrouver le premier enregistrement
	**/
	public function findFirst($req){
		return current($this->find($req)); 

	}

	/**
	* Récupère le nombre d'enregistrements
	**/
	public function findCount($conditions){

		$res = $this->find(array(
			'fields' => 'COUNT(*) as count',
			//'fields' => 'COUNT('.$this->primaryKey.') as count',
			'conditions' => $conditions
			));
			echo $res->count;
		return $res->count;  
	}
	
	public function findRowCount($result){
	
	   /* Récupère le nombre de lignes qui correspond à la requête SELECT */
			return $result->rowCount;

	}

	/** 
	* Permet de récupérer un tableau indexé par primaryKey et avec name pour valeur
	**/
	function findList($req = array()){
		if(!isset($req['fields'])){
			$req['fields'] = $this->primaryKey.',name';
		}
		$d = $this->find($req); 
		$r = array(); 
		foreach($d as $k=>$v){
			$r[current($v)] = next($v); 
		}
		return $r; 
	}

	/**
	* Permet de supprimer un enregistrement
	* @param $id ID de l'enregistrement à supprimer
	**/	
	public function delete($req = array()){
		
		$sql = ' DELETE FROM '.$this->table;
		//$sql .= " WHERE {$this->primaryKey} = $id";
		
		// Construction de la condition
		if(isset($req['conditions']) && !empty($req['conditions'])){
			$sql .= ' WHERE ';
			if(!is_array($req['conditions'])){
				$sql .= $req['conditions']; 
			}else{
				$cond = array(); 
				foreach($req['conditions'] as $k=>$v){
					if(!is_numeric($v)){
					//	$v = '"'.mysql_real_escape_string($v).'"'; 
						$v = $this->db->quote($v); 

					}
					
					$cond[] = "$k=$v";
				}
				$sql .= implode(' AND ',$cond);
			}

		}

		$del=$this->db->query($sql); 
		
		/* Return number of rows that were deleted */
		$count = $del->rowCount();
		return $count;
	}

		/**
	* Permet de sauvegarder des données
	* @param $data Données à enregistrer
	**/
	public function update($data, $conditions){

		//$key = $this->primaryKey;
		$fields =  array();
		$d = array(); 
		foreach($data as $k=>$v){
				$fields[] = "$k=:$k";
				$d[":$k"] = $v; 
		}
		$sql = 'UPDATE '.$this->table.' SET '.implode(',',$fields);
		
// $_SESSION['ind_affiche']=1;
		// Construction de la condition
		if(isset($conditions) && !empty($conditions)){
			$sql .= ' WHERE ';
			if(!is_array($conditions)){
				$sql .= $conditions; 
			}else{
				$cond = array(); 
				foreach($conditions as $k=>$v){
					if(!is_numeric($v)){
					//	$v = '"'.mysql_real_escape_string($v).'"'; 
						$v = $this->db->quote($v); 

					}
					
					$cond[] = "$k=$v";
				}
				$sql .= implode(' AND ',$cond);
			}

		}		

		if ($_SESSION['ind_affiche']==1) { echo $sql.'<br/>'; $_SESSION['ind_affiche']=0; }  
		$pre = $this->db->prepare($sql);

		$pre->execute($d);
		
		/* Return number of rows that were deleted */
		$count = $pre->rowCount();
		return $count;

}
	/**
	* Permet de sauvegarder des données
	* @param $data Données à enregistrer
	**/
	public function insert($data){
		//var_dump($data); echo "<br/>";
		$key = $this->primaryKey;
		$fields =  array();
		$d = array(); 
		foreach($data as $k=>$v){
			if($k!=$this->primaryKey){
				$fields[] = "$k=:$k";
				$d[":$k"] = $v; 
			}elseif(!empty($v)){
				$d[":$k"] = $v; 
			}
		}

		$sql = 'INSERT INTO '.$this->table.' SET '.implode(',',$fields);


		if ($_SESSION['ind_affiche']==1) { echo $sql.'<br/>'; $_SESSION['ind_affiche']=0; }  //$_SESSION['ind_affiche']=0;			
		$pre = $this->db->prepare($sql);
		
		$pre->execute($d);

		/* Return number of rows that were inserted */
		$count = $pre->rowCount();
		return $count;
}

} // fin de classe