ACC SHELL
<?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