ACC SHELL

Path : /srv/www/vhosts/agroing/web/models/
File Upload :
Current File : /srv/www/vhosts/agroing/web/models/import_model.php

<?php
/**
 * k importu dat z jinych systemu
 * je potreba mit nahranou databazi daneho systemu v nasi db
 * webove rozhrani je na adrese /admin/import
 *
 * @author Vlahovic
 */
class Import_model extends Sites_model{
	private $import_posible_systems=array('radiant'=>'Radiant');
	private $import_database;
	private $import_system;
	private $import_tmp_tables=array('sites','sites_parts','files','urls');
	private $import_ready=array();
	private $import_system_method;
	private $control_system_method;
	private $import_db_conn;
	private $convert_id=array();
	private $convert_idr=array();
	/**
	 * absolutni adresa do rootu projektu s lomitkem na konci
	 */
	private $app_root;
	/**
	 * s http:// na zacatku, bez lomitka na konci
	 */
	private $import_server;
	/**
	 * absolutni adresa s lomitkem na konci
	 */
	private $images_dir=false;

	/* ************************************************************************ */
	/* magic methods																														*/
	/* ************************************************************************ */
	public function __construct()
	{
		parent::__construct();
	}


	public function __destruct()
	{
		// ackoliv jde o temporary table, tak na localhostu se mi po ukonceni pripojeni neodstranily
		// takze je preventivne tady jeste dropuju manualne...
		foreach($this->import_tmp_tables as $table){
			$query="DROP TABLE `tmp_".$table."`";
			$this->db->query($query);
		}
	}

	/* ************************************************************************ */
	/* public methods																														*/
	/* ************************************************************************ */
	public final function do_import($database,$system,$server){
		$return=false;
		// muze trvat hooodne dlouho...
		set_time_limit(0);
		// nastaveni, testovani...
		$this->set_app_root()->set_import_database($database)->set_import_system($system)->set_import_server($server)->set_images_dir()->create_temporary_tables()->set_import_system_method()->set_control_system_method()->set_import_db_conn();
		// importuje, pokud nejsou chyby
		$import_system=($this->is_import_ready() && $this->control_system() ? $this->import_system() : false);
		if($import_system){
			// prehrne z docasne tabulky do ostre, doplni lft a rgt, prepise id zaznamu
			$return=$this->move_data_to_production_table();
		}
		elseif($import_system===null){
			throw new Exception('No rows imported to temporary table.');
		}
		else{
			throw new Exception('Error during import data to temporary tables or incorect output value of import method.');
		}
		return $return;
	}

	public final function get_import_posible_systems(){
		return $this->import_posible_systems;
	}

	/* ************************************************************************ */
	/* private methods																													*/
	/* ************************************************************************ */
	private function set_app_root(){
		$this->app_root=str_replace(array('\\','models/import_model.php'),array('/',false),__FILE__);
		return $this;
	}

	private function set_images_dir(){
		$this->images_dir=$this->app_root.'w/'.$this->data['settings']['name'].'/files/';
		return $this;
	}

	private function set_import_database($database){
		$this->import_database=$database;
		return $this;
	}

	private function set_import_system($system){
		$this->import_system=$system;
		return $this;
	}

	private function set_import_server($server){
		$this->import_server='http://'.str_ireplace('http://', false, $server);
		if(substr($this->import_server, -1)=='/'){
			$this->import_server=substr($this->import_server, 0, -1);
		}
		return $this;
	}

	/**
	 * pripojeni k databazi ze ktere se bude importovat
	 *
	 * @return Import_model
	 */
	private function set_import_db_conn(){
		$config=array();
		$config['hostname'] = DB_HOST;
		$config['username'] = DB_USER;
		$config['password'] = DB_PASS;
		$config['database'] = $this->import_database;
		$config['dbdriver'] = "mysql";
		$config['dbprefix'] = "";
		$config['pconnect'] = FALSE;
		$config['db_debug'] = TRUE;
		$config['cache_on'] = FALSE;
		$config['cachedir'] = "";
		$config['char_set'] = "utf8";
		$config['dbcollat'] = "utf8_general_ci";

		$this->import_db_conn=$this->load->database($config,true);
		if(!$this->import_db_conn){
			throw new Exception('Cant connect import database "'.$this->import_database.'".');
			$this->import_ready[]=false;
		}
		return $this;
	}

	/**
	 * nastavi nazev metody, ktera bude k importu pouzita
	 * a hned otestuje, zda existuje
	 *
	 * @return Import_model
	 */
	private function set_import_system_method(){
		$this->import_system_method='import_system_'.$this->import_system;
		$this->exists_specific_method('import');
		return $this;
	}

	/**
	 * nastavi nazev metody, ktera bude pouzita ke kontrole
	 * a hned otestuje, zda existuje
	 *
	 * @return Import_model
	 */
	private function set_control_system_method(){
		$this->control_system_method='control_system_'.$this->import_system;
		$this->exists_specific_method('control');
		return $this;
	}

	/**
	 * vytvori docasne tabulky pro import
	 *
	 * @return Import_model
	 */
	private function create_temporary_tables(){
		foreach($this->import_tmp_tables as $tmp_table){
			$new_query=array();
			// zjisti strukturu
			$query="SHOW CREATE TABLE ".$tmp_table;
			$create=$this->db->query($query)->row_array();
			// prida TEMPORARY a zmeni nazev
//			$query=str_replace(array('TABLE `'.$tmp_table.'`',"\r\n","\n"), array('TABLE IF NOT EXISTS `tmp_'.$tmp_table.'`','[[:br]]','[[:br]]'),$create['Create Table']);
			$query=str_replace(array('TABLE `'.$tmp_table.'`',"\r\n","\n"), array('TEMPORARY TABLE IF NOT EXISTS `tmp_'.$tmp_table.'`','[[:br]]','[[:br]]'),$create['Create Table']);
			// rozseka po radcich
			$query=explode('[[:br]]',$query);
			// posledni cast nahradi - odstrani autoinkrement, typ tabulky, ...
			$query[(count($query)-1)]=')';
			// vyhodi cizi klice, prida parent_id...
			foreach($query as $i => $v){
				if(strpos($v, 'CONSTRAINT')!==false){
					$new_query[($i-1)]=substr($query[($i-1)], 0,-1);
//					unset($query[$i]);
				}
				else{
					$new_query[]=$v;
				}
				// do sites prida parent_id
				if($tmp_table=='sites' && $i==1){
					$new_query[]='  `parent_id` int(11) unsigned NULL,';
					$new_query[]='  `list` int(8) unsigned NOT NULL,';
				}
				elseif($tmp_table=='urls' && $i==1){
					$new_query[]='  `id_sites` int(11) unsigned NULL,';
				}
			}
			$query=$new_query;
			// spoji
			$query=implode("\n",$query);
			// vytvori
			$this->import_ready[]=$this->db->query($query);
		}
		return $this;
	}

	/**
	 * info o tom, zda je mozno pokracovat
	 *
	 * @return boolean
	 */
	private function is_import_ready(){
		if(in_array(false, $this->import_ready)){
			return false;
		}
		return true;
	}


	/**
	 * zjistuje jestli existuje metoda pro prislusnou operaci
	 *
	 * @return boolean
	 */
	private function exists_specific_method($use){
		$method_name=$use.'_system_'.$this->import_system;
		if(method_exists($this, $method_name)){
			return true;
		}
		$this->import_ready[]=false;
		throw new Exception('Unexisting method "'.$method_name.'" for "'.$use.'" selected system "'.$this->import_system.'".');
		return false;
	}

	/**
	 * vola prislusnou kontrolni metodu
	 *
	 * @return boolean
	 */
	private function control_system(){
		$method=false;
		$method=$this->control_system_method;
		// tvurce kontrolni metody by ji mel postavit tak, aby vracela boolean
		return $this->$method();
	}

	/**
	 * jen vola prislusnou importovaci metodu
	 *
	 * @return boolean
	 */
	private function import_system(){
		$method=false;
		$method=$this->import_system_method;
		// tvurce importovaci metody by ji mel postavit tak, aby vracela boolean
		return $this->$method();
	}

	/**
	 * kontroluje, jestli ve zdrojove databazi jsou pozadovane tabulky
	 *
	 * @param boolean $needed_tables
	 */
	private function control_imported_system_tables($needed_tables){
		$needed_tables_working=array();
		foreach($needed_tables as $table){
			$needed_tables_working[$table]=false;
		}
		$query="SHOW TABLES";
		$tables=$this->import_db_conn->query($query)->result_array();
		foreach($tables as $v){
			if(isset($needed_tables_working[$v['Tables_in_'.$this->import_database]])){
				$needed_tables_working[$v['Tables_in_'.$this->import_database]]=true;
			}
		}
		if(in_array(false, $needed_tables_working)){
			$this->import_ready[]=false;
			throw new Exception('No needed tables in database "'.$this->import_database.'".');
			return false;
		}
		return true;
	}


	/**
	 * uklada jednotlive strany do tmp tabulky
	 *
	 * @param integer $id
	 * @param integer $parent_id
	 * @param string $published_at [optional]
	 * @param boolean $sitemap [optional]
	 * @param string $tags [optional]
	 * @param integer $list [optional]
	 * @return boolean
	 */
	private function save_tmp_site($id,$parent_id,$published_at=false,$list=0,$sitemap=false,$tags=false){
		if($id){
			if(empty($published_at) || strpos($published_at,"0000")!==false){
				$published_at = date("Y-m-d H:i:s");
			}
			$parent_id=(intval($parent_id) ? intval($parent_id) : 'NULL');
			$sitemap=($sitemap ? '1' : '0');
			$tags=(trim($tags) ? "#".str_replace(" ","##",trim($tags))."#" : false);
			$query="INSERT INTO tmp_sites
				(`id`,`parent_id`,`published_at`,`sitemap`,`tags`,`list`)
				VALUES
				(".intval($id).", ".$parent_id.", '".$published_at."', ".$sitemap.", '".$tags."', ".intval($list).")";
			$res=$this->db->query($query);
			return $res;
			var_dump($query);
		}
		return false;
	}

	/**
	 * uklada casti strany
	 *
	 * @param integer $id
	 * @param string $content
	 * @param string $part
	 * @param string $lang [optional]
	 * @return boolean
	 */
	private function save_tmp_site_part($id,$content,$part,$lang='cz'){
		if($id && $content){
			$query="INSERT INTO tmp_sites_parts
				(`id_sites`,`content`,`part`,`lang`)
				VALUES
				(".intval($id).", '".$content."', '".$part."', '".$lang."')";
			return $this->db->query($query);
		}
		return false;
	}


	/**
	 * ulozi adresy clanku
	 *
	 * @param integer $id
	 * @param string $url
	 * @return boolean
	 */
	private function save_tmp_urls($id,$url){
		$return=false;
		if($id && $url){
			$query="INSERT INTO tmp_urls
				(`id_sites`,`sef`)
				VALUES
				(".intval($id).",'".$url."')";
			$return=$this->db->query($query);
		}
		return $return;
	}


	/**
	 * ulozi obrazek do pomocne tabulky
	 *
	 * @param integer $id_sites
	 * @param string $url skutecna (cela) adresa obrazku - http protokol
	 * @param string $file [optional]
	 * @param string $title [optional]
	 * @param integer $list  [optional]
	 * @return boolean
	 */
	private function save_tmp_file($id_sites,$url,$file=false,$title=false,$list=0){
		$return=false;
		if($url){
			$query="INSERT INTO tmp_files
				(`id_sites`,`file`,`file_title`,`file_url`,`list`)
				VALUES
				(".intval($id_sites).", '".$file."', '".$title."', '".$url."', ".intval($list).")";
			$return=$this->db->query($query);
		}
		return $return;
	}


	/**
	 * data z docasne tabulky prhrne do ostre a doplni nezbytne udaje jako lft, rgt, opravena id, atd.
	 *
	 * @return boolean
	 */
	private function move_data_to_production_table(){
		$return=false;
		$result=array();
		$root_relation=($this->root_relation['id'] ? $this->get_relation($this->root_relation['id'],false,false) : false);
		$root_lft=(!empty($root_relation) ? $root_relation['rgt'] : false);
		$root_depth=(!empty($root_relation) ? $root_relation['depth'] : 0);
		$root_idr=(!empty($root_relation) ? $root_relation['id'] : 0);
		$root_id=(!empty($root_relation) ? $root_relation['id_sites'] : 0);
		$root_list=($this->children_count($root_idr))+1;
		$this->root_relation['id']=null;
		$query="
			# zjisti detaily jednotlivych zaznamu
			SELECT
				`id`,
				`id` AS `id_sites`,
				IFNULL(`parent_id`,'NULL') AS `parent_id`,

				# po testu funkcnosti smazat uplne...
				# IFNULL(`parent_id`,'NULL') AS `parent_site_id`,
				
				`list`,
				`tags`,
				`sitemap`,
				`published_at`,
				'' AS depth,
				'' AS lft,
				'' AS rgt
			FROM tmp_sites
			ORDER BY (list),(id)";
		$linear_traversal_structure=$this->prepare_linear_traversal_structure($this->db->query($query)->result_array(),$root_lft,$root_depth);
		if(is_array($linear_traversal_structure) && count($linear_traversal_structure)){
//			var_dump($linear_traversal_structure);
			// CELE MUSI BYT V TRANSAKCI!!!
			// 1 - aby se nestalo, ze behem ukladani vytvori nekdo dalsi polozku, ktera se nacpe mezi prave vkladane a rozhodi tak jejich id
			// 2 - aby se dalo pri jakekoliv chybe vratit do stavu pred importem
			if($this->db->query('START TRANSACTION')){
				foreach($linear_traversal_structure as $item){
					$title=false;
					/* **************************************************************** */
					/* ulozeni dat do sites																							*/
					/* **************************************************************** */
					$query="INSERT INTO sites (`tags`,`published_at`,`sitemap`) VALUES ('".$item['tags']."','".$item['published_at']."','".$item['sitemap']."')";
					$result[]=$this->db->query($query);
					$last_inserted=$this->db->query("SELECT LAST_INSERT_ID() AS id")->row_array();
					$last_inserted_id=$last_inserted['id'];
					$this->convert_id[$item['id']]=$last_inserted_id;

					/* **************************************************************** */
					/* ulozeni dat do  sites_parts																			*/
					/* **************************************************************** */
					$query="SELECT * FROM tmp_sites_parts WHERE `id_sites`=".$item['id'];
					$parts=$this->db->query($query)->result_array();
					$values=array();
					foreach($parts as $part){
						// pro vytvoreni adresy
						if($part['part']=='title'){
							$title=$part['content'];
						}
						$values[]="(".$last_inserted_id.",'".$part['part']."','".$part['lang']."','".$part['content']."')";
					}
					if(count($values)){
						$query="INSERT INTO `sites_parts` (`id_sites`,`part`,`lang`,`content`) VALUES \r\n\t\t".implode(",\r\n\t\t",$values);
						$result[]=$this->db->query($query);
					}
					// kazda strana musi mit nejaky obsah... je to chyba?
					else{
						$result[]=false;
						throw new Exception('Page with id '.$item['id'].' have no parts.');
					}

					/* **************************************************************** */
					/* ulozeni dat do relations																					*/
					/* **************************************************************** */
					$parent_id=($item['parent_id'] && $item['parent_id']!='NULL' ? $this->convert_id[$item['parent_id']] : $root_id);
					$parent_idr=($item['parent_id'] && $item['parent_id']!='NULL' ? $this->convert_idr[$parent_id] : $root_idr);
					$list=($item['parent_id'] && $item['parent_id']!='NULL' ? $item['list'] : $root_list);
					$query="
						# ulozeni novych polozek do relations
						INSERT INTO `relations` (`id_sites`,`parent_id`,`parent_site_id`,`table`,`list`,`depth`,`lft`,`rgt`)
						VALUES (
							".$last_inserted_id.",
							".$parent_idr.",
							".$parent_id.",
							'sites',
							".$list.",
							".$item['depth'].",
							".$item['lft'].",
							".$item['rgt']."
						)";
					$result[]=$this->db->query($query);
					// pro pozdejsi moznost prevodu
					$last_inserted=$this->db->query("SELECT LAST_INSERT_ID() AS id")->row_array();
					$last_inserted_idr=$last_inserted['id'];
					$this->convert_idr[$last_inserted_id]=$last_inserted_idr;

					/* **************************************************************** */
					/* ulozeni obrazku (db a filesystem)																*/
					/* **************************************************************** */
					$query="SELECT * FROM tmp_files WHERE `id_sites`=".$item['id'];
					$files=$this->db->query($query)->result_array();
					$values=array();
					foreach($files as $file){
						$copy_file=$this->copy_file_from_server($file['file_url'],$file['file']);
						if($copy_file){
							$values[]="(".$last_inserted_id.",'".$file['file']."','".$file['file_title']."','".$copy_file."', ".$file['list'].")";
						}
					}
					if(count($values)){
						$query="INSERT INTO `files` (`id_sites`,`file`,`file_title`,`file_url`,`list`) VALUES \r\n\t\t".implode(",\r\n\t\t",$values);
						$result[]=$this->db->query($query);
					}

					/* **************************************************************** */
					/* ulozeni url																											*/
					/* **************************************************************** */
					$query="SELECT * FROM tmp_urls WHERE `id_sites`=".$item['id']." LIMIT 1";
					$url=$this->db->query($query)->row()->sef;
					if($url){
						$query="INSERT INTO urls (`id_relations`,`url`,`sef`) VALUES (".$last_inserted_idr.",'home/site/".$last_inserted_idr."','".$this->trim_slashes($url)."')";
						$result[]=$this->db->query($query);
					}
					$query="INSERT INTO urls (`id_relations`,`url`,`sef`) VALUES (".$last_inserted_idr.",'home/site/".$last_inserted_idr."','".Tools::str2url($title)."')";
					$result[]=$this->db->query($query);
				}
				// jen pro testovaci ucely
//				$result[]=false;
				// nastala nejaka chyba...
				if(in_array(false, $result)){
					$this->db->query('ROLLBACK');
				}
				// vse je ok
				else{
					$return=$this->db->query('COMMIT');
					$this->repair_tree();
				}
			}
		}
		return $return;
	}


	/**
	 * oreze z retezce bile znaky a lomitka
	 *
	 * @param string $string
	 * @return string
	 */
	private function trim_slashes($string){
		$string=trim($string);
		$arr=explode('/',$string);
		if(count($arr)){
			$new_arr=array();
			foreach($arr as $v){
				if($v){
					$new_arr[]=$v;
				}
			}
			$string=implode('/',$new_arr);
		}
		return 	$string;
	}



	/**
	 * stahne obrazek ze zdrojoveho serveru a ulozi na nas
	 *
	 * @param string $file plna adresa souboru s obrazkem
	 * @param string $title titulek souboru - bude z nej novy nazev
	 * @return mixed pokud vse probehne ok tak vrati nazev obrazku, jinak false
	 */
	private function copy_file_from_server($file,$title){
		// adresar kam se ma ulozit
		$system_dir=false;
//		$system_dir='import_from_'.$this->import_system.'/';// pouze pokud chci mit fotky v zanorene podslozce
		$full_dir_addr=$this->images_dir.$system_dir;
		$return=false;
		// pokud neexistuje tak vytvori
		if(!file_exists($full_dir_addr) || !is_dir($full_dir_addr)){
			mkdir($full_dir_addr, 0777);
		}
		if(file_exists($full_dir_addr) && is_dir($full_dir_addr)){
			// kopie obrazku ze zdrojoveho serveru
			$content = file_get_contents($file);
			$old_filename=end(explode('/',$file));
			$file_suffix=end(explode('.',$old_filename));
			// novy nazev souboru z titulku
			if($title){
				$filename=Tools::str2url($title).'.'.$file_suffix;
			}
			// nebo pokud neni tak stary nazev souboru
			else{
				$filename=$old_filename;
			}
			// kopirovani k nam
			$addr = $full_dir_addr.$filename;
			$new_file_url=$system_dir.$filename;
			// obrazek neni na serveru
			if(!file_exists($addr)){
				$fp = fopen($addr, 'w');
				$write=fwrite($fp, $content);
				fclose($fp);
				if($write){
					$return=$new_file_url;
				}
			}
			// obrazek uz je na serveru
			else{
				$return=$new_file_url;
			}
		}
		return $return;
	}


	/**
	 * posklada adresu do adresare se zdrojovymi obrazky
	 * @param type $dir
	 */
	private function set_import_system_image_dir($dir){

	}


	/* ************************************************************************ */
	/* import systemu radiant																										*/
	/* ************************************************************************ */





	/**
	 * kontroluje jestli importovana databaze ma spravne tabulky a sloupce
	 * metoda se vola dynamicky v metode control_system(), proto je oznacovana jako nepouzita
	 *
	 * @return boolean
	 */
	private function control_system_radiant(){
		$needed_tables=array('pages','page_parts','page_attachments');
		return $this->control_imported_system_tables($needed_tables);
	}


	/**
	 * importuje data ze systemu Radiant
	 * metoda se vola dynamicky v metode import_system(), proto je oznacovana jako nepouzita
	 *
	 * @return boolean false pri chybe; null pokud nic neimportuje; true pokud je vse ok
	 */
	private function import_system_radiant(){
		$this->set_import_system_image_dir('');
		$query="SELECT `id`,`title`,`slug`,`breadcrumb`,`parent_id`,`published_at`,`position` FROM `pages`";
		$pages=$this->import_db_conn->query($query)->result_array();
		$return=false;
		$save=null;
		foreach($pages as $page){
			// ulozi zakladni informace o strance
			$save=array();
			$save[]=$this->save_tmp_site($page['id'],$page['parent_id'],$page['published_at'],$page['position'],1);
			$save[]=$this->save_tmp_site_part($page['id'],($page['breadcrumb'] ? $page['breadcrumb'] : $page['title']),'title');
			$save[]=$this->save_tmp_site_part($page['id'],$page['title'],'h1_title');
			$save[]=$this->save_tmp_site_part($page['id'],$page['title'],'meta_title');

			// ulozi parts
			$query="SELECT `name`,`content` FROM `page_parts` WHERE `page_id`=".$page['id'];
			$parts=$this->import_db_conn->query($query)->result_array();
			foreach($parts as $part){
				$part_name=$part['name'];
				$save[]=$this->save_tmp_site_part($page['id'],$part['content'],$part_name);
			}

			// ulozi obrazky
			$query="SELECT `id`,`filename`,`title`,`description`,`position` FROM `page_attachments` WHERE `page_id`=".$page['id']." AND `parent_id` IS NULL";
			$files=$this->import_db_conn->query($query)->result_array();
			foreach($files as $file){
				// posklada celou adresu obrazku na zdrojovem serveru
				$full_url=$this->import_server.'/page_attachments/0000/'.str_pad($file['id'], 4, '0', STR_PAD_LEFT).'/'.$file['filename'];
				$save[]=$this->save_tmp_file($page['id'],$full_url,$file['title'],$file['description'],$file['position']);
			}

			// ulozi url adresu
			$query="
				# posklada celou url jednotlivych clanku
				SELECT
				CONCAT(
					IF(p6.slug IS NOT NULL AND p6.slug!='/', CONCAT('/', p6.slug), ''),
					IF(p5.slug IS NOT NULL AND p5.slug!='/', CONCAT('/', p5.slug), ''),
					IF(p4.slug IS NOT NULL AND p4.slug!='/', CONCAT('/', p4.slug), ''),
					IF(p3.slug IS NOT NULL AND p3.slug!='/', CONCAT('/', p3.slug), ''),
					IF(p2.slug IS NOT NULL AND p2.slug!='/', CONCAT('/', p2.slug), ''),
					IF(p1.slug !='/', CONCAT('/', p1.slug), '')
				) AS `url`
				FROM `pages` AS p1
				LEFT JOIN `pages` AS p2 ON p2.id=p1.parent_id
				LEFT JOIN `pages` AS p3 ON p3.id=p2.parent_id
				LEFT JOIN `pages` AS p4 ON p4.id=p3.parent_id
				LEFT JOIN `pages` AS p5 ON p5.id=p4.parent_id
				LEFT JOIN `pages` AS p6 ON p6.id=p5.parent_id
				WHERE p1.`id`=".$page['id']."
				LIMIT 1
				";
			$url=$this->import_db_conn->query($query)->row()->url;
			$save[]=$this->save_tmp_urls($page['id'], $url);
		}
		if($save===null){
			$return=null;
		}
		if(!in_array(false,$save)){
			$return=true;
		}
		return $return;
	}
}

ACC SHELL 2018