<?php 
/**
 *  mysql.php 数据库实现类
 *
 * @copyright			(C) 2019 YUNYECMS
 * @lastmodify			2019-2-24
 */
final class mysql {
	 /**
	  * 数据库配置信息
	  */
	 private $config;
	 /**
	  * 数据库连接资源句柄
	  */
	 private $link;
	 /**
	  *	最后一次查询的资源句柄
	  */
	 public $lastresult;
	/**
	 *  统计数据库查询次数
	 */
	public $querycount = 0;
	/**
	 * 数据类实例
	 */
	static private $mysqlobj=array();
	public function __construct($configs){
		$this->config=$configs;	
		$this->connect();	
	}
	public function __destruct(){	
		$this->close();
	}
	
	private function mysql($configs){
		$this->config=$configs;
		$this->connect();	
	}	
	
	private function __clone(){
	}
	
	private function connect(){
		$func = $this->config['pconnect'] == 1 ? 'mysql_pconnect' : 'mysql_connect';
		if(!$this->link = $func($this->config['hostname'], $this->config['username'], $this->config['password'], 1)) {
			$this->DisplayError('Can not Connect to MySQL server',"hook_mysql_install");
		}		
		if($this->GetVersion(true) > '4.1') {
			$charset = isset($this->config['dbchar']) ? $this->config['dbchar'] : 'utf8';
			$serverset = $charset ? "character_set_connection='$charset',character_set_results='$charset',character_set_client=binary" : '';
			$serverset .= $this->GetVersion() > '5.0.1' ? ((empty($serverset) ? '' : ',')." sql_mode='' ") : '';
			$serverset && mysql_query("SET $serverset", $this->link);		
		}		
		if($this->config['database'] && !@mysql_select_db($this->config['database'], $this->link)) {
			$this->DisplayError('Cannot use database "'.$this->config['database'].'"');
		}
	}	
	public function DisplayError($message='',$hook=''){
		if(!empty($hook)){
			$this->$hook($message);
			}else{
				  $html="<b><a href='http://www.yunyecms.com/faq' target='_blank'><i class='fa fa-life-ring'></i> Need Help? </a></b>";
				  if($this->config['debug']){
				  $errorinfo ='<b>MySQL Error: </b>'.$this->GetError().'<br/>';
				  $errorinfo.='<b>MySQL Errno: </b>'.$this->GetErrno().'<br/>';
				  $errorinfo.=$html;
				  messagebox($message,'nback',"info","",$errorinfo);
				  exit;
			      }else{
				  messagebox($message,'nback',"info","",$html);
				  exit;
			      }	
		  }
	}
	public function hook_mysql_install($message=''){
		if(!file_exists(ROOT.'/data/install.lock')){
		   if(file_exists(ROOT.'/install')){
			echo "<script>";
			echo "window.location.href='".ROOT."/install'";
			echo "</script>";
		   }else{
			   	  $html="<a href='http://www.yunyecms.com/faq' target='_blank' ><i class='fa fa-life-ring'></i> Need Help?</a>";
				  if($this->config['debug']){
				  $errorinfo ='<b>MySQL Error: </b>'.$this->GetError().'<br/>';
				  $errorinfo.='<b>MySQL Errno: </b>'.$this->GetErrno().'<br/>';
				  $errorinfo.=$html;
				  messagebox($message,'nback',"info",$errorinfo);
				  exit;
			      }else{
				  messagebox($message,'nback',"info",$html);
				  exit;
			      }	
			   }
		}else{
			 	  $html="<a href='http://www.yunyecms.com/faq' target='_blank' ><i class='fa fa-circle-o'></i> Need Help?</a>";
				  if($this->config['debug']){
				  $errorinfo ='<b>MySQL Error: </b>'.$this->GetError().'<br/>';
				  $errorinfo.='<b>MySQL Errno: </b>'.$this->GetErrno().'<br/>';
				  $errorinfo.=$html;
				  messagebox($message,'nback',"info",$errorinfo);
				  exit;
			      }else{
				  messagebox($message,'nback',"info",$html);
				  exit;
			      }	
		  }
		exit;
	 }	
	
	final static public function GetObject($configs=array('hostname'=>'','database'=>'')){
			$db=$configs['hostname'].$configs['database'];		
			if(!isset(self::$mysqlobj[$db])){				
				if(!is_array($configs)){
					$this->DisplayError("The configuration file is not an array");
				}	
				$C=__CLASS__;	
				self::$mysqlobj[$db]=new $C($configs);				
			}
			return self::$mysqlobj[$db];
	}
	
	public function close() {
		if (is_resource($this->link)) {
			@mysql_close($this->link);
		}
	}
	
	public function GetVersion($version=false) {
		if(!is_resource($this->link)) {
			$this->connect();
		}
		$mysql_version= mysql_get_server_info($this->link);
		$mysql_version = explode(".",trim($mysql_version));
		if($version){
			return $mysql_version[0].'.'.$mysql_version[1];
		}else{
			return $mysql_version[0].'.'.$mysql_version[1].'.'.$mysql_version[2];
		}

	}	
	public function GetError(){
		return @mysql_error($this->link);
	}
	public function GetErrno(){
		return intval(@mysql_errno($this->link));
	}
	/**
	 * 获取最后一次添加记录的主键号
	 * @return int 
	 */
	 public function insert($data,$table,$return_insert_id = false, $replace = false) {
		if(!is_array( $data ) || $table == '' || count($data) == 0) {
			return false;
		}
		$fielddata = array_keys($data);
		$valuedata = array_values($data);
		array_walk($fielddata, array($this, 'add_special_char'));
		array_walk($valuedata, array($this, 'addquote'));
		$field = implode (',', $fielddata);
		$value = implode (',', $valuedata);
		$strsql = $replace ? 'REPLACE INTO' : 'INSERT INTO';
		$strsql = $strsql.' `'.$this->config['database'].'`.`'.$table.'`('.$field.') VALUES ('.$value.')';
		$query = $this->execute($strsql);
		return $return_insert_id ? $this->insert_id() : $query;
	}
	 
	public function update($data,$table, $where = '') {
		$where = $where ? ' WHERE '.$where: '';
		if(is_array($data)) {
			$datas = array();
			foreach ($data AS $key => $value) {
				$datas[] = "`".$key."`='".mysql_real_escape_string($value)."'";
			}
			$setdata = implode(',', array_values($datas));
		} else {
			$setdata = mysql_real_escape_string($data);
		}
		$sql = 'UPDATE `'.$this->config['database'].'`.`'.$table.'` SET '.$setdata.' '.$where;
		return $this->execute($sql);
	}	 
	 
	public function insert_id() {
		return mysql_insert_id($this->link);
	}
		
	/**
	 * 对字段两边加反引号，以保证数据库安全
	 * @param $value 数组值
	 */
	public function add_special_char(&$value) {
		if('*' == $value || false !== strpos($value, '(') || false !== strpos($value, '.') || false !== strpos ( $value, '`')) {
			//不处理包含* 或者 使用了sql方法。
		} else {
			$value = '`'.trim($value).'`';
		}
		if (preg_match("/\b(select|insert|update|delete)\b/i", $value)) {
			$value = preg_replace("/\b(select|insert|update|delete)\b/i", '', $value);
		}
		return $value;
	}		
		
	/**
	 * 数据库查询执行方法
	 * @param $sql 要执行的sql语句
	 * @return 查询资源句柄
	 */
	public function execute($sql) {
		//$sql=mysql_real_escape_string($sql);
		if(!is_resource($this->link)) {
			$this->Connect();
		}		
		$this->lastresult = mysql_query($sql,$this->link) or $this->DisplayError($sql);
		$this->querycount++;
		return $this->lastresult;
	}	

	/**
	 * 释放查询资源
	 * @return void
	 */
	public function free() {
		if(is_resource($this->lastresult)) {
			mysql_free_result($this->lastresult);
			$this->lastresult = null;
		}
	}
	
	/**
	 * 检查表是否存在
	 * @param $table 表名
	 * @return boolean
	 */
	public function table_exists($table) {
		$tables = $this->list_tables();
		return in_array($table, $tables) ? 1 : 0;
	}
	/*
	* 列表
	*/
	public function list_tables() {
		$tables = array();
		$this->execute("SHOW TABLES");	
		while($r = mysql_fetch_assoc($this->lastresult)) {
			$tables[] = $r['Tables_in_'.$this->config['database']];
		}
		return $tables;
	}
	
	//数据总数查询，需要一个结果集
	public function num_rows($lastresult)
	{	
		return mysql_num_rows($lastresult);			
	}
	
	//数据总数查询
	
	public function num_count($lastresult){
		$data=$this->get_one($lastresult,MYSQL_NUM);
		return $data[0];
	}
	
	/**
	 * 获取最后数据库操作影响到的条数
	 * @return int
	 */
	 
	public function affected_rows(){
		return mysql_affected_rows($this->link);
	}
	
	/**
	 * 返回一条查询结果集
	 * $lastresult      外部的结果集，如果没有就调用内部的结果集
	 * @param $type		返回结果集类型	
	 * 					MYSQL_ASSOC，MYSQL_NUM 和 MYSQL_BOTH
	 * @return array
	 */
	final public function get_one($lastresult=null,$type=MYSQL_ASSOC){
		if(!$type)$type=MYSQL_ASSOC;
		if(is_resource($lastresult)){		
			$datalist=mysql_fetch_array($lastresult,$type);
			$this->free();
			return $datalist;
		}
		if(!is_resource($this->lastresult)){
			$this->free();
			return false;
		}		
		$datalist=mysql_fetch_array($this->lastresult,$type);
		$this->free();
		return $datalist;
	}
	
	public function delete($table, $where = '') {
		$where = $where ? ' WHERE '.$where: '';
		$sql = 'DELETE FROM `'.$table.'`'.$where;
		return $this->execute($sql);
	}	
	
	
	/**
	 * 遍历查询结果集
	 * @param $type		返回结果集类型	
	 * 					MYSQL_ASSOC，MYSQL_NUM 和 MYSQL_BOTH
	 * @param $type		按照键名排序	
	 * @return array
	 */
	final public function &get_fetch_array($type=1,$key=''){		
		if(!is_resource($this->lastresult)){
			$this->free();
			return false;
		}			
		$datalist = $data = array();
		if(!$key){
			while($data=mysql_fetch_array($this->lastresult,$type)){				
				$datalist[]=$data;
			}	
		}else{
			while($data=mysql_fetch_array($this->lastresult,$type)){				
					$datalist[$data[$key]]=$data;
			}
		}
		$this->free();
		return $datalist;
	}	


 	final public  function sqls($where, $font = ' AND ',$op='=') {
		if (is_array($where)) {
			$sql = '';
			foreach ($where as $key=>$val){
				$sql .= $sql ? " $font `$key` $op '$val' " : " `$key` $op '$val'";
			}
			return $sql;
		} else {
			return $where;
		}
	}
	
	public function escape_string($string) {
		return mysql_real_escape_string($string);
	}	
	
	public function addquote(&$value, $quotation = 1) {
		$value=mysql_real_escape_string($value);
		if ($quotation) {
			$quote = '\'';
		} else {
			$quote = "'";
		}
		$value = $quote.$value.$quote;
		return $value;
	}
	//加反引号
    protected function parseKey(&$key) {
        $key   =  trim($key);
        if(!preg_match('/[,\'\"\*\(\)`.\s]/',$key)) {
           $key = '`'.$key.'`';
        }
        return $key;
    }	
	
	
	/////
}

?>