<?php 
namespace imcat;

// 分页类
// 优化1: 多页提交,不重复计算记录数目
// 优化2: ORDER BY 主键,不用 OFFSET
class comPager{    
    
// sql
    
public  $sfrom = '';
    public  
$where = '';
    
// page
    //public  $paras = '?';
    
public  $psize = 20; //分页大小
    
public  $page = 1; //当前页
    
public  $pcnt = 1; //总前页
    // page para
    
public  $prec = 0; //总记录数
    
public  $ptype = 'start'; //first,prev,next,last
    
public  $pkey = ''; 
    
// order    
    
public  $order = ''; //排序字段,含前缀,如a.aid
    
public  $orderb = ''; //排序字段,去掉了前缀,如aid
    
public  $odesc = true;
    public  
$opkey = false; 
    
    public  
$rs = array();
    public  
$bar = array();
    public  
$cfg = array();
    public  
$sql = array('','');

    
//function __destory(){  basDebug::bugLogs('page'); }
    
function __construct($sfrom,$where,$psize=0,$order=''){ 
        
$this->sfrom = $sfrom;
        
$this->where = $where;
        
$this->psize = $psize;
        
$this->order = $order;
        if(
strpos($order,'.') || strpos($order,' ')){
            
$this->orderb = substr($order,strpos($order,'.')+1);
        }else{
            
$this->orderb = $order;    
        }
        
// init;
        
$a = array('page','prec','ptype','pkey',); // 'odesc','opkey',
        
foreach($a as $k){
            if(isset(
$_GET[$k])){ 
                
$__v = basReq::val($k,'Key',24); 
                if(
in_array($k,array('page',))) $__v = max(1,intval($__v));
                if(
in_array($k,array('prec',))) $__v = max(0,intval($__v));
                
$this->$k = $__v;
            }
        }
        if(
''!==$om=basReq::val('odesc','N',1)){ $this->odesc = $om; }
    }
    
    function 
set($key,$value=0){
        if(
is_array($key)){
            foreach(
$key as $k=>$v) $this->set($k,$v);
        }else{
            
$this->$key = $value;
        } 
    }
    
    function 
sql($cnt=''){ 
        
$sfrom = ' SELECT '.$this->sfrom;
        if(
$cnt){
            
$where = $this->where ? ' WHERE '.$this->where : '';
            
$this->sql[1] = basSql::fmtCount($sfrom.$where,$cnt);
            return 
$this->sql[1];
        }else{
            
$where = ' WHERE '.($this->where ? $this->where : '1=1');
            
$ptype = $this->ptype;
            
$pkey = $this->pkey; 
            
$odesc = $this->odesc;
            if(
$this->opkey&&$ptype){
                if(
$ptype=='start'){
                    
//$where .= "";
                
}else if($ptype=='end'){
                    
//$where .= "";
                
}else if($ptype=='next'){ 
                    if(
$odesc) $where .= " AND {$this->order}<'$pkey'";
                    if(!
$odesc) $where .= " AND {$this->order}>'$pkey'";
                }else if(
$ptype=='prev'){
                    if(
$odesc) $where .= " AND {$this->order}>'$pkey'";
                    if(!
$odesc) $where .= " AND {$this->order}<'$pkey'";
                } 
                if(
$ptype=='end'){
                    
$lcnt = $this->prec%$this->psize;
                    
$lcnt = $lcnt ? $lcnt : $this->psize;
                    
$limit = ' LIMIT '.$lcnt; 
                }else{
                    
$limit = ' LIMIT '.$this->psize;
                }
            }else{
                
$offset = ($this->page-1)*$this->psize;
                
$limit = " LIMIT $offset,".$this->psize;
            }
            if(
$where==' WHERE 1=1') $where = "";
            if(
$ptype=='end'||$ptype=='prev'){
                
$ord_in = ' ORDER BY '.$this->order.($this->odesc ? '' : ' DESC');
                
$ord_out = ' ORDER BY '.$this->orderb.($this->odesc ? ' DESC' : '');
                
$this->sql[0] = "SELECT * FROM ($sfrom $where $ord_in $limit) _tab__ $ord_out ";
            }else{
                
$order = ' ORDER BY '.$this->order.($this->odesc ? ' DESC' : '');
                
$this->sql[0] = $sfrom.$where.$order.$limit;
            }
            return 
$this->sql[0];
        }
    }
    function 
exe($dbkey=''){
        
$db = glbDBObj::dbObj($dbkey);
        
$rs = $db->query($this->sql());
        if(!
$this->prec){ 
            
$rec = $db->query($this->sql('_rc_recs_'));
            
$this->prec = $rec[0]['_rc_recs_'];
        } 
        
$this->pcnt = ceil($this->prec/$this->psize);
        
$this->bar = $this->links();
        return 
$rs;
    }
    
    function 
show($kfirst='',$klast='',$type='',$pbase=''){
        
$pbase = empty($pbase) ? basReq::getUri(-1,'','page|prec|ptype|pkey') : $pbase; 
        
$a = $this->bar; $bar = ''; $para = "&prec=$this->prec&page=";
        
$p0 = array("{pfirst}","{pprev}","{pnext}","{plast}",); 
        
$p1 = array("{$para}1","$para".($this->page-1),"$para".($this->page+1),"$para".$this->pcnt,); 
        if(
$this->opkey){
            
$p1[0] .= "&ptype=start";
            
$p1[1] .= "&ptype=prev&pkey=$kfirst";
            
$p1[2] .= "&ptype=next&pkey=$klast";
            
$p1[3] .= "&ptype=end";
        }
        
$a['pjump'] = str_replace("{pjump}","{$para}0&ptype=0",$a['pjump']); 
        foreach(
$a as $k=>$v){
            
$v = str_replace("<li>","\n<li class='pg_$k'>",$v);
            if(
in_array($k,array('first','prev','next','last'))){
                
$v = str_replace($p0,$p1,$v);
            }
            
$bar .= $v; 
        } 
//echo $pbase;
        
$bar = str_replace(["{url}&",'{url}'], [strpos($pbase,'?')>0?"$pbase&":"$pbase?","$pbase"], $bar);
        foreach (
$this->cfg as $ck => $cv) {
            
$this->cfg[$ck] = str_replace($p0, $p1, $this->cfg[$ck]);
            
$this->cfg[$ck] = str_replace(["{url}&",'{url}'], [strpos($pbase,'?')>0?"$pbase&":"$pbase?","$pbase"], $this->cfg[$ck]);
        }
        return 
"<ul class='pagination'>\n$bar</ul>\n";
    }
    
    function 
links(){
        
$pcnt = intval($this->pcnt);
        
$a = array(); 
        
$sFirst = '<span class="fa fa-fast-backward"></span>';
        
$sPrev = '<span class="">&laquo;</span>';
        
$sNext = '<span class="">&raquo;</span>';
        
$sLast = '<span class="fa fa-fast-forward"></span>';
        
        
$a['pagno'] = "<li class='pg_pagno'><a class='disabled'>$this->page/$pcnt</a></li>\n";
        
$a['first'] = "<li><a class='disabled'>$sFirst</a></li>\n";
        
$a['prev']  = "<li><a class='disabled'>$sPrev</a></li>\n";
        
$a['pjump'] = "<li class='pg_pjump'><input type='text' id='pg_pjump' pjurl='{url}{pjump}' pjmax='{$pcnt}' value='$this->page' class='form-control' onchange='goPjump(this)'/></li>\n";
        
$a['next']  = "<li><a class='disabled'>$sNext</a></li>\n";
        
$a['last']  = "<li><a class='disabled'>$sLast</a></li>\n";
        
$a['total'] = "<li class='pg_total'><a class='disabled'>$this->prec</a></li>\n";

        
$cfg['page'] = $this->page; $cfg['pcnt'] = $pcnt;
        
$cfg['first'] = $cfg['prev'] = $cfg['next'] = $cfg['last'] = '#';

        if(
$pcnt<=1) return $a;
        if(
$this->page==$pcnt){
            
$a['first'] = "<li><a href='{url}{pfirst}'>$sFirst</a></li>\n";
            
$a['prev']  = "<li><a href='{url}{pprev}' >$sPrev</a></li>\n";
            
$cfg['first'] = "{url}{pfirst}";
            
$cfg['prev'] = "{url}{pprev}";
        }elseif(
$this->page==1){
            
$a['next']  = "<li><a href='{url}{pnext}' >$sNext</a></li>\n";
            
$a['last']  = "<li><a href='{url}{plast}' >$sLast</a></li>\n";
            
$cfg['next'] = "{url}{pnext}";
            
$cfg['last'] = "{url}{plast}";
        }else{
            
$a['first'] = "<li><a href='{url}{pfirst}'>$sFirst</a></li>\n";
            
$a['prev']  = "<li><a href='{url}{pprev}' >$sPrev</a></li>\n";
            
$a['next']  = "<li><a href='{url}{pnext}' >$sNext</a></li>\n";
            
$a['last']  = "<li><a href='{url}{plast}' >$sLast</a></li>\n";
            
// 
            
$cfg['first'] = "{url}{pfirst}";
            
$cfg['prev'] = "{url}{pprev}";
            
$cfg['next'] = "{url}{pnext}";
            
$cfg['last'] = "{url}{plast}";
        }
        
$this->cfg = $cfg;
        return 
$a;
    }

    static function 
fixUrl($key='home'){
        global 
$_cbase;
        
$bar = &$_cbase['page']['bar'];
        if(!
strpos($bar,"?$key&")){
            
$bar = str_replace('?',"?$key&",$bar);
        }
        return 
$bar;
    }
    
}