<?php
    require 'Model';
    class MNative extends Model{
	/*----------------extended----------------*/
        function __construct($db_name='u655931133_tourmap',$server='mysql.hostinger.es',$user='u655931133_root',$password='sodita',$port=3306){
            parent::__construct($server,$user,$password,$db_name,$port);
	    //echo phpinfo();
            //var_dump($this->connection);
            $this->connection=mysqli_connect($server,$user,$password,$db_name,$port);
	    $connect=$this->connection;
            if($connect){
                //validating, etc...
            }
            else
                $this->error->add('Connection Error','Number of error -> None , Message -> No connection with mysqli driver , Query to apply: Constructor');
        }
	function prepared_select_query($query_name,$params_array,$number_results){
		//better performance compared to the select method
		$rows=NULL;
		$prepared=$this->prepared_query($query_name,$params_array,$number_results,FALSE);
		if($prepared){
			$condition=false;
			$one=NULL;
			$two=NULL;
			$three=NULL;
			$four=NULL;
			$five=NULL;
			$six=NULL;
			$seven=NULL;
			$eight=NULL;
			$nine=NULL;
			$ten=NULL;
			switch($number_results){
				case 10:$condition=$prepared->bind_result($one,$two,$three,$four,$five,$six,$seven,$eight,$nine,$ten);break;
				case 9: $condition=$prepared->bind_result($one,$two,$three,$four,$five,$six,$seven,$eight,$nine);break;
				case 8: $condition=$prepared->bind_result($one,$two,$three,$four,$five,$six,$seven,$eight);break;
				case 7: $condition=$prepared->bind_result($one,$two,$three,$four,$five,$six,$seven);break;
				case 6: $condition=$prepared->bind_result($one,$two,$three,$four,$five,$six);break;
				case 5: $condition=$prepared->bind_result($one,$two,$three,$four,$five);break;
				case 4: $condition=$prepared->bind_result($one,$two,$three,$four);break;
				case 3:	$condition=$prepared->bind_result($one,$two,$three);break;
				case 2: $condition=$prepared->bind_result($one,$two);break;
				case 1:	$condition=$prepared->bind_result($one);break;
			}
			if($condition){
				$rows=array();
				while($prepared->fetch()){
					$result=array($one,$two,$three,$four,$five,$six,$seven,$eight,$nine,$ten);
					$rows[]=$result;
				}
				$prepared->close();
				if(count($rows)==0)
					$this->advise->add('Prepared select query zero results obtained','Message -> This query gave zero rows result, Query to apply:  '.$this->bind_query($this->prepared_select[$query_name],$params_array));
			}
			else
				$this->error->add('Prepared select query results Error','Number of error ->  None, Message -> It was imposible to assign the result columns  to the variables, Query to apply:  '.$this->bind_query($this->prepared_select[$query_name],$params_array));
		}
				
		return $rows;
	}
	private function bind_query($prepared,$params_array=array()){
		$length=strlen($prepared);$length2;
		$aux='';
		$y=0;$z=0;
		if(count($params_array)>0){
			for($i=0;$i<$length;$i++){
				if($prepared[$i]=='?'){
					$length2=strlen($params_array[$y]);
					for($z=0;$z<$length2;$z++){
						if($z==0)
							$aux.=$params_array[$y][$z];
						else
							$aux.=$params_array[$y][$z];
					}
					$y++;
				}
				else
					$aux.=$prepared[$i];
			}
		}
		return $aux;
	}
	private function prepared_query($query_name,$params_array,$number_results,$prepared_action=TRUE){
		$return=FALSE;
		$connect=$this->connection;
		if($connect){
			$condition=($prepared_action?$number_results==0:$number_results>0);
			if($condition){
				$prepared=($prepared_action?$this->prepared_action[$query_name]:$this->prepared_select[$query_name]);
				if($prepared){
					$aux=$prepared;
					$prepared=$connect->prepare($prepared);
					if($prepared){
						$aux=NULL;
						$types='';
						foreach ($params_array as $k=>$v){
							if(is_integer($v) OR is_long($v))	
								$types.='i';
							else if(is_object($v) OR is_resource($v))	
								$types.='b';
							else if(is_float($v) OR is_real($v) OR is_double($v))
								$types.='d';
							else
								$types.='s';	
						}
						switch(count($params_array)){
							case 10:$prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4],$params_array[5],$params_array[6],$params_array[7],$params_array[8],$params_array[9]);break;
							case 9: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4],$params_array[5],$params_array[6],$params_array[7],$params_array[8]);break;
							case 8: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4],$params_array[5],$params_array[6],$params_array[7]);break;
							case 7: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4],$params_array[5],$params_array[6]);break;
							case 6: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4],$params_array[5]);break;
							case 5: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3],$params_array[4]);break;
							case 4: $prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2],$params_array[3]);break;
							case 3:	$prepared->bind_param($types,$params_array[0],$params_array[1],$params_array[2]);break;
							case 2: $prepared->bind_param($types,$params_array[0],$params_array[1]);break;
							case 1:	$prepared->bind_param($types,$params_array[0]);break;
						}
						$return=$prepared->execute();
						if($prepared_action)
							$return=$prepared;					
						else{
							if($return)
								$return=$prepared;
							else
								$this->error->add('Prepared '.($prepared_action?'action ':'select ').'query executed Error','Number of error ->  '.$connect->errno.', Message -> '.$connect->error.', Query to apply:  '.$this->bind_query($prepared,$params_array));
						}
					}
					else
						$this->error->add('Prepared '.($prepared_action?'action ':'select ').'query definition Error','Number of error ->  None, Message -> Prepared '.($prepared_action?'action ':'select ').' query wasn\'t executed correctly, Query to apply:'.$aux);
				}
				else
					$this->error->add('Prepared '.($prepared_action?'action ':'select ').'query definition Error','Number of error ->  None, Message -> Prepared '.($prepared_action?'action ':'select ').' query isn\'t loaded on the model object, Query to apply: NULL');
			}
			else
				$this->error->add('Prepared '.($prepared_action?'action ':'select ').'query number of rows Error','Number of error ->  None, Message -> A number '.($prepared_action?'equal to ':'more than ').'"0" must be definition to get an array of rows, Query to apply: NULL');
		}
		else{
			$this->error->add('Prepared query connection Error','Number of error -> None , Message -> No connection with mysqli driver , Query to apply: NULL');
		}

		return $return;
	}
	function prepared_action_query($query_name,$params_array,$number_results){
		//better performance compared to the action method
		$num_rows_modified=-2;
		$prepared=$this->prepared_query($query_name,$params_array,$number_results);
		if($prepared){
			$p=$this->prepared_action[$query_name];
			$splitted=explode(' ',$p);
			$query_type=strtolower($splitted[0]);
			if($query_type=='insert'){
				$num_rows_modified=$prepared->affected_rows;
				$this->last_insert_id=$prepared->insert_id;
				//$this->last_insertion_id

				if($num_rows_modified<=0)
					$this->advise->add('Prepared action query executed','Message -> Because num_rows_modified is or minor than "0", so the query data already existed on this table as the next sql text says: '.$prepared->error .'which number error is: '.$prepared->errno.', Query to apply:  '.$this->bind_query($p,$params_array));
			}
			else{
				//if no action query but modify or delete query
				$num_rows_modified=$this->action_advise($this->bind_query($p,$params_array),$num_rows_modified);
			}
		}
		
		return $num_rows_modified;
	}
	private function action_advise($prepared,$num_rows_modified){
		if(!is_numeric($num_rows_modified))
			$num_rows_modified=0;
		if($num_rows_modified===0)
			$this->advise->add('Prepared action query executed','Message -> No affected rows exist , Query to apply: '.$prepared);
		else if(is_numeric($num_rows_modified) && $num_rows_modified<0)
			$this->advise->add('Prepared action query executed','Message - >All rows affected,  Query to apply:  '.$prepared);
		else if(is_numeric($num_rows_modified) && $num_rows_modified>0)
			$this->advise->add('Prepared action query executed',''.$num_rows_modified.' rows affected, Query to apply:  '.$prepared);
		return $num_rows_modified;
	}
	private function action_table_seek($query_sentence){
		$query_sentence=strtolower($query_sentence);
		$splitted=explode( ' ',$query_sentence);
		$table='';
		$from=FALSE;
		$set=FALSE;
		$into=FALSE;
		$length=count($splitted);
		for($i=0;$i<$length;$i++){
			if(($from) OR ($into)){
				$table=$splitted[$i];
				break;
			}
			else if($set){
				$table=$splitted[$i-2];
				break;
			}
			if($splitted[$i]=='from')
				$from=TRUE;
			else if($splitted[$i]=='into')
				$into=TRUE;
			else if(($splitted[$i]=='set') OR
				($splitted[$i]=='modify') OR
				($splitted[$i]=='change')
  			       )
				$set=TRUE;
		}
		return ucfirst($table);
	}
	private function action_messages_maker($table,$query_sentence,$num_rows_modified,$total_rows,$prepared=TRUE){
		if($num_rows_modified!=-1){
			$splitted=explode(' ',$query_sentence);
			$query_type=strtolower($splitted[0]);
			switch($query_type){
				case 'update':
					if($num_rows_modified==0)
						$this->advise->add('No rows updated on the "'.$table.'" table','Message -> Because num_rows_modified is "0", so the query data already existed on this table. Number of rows right now is '.$total_rows.' ; Query to apply -> '.$query_sentence);
					else
						$this->advise->add('Rows updated','Message -> '. $num_rows_modified .'  rows updated  of '.$total_rows.'  rows ; Query to apply -> '.$query_sentence);
					break;
				case 'insert':
					$this->advise->add('Rows inserted on the "'.$table.'" table','Message -> '. $num_rows_modified .'  Number of rows right  now: '.($total_rows+$num_rows_modified).'  rows ; Query to apply -> '.$query_sentence);
					break;
				case 'delete':
					if($num_rows_modified===0)
						$this->advise->add('Rows deleted from the "'.$table.'" table','Message -> '.$total_rows.'  rows deleted of '.$total_rows.' rows ; Query to apply -> '.$query_sentence);
					else
						$this->advise->add('Rows deleted from the "'.$table.'" table','Message -> '.$num_rows_modified.'  rows affected  of '.$total_rows.' rows ; Query to apply -> '.$query_sentence);
					break;
				case 'alter':
					if($num_rows_modified==0)
						$this->advise->add('Rows altered from the "'.$table.'" table','Message -> '.$total_rows.'  rows affected of '.$total_rows.' rows ; Query to apply -> '.$query_sentence);
					else
						$this->advise->add('Rows altered from the "'.$table.'" table','Message -> '.$num_rows_modified.'  rows affected  of '.$total_rows.' rows ; Query to apply -> '.$query_sentence);
					break;
			}
		}
		else{
			$connect=$this->connection;
			try{
				$this->error->add(($prepared?'Prepared action ':'Action ').'query Error','Number of error -> '.$connect->errno.' , Message -> '.$connect->error.' , Query to apply: '.$query_sentence);
			}
			catch(Exception $e){
				$this->advise->add('Delete query executed','All rows deleted, Query to apply -> '.$query_sentence);
			}
		}
	}
	function action($query_sentence){
		$connect=$this->connection;
		$num_rows_modified=-2;
		if($connect){
			$table=$this->action_table_seek($query_sentence);
			$result=$connect->query('select * from '.$table,MYSQLI_STORE_RESULT);
			$total_rows=0;
			if($result)
				$total_rows=$result->num_rows;
			else{
				$this->error->add('Action query Error','Number of error -> '.$connect->errno.' , Message -> '.$connect->error.' , Query to apply: select * from '.$table);
				return -1;
			}
			$result->close();
			$result=$connect->query($query_sentence);
			if($connect->error==''){
				try{
					$num_rows_modified=$connect->affected_rows;
					$this->action_messages_maker($table,$query_sentence,$num_rows_modified,$total_rows,FALSE);
					$result=NULL;
				}
				catch(Exception $e){
					//if no action query but modify (or delete one)
					$num_rows_modified=$this->action_advise($query_sentence,$num_rows_modified);
				}
			}
			else
				$this->error->add('Action query Error','Number of error -> '.$connect->errno.' , Message -> '.$connect->error.' , Query to apply: '.$query_sentence);
		}
		else
			$this->error->add('Action query connection Error','Number of error -> None , Message -> No connection with mysqli driver , Query to apply: '.$query_sentence);
		return $num_rows_modified;

	}
	function select($query_sentence){
		$connect=$this->connection;
		$result=NULL;
		if($connect){
			$result=$this->connection->query($query_sentence,MYSQLI_STORE_RESULT);
			if($result!==FAlSE){
				if($result->num_rows>0){
					$result_aux=array();
					while($row=$result->fetch_object()){
						$field_info=$result->fetch_fields();
						$length=count($field_info);
						if($length>0){
							foreach($row as $field_name=>$field_value){
								for($i=0;$i<$length;$i++){
									if($field_info[$i]->name==$field_name){
										/*info per row:
											name
											orgname
											orgtable (organization)
											table (talbe name)
											db (db name)
											max_length
											length
											charsetnr (charsetnumber)
											decimals (number of decimals)
											flags
										*/
										$row->info->$field_name=$field_info[$i];
										break;
									}
								}
							}
						}
						$result_aux[]=$row;
					}
					$result->close();
					$this->advise->add('Select query executed',count($result_aux).'  files obtained, Query to apply -> '.$query_sentence);
					$result=$result_aux;
				}
				else{
					$this->advise->add('No files result on the query','Query to apply-> '.$query_sentence);
					$result=array();
				}
			}
			else{
				$this->error->add('Query Error','Number of error -> None Message -> Query doesn\'t executed, Query to apply: '.$query_sentence);	
				$result=NULL;
			}
		}
		else
			$this->error->add('Select query connection Error','Number of error -> None , Message -> No connection with mysqli driver , Query to apply: '.$query_sentence);
		return $result;
	}
	/*-------------------------------toolkit methods--------------------------------*/
	function close_connection(){
		$result=false;
		$connect=$this->connection;
		if($connect){
			$connect->close();
			$result=true;
		}
		else
			$this->error->add('Close Connection Error','Number of error -> None , Message -> No connection with mysqli driver');

		return $result;
			
	}
	function change_db($new_db_name){
		$result=false;
		$connect=$this->connection;
		if($connect){
			$connect->query('use '.$new_db_name);
			$result=true;
		}
		else
			$this->error->add('Change database connection Error','Number of error -> None, Message -> No connection with mysqli driver, Database to change: '.$new_db_name);

		return $result;
	}
	protected function special_query($query_sentence){
		$result=null;
		$connect=$this->connection;
		if($connect){
			$result=array();
			$rows=$connect->query($query_sentence);
			if($rows->num_rows>0){
				while($row=$rows->fetch_array())
					$result[]=$row;
			}
			else{
				if($rows->num_rows==0)
					$this->advise->add('No files result on the query to apply','Query to apply-> '.$query_sentence);
				else
					$this->error->add('Query Error','Number of error -> '.$connect->errorno.' Message -> '.$connect->error.' Query to apply: '.$query);
			}
		}
		else
			$this->error->add('Connection Error','Number of error -> None , Message -> No connection with mysqli driver, Query to apply: '.$query_sentence);

		return $result;
	}
	function  list_tables(){
		return $this->special_query('show tables');
	}
	function list_databases(){
		return $this->special_query('show databases');
	}
	function create_db($db_name){
		$result=false;
		$connect=$this->connection;
		if($connect){
			$connect->query('create database if not exists '.$db_name);
			$result=true;
		}
		else
			$this->error->add('Create database connnection Error','Number of error -> None , Message -> No connection with mysqli driver, Database to create: '.$db_name);

		return $result;
	}
	function create_table($table_name){
		$result=false;
		$connect=$this->connection;
		if($connect){
			$connect->query('create table if not exists '.$table_name.'( id_'.$table_name.' int not null auto_increment,primary   
 key (id_'.$table_name.'))engine=innodb');
			$result=true;
		}
		else
			$this->error->add('Create table connection Error','Number of error -> None , Message -> No connection with mysqli driver,Table to create: '.$table_name);

		return $result;
	}
	function last_inserted_id(){
		$id=$this->last_insert_id;
		$return=-1;		
		if($id===0)
			$this->advise->add('Last id is not a number','Go to this table and watch that it is true: the last inserted id is not a number');
		else	
			$return=$this->last_insert_id;

		return $return;
	}
    }

//End of file MNative
//Path of the file: /model/MNative
