<?php 
class InstallerHelper {
/*
//class to support   install plugins
// now supports to declare controled tree of objects :
// ROOT
[MYSQL_SCHEMA]
   [__SCHEMA_FUNCTIONS__ARRAY__] => Array
        (
            [FUNCTION] => Array
                (
                    [CRM_LISTA_ZASOBOW_tree_detect_kierownik] => stdClass Object
                        (
                            [Function] => CRM_LISTA_ZASOBOW_tree_detect_kierownik
                            [sql_mode] => 
                            [Create Function] => CREATE DEFINER=`root`@`localhost` FUNCTION `CRM_LISTA_ZASOBOW_tree_detect_kierownik`(`node` INT) RETURNS text CHARSET latin2
							[character_set_client] => latin1
                            [collation_connection] => latin1_swedish_ci
                            [Database Collation] => latin2_general_ci
                            
                            
                            
			[PROCEDURE] => Array
                (
                    [JOINL3COLUMN] => stdClass Object
                        (
                            [Procedure] => JOINL3COLUMN
                            [sql_mode] => 
                            [Create Procedure] => string() like  CREATE DEFINER=`root`@`localhost` PROCEDURE `JOINL3COLUMN`( TEST_BASE varchar(255),	TEST_TABLE varchar(255),
                            [character_set_client] => latin2
                            [collation_connection] => latin2_general_ci
                            [Database Collation] => latin2_general_ci
                        )

                )

        )
        
       
       [TABLES] 

	   			[NAME]
				[Table_type] => BASE TABLE
				[FIELDS] => Array
	                (
    	                [0] => stdClass Object
	                        (
   	                         [Field] => ID (name)
   									 [Type] => int(10)
   							 [Null] => NO
   							 [Key] => PRI
   							 [Default] => 
   							 [Extra] => auto_increment
   							 )

        
        
        
   				[INDEX] => Array
                     (
                    [PRIMARY] => stdClass Object
                        (
                            [Table] => BUILDINGS
                            [Non_unique] => 0
                            [Key_name] => PRIMARY
                            [Seq_in_index] => 1
                            [Column_name] => `ID`
                            [Collation] => A
                            [Cardinality] => 1302
                            [Sub_part] => 
                            [Packed] => 
                            [Null] => 
                            [Index_type] => BTREE
                            [Comment] => 
                       )

			   [VALUES] => Array
                (
                    [0] => stdClass Object
                        (
                            [ID] => 1
                            [NAZWA] => MIANOWNIK
                            [PYTANIE] => KTO CO
                            [OPIS] => KTO WYKONUJE
                            [FORM_TREAT] => X
                        )

                    [1] => stdClass Object
                        (
                            [ID] => 2
                            [NAZWA] => DOPEŁNIACZ
                            [PYTANIE] => KOGO CZEGO
                            [OPIS] => KOGO CZEGO
                            [FORM_TREAT] => R
                        )


		[_CRM_PROCES_USER_STATS_wiev] => Array
       	 (
            [Table_type] => VIEW
            [VIEW] => stdClass Object
                (
                    [View] => _CRM_PROCES_USER_STATS_wiev
                    [Create View] => CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `_CRM_PROCES_USER_STATS_wiev` AS select concat(`au`.`ID`,`cw`.`ID`) AS `ID`,`cps`.`ID` AS `ID_PROCES`,left(`cps`.`DESC`,50) AS `DESC`,`au`.`ADM_ACCOUNT` AS `ADM_ACCOUNT`,`cps`.`path` AS `path`,'TEORETYCZNY' AS `TEST_TYPE`,`cps`.`SCQuest` AS `SCQuest`,max(`ct`.`OCENA`) AS `OCENA`,max(`ct`.`TEST_END`) AS `TEST_END` from ((((`ADMIN_USERS` `au` left join `CRM_AUTH_PROFILE` `cap` on(((`cap`.`REMOTE_ID` = `au`.`ID`) and (`cap`.`REMOTE_TABLE` = 'ADMIN_USERS') and (`cap`.`A_STATUS` in ('NORMAL','WAITING'))))) left join `CRM_WSKAZNIK` `cw` on(((`cw`.`ID_ZASOB` = `cap`.`ID_ZASOB`) and (`cw`.`A_STATUS` in ('NORMAL','WAITING'))))) left join `CRM_TESTY` `ct` on(((`ct`.`ID_PROCES_INIT` = `cw`.`ID_PROCES`) and (`ct`.`ID_TESTER` = `au`.`ID`) and (`ct`.`TEST_TYPE` = 'TEORETYCZNY')))) left join `_CRM_PROCES_INIT_STATS` `cps` on((`cps`.`ID` = `cw`.`ID_PROCES`))) where ((`au`.`A_STATUS` = 'NORMAL') and (`cps`.`SCQuest` > 0)) group by `au`.`ID`,`cps`.`ID` union select concat(`au`.`ID`,`cw`.`ID`) AS `ID`,`cps`.`ID` AS `ID_PROCES`,left(`cps`.`DESC`,50) AS `DESC`,`au`.`ADM_ACCOUNT` AS `ADM_ACCOUNT`,`cps`.`path` AS `path`,'PRAKTYCZNY' AS `TEST_TYPE`,`cps`.`SCQuestPract` AS `SCQuestPract`,max(`ct`.`OCENA`) AS `OCENA`,max(`ct`.`TEST_END`) AS `TEST_END` from ((((`ADMIN_USERS` `au` left join `CRM_AUTH_PROFILE` `cap` on(((`cap`.`REMOTE_ID` = `au`.`ID`) and (`cap`.`REMOTE_TABLE` = 'ADMIN_USERS') and (`cap`.`A_STATUS` in ('NORMAL','WAITING'))))) left join `CRM_WSKAZNIK` `cw` on(((`cw`.`ID_ZASOB` = `cap`.`ID_ZASOB`) and (`cw`.`A_STATUS` in ('NORMAL','WAITING'))))) left join `CRM_TESTY` `ct` on(((`ct`.`ID_PROCES_INIT` = `cw`.`ID_PROCES`) and (`ct`.`ID_TESTER` = `au`.`ID`) and (`ct`.`TEST_TYPE` = 'PRAKTYCZNY')))) left join `_CRM_PROCES_INIT_STATS` `cps` on((`cps`.`ID` = `cw`.`ID_PROCES`))) where ((`au`.`A_STATUS` = 'NORMAL') and (`cps`.`SCQuestPract` > 0)) group by `au`.`ID`,`cps`.`ID` order by `ADM_ACCOUNT`,`path`,`OCENA` desc
                    [character_set_client] => utf8
                    [collation_connection] => utf8_general_ci
                )

        )


*/

  
 //   protected $parent;
    var $required_childs; //potrzebne dzieci
    var $allowed_childs; //dostepne dzieci

    var $required_attrs; //potrzebne wartosci
	var $allowed_attrs; //dostepne opcje
    var $attrs ; //opcje ustawione
    var $childs=array(); //dzieci
    var $object_type; //nazwa typu obiektu
	var $attr_relation;
    public function __construct($object_type,$parent=null) {
		echo "<br> constr ".$obj_type;
		if(empty($object_type)) {
			self::add_allowed_childs('MYSQL_SCHEMA');
		    self::makeoptions();
			self::set_type('ROOT');
		} else self::set_type($object_type,$parent);
			
    }

	function makeoptions() { //make required->possible
		foreach ($this->required_attrs  as $opt) {
			if(!in_array($opt, $this->allowed_attrs)) self::add_allowed_attrs($opt);
		} 
		foreach ($this->required_childs  as $opt) {
			if(!in_array($opt, $this->allowed_childs)) self::add_allowed_childs($opt);
		} 
	}

	function set_option($name,$value) {
		if(in_array($name, $this->allowed_attrs))
		$this->attrs[$name]=$value;
		else die('Not allowed attr!'.$name. " , allowed options(".implode(',', $this->allowed_attrs).") or childs (".implode(',', $this->allowed_childs).")");
		echo "<br> obj type ".$this->object_type;
		self::attr_relation_parse(); 
		return $this;
	}
  
	function add_required_option($name) {
		if(!in_array($name, $this->required_attrs))
			$this->required_attrs[]=$name;
	}
	function add_allowed_attrs($name) {
		if(!in_array($name, $this->allowed_attrs))
			$this->allowed_attrs[]=$name;
	}
	function add_allowed_childs($name) {
		if(!in_array($name,$this->allowed_childs))
			$this->allowed_childs[]=$name;
	}
	function add_required_child($name) {
		if(!in_array($name, $this->required_childs))
			$this->required_childs[]=$name;
	}

  
	protected function set_type($name,$parent) {
	    //if(!empty($parent) && ($name<>'ROOT'))
	    //$this->object_type=$parent."::".$name;
	     	    $this->object_type=$name;
    }
  
  
	function create_parent_object($name) {
		if(empty($name)) die('Set obj type to create parent!');
//		$this->childs[]=new self($name,$this->object_type);
//		return current($this->childs);
		$new=new self($name,$this->object_type);
		$this->childs[]=$new;
		return $new;

	}
	
		function new_child($name) {
			foreach($this->required_attrs as $opt) {
				if(!isset($this->attrs[$opt])) {
				 echo "<br> Error - not all requested attrs were set: (".$opt.") are set ".implode(',', $this->attrs);
				 $this;
				}
			}
			
			
			if(in_array($name,$this->allowed_childs)) {
				echo "<br> executing child ".$name." using class ".$this->object_type;
				$classname=$this->object_type;
				//return self::$name($name);
				return $classname::$name($name);

			}
			else echo "<br> Error - not possible option ".$name." only ".implode(',', $this->allowed_childs);
	
		}
  
     
   
  
  
	protected	function add_attr_relation($attr_name,$attr_value,$attr_require) {
		$this->attr_relation[$attr_name][$attr_value]=$attr_require;
	}

	function attr_relation_parse() {
		foreach($this->attrs as $name=>$val) {
			if(isset($this->attr_relation[$name])) {
				foreach($this->attr_relation[$name] as $val_test=>$require)	{
					if($val==$val_test) self::add_required_option($require);
				}
			}
		}
	}
	

  


	function get_info($obj) {
		var_dump($obj);
		
	}





function __installer_menu() {
	//TODO
  	$_GET['ID_ROOT_DB_NEW_TABLE'] = V::get('ID_ROOT_DB_NEW_TABLE', '', $_GET);
  	$_GET['ID_ROOT_FUNCTIONS_NEW_FUNCTION'] = V::get('ID_ROOT_FUNCTIONS_NEW_FUNCTION', '', $_GET);
  	$_GET['ID_ROOT_PROCES_NEW_PROCES'] = V::get('ID_ROOT_PROCES_NEW_PROCES', '', $_GET);
  	$_GET['ID_FUNCTION_ADD_PROCESS'] = V::get('ID_FUNCTION_ADD_PROCESS', '', $_GET);


}


function __install($obj) {
	
	if(empty($obj))
	$cur=$this;
	
	foreach($cur->childs as $id=>$obj) {
			DEBUG_S(-3,'Instalacja modulu '.$id." uzywajac klasy ".$obj->object_type,$obj);
			$klasa=$obj->object_type;
			MYSQL_SCHEMA::__install($obj);
			
	}
	
	//DB::query($sql);
	
	
	//TODO uzyj funkcji do zarejestrowania komorek tej tabeli w ZASOBACH
	//TODO zglos funkcje ID w zasobach
	//TODO zarejestruj jakis proces w systemie do obslugi tej tabeli - dedykowany proces do uzycia funkcji oraz uzycia komorek (wskaz numer procesu gdzie go wstawic)
	//TODO wybierz jakies stanowisko do podpiecia tego procesu

	
	}


}

class ROOT extends InstallerHelper {
	
	
	 function MYSQL_SCHEMA($name) {
		$obj=self::create_parent_object($name);
	 	$obj->add_allowed_childs('TABLES');
	    $obj->add_allowed_childs('__SCHEMA_FUNCTIONS__ARRAY__');
//	    $obj->add_required_option('TABLE_NAME');
	    $obj->makeoptions();
		return $obj;
    }

	
}


class MYSQL_SCHEMA extends ROOT {
	
	 function TABLES($name) { //parent do MYSQL_SCHEMA
		$obj=self::create_parent_object($name);
		$obj->add_required_option('NAME');
		$obj->add_required_option('Table_type');

	 	$obj->add_allowed_childs('VALUES');
	    $obj->add_allowed_childs('INDEX');
	    $obj->add_required_child('FIELDS');
	    $obj->makeoptions();
		return $obj;
    }
	
	
	
	function __install($obj) {
	
	
	$i=0;
	foreach($obj->childs as $id=>$obj_) {
		$i++;
			DEBUG_S(-3,'Installer MYSQL Instalacja modulu '.$cur->object_type." uzywajac klasy ".$obj_->object_type,$obj_,__FILE__,__FUNCTION__,__LINE__);
			$klasa=$obj_->object_type;
			$ret[$i]=$klasa::__install($obj_);
		}
	DEBUG_S(-3,'Installer MYSQL Instalacja modulu - RESULT',$ret,__FILE__,__FUNCTION__,__LINE__);
	foreach($ret as $id=>$obj_) {
		foreach($obj_ as $id_=>$obj__) {
			if($id_=='SQL_NEW_TABLE') echo "<HR> SQL : ".$obj__;
			if($id_=='SQL_ALTER_TABLE') {
				foreach($obj__ as $obj___) {
					 echo "<HR> SQL : ".$obj___;
				}
			}
		}
	} 
	return $ret;
	}
	
	
}


class TABLES extends MYSQL_SCHEMA {
	
	  function INDEX($name) { //parent do MYSQL_SCHEMA
		$obj=self::create_parent_object($name);
		$obj->add_required_option('Non_unique');
		$obj->add_required_option('Key_name');
		$obj->add_required_child('Column_name'); //kolumny

	    $obj->makeoptions();
		return $obj;
    }
      function FIELDS($name) { //parent do MYSQL_SCHEMA
		$obj=self::create_parent_object($name);
		$obj->add_required_option('Field');
		$obj->add_required_option('Null');
		$obj->add_required_option('Key');
		$obj->add_required_option('Default');
		$obj->add_required_option('Extra');
		$obj->add_required_child('Type');

	    $obj->makeoptions();
		return $obj;
    }

function __install($obj) {
	
	$return->SQL_NEW_TABLE="create table if not exists ".$obj->attrs['NAME']." ( ";



	$i=0;
	foreach($obj->childs as $id=>$obj_) {
	$i++;
			DEBUG_S(-3,'Installer MYSQL::TABLE Instalacja modulu '.$cur->object_type." uzywajac klasy ".$obj_->object_type,$obj_);
			$klasa=$obj_->object_type;
			$obj_type=$obj_->object_type;
			
			$ret[$i]->$obj_type=$klasa::__install($obj_);

			if($obj_->object_type=='FIELDS') {
				$ret[$i]->SQL=" `{$obj_->attrs['Field']}` {$ret[$i]->FIELDS} ";
				if(!empty($obj_->attrs['Default'])) $ret[$i]->SQL=" default ".$obj_->attrs['Default']." ";
				if(!isset($return->SQL_FIELDS)) $return->SQL_FIELDS=$ret[$i]->SQL; else  $return->SQL_FIELDS.=",".$ret[$i]->SQL;
				$return->SQL_ALTER_TABLE[]="alter ignore table ".$obj->attrs['NAME']." add ".$ret[$i]->SQL;
			}

//			$ret[$i]->TYPE

	}
	
	
	$return->SQL_NEW_TABLE.=$return->SQL_FIELDS." ) ";
	DEBUG_S(-3,'Installer MYSQL::TABLE zwrocil ',array($ret,$return),__FILE__,__FUNCTION__,__LINE__);
	return $return;

}
	
}

class INDEX extends TABLES {	

	function Column_name($name) {
			$obj=self::create_parent_object($name);
	 		$obj->add_required_option('column'); //column to index
	 		$obj->add_allowed_attrs('Non_unique'); //column to index

	 		$obj->makeoptions();
	 		return $obj;
	}
	
	
	 	 function __install($obj) {
		 	 if(isset($obj->attrs['Non_unique'])) 
		 	  $return->CREATE_SQL="add unique `{$obj->attrs['Key_name']}` (";
	 	 	 else 
	 	 	  $return->CREATE_SQL="add key `{$obj->attrs['Key_name']}` (";


		 	 $i=0;
		 	 foreach($obj->childs as $id=>$obj_) {
			 $i++;
			   DEBUG_S(-3,'Installer MYSQL::TABLE:INDEX Instalacja modulu w przygotowaniu '.$cur->object_type." uzywajac klasy ".$obj_->object_type,$obj_,__FILE__,__FUNCTION__,__LINE__);
			   $ret[$i]->COLUMNS=$obj_->attrs['column'];
			   if(isset($column)) $column.=",`".$obj_->attrs['column']."`"; else $column="`".$obj_->attrs['column']."`";
			}
			$return->CREATE_SQL.=$column.")";
			return $return;
//			return $ret;
		
	}
	
	
}


class FIELDS extends TABLES { //typ typy komorek
	
		function Type($name) {
			$obj=self::create_parent_object($name);
	 		$obj->add_allowed_childs('varchar');
	 		$obj->add_allowed_childs('enum');
	 		$obj->add_allowed_childs('int');
	 		$obj->add_allowed_childs('text');

	 		$obj->makeoptions();
	 		return $obj;
	 }
	
	
	
	 function __install($obj) {
	
		 foreach($obj->childs as $id=>$obj) { //tylko jeden wiersz jest
			DEBUG_S(-3,'Installer MYSQL::TABLE:FIELDS Instalacja modulu '.$cur->object_type." uzywajac klasy ".$obj->object_type,$obj);
			$klasa=$obj->object_type;
			$ret=$klasa::__install($obj);
			if(!empty($ret)) $return=$ret->TYPE."".$ret->SQL_SIZE."";
			DEBUG_S(-3,' - zwrocil ',$sql);
			return $return;

		 }

	}

	
	
}




class Type extends FIELDS { //typ typy komorek
	
		function int($name) {
			$obj=self::create_parent_object($name);
	 		$obj->add_required_option('M'); //as in mysql documentation - it is the size of cell
	 		$obj->makeoptions();
	 		return $obj;
	 }
	 function varchar($name) {
			$obj=self::create_parent_object($name);
	 		$obj->add_required_option('M'); //as in mysql documentation - it is the size of cell
	 		$obj->makeoptions();
	 		return $obj;
	 }
	  function text($name) {
			$obj=self::create_parent_object($name);
	 		$obj->makeoptions();
	 		return $obj;
	 }
	 
	 
	 	 function __install($obj) {

		 	 foreach($obj->childs as $id=>$obj) {
	
			DEBUG_S(-3,'Installer MYSQL::TABLE:FIELDS::TYPE Instalacja modulu '.$cur->object_type." uzywajac klasy ".$obj->object_type,$obj);
				if(isset($obj->attrs['M'])) {
					$ret->SQL_SIZE="(".$obj->attrs['M'].")";
					$ret->TYPE=$obj->object_type;
					
				}	else $ret->TYPE=$obj->object_type;
				
				return $ret;
			}
		
	}
	 
	
}







