<?php
/**
 * This class itemtype base class.
 *  
 */
global $MAIN_FILE;
require_once $MAIN_FILE;
require_once XOOPS_TRUST_PATH.'/modules/xdbmigrate/cmd/inc/migrate_db.inc.php';
abstract class xdbmigrate_itemtype_base{
  
  protected $db;
  protected $ng_item_name;
  protected $file_map_arr;
  protected $dup_arr;
  protected $description = null; #description put NG xml name.

  public function init($db){
    $this->db = $db;
    $this->file_map_arr = array();
    $this->dup_arr = array();
  }
  
  /**
   * Set,Get XooNIps Next Genetation Xoonips_item_type.name
   * @param string $name 
   */
  public function set_ng_item_name($name){
    $this->ng_item_name = $name;
  }
  
  public function get_ng_item_name() {
    return $this->ng_item_name;
  }
  
  /**
   *
   * File info conversion add
   * 
   * @param string $file_type_name
   * @param string $xml 
   */
  public function add_file_mapping_array($file_type_name,$xml) {
    $this->file_map_arr[$file_type_name] = $xml;
  }
  
  /**
   *  descripton set NG xml name.
   * 
   * @param string $desc 
   */
  public function set_description($desc) {
    $this->description = $desc;
  }

  #
  #xoonips_item_basic related functions.
  #
  
  /**
   * get array(table_name,column_name)=g(xml,item_type_name)
   * 
   * xml = item group id.
   * 
   * @param string $xml field_group.xml value 
   * @param string $item_type_name item_type.name value.You give XooNIps 3.46a module name.
   * @return mix  Success:Array,Fail:False
   */
  private $sql1;
  protected function get_table_column_by_group($xml,$item_type_name = NULL){
    
    if(is_null($item_type_name)){
      $item_type_name = $this->get_ng_item_name();
    }
    $group_link = XOOPS_DB_PREFIX.'_xoonips_item_type_field_group_link';
    $detail = XOOPS_DB_PREFIX.'_xoonips_item_field_detail';
    $field_group = XOOPS_DB_PREFIX.'_xoonips_item_field_group';
    $detail_link = XOOPS_DB_PREFIX.'_xoonips_item_field_group_field_detail_link';
    $item_type = XOOPS_DB_PREFIX.'_xoonips_item_type';
#$sql =<<<EOT
$this->sql1 =<<<EOT
  select distinct field_group.group_id,detail.table_name,detail.column_name ,detail.item_field_detail_id,detail.xml
  from {$group_link} as group_link,
        {$detail} as detail,
        {$field_group} as field_group,
        {$detail_link} as detail_link,
        {$item_type} as item_type
  where item_type.name = '{$item_type_name}' and
       item_type.item_type_id = group_link.item_type_id and
       detail_link.item_field_detail_id = detail.item_field_detail_id and 
        field_group.xml = '{$xml}' and 
        field_group.group_id = detail_link.group_id and detail.released=true and field_group.released=true and
        detail_link.item_field_detail_id = detail.item_field_detail_id;
EOT;
    $result_array = $this->db->query($this->sql1);
    if(is_array($result_array)){
      if(count($result_array) == 1){
        return $result_array[0];
      }
      return $result_array;
    }
    return FALSE;
  }
    
  public function get_sql(){
    return $this->sql1;
  }
  
  /**
   * get array(table_name,column_name)=g(xml,item_type_name)
   * 
   * xml = item id.item clause
   * 
   * @param string $xml detail.xml value 
   * @param string $item_type_name item_type.name value.You give XooNIps 3.46a module name.
   * @return mix  Success:Array,Fail:False
   */  
  protected function get_table_column_by_item($xml,$item_type_name=null){
    
    if(is_null($item_type_name)){
      $item_type_name = $this->get_ng_item_name();
    }    
    $group_link = XOOPS_DB_PREFIX.'_xoonips_item_type_field_group_link';
    $detail = XOOPS_DB_PREFIX.'_xoonips_item_field_detail';
    $detail_link = XOOPS_DB_PREFIX.'_xoonips_item_field_group_field_detail_link';
    $item_type = XOOPS_DB_PREFIX.'_xoonips_item_type';
$this->sql1 =<<<EOT
select xml,table_name,column_name,detail_link.group_id,detail.item_field_detail_id
from {$detail} as detail,
    {$detail_link} as detail_link,
    {$group_link} as group_link,
    {$item_type} as item_type
where detail.item_field_detail_id = detail_link.item_field_detail_id and
    detail_link.group_id = group_link.group_id and
    group_link.item_type_id = item_type.item_type_id and detail.released = true and
    item_type.name = '{$item_type_name}' and xml='{$xml}'
EOT;
    $result_array = $this->db->query($this->sql1);
    if(count($result_array) == 1){
      return $result_array[0];
    }
    return FALSE;
  }

  /**
   * item_type get NG xoonips_item_type.
   * 
   * @return mix Success:item_type_id Fail:False 
   */
  protected function get_ng_item_type_id(){
    $tbl = get_tbl('xoonips_item_type');
    $sql = "select item_type_id from {$tbl} where name='{$this->ng_item_name}' and released=1";
    $result_array = $this->db->query($sql);
    if(count($result_array) == 1){
      return $result_array[0];
    }
    return FALSE;
  }

  /**
   * When file convert,this search module.
   * 
   * @param int $item_id
   * @param string $file_type_name
   * @return mixed Success:Array,Fail:false
   */
  protected function get_search_module($item_id,$file_type_name){
    $file_wktbl = get_WK_tbl('xoonips_file');
    $type_wktbl = get_WK_tbl('xoonips_file_type');
    $sql = "select file_id,search_module_name,search_module_version,type.file_type_id ".
           "from {$file_wktbl} as file,{$type_wktbl} as type ".
           "where item_id={$item_id} and file.file_type_id = type.file_type_id and type.name = '{$file_type_name}'";
    $tmparr = $this->db->query($sql);
    if(count($tmparr) == 0){
      return FALSE;
    }
    $retarray =array();
    foreach ($tmparr as $result_array) {
      if(is_array($result_array)){
        if(strcmp($result_array["search_module_name"],'pdf') == 0){
          $result_array['search_module_version'] = 200;
        }
        $retarray[] = $result_array;
      }else{
        return FALSE;
      }
    }

    if(count($retarray)>0)return $retarray;
    return FALSE;
  }

  /**
   * insert optional table and optional value
   * 
   * @param array $result_array This array have to include column table_name,column_name and group_id.
   * @param int    $item_id
   * @param string $val
   * @param int $occurence Occurence specify.Default auto.
   * @return boolean Success:True,Fail:False
   */
  protected function insert_any($result_array,$item_id,$val,$occurence=null){
    if(is_string($val) && strlen($val)==0)return true;
    if(is_null($val))return true;
    $tbl = XOOPS_DB_PREFIX.'_'.$result_array['table_name'];
    $col = $result_array['column_name'];
    $group_id = $result_array['group_id'];
    $val1 = $this->db->quote($val);
    if(is_null($occurence)){
      $this->sql1 = "insert into {$tbl} (item_id,group_id,{$col})".
              " values({$item_id},{$group_id},{$val1})";
    }else{
      $this->sql1 = "insert into {$tbl} (item_id,group_id,{$col},occurrence_number)".
              " values({$item_id},{$group_id},{$val1},{$occurence})";
    }
    $result_array = $this->db->exec($this->sql1);
    if($result_array === FALSE){
      return false;
    }
    return true;
  }
  
  /**
   * When title insert to xoonips_item_title,this function get title_id.
   * 
   * @param int $item_id
   * @return boolean|int 
   */
  protected function get_title_id($item_id) {
    $tbl = get_tbl('xoonips_item_title');
    $sql = "select max(title_id) as title_id from {$tbl} where item_id={$item_id}";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    if(count($result_array) == 0){
      return 0;
    }
    $ret =  $result_array[0]['title_id'];
    if(is_null($ret))return 0;
    else return $ret;
  }
 
  /**
   * Insert title
   * 
   * @param int $item_id
   * @param int $item_field_detail_id
   * @return boolean Success:True,Fail:False
   */
  public function insert_title($item_id,$item_field_detail_id) {
    $title_id = $this->get_title_id($item_id);
    if($title_id === FALSE){
      return false;
    }    
    $tbl = get_tbl('xoonips_item_title');
    $wktbl = get_WK_tbl('xoonips_item_title');
    $sql = "insert into {$tbl} (item_id,item_field_detail_id,title_id,title)".
    " select item_id,{$item_field_detail_id} ,title_id,title from {$wktbl} where item_id={$item_id} and title_id = {$title_id}";
    $result_array = $this->db->exec($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;    
  }


  /**
   * xoonips_item_title migrate.
   * 
   * @param int $item_id 
   * @return boolean Succes:true,Fail:false
   */
  protected function migrate_item_title($item_id) {
    $retarr = $this->get_table_column_by_group('title', $this->get_ng_item_name());
    if($retarr === FALSE)return false;
    $item_field_detail_id = $retarr['item_field_detail_id'];
    return $this->insert_title($item_id,$item_field_detail_id);
  }

  /**
   * xoonips_item_keyword migrate.
   * 
   * @param int $item_id 
   * @return boolean Succes:true,Fail:false
   */
  public function migrate_item_keyword($item_id,$keyword = null) {
    $tbl = get_tbl('xoonips_item_keyword');
    $wktbl = get_WK_tbl('xoonips_item_keyword');
    if(is_null($keyword)){
      $sql = "insert into {$tbl} (item_id,keyword_id,keyword)".
      " select item_id,keyword_id+1,keyword from {$wktbl} where item_id={$item_id}";
    }else{
      $sql = "insert into {$tbl} (item_id,keyword_id,keyword)".
      " select item_id,keyword_id+1,'{$keyword}' from {$wktbl} where item_id={$item_id}";      
    }
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;
  }

  /**
   * xoonips_related_to migrate.
   *
   * @param int $item_id
   * @return boolean Succes:true,Fail:false
   */
  protected function migrate_related_to($item_id) {
    $tbl = get_tbl('xoonips_item_related_to');
    $wktbl = get_WK_tbl('xoonips_related_to');
    $sql = "insert into {$tbl} (item_id,child_item_id)".
    " select parent_id,item_id from {$wktbl} where parent_id={$item_id}";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;
  }
  
  /**
   * changelog migrate.
   * 
   * @param int $item_id
   * @return boolean Succes:true,Fail:false 
   */
  protected function migrate_changelog($item_id){
    $tbl = get_tbl('xoonips_item_changelog');
    $wktbl = get_WK_tbl('xoonips_changelog');
      $sql = "insert into {$tbl} (log_id,uid,item_id,log_date,log)".
    " select * from {$wktbl} where item_id={$item_id}";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;  
  }

  /**
   * item_users_link migrate.
   * 
   * @param int $item_id
   * @param int $uid
   * @return boolean Succes:true,Fail:false  
   */
  protected function migrate_item_users_link($item_id,$uid) {
    $tbl = get_tbl('xoonips_item_users_link');
    $wktbl = get_WK_tbl('xoonips_item_basic');
    $sql = "insert into {$tbl} (item_id,uid,weight)".
    " select item_id,uid,1 from {$wktbl} where item_id={$item_id}";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;     
  }
  
  /**
   * This function migrate xoonips_file
   * xoonips_file migrate to xoonips_item_file.
   *
   * @param int $item_id
   * @param array $modarr module info
   * @param array $detail_array
   * @return Success:true,Fail:false
   */
  protected function migrate_file($item_id,&$modarr,&$detail_array) {
    $tbl = get_tbl('xoonips_item_file');
    $wktbl = get_WK_tbl('xoonips_file');

    $sql = "insert into {$tbl} (file_id,item_id,original_file_name,mime_type,file_size,caption,sess_id,search_module_name,search_module_version,timestamp,download_count,group_id,item_field_detail_id)".
    " select file_id,item_id,original_file_name,mime_type,file_size,caption,sess_id,'{$modarr['search_module_name']}','{$modarr['search_module_version']}',unix_timestamp(timestamp),download_count,{$detail_array['group_id']},{$detail_array['item_field_detail_id']}".
    " from {$wktbl} where item_id={$item_id} and file_id = {$modarr['file_id']}";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }      

    return true;     
  
  }

  #
  #create item_type
  #
  /**
   * insert xoonips_item table.
   * 
   * @param int $item 
   * @param int $item_type_id
   * @return boolean Succes:true,Fail:false
   */
  protected function insert_xoonips_item($item,$item_type_id) {
    $tbl = XOOPS_DB_PREFIX.'_xoonips_item';
    $doi = (strlen($item['doi'])>0)?"'{$item['doi']}'":"''";
    $sql = "insert into {$tbl} (item_id,item_type_id,doi,creation_date,last_update_date)".
           " values({$item['item_id']},{$item_type_id},{$doi},{$item['creation_date']},{$item['last_update_date']})";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return false;
    }
    return true;
  }

  /**
   * rights convert
   * 
   * @param array $param
   * @return string 
   */
  protected function make_rights($param) {
    $right = $param['use_cc'].$param['cc_commercial_use'].$param['cc_modification'].'Unported,';
    if($param['use_cc'] == 0){
      $right .= $param['rights'];
    }
    return $right;
  }
  
  /**
   * convert xoonips_file
   * 
   * @param int $item_id 
   */
  protected function file_tbl_conv($item_id) {
    #get XooNIps3.46a file info
    foreach ($this->file_map_arr as $key => $xml) {
      $modarr = $this->get_search_module($item_id,$key);
      if($modarr === FALSE)continue;
      $detail_array = $this->get_table_column_by_group($xml,$this->get_ng_item_name());
      if(is_array($detail_array)){
        if(array_key_exists(0, $detail_array)){
          foreach ($detail_array as $value) {
            foreach ($modarr as $mod_each) {
              $this->migrate_file($item_id,$mod_each,$value);
            }
          }
        }else{
          foreach ($modarr as $mod_each) {
            $this->migrate_file($item_id,$mod_each,$detail_array);
          }
          
        }
      }      
    }
  }
  
  
  /**
   * upload dir from xoonips_cofig
   * 
   * @return mixed Success:directory name,Fail:Negative Number
   */
  protected function get_upload_dir($tbl) {
    $sql = "select value from {$tbl} where name='upload_dir'";
    $result_array = $this->db->query($sql);
    if($result_array === FALSE){
      return -errmsg(APP_MIGRATE, 'E2801');
    }
    return $result_array[0]['value'];
  }

  
  /**
   * get Old XooNIps file name
   * 
   * @param int $file_id 
   * @return mixed Success:file name(fullpath),Fail:False
   */
  protected function get_old_file($file_id) {
    $upload_dir = $this->get_upload_dir(get_WK_tbl('xoonips_config'));
    if(is_int($upload_dir)) return $upload_dir;
    return $upload_dir."/{$file_id}";
  }
  
  /**
   * get upladdir and make directory string.
   * 
   * @param int $item_id
   * @return string directory 
   */
  protected function get_ng_dir($item_id) {
    $upload_dir = $this->get_upload_dir(get_tbl('xoonips_config'));
    if(is_int($upload_dir)) return $upload_dir;
    return $upload_dir."/item/{$item_id}";    
  }

  /**
   * get NG uploaddir.
   * 
   * @param int $item_id
   * @param int $file_id
   * @return string filename
   */
  protected function get_ng_file($item_id,$file_id)
  {
    $upload_dir = $this->get_ng_dir($item_id);
    if(is_int($upload_dir)) return $upload_dir;
    return $upload_dir."/{$file_id}";
  }
 
  /**
  *mkdir NG file directory
  * @param int $item_id
  * @return int Success:0,Fail:Negative Number
  */
  protected function mkdir_ng_filedir($item_id) {
    $pathname = $this->get_ng_dir($item_id);
    if(is_int($pathname))return $pathname;
    if(file_exists($pathname))return 0;
    $rc = mkdir($pathname, 0755, TRUE);
    if($rc === false){
      return -errmsg(APP_MIGRATE, 'E2802',$pathname);
    }
    $rc = chown($pathname,"apache");
    if($rc === false){
      return -errmsg(APP_MIGRATE, 'E2803',$pathname);
    }
    $rc = chgrp($pathname,"apache");
    if($rc === false){
      return -errmsg(APP_MIGRATE, 'E2804',$pathname);
    }
    return 0;
  }
  
  /**
   * File conver Next Generation XooNIps directory struncture.
   * if files have thmbnail ,it convert Next Generation XooNIps formal.
   * 
   * @param int $item_id 
   * @return boolean Success:True,Fail:False
   */
  protected function file_conv($item_id) {
    #Is this item_id has file or image?
    
    $wktbl = get_WK_tbl('xoonips_file');
    $sql = "select file_id,thumbnail_file from {$wktbl} where item_id={$item_id}";
    $result_arrays = $this->db->query($sql);
    if(is_array($result_arrays)){
      foreach ($result_arrays as $file_info_array) {
        #convert this file.
        $file_id = $file_info_array['file_id'];
        $rc = $this->mkdir_ng_filedir($item_id);  #NG file mkdir
        if($rc < 0)return false;
        $old_file = $this->get_old_file($file_id);
        if(is_int($old_file))return false;
        $ng_file  = $this->get_ng_file($item_id,$file_id);
        if(is_int($ng_file))return false;
        if(file_exists($old_file) && copy($old_file,$ng_file) === FALSE){
          errmsg(APP_MIGRATE, 'E2805',$old_file.' '.$ng_file);
          return false;
        }
        
        #copy thumbnail.
        if(!is_null($file_info_array['thumbnail_file'])){
          $thumb_file = $ng_file."_thumbnail";
          $fp = fopen($thumb_file,"w");
          if($fp === FALSE){
            errmsg(APP_MIGRATE, 'E2806',$thumb_file);
            return false;
          }
          fwrite($fp,$file_info_array['thumbnail_file']);
          fclose($fp);
        }
      }
    }
    return TRUE;
  }


  /**
   * Migrate Simple date
   * 
   * @param array $item
   * @return int Success:0,Fail:Negative Number
   */
  protected function migrate_simple_date($item) {
    #pubication_year,month,mday convert to UNIX Time.
    $item_id = $item['item_id'];
    $tm = mktime(0, 0, 0, $item['publication_month'], $item['publication_mday'],$item['publication_year']);
    
    $date_array = $this->get_table_column_by_group('date');
    if($date_array === FALSE){
      return -errmsg(APP_MIGRATE, 'E2401');
    }
    
    $rc = $this->insert_any($date_array, $item_id, $tm);
    if($rc === FALSE){
      return -errmsg(APP_MIGRATE, 'E2402');
    }
    
    return 0;
  }

  /**
   * common table operate function.
   * 
   * following tables operate 
   * xoonips_item,xoonips_item_title,xoonips_item_keyword,xoonips_item_extend,
   * xoonips_item_related_to,xoonips_item_chacelog,xoonips_item_users_link
   * 
   * @param array $item xoonips_basic_item info(origin 3.46a)
   */
  public function migrate_xoonips_item($item) {
    $item_id = $item['item_id'];
    $uid = $item['uid'];
    $item_type_id = $this->get_ng_item_type_id();
    
    #
    #migrate xoonips_item_type
    #
    if($this->insert_xoonips_item($item,$item_type_id['item_type_id']) == false){
      return -1;
    }
    
    #migrate description
    if(!is_null($this->description)){
      $result_array = $this->get_table_column_by_group($this->description,$this->get_ng_item_name());
      $this->insert_any($result_array,$item_id,$item['description']);
    }
    
    #migrate lang
    if($item['name'] !== 'xnparticle'){
      $result_array = $this->get_table_column_by_group('langs',$this->get_ng_item_name());
      $this->insert_any($result_array,$item_id,$item['lang']);
    }
    
    #migrate xoonips_item_title
    $rc = $this->migrate_item_title($item_id);    
    
    #migrate xoonips_item_keyword
    if(strcasecmp($item['name'],"xnparticle")!=0){  #2013-04-12  Article use xnparticle_item_detail_child_keywords.
                                              # Same values but other formats at xoonips_item_keyword table.
      $rc = $this->migrate_item_keyword($item_id);
    }
    
    #migrate xoonips_related_to
    $rc = $this->migrate_related_to($item_id);
    
    #migrate xoonips_changelog
    $rc = $this->migrate_changelog($item_id);
    
    #migrate xoonips_item_users_link
    $rc = $this->migrate_item_users_link($item_id, $uid);
    
    #file table convert
    if(count($this->file_map_arr) > 0){
      $this->file_tbl_conv($item_id);
      $this->file_conv($item_id);
    }
    
    #Call User Callback function.
    return $this->migrate($item);
  }

  /**
   * Add duplication table name.
   * 
   * @param string $tbl table name
   */
  protected function add_dup_table($tbl)
  {
    array_push($this->dup_arr, $tbl);
  }
  
  /**
   * get duplication tables array.
   * 
   * @return array duplication tables array.
   */
  public function get_dup_table() {
    return $this->dup_arr;
  }


  /**
   * You MUST implement migrate method. 
   */
  abstract public function migrate($item);

}
