<?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]) ? : ($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=='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;
    }

}