<?php
/**
* @author:  Bunzia Alexander <nifus@mail.ru> <http://www.weblancer.net/users/nifus/>
* @copyright: Copyright (c) 2010, Bunzia Alexander
* @version: 1.0
* @license: http://www.gnu.org/copyleft/gpl.html GNU/GPL
* @package: HiLo CMS
*/


/***
* Конструктор sql запросов
*
*
*/
class query{
		//	алиса основной таблицы, переопределяется потомком
	public $alias;
		//	полное имя основной таблицы, переопределяется потомком
	public $table;
		//	для сложных sql запросов, можно просто передать код sql
	private $sql;
		//	ресур возвращаемый из базы данных
	private $result = '';
		//	LIMIT $page, ... 
	private $page = false;
		//количество строк за раз
		//	LIMIT ..., $count_rows
	private $count_rows = false;
		//	массив условий
	private $sql_where = array();
		//	массив сортировок
	private $sql_order = array();
		//	сложные условия
	private $anothe_where = array();
		//	группировки 
	private $sql_groupby = array();
	
		//	вспомогательные таблицы 
	private $sql_tables = array();
		//	получаемые столбцы
	private $sql_parametrs = array();

		//	общее количество полученных столбцов
	private $_result_count_rows = false;
		//	отладка
	private $debug;
		//	переопределяемое свойство, содержит последнюю ошибку
	protected $last_error = FALSE;
	
		//	сложный запрос сразу заносим, а не генерим
	public function set_sql($sql){
		 $this -> sql = $sql;
	}
		//	 сортировка
	public function set_orderby($key,$value){
		if ( !empty($value) && !in_array($value, array('ASC','DESC')) ){
			return FALSE;
		}
		$this -> sql_order[$key] = $value;
		return TRUE;
	}
		//	условия
	public function set_where($key,$value){
		if ( empty($key) ){
			return FALSE;
		}
		$this -> sql_where[$key] = $value;
		return TRUE;
	}

	public function where_more($key,$value){
		return $this -> set_anothe_where( " $key>$value " );
	}

	public function where_less($key,$value){
		return $this -> set_anothe_where( " $key<$value " );
	}

		//	сложные условия
	public function set_anothe_where($sql){
		$this -> anothe_where[]=$sql;
		return TRUE;
	}
		//	группировка результатов
	public function set_groupby($key){
		$this -> sql_groupby[] = $key;
		return TRUE;
	}
		//	постраничный вывод
	public function set_page($page){
		$page = intval($page);
		$this -> page = !empty($page) ? $page : 1;
		return TRUE;
	} 
	
	public function set_limit($page,$count){
	  $this -> set_count_rows($count);
	  $this -> set_page($page);
	  return TRUE;
	}
		//	сколько выводить за раз
	public function set_count_rows($count){
		$count = intval($count);
		//	ошибка привидёт к краху запроса, её допускать нельзя
		if ( empty($count) ){
			sys_error('500',E_EMPTY_COUNT_ROWS);
			return FALSE;
		}
		$this -> count_rows = $count;
		return TRUE;
	}  
		//	отладка запроса
	public function set_debug($flag){
		$this -> debug=$flag;
	}
	
		
	public function row(){
	global $MAIN_DB;
		$row = $MAIN_DB -> fetch_assoc($this->result);
		if ( false===$row ){
			return false;
		}
		$result=array();
		$i=0;
		$f = $this -> fields_get;

		if ( empty($f) ){
		  $f = $this;
		}
		foreach( $row AS $func=>$value ){
			if ( method_exists($f  ,$func) ){
	
			  $result[$func] =call_user_func( array($f,$func),$value,$row);
				//$result[$func] = $f  :: $func($value,$row);
			}else{
				$result[$func] = $value;
			}
			$result[$i] = $result[$func];
			$i++;
		}
		return $result;
	}
	
	public function make_sql($parametrs,$flag_found_rows=false){
			//	sql_parametrs - поля которые нужно получить
			if ( !empty($parametrs) ){
				$this -> sql_parametrs[]=$parametrs;
			}
			$parametrs = implode(',',$this -> sql_parametrs);
				//	параметры не заданы
			if ( empty($parametrs) ){
				sys_error('500',E_DATABASE_EMPTY_PARAMETRS);
				return FALSE;
			}
			$result = array();
			$found_rows = $flag_found_rows ? 'SQL_CALC_FOUND_ROWS' : '';
				//	условия
			if ( sizeof($this -> sql_where)>0 || sizeof($this -> anothe_where)>0 ){
				$sql_where = array();
		
				foreach( $this -> anothe_where AS $k=>$v){
						$sql_where[]=$v;
				}
				foreach( $this -> sql_where AS $k=>$v){
					if ( empty($k)){
						$sql_where[]=$v;
						continue;
					}
					if ( is_array($v) ){
						$sql_where[]="$k IN (".implode(',',$v).")";
					}else{
						$sql_where[]="$k = '".mysql_real_escape_string($v)."'";
					}
				}
				$sql_where = 'WHERE '.implode(' AND ',$sql_where);
			}else{
				$sql_where='';
			}
				//	сортировка
			$sql_order = '';
			if ( sizeof($this -> sql_order)>0 ){
				$sql_order = array();
				foreach( $this -> sql_order AS $k=>$v){
					$sql_order[]="$k $v";
				}
				$sql_order = 'ORDER BY '.implode(' , ',$sql_order);
			}
			//	groupby
			$sql_grouby = '';
			if ( sizeof($this -> sql_groupby)>0 ){
				$sql_grouby = array();
				foreach( $this -> sql_groupby AS $k){
					$sql_grouby[]="$k";
				}
				$sql_grouby = 'GROUP BY '.implode(' , ',$sql_grouby);
			}
				//	лимит на выборку
			$sql_limit = '';
			if ( $this -> count_rows!==false && $this -> page !==false  ){
				$sql_limit = "LIMIT ".(($this -> page-1)*$this -> count_rows).",".$this -> count_rows;
			}
			
				//	сборка запроса
			$sql = "SELECT $found_rows $parametrs FROM ".$this -> table." ".$this -> alias." ";
			foreach( $this -> sql_tables AS $table_info ){
				$sql .= " ".$table_info['join']." ".$table_info['name']." ".$table_info['alias']." USING(".$table_info['key'].")";
			}			
			return $sql .=	"$sql_where  $sql_grouby  $sql_order $sql_limit";
	}
	
	

	/**
	* Собираем и выполняем sql запрос 
	*
	* @var: parametrs str Список получаемых столбцов 
	* @var: flag_found_rows bool Нужно или нет получать общее количество строк без учёта LIMIT
	* @return: bool
	*/
	public function get($parametrs,$flag_found_rows=false){
	global $MAIN_DB;
		$sql = $this -> sql;
		if ( empty($this -> sql) ){
			$sql = $this -> make_sql($parametrs,$flag_found_rows);
		}
		
		if ( $this -> debug ){
			HL::ajaxDebug($sql); 
		}
		$res = $MAIN_DB -> query($sql);
		if ( $flag_found_rows ){
			$sql = 'SELECT FOUND_ROWS()';
			list($count) = $MAIN_DB -> fetch_array( $MAIN_DB -> query($sql) );
			$this -> _result_count_rows = $count;
		}else{
			$this -> _result_count_rows = $MAIN_DB -> num_rows($res);
		}
		
		return $this->result = $res;
	}
		
	/**
	* Получаем результат в массив
	*
	*
	*/
  public function rows(){
    $rows = array();
		while( $row = $this -> row() ){
			$rows[] = $row;
		}	
		return $rows;
  }
		
	public function get_count_rows(){
		return $this -> _result_count_rows;
	}
	
 	
	
		//	получить алиас по названию таблицы
	protected function get_alias($v){
		if ( empty($v) ){
			sys_error('500',E_DATABASE_EMPTY_TABLE );
		}
		if ( isset($this ->sql_tables[$v] ) ){
			return $this -> sql_tables[$v]['alias'];
		}
		if ( $this -> table == $v ){
			return $this -> alias;
		}
		sys_error('500',sprintf(E_DATABASE_EMPTY_ALIAS_NAME,$v));
		return false;
	}
	
	protected function get_table(){
		return $this -> table; 
	}
	
		//	подключаем таблицу для формироания left JOIN
	protected function include_table($table,$alias,$key,$parametrs=false,$join="LEFT JOIN"){
		if ( empty($table) ){
			sys_error('500',E_DATABASE_EMPTY_TABLE);
			return false;
		}
		if ( empty($alias) ){
			sys_error('500',E_DATABASE_EMPTY_ALIAS);
			return false;
		}
		if ( empty($key) ){
			sys_error('500',E_DATABASE_EMPTY_LINK_KEY);
			return false;
		}
		$this -> sql_tables[$table]=array(
			'name'=>$table,
			'alias'=>$alias,
			'key'=>$key,
			'join'=>$join
			);
		if ( !empty($parametrs) ){
			$this -> sql_parametrs[]=$parametrs;
		}
	}
	
			//	название главной таблицы
	public function set_table($table){
		if ( empty($table) ){
			sys_error('500',E_DATABASE_EMPTY_TABLE);
		}
		$this -> table = $table;
		return TRUE;
	}
	
		//	алиас для главной таблицы
	protected function set_alias($alias){
	
		if ( empty($alias) ){
			sys_error('500',E_DATABASE_EMPTY_ALIAS);
		}
		$this -> alias = $alias;
		
		return TRUE;
	}
	
	
	
		
	
	
	
	
	
	
	
}	
	
?>
