<?php

class admin_schema extends module {
	
	var $templ = "admin_schema.htm";
	var $_get_vars = array( 'act', 'obj_name', 'attr_name'  );
	var $_post_vars = array( 'act', 'attr_name', 'attr_type', '_obj', 'obj_names', 'obj_title' );
	var $obj_cache = array();
	var $migrationPrefix = '';

	function _init() {
		$this->migrationPrefix = date('Ymd-Hi');
		return parent::_init();
	}

	function _on_() {
		global $R, $core_db;
		$tpl = $R->getTpl( $this->templ, 'body' );
		$tplr = $R->getTpl( $this->templ, 'row' );
		
		$db2 = $core_db->q( "SELECT DISTINCT `obj_name` FROM `_sys_datatypes` ORDER BY `obj_name`" );
		while( $db2->r() ) {
			$tt = $R->set('obj_name', $db2->f('obj_name'), $tplr );
			$tpl = $R->parse( 'rows', $tt, $tpl );
			$this->obj_cache[] = $db2->f('obj_name');
		}
		$tpl = $R->set( 'form', $this->r_table(), $tpl );
		
		return $R->clear( $tpl );
	}
	
	
	function r_table() {
		global $R, $core_db;
		
		if (!$this->obj_name) return;
		
		$tpl = $R->getTpl( $this->templ, 'edit_table' );
		$tplr = $R->getTpl( $this->templ, 'edit_table_row' );
		
		$db2 = $core_db->q( 'SELECT * FROM `_sys_datatypes` WHERE `obj_name` = "' . $this->obj_name . '" ORDER BY `attr_order`' );
		while( $db2->r() ) {
			$tt = $R->set('name', $db2->f('attr_name'), $tplr );
			$tt = $R->set('attr_desc', $db2->f('attr_desc'), $tt );
			$tt = $R->set('attr_templ', $db2->f('attr_templ'), $tt );
			$tt = $R->set('attr_order', $db2->f('attr_order'), $tt );
			$tt = $R->set('attr_hide', $db2->f('attr_hide')?'checked':'', $tt );
			$tt = $R->set('attr_mand', $db2->f('attr_mand')?'checked':'', $tt );
			$tt = $R->set('attr_view', $this->r_types( $db2->f('attr_type') ), $tt );
			$tpl = $R->parse( 'rows', $tt, $tpl );
		}
		$tpl = $R->set('obj_name', $this->obj_name, $tpl );
		$tpl = $R->set('attr_view', $this->r_types(), $tpl );

		$sql = "SELECT TABLE_COMMENT FROM `information_schema`.`TABLES` where TABLE_SCHEMA = '".$core_db->dbname."' and TABLE_NAME = '".$this->obj_name."' ";
		$db2 = $core_db->q($sql);
		$db2->nr();
		$tpl = $R->set('obj_title', htmlspecialchars($db2->f('TABLE_COMMENT')), $tpl);


		return $R->clear( $tpl );
	}
	
	function r_types( $val = '' ) {
		global $loaded_attrs;
		sort($loaded_attrs);
		sort($this->obj_cache);
		$html = '<option value="" selected>---</option>';
		foreach ($loaded_attrs as $v ) {
		    $classname = 'attr_' . $v;
		    $size = $classname::getDBType();
		    
		    //eval('$'."size = attr_$v::getDBType();");
			
			switch( $v ) {
				case 'LINK':
					$html .= '<optgroup label="'.$v.'">';
					foreach( $this->obj_cache as $obj_name ) {
						$vv = $v . '|' . $obj_name;
						$title = "LINK " . $obj_name;
						if ( $vv == $val ) 
							$html .= '<option value="' . $vv . '" selected>' . $title . " [$size]" .'</option>';
						 else
							$html .= '<option value="' . $vv . '">' . $title . " [$size]" .'</option>';
					}
					$html .= '</optgroup>';
				break;
				case 'MLINK':
					$html .= '<optgroup label="'.$v.'">';
					foreach( $this->obj_cache as $obj_name ) {
						$vv = $v . '|' . $obj_name;
						$title = "MLINK " . $obj_name;
						if ( $vv == $val ) 
							$html .= '<option value="' . $vv . '" selected>' . $title . " [$size]" .'</option>';
						 else
							$html .= '<option value="' . $vv . '">' . $title . " [$size]" .'</option>';
					}
					$html .= '</optgroup>';
				break;
				default:
					if ( $v == $val ) 
						$html .= '<option value="' . $v . '" selected>' . $v ." [$size]" . '</option>';
					 else
						$html .= '<option value="' . $v . '">' . $v . " [$size]" .'</option>';
				break;
			}			
		}
		return $html;
	}
	
	function _on_add_attr() {
		global $cat, $core_db, $auth;
		if (!$this->attr_name ) cdie('no attr name');
		if (!$this->attr_type ) cdie('no attr type');

		$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибута" );
        $this->do_add($this->obj_name, $this->attr_name, $this->attr_type);
        
		_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
	}
    
    function do_add( $obj_name, $attr_name, $attr_type, $attr_title = '', $attr_templ = '', $attr_order = 100 ) {
		global $cat, $core_db, $auth;
		$sys_obj = false;
		if ( ( strpos( $obj_name, '_sys_') !== false ) ) {
			$sys_obj = true;	
		}
		
		
		/* CREATE TABLE */
		$sql  = "CREATE TABLE IF NOT EXISTS `" . $obj_name . "` (";
		$sql .= "	`id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ";
		$sql .= ")  ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci";
		$core_db->q( $sql );
		$this->sLog( $sql );
		/* ADD Attribute */
		
		$v =  explode('|',$attr_type);
		$v = $v[0];
	    eval('$'."size = attr_$v::getDBType();");

		$sql = "ALTER TABLE `" . $obj_name . "` ADD `" . $attr_name . "` " . $size . " NOT NULL";
		$core_db->q( $sql );
		$this->sLog( $sql );

		if (substr($attr_type,0,4) == 'LINK') {
		/* ADD index */
			$sql = "ALTER TABLE `" . $obj_name . "` ADD INDEX ( `" . $attr_name . "` )";
			$core_db->q( $sql );
			$this->sLog( $sql );
		}


		if ($attr_type == 'tree_object') {
			/* ADD index */
			$sql = "ALTER TABLE `" . $obj_name . "` ADD INDEX ( `" . $attr_name . "` )";
			$core_db->q( $sql );
			$this->sLog( $sql );
		}

		/* ADD to Datatype table */
		$sql = 'REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("'.$obj_name.'","'.$attr_name.'","'.$attr_type.'","'.$attr_title.'","'.$attr_templ.'","'.$attr_order.'")';

		$core_db->q( $sql );
		$this->sLog( $sql );        
    }
    
    function _on_do_urled() {
        global $cat;

		$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибутов" );
        $this->do_add($this->obj_name, 'title', 'input', 'Название','', 50);
        $this->do_add($this->obj_name, 'url', 'full_url', 'Полный URL','prefix|cat_id',60 );
        $this->do_add($this->obj_name, 'description', 'redactor_html', 'Текстовый блок');
        $this->do_add($this->obj_name, 'page_description', 'input', 'seo description','',504);
        $this->do_add($this->obj_name, 'page_h1', 'input', 'seo H1','',502);
        $this->do_add($this->obj_name, 'page_keywords', 'input', 'seo keywords','',503);
        $this->do_add($this->obj_name, 'page_title', 'input', 'seo title','',501);
        $this->do_add($this->obj_name, '_sys_deleted', 'checkbox', 'Удалённый','', 1000);
        $this->do_add($this->obj_name, '_sys_order', 'int12', 'Порядок сортировки','', 800);
        $this->do_add($this->obj_name, '_sys_unvisible', 'checkbox', 'Невидимый','', 999);
        $this->do_add($this->obj_name, '_sys_lastchange', 'datetime_modify', 'Последнее изменение','', 999);

		_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
    }


    function _on_do_treeobj() {

        global $cat;

		$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибутов" );
        $this->do_add($this->obj_name, 'title', 'input', 'Название','', 50);
        $this->do_add($this->obj_name, 'parent_id', 'tree_object', 'Родитель','',60 );
        $this->do_add($this->obj_name, 'path_ids', 'input', 'Путь по ID');
        $this->do_add($this->obj_name, 'path_titles', 'input', 'Путь по названию','',504);
        $this->do_add($this->obj_name, 'level', 'int12', 'Уровень','',502);
        $this->do_add($this->obj_name, '_sys_unvisible', 'checkbox', 'Невидимый','', 999);

		_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
    }

	
	function _on_save_object() {
		global $core_db, $cat, $auth;
		$attrs = array( 'attr_type', 'attr_templ', 'attr_desc', 'attr_hide', 'attr_mand', 'attr_order', '_sys_deleted' );
		$obj = $this->_obj[$this->obj_name];

		$sys_obj = false;
		if ( ( strpos( $this->obj_name, '_sys_') !== false ) ) {
			$sys_obj = true;	
		}


		// Вычисляем текущие хеши, чтобы понять, есть ли изменения в данных
		$oldObjHash = [];
		$db2 = $core_db->q( 'SELECT * FROM `_sys_datatypes` WHERE `obj_name` = "' . $this->obj_name . '" ORDER BY `attr_order`' );
		while( $db2->r() ) {
			$attr_hash_array = [];
			foreach ($attrs as $k ) {
				$attr_hash_array[$k] = $db2->f($k);		
			}
			$oldObjHash[$db2->f('attr_name')] = md5(json_encode($attr_hash_array));
		}

		$sql = "SELECT TABLE_COMMENT FROM `information_schema`.`TABLES` where TABLE_SCHEMA = '".$core_db->dbname."' and TABLE_NAME = '".$this->obj_name."' ";
		$db2 = $core_db->q($sql);
		$db2->nr();
		$oldObjTitle = $db2->f('TABLE_COMMENT');
	

		foreach ( $obj  as $attr_name => $attr_vals ) {
			$presave = [];
			foreach ($attrs as $k ) {
				if (isset( $attr_vals[$k])) {
					$presave[$k] = $attr_vals[$k];		
				} else {
					$presave[$k] = "0";
				}
			}
			$attr_hash = md5(json_encode($presave));
		
			$presave['obj_name'] = $this->obj_name;		
			$presave['attr_name'] = $attr_name;		
			if ($attr_hash != $oldObjHash[$attr_name]) {
				$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Изменение атрибута " . $attr_name );
				$sql = 'REPLACE INTO `_sys_datatypes` (`' . implode('`, `',array_keys($presave)) . '`) VALUES ("'.implode('" , "',array_values($presave)) . '")';
				$core_db->q( $sql );
				$this->sLog( $sql );
			}
		}

		if ($oldObjTitle != $this->obj_title) {
			$sql = "ALTER TABLE `".$this->obj_name."` COMMENT = '".db_escape_string($this->obj_title)."';";
			$core_db->q( $sql );
			$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Изменение комментария " . $this->obj_name );
			$this->sLog( $sql );
		}


		_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
	}
	
	function sLog( $txt = '' ) {
		$f = fopen( _ENGINE_DIR . 'migrations/' . $this->migrationPrefix . '-' . $this->obj_name . ".sql", "a" );
		fputs($f, $txt . ";\n" );
		fclose($f);

		$this->saveMigration($this->migrationPrefix . '-' . $this->obj_name . ".sql");

	}
	
	
	function _on_del_attr() {
		global $core_db, $cat;
		$obj_name = $this->obj_name;
		$attr_name = $this->attr_name;
		if ( $obj_name && $attr_name ) {

			$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Удаление атрибута " . $attr_name );

			$core_db->q("DELETE FROM `_sys_datatypes` WHERE `obj_name` = '".$obj_name."' AND `attr_name` = '".$attr_name."'");
			$this->sLog("DELETE FROM `_sys_datatypes` WHERE `obj_name` = '".$obj_name."' AND `attr_name` = '".$attr_name."'");

			$core_db->q("ALTER TABLE `".$obj_name."` DROP `".$attr_name."`");
			$this->sLog("ALTER TABLE `".$obj_name."` DROP `".$attr_name."`");
		}
		
		_redirect('?cat=' . $cat->cat . '&obj_name='. $obj_name);
	}

   function _on_export() {
        global $cat, $core_db;
        
        $objname = $this->obj_name;
        
        $sql = "SHOW CREATE TABLE `".$objname."`";
        $db2 = $core_db->q($sql);
        $db2->nr();
        $sql_arr[] = $db2->f('Create Table');
        
        
        $sql = "SELECT * FROM `_sys_datatypes` WHERE `obj_name` = '".$objname."'";
        $db2 = $core_db->q($sql);
        while( $db2->nr() ) {
            
             $sql_arr[] = "REPLACE INTO `_sys_datatypes` 
                (`obj_name`,`attr_name`,`attr_type`,`attr_templ`,`attr_desc`,`attr_hide`,`attr_mand`,`attr_order`)
                VALUES
                (
                '".db_escape_string($db2->f('obj_name'))."',
                '".db_escape_string($db2->f('attr_name'))."',
                '".db_escape_string($db2->f('attr_type'))."',
                '".db_escape_string($db2->f('attr_templ'))."',
                '".db_escape_string($db2->f('attr_desc'))."',
                '".db_escape_string($db2->f('attr_hide'))."',
                '".db_escape_string($db2->f('attr_mand'))."',
                '".db_escape_string($db2->f('attr_order'))."'
                )
            ";
        }
        
        
        $html .= implode($sql_arr, ';<br>');
        
        echo $html;
        die();
    }

    function _on_export_grp() {
        global $core_db;
        
        foreach( $this->obj_names as $objname ) {
                $sql = "SHOW CREATE TABLE `".$objname."`";
                $db2 = $core_db->q($sql);
                $db2->nr();
                $sql_arr[] = $db2->f('Create Table');
                
                
                $sql = "SELECT * FROM `_sys_datatypes` WHERE `obj_name` = '".$objname."'";
                $db2 = $core_db->q($sql);
                while( $db2->nr() ) {
                    
                     $sql_arr[] = "REPLACE INTO `_sys_datatypes` 
                        (`obj_name`,`attr_name`,`attr_type`,`attr_templ`,`attr_desc`,`attr_hide`,`attr_mand`,`attr_order`)
                        VALUES
                        (
                        '".db_escape_string($db2->f('obj_name'))."',
                        '".db_escape_string($db2->f('attr_name'))."',
                        '".db_escape_string($db2->f('attr_type'))."',
                        '".db_escape_string($db2->f('attr_templ'))."',
                        '".db_escape_string($db2->f('attr_desc'))."',
                        '".db_escape_string($db2->f('attr_hide'))."',
                        '".db_escape_string($db2->f('attr_mand'))."',
                        '".db_escape_string($db2->f('attr_order'))."')
                    ";
                }
                
        

        }
        
        header('Content-Disposition: attachment; filename=dump.sql');

        $html .= implode($sql_arr, ';' . PHP_EOL);
        echo $html;
        
        die();
    }
    
    
    function saveMigration($filename) {
    	global $core_db;
   	    $core_db->q('SELECT apply_datetime FROM _sys_db_migrations WHERE `filename` = "'.db_escape_string($filename).'" ');
   	    if (!$core_db->nr()) {
		 	$core_db->q('INSERT INTO _sys_db_migrations (`filename`,`apply_datetime`) values ("'.db_escape_string($filename).'", "'.date('Y-m-d H:i:s').'" ) ');
		}
    }

}	

?>