<?php
namespace imcat;

// DBExt
class glbDBExt{    
    
    static function 
moveOneField($mod, $cid){
        
$db = glbDBObj::dbObj();
        
// create:field
        
$tabf = 'base_fields';
        
$r = $db->table($tabf)->where("model='$mod' AND kid='$cid'")->find();
        if(
in_array($r['dbtype'],array('nodb','file'))) return; 
        
$tabid = (empty($r['etab'])?'docs':'dext')."_$mod"; 
        
$tabto = (empty($r['etab'])?'dext':'docs')."_$mod"; 
        
$cols = $db->fields($tabto); 
        
self::setOneFAE($tabto,$cid,$r,$cols);
        
// move:data
        
$sin = "SELECT `$cid` FROM $db->pre{$tabid}$db->ext f WHERE f.did=n.did";
        
$sql = "UPDATE $db->pre{$tabto}$db->ext n SET n.$cid = ($sin) "; 
        
$db->query($sql);
        
// end:del-old-field, upd-field-cfg
        
$db->query("ALTER TABLE $db->pre{$tabid}$db->ext DROP `$cid` ");
        
$dupd['etab'] = empty($r['etab']) ? '1' : '0';
        
$db->table($tabf)->data($dupd)->where("model='$mod' AND kid='$cid'")->update();
        
glbCUpd::upd_model($mod);
    }

    
// 字段 - 添加/删除/修改 
    
static function setOneField($mod,$cid,$act='del',$cfg=array()){
        
$db = glbDBObj::dbObj();
        
$tabf = 'base_fields';
        
$r = $db->table($tabf)->where("model='$mod' AND kid='$cid'")->find();
        if(!empty(
$r) && in_array($r['dbtype'],array('nodb','file'))) return; # $r null
        
if(empty($r) && !empty($cfg)) $r = $cfg;
        
$tabid = self::getTable($mod,empty($r['etab'])?'0':1); 
        
$cols = $db->fields($tabid); 
        if(
$act=='del'){
            if(isset(
$cols[$cid])) $db->query("ALTER TABLE $db->pre{$tabid}$db->ext DROP `$cid` ");
            
$db->table($tabf)->where("model='$mod' AND kid='$cid'")->delete();     
        }else{
            
self::setOneFAE($tabid,$cid,$r,$cols);
        }
    }
    static function 
setOneFAE($tabid,$cid,$r,$cols=array()){
        
$db = glbDBObj::dbObj();
        
$sql = "ALTER TABLE $db->pre{$tabid}$db->ext";
        if(isset(
$cols[$cid])) $sql.= " CHANGE `$cid` ";
        else                   
$sql.= " ADD ";
        
$dblen = intval(@$r['dblen']);
        
$sql.= " `$cid` $r[dbtype]".($r['dbtype']=='varchar' ? ($dblen>0?"($dblen)":'(12)') : ''); 
        
$sql.= (strpos("($r[vreg]",'nul:') ? " NULL " : ' NOT NULL '); 
        if(
strstr($r['dbtype'],'char')){
            
$sql.= " DEFAULT '".(strlen($r['dbdef'])==0?'':$r['dbdef'])."' "; 
        }elseif(
strstr($r['dbtype'],'int') || in_array($r['dbtype'],['float','double','decimal'])){
            
$sql.= " DEFAULT '".(strlen($r['dbdef'])==0?'0':$r['dbdef'])."' "; 
        }
        
$after = self::findAfterField($cols,$cid);
        if(!isset(
$cols[$cid])) $after && $sql.= " AFTER `$after` ";
        
$db->query($sql);
    }

    static function 
setfieldDemo($mod,$obj,$org='(drop)'){
        
$db = glbDBObj::dbObj();
        if(
$org=='(drop)'){
            
$db->query("DROP TABLE IF EXISTS $db->pre{$obj}$db->ext ");
            
$db->table('base_fields')->where("model='$mod'")->delete(); 
        }else{ 
            
$_ta = explode('_',$org);
            
$obj && $db->query("CREATE TABLE IF NOT EXISTS $db->pre{$obj}$db->ext LIKE $db->pre{$org}$db->ext");
            if(
in_array($_ta[0],array('coms','docs','users'))){ //增加默认字段配置'dext',
                
$pid = $_ta[1]; 
                
$_cfg = glbConfig::read($pid);
                
$farr = @$_cfg['f']; 
                
$top = 120; 
                if(
$farr){ foreach($farr as $k=>$v){
                    
$tabid = 'base_fields';
                    if(!
$db->table($tabid)->where("kid='$k' AND model='$mod'")->find()){
                        
$fm = array('kid'=>$k,'model'=>$mod,'top'=>$top,)+$v; 
                        
$db->table($tabid)->data($fm)->insert();
                    }
                    
$top += 4; 
                } }
            }
        }
    }
    
    
// tab下-添加字段,在什么字段后面
    
static function findAfterField($tab,$col){
        
$_groups = glbConfig::read('groups');
        
$a = is_array($tab) ? $tab : $db->fields($tab);
        if(isset(
$_groups[$col]) && $_groups[$col]['pid']=='types' && isset($a['catid'])){
            
$def = 'catid';
        }else{
            
$def = ''; $bak = ''; 
            foreach(
$a as $k=>$v){
                if(
$k=='aip'){ 
                    
$def = empty($bak) ? 'aip' : $bak;
                    break;
                }
                if(
substr("$k)))",0,3)==substr("$col)))",0,3)){
                    
$def = $k;
                }
                
$bak = $k;
            }
        }
        return 
$def;
    }
        
    
/* *****************************************************************************
      *** 数据库相关函数 
    - db前缀
    - by Peace(XieYS) 2012-07-23
    ***************************************************************************** */
    // tab, $tmp(md2,md3,mdh),max,
    
static function dbAutID($tab='utest_keyid', $tmp='max', $n=0, $xTime=''){
        
$db = glbDBObj::dbObj();
        
$tabf = $db->pre.$tab.$db->ext;
        
$tfix = substr($tab,0,5); 
        if(
in_array($tfix,array('docs_','coms_','advs_','users'))){
            
$tkey = substr($tfix,0,1).'id';
            
$tno = substr($tfix,0,1).'no';
        }else{
            
$tkey = 'kid'; 
            
$tno = 'kno';
        }
        
$ktmp = basKeyid::kidTemp($tmp, $xTime); // 2018-mdh-1233
        
if($tmp=='max'){
            
$kno = 1;
            
$kid = $ktmp;
        }else{
            
$pdb = substr($ktmp,0,strrpos($ktmp,'-')).'%';
            
$mdb = $db->query("SELECT max($tno) as $tno FROM $tabf WHERE $tkey LIKE '$pdb'");
            
$kno = empty($mdb[0][$tno]) ? 1 : ($mdb[0][$tno]+1) % 99;
            
$kfix = $kno<10 ? '0'.$kno : $kno;
            
$kid = substr($ktmp,0,strlen($ktmp)-2).$kfix;
        }
        if(
$n) $kid = substr($kid,0,strlen($kid)-2).basKeyid::kidRand('k',2);
        
$rec = $db->table($tab)->where("$tkey='$kid'")->find();
        if(
$rec) return self::dbAutID($tab, $tmp, $n+1, $xTime);
        else return array(
$kid,$kno);
    }

    static function 
dbNxtID($tab,$mod,$pid='0'){
        
$sqlm = $tab=='bext_relat' ? '' : ($tab=='base_model' ? 'pid' : 'model')."='$mod' AND ";
        
$mcfg = glbConfig::read($mod); //"$sqlm kid REGEXP ('^{$fix}[0-9]{3}$')";
        
$fd = $pid ? ($mcfg['i'][$pid]['deep']+1) : '1';
        
$tid = ''; // 找:本pid下最大的一个ID
        
if(!empty($mcfg['i'])){ foreach($mcfg['i'] as $ik=>$iv) {
            if(!empty(
$iv['pid']) && $iv['pid']==$pid && preg_match("/^[a-z]{1,6}\d{2,10}$/i",$ik)){
                
$tid = max($tid,$ik);
            }
        } }
        if(
$tid){ // 找:所有的类似最大的一个ID
            
preg_match("/^([a-z]{1,5})(\d{2,10})$/i",$tid,$tmp); 
            
$fix = $tmp[1]; $no = $tmp[2]; $nl = strlen($no);
            foreach(
$mcfg['i'] as $ik=>$iv) {
                if(
$iv['pid']==$pid) continue;
                if(
$iv['deep']!=$fd) continue;
                if(
preg_match("/^$fix\d{{$nl}}$/i",$ik)){
                    
$tid = max($tid,$ik);
                }
            } 
//echo $tid;
            // 找:下一个
            
preg_match("/^([a-z]{1,5})(\d{2,10})$/i",$tid,$tmp);
            
$nid = $fix.basKeyid::kidNext('',$tmp[2],$tmp[2],2,strlen($tmp[2]));
            
// 是否存在
            
$whr = "$sqlm kid='$nid'"; // echo "(n=$nid";
            
$re = glbDBObj::dbObj()->table($tab)->where($whr)->order('kid DESC')->find();
            if(!
$re){ return $nid; }
        }
        
$fix = substr($mod,0,1).$fd;
        
$whr = "$sqlm kid LIKE '$fix%'";
        
$re = glbDBObj::dbObj()->table($tab)->where($whr)->order('kid DESC')->find();
        if(
$re){
            
$nid = substr($re['kid'],2);
            
$nid = basKeyid::kidNext('',$nid,'012',2,3);
        }else{ 
$nid = '012'; }
        return 
$fix.$nid;
    }
    
    
// ext: 0-tab, 1-ext, kid, arr
    
static function getTable($mod,$ext='0'){ 
        
$_groups = glbConfig::read('groups');
        if(!isset(
$_groups[$mod])) return '';
        if(
$_groups[$mod]['pid']=='docs'){
            
$tabid = $ext==1 ? 'dext_'.$mod : 'docs_'.$mod;
            
$keyid = 'did';
        }elseif(
$_groups[$mod]['pid']=='users'){
            
$tabid = 'users_'.$mod;
            
$keyid = 'uid';
        }elseif(
$_groups[$mod]['pid']=='advs'){
            
$tabid = 'advs_'.$mod;
            
$keyid = 'aid';
        }elseif(
$_groups[$mod]['pid']=='coms'){    
            
$tabid = 'coms_'.$mod;
            
$keyid = 'cid';
        }elseif(
$_groups[$mod]['pid']=='types'){    
            
$tabid = empty($_groups[$mod]['etab']) ? 'types_common' : 'types_'.$mod;
            
$keyid = 'kid';
        }else{
            
$tabid = $keyid = '';    
        }
        if(
is_numeric($ext)){ // 0, 1
            
return $tabid;
        }else{ 
// kid,arr
            
return $ext=='kid' ? $keyid : array($tabid,$keyid);
        }
    }
    
    static function 
getKids($mod,$kid='',$whr='',$ret='sub'){
        
$tabid = self::getTable($mod); 
        
$kid = $kid ? basStr::filKey($kid,'_-.') : self::getKeyid($mod); 
        
$list = glbDBObj::dbObj()->table($tabid)->field($kid)->where($whr)->select();
        
$re = array();
        if(
$list){
        foreach(
$list as $r){
            
$re[] = $r[$kid];
        } }
        if(empty(
$re)){
            
$re[] = '(null)';    
        }
        if(
$ret=='sub'){
            
$re = "'".implode("','",$re)."'";
        }
        return 
$re;
    }
    
    static function 
dbComment($tabid='~return~'){ 
        static 
$dbdict,$fmod,$fdemo;
        
$db = glbDBObj::dbObj();
        
$fsystem = basLang::ucfg('fsystem');
        if(empty(
$dbdict)){
            
$dict = $db->table('bext_dbdict')->field("kid,tabid,title")->select();
            foreach(
$dict as $v){
                
$dbdict[$v['tabid']][$v['kid']] = $v['title'];
            }
        }
        if(empty(
$fmod)){
            
$dict = $db->table('base_fields')->field("kid,model,title")->select();
            foreach(
$dict as $v){
                
$fmod[$v['model']][$v['kid']] = $v['title'];
            }
        }    
        if(empty(
$fdemo)){
            
$fdemo = array();
            
$demo = glbConfig::read('fdemo','sy');
            foreach(array(
'init_users','init_coms','init_dext','init_docs',) as $part){
                
$fpart = $demo[$part];
                foreach(
$fpart as $f=>$v){
                    
$fdemo[$f] = $v['title'];
            } }
        }
        if(
$tabid=='~return~') return array('fsystem'=>$fsystem,'fdemo'=>$fdemo,);
        
$fields = $db->fields($tabid);
        
$moda = explode('_',$tabid); 
        
$modid = $moda[1];
        foreach(
$fields as $f=>$v){
            
$flag = 'def'; $rem = '';
            if(isset(
$fmod[$modid][$f])){ //模型设置
                
$flag = 'mod';
                
$rem = $fmod[$modid][$f];
            }elseif(empty(
$dbdict[$tabid][$f])){ //dbdict为空
                
if(isset($fdemo[$f])){
                    
$flag = 'demo';
                    
$rem = $fdemo[$f];
                }
                if(isset(
$fsystem[$f])){
                    
$flag = 'sys';
                    
$rem = $fsystem[$f];
                }
            }else{ 
//dbdict设置
                
$rem = $dbdict[$tabid][$f];    
                if(isset(
$fsystem[$f]) || in_array($moda[0],array('active','advs','base','bext','logs'))){
                    
$flag = 'sys';
                }
            }
            
$fields[$f]['_flag'] = $flag;
            
$fields[$f]['_rem'] = basStr::filTitle($rem);
        }
        
$_groups = glbConfig::read('groups');
        if(isset(
$_groups[$modid]) && $_groups[$modid]['pid']==$moda[0]){
            
$fields[0]['_flag'] = 'sys'; 
            
$cfg = basLang::ucfg('cfglibs.dbext');
            
$fields[0]['_rem'] = $_groups[$modid]['title'].('['.$cfg[$moda[0]].']').basLang::show('dbdict_tab');
        }
        if(isset(
$_groups[$modid]) && $moda[0]=='dext'){
            
$fields[0]['_flag'] = 'sys';
            
$fields[0]['_rem'] = $_groups[$modid]['title'].basLang::show('dbdict_extab');
        }
        if(isset(
$fsystem['_stabs'][$tabid])){
            
$fields[0]['_flag'] = 'sys';
            
$fields[0]['_rem'] = $fsystem['_stabs'][$tabid];
        }
        if(empty(
$fields[0]['_rem'])&& !empty($dbdict[$tabid][0])){
            
$fields[0]['_flag'] = '';
            
$fields[0]['_rem'] = $dbdict[$tabid][0];
        }
        return 
$fields;
    }
    
    
// 获取一组扩展参数
    
static function getExtp($type){ 
        
$data = array();
        
$whr = strpos($type,'%') ? " LIKE '$type'" : "='$type'";
        
$list = glbDBObj::dbObj()->table('bext_paras')->where("pid$whr AND enable=1")->order('top')->limit(99)->select();
        if(
$list){ foreach($list as $i=>$r){ 
            
$r['i'] = $i+1;
            foreach(array(
'aip','atime','auser','eip','etime','euser','cfgs','note','enable') as $k2){
                unset(
$r[$k2]);
            }
            
$data[$r['kid']] = $r;
        } } 
        return 
$data;
    }

}