<?php if(!defined("RUN_MODE")) die();?>
<?php
/**
 * The model file of stat module of ChanzhiEPS.
 *
 * @copyright   Copyright 2009-2010 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
 * @license     ZPLV1.2 (http://zpl.pub/page/zplv12.html)
 * @author      Xiying Guan <guanxiying@xirangit.com>
 * @package     stat
 * @version     $Id$
 * @link        http://www.chanzhi.org
 */
class statModel extends model
{
    /**
     * Get basic line.
     * 
     * @param  string    $type 
     * @param  string    $timeType 
     * @param  array    $labels 
     * @access public
     * @return array
     */
    public function getBasicLine($type, $timeType, $labels)
    {
        $traffic = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('type')->eq('basic')->andWhere('item')->eq($type)
            ->andWhere('timeValue')->in($labels)
            ->andWhere('timeType')->eq($timeType)
            ->fetchAll('timeValue');

        foreach($labels as $time)
        {
            $pv[] = isset($traffic[$time]) ? $traffic[$time]->pv : 0;
            $uv[] = isset($traffic[$time]) ? $traffic[$time]->uv : 0;
            $ip[] = isset($traffic[$time]) ? $traffic[$time]->ip : 0;
        }

        $colors = $this->config->stat->chartColors;

        $chartData = array();

        $uvChart = new stdclass(); 
        $uvChart->label = $this->lang->stat->uv;
        $uvChart->color = $colors['0'];
        $uvChart->data  = $uv;

        $pvChart = new stdclass(); 
        $pvChart->label = $this->lang->stat->pv;
        $pvChart->color = $colors['1'];
        $pvChart->data  = $pv;

        $ipChart = new stdclass(); 
        $ipChart->label = $this->lang->stat->ipCount;
        $ipChart->color = $colors['2'];
        $ipChart->data  = $ip;

        $chartData['pv'] = $pvChart;
        $chartData['uv'] = $uvChart;
        $chartData['ip'] = $ipChart;
        return $chartData;
    }

    /**
     * Get item lines of a type.
     * 
     * @param  string    $type 
     * @param  string    $timeType 
     * @param  array     $labels 
     * @access public
     * @return array
     */
    public function getTypeLine($type = '', $timeType, $labels, $groupBy = 'item', $item = '')
    {
        $traffic = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('type')->eq($type)
            ->beginIf($item != '')->andWhere('item')->eq($item)->fi()
            ->andWhere('timeType')->eq($timeType)
            ->andWhere('timeValue')->in($labels)
            ->fetchGroup($groupBy, 'timeValue');

        if(empty($traffic)) return array();

        $colors = $this->config->stat->chartColors;

        $i = 0;
        foreach($traffic as $item => $reports)
        {
            $colors[$item] = isset($colors[$item]) ? $colors[$item] : $colors[$i];
            $i ++;

            $pvChart = new stdclass;
            $pvChart->data  = array();
            $pvChart->label = zget($this->lang->stat->itemList, $item);
            $pvChart->color = $colors[$item];

            $uvChart = new stdclass;
            $uvChart->data  = array();
            $uvChart->label = zget($this->lang->stat->itemList, $item);
            $uvChart->color = $colors[$item];

            $ipChart = new stdclass;
            $ipChart->data  = array();
            $ipChart->label = zget($this->lang->stat->itemList, $item);
            $ipChart->color = $colors[$item];

            if($type == 'article' || $type == 'product')
            {
                $extraChart = new stdclass;
                $extraChart->data  = array();
                $extraChart->label = $type == 'article' ? $this->lang->stat->page->message : $this->lang->stat->page->sales;
                $extraChart->color = $colors[$i];
            }

            foreach($labels as $day)
            {
                $pvChart->data[]    = isset($reports[$day]) ? $reports[$day]->pv : 0;
                $uvChart->data[]    = isset($reports[$day]) ? $reports[$day]->uv : 0;
                $ipChart->data[]    = isset($reports[$day]) ? $reports[$day]->ip : 0;

                if($type == 'article' || $type == 'product')
                {
                    $extraChart->data[] = isset($reports[$day]) ? $reports[$day]->extra : 0;
                }
            }

            $pvCharts[]    = $pvChart;
            $uvCharts[]    = $uvChart;
            $ipCharts[]    = $ipChart;

            if($type == 'article' || $type == 'product')
            {
                $extraCharts[] = $extraChart;
            }
        }

        if($type == 'article' || $type == 'product')
        {
            return array('pvChart' => $pvCharts, 'uvChart' => $uvCharts, 'ipChart' => $ipCharts, 'extraChart' => $extraCharts);
        }
        else
        {
            return array('pvChart' => $pvCharts, 'uvChart' => $uvCharts, 'ipChart' => $ipCharts);
        }
    }

    /**
     * Get pie chart data of one type.
     * 
     * @param  string  $type
     * @param  int     $begin 
     * @param  int     $end 
     * @access public
     * @return array
     */
    public function getNewGuest($type, $begin = '', $end = '', $groupBy = 'item', $item = '')
    {
        $reports = $this->dao->select('sum(uv) as uv')->from(TABLE_STATREPORT)
            ->where('type')->eq($type)
            ->andWhere('timeType')->eq('day')
            ->beginIf($item != '')->andWhere('item')->eq($item)->fi()
            ->beginIf($begin != '')->andWhere('timeValue')->ge($begin)->fi()
            ->beginIf($end != '')->andWhere('timeValue')->le($end)->fi()
            ->beginIf($groupBy != '')->groupBy($groupBy)->fi()
            ->fetchAll();

        $total = 0;
        foreach($reports as $uv)
        {
            $total += $uv->uv;
        }

        return $total;
    }
    /**
     * Get pie chart data of one type.
     * 
     * @param  string  $type
     * @param  int     $begin 
     * @param  int     $end 
     * @access public
     * @return array
     */
    public function getPieByType($type, $begin = '', $end = '', $groupBy = 'item', $item = '')
    {
        $charts  = array();
        $reports = $this->dao->select('*, sum(ip) as ip, sum(pv) as pv, sum(uv) as uv')->from(TABLE_STATREPORT)
            ->where('type')->eq($type)
            ->andWhere('timeType')->eq('day')
            ->beginIf($item != '')->andWhere('item')->eq($item)->fi()
            ->beginIf($begin != '')->andWhere('timeValue')->ge($begin)->fi()
            ->beginIf($end != '')->andWhere('timeValue')->le($end)->fi()
            ->beginIf($groupBy != '')->groupBy($groupBy)->fi()
            ->fetchAll($groupBy);

        $colors = $this->config->stat->chartColors;
        $this->loadModel('log');
        
        $i = 0;       
        foreach($reports as $item => $report)
        {
            $color[$item] = isset($color[$item]) ? $color[$item] : $colors[$i];
            $i ++;
            
            $pv = new stdclass();
            $pv->value = $report->pv;
            $pv->color = $color[$item];
            $pv->label = zget($this->lang->stat->itemList, $item);

            $uv = new stdclass();
            $uv->value = $report->uv;
            $uv->color = $color[$item];
            $uv->label = zget($this->lang->stat->itemList, $item);

            $ip = new stdclass();
            $ip->value = $report->ip;
            $ip->color = $color[$item];
            $ip->label = zget($this->lang->stat->itemList, $item);

            $charts['pv'][] = $pv;
            $charts['uv'][] = $uv;
            $charts['ip'][] = $ip;
        }

        return $charts;
    }

    /**
     * Get day labels between begin and end date.
     * 
     * @param  int    $begin 
     * @param  int    $end 
     * @access public
     * @return void
     */
    public function getDayLabels($begin, $end)
    {
        $days = (strtotime($end) - strtotime($begin)) / (24 * 60 * 60);
        if($days > $this->config->stat->maxDays) $days = $this->config->stat->maxDays;
        for($i = $days; $i >= 0;  $i--) $dayLabels[] = date('Ymd', strtotime("-{$i} day", strtotime($end)));
        return $dayLabels;
    }

    /**
     * Get hour labels of one date.
     * 
     * @param  int     $day 
     * @param  bool    $showDate
     * @access public
     * @return array
     */
    public function getHourLabels($day, $showDate = true)
    {
        if($showDate)
        {
            foreach($this->config->stat->hourLabels as $hour) $labels[] = $day . $hour;
        }
        else
        {
            foreach($this->config->stat->hourLabels as $hour) $labels[] = $hour . ':00';
        }
        return $labels;
    }
    
    /**
     * Get keywords list.
     * 
     * @param  int       $begin 
     * @param  int       $end 
     * @param  string    $orderBy 
     * @param  object    $pager 
     * @access public
     * @return void
     */
    public function getKeywordsList($begin, $end, $orderBy, $pager)
    {
        $keywords = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('type')->eq('keywords')
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->orderBy($orderBy)
            ->page($pager)
            ->fetchAll();
        if(empty($keywords)) return $keywords;

        $keywordGroup = array();
        foreach($keywords as $keyword)
        {
            if(!isset($keywordGroup[$keyword->item][$keyword->extra]))
            {
                $keywordGroup[$keyword->item][$keyword->extra] = $keyword;
            }
            else
            {
                $sumKeyword = $keywordGroup[$keyword->item][$keyword->extra];
                $sumKeyword->pv += $keyword->pv;
                $sumKeyword->uv += $keyword->uv;
                $sumKeyword->ip += $keyword->ip;

                $keywordGroup[$keyword->item][$keyword->extra] = $sumKeyword;
            }
        }
        return $keywordGroup;
    }

    /**
     * Get keywords list.
     * 
     * @param  int       $begin 
     * @param  int       $end 
     * @param  string    $orderBy 
     * @param  object    $pager 
     * @access public
     * @return void
     */
    public function getDomainList($begin, $end, $orderBy = '', $pager = null)
    {
        $noAllowedDomainList = array('127.0.0.1', 'localhost', $_SERVER['HTTP_HOST']);
        if(isset($this->config->site->domain)) $noAllowedDomainList[] = $this->config->site->domain;
        if(isset($this->config->site->allowedDomain)) $noAllowedDomainList[] = $this->config->site->allowedDomain;

        return $this->dao->select('*, sum(pv) as pv, sum(uv) as uv, sum(ip) as ip')->from(TABLE_STATREPORT)
            ->where('type')->eq('domain')
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->andWhere('item')->notin($noAllowedDomainList)
            ->groupBy('item')
            ->orderBy($orderBy)
            ->page($pager)
            ->fetchAll('item');
    }

    /**
     * Get traffic info of a keyword.
     * 
     * @param  string    $keyword 
     * @param  int    $begin 
     * @param  int    $end 
     * @access public
     * @return object
     */
    public function getTrafficByKeyword($keyword, $begin, $end)
    {
         return $this->dao->select('*, sum(pv) as pv, sum(uv) as uv, sum(ip) as ip')->from(TABLE_STATREPORT)
            ->where('type')->eq('keywords')
            ->andWhere('item')->eq($keyword)
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->fetch();
    }

    /**
     * Get data for keyword line chart.
     * 
     * @param  string    $keyword 
     * @param  int    $begin 
     * @param  int    $end 
     * @access public
     * @return array
     */
    public function getItemLine($type, $item, $begin, $end)
    {
        $labels  = $this->getDayLabels($begin, $end);
        if($begin == $end) $labels = $this->getHourLabels($begin);
        $traffic = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('type')->eq($type)
            ->andWhere('item')->eq($item)
            ->beginIf($begin == $end)->andWhere('timeType')->eq('hour')->fi()
            ->beginIf($begin != $end)->andWhere('timeType')->eq('day')->fi()
            ->andWhere('timeValue')->in($labels)
            ->fetchAll('timeValue');

        if(empty($traffic)) return array();

        foreach($labels as $time)
        {
            $pv[] = isset($traffic[$time]) ? $traffic[$time]->pv : 0;
            $uv[] = isset($traffic[$time]) ? $traffic[$time]->uv : 0;
            $ip[] = isset($traffic[$time]) ? $traffic[$time]->ip : 0;
        }

        $chartData = array();

        $pvChart = new stdclass(); 
        $pvChart->label = $this->lang->stat->pv;
        $pvChart->color = 'green';
        $pvChart->data  = $pv;

        $uvChart = new stdclass(); 
        $uvChart->label = $this->lang->stat->uv;
        $uvChart->color = 'blue';
        $uvChart->data  = $uv;

        $ipChart = new stdclass(); 
        $ipChart->label = $this->lang->stat->ipCount;
        $ipChart->color = 'red';
        $ipChart->data  = $ip;

        $chartData[] = $pvChart;
        $chartData[] = $uvChart;
        $chartData[] = $ipChart;
        return $chartData;
    }

    /**
     * Parse begin and end date.
     * 
     * @param  string    $mode 
     * @param  int       $begin 
     * @param  int       $end 
     * @access public
     * @return void
     */
    public function parseDate($mode, $begin, $end)
    {
        if($mode == 'today')
        {
            $begin = $end = date("Ymd");
        }
        elseif($mode == 'yesterday')
        {
            $begin = $end = date("Ymd", strtotime("-1 day"));
        }
        elseif($mode == 'weekly')
        {
            $begin =  date("Ymd", strtotime("-7 day"));
            $end   = date('Ymd');
        }
        elseif($mode == 'monthly')
        {
            $begin =  date("Ymd", strtotime("-30 day"));
            $end   = date('Ymd');
        }
        else
        {
            $begin = date('Ymd', strtotime($begin));
            $end   = date('Ymd', strtotime($end));
        }

        if(!$begin) $begin = date('Ymd', strtotime($begin));
        if(!$end)   $end   = date('Ymd', strtotime($end));

        $params = new stdclass();
        $params->begin = $begin;
        $params->end   = $end;
        return $params;
    }

    /**
     * Get item extra pie data.
     * 
     * @param  string   $domain 
     * @param  int      $begin 
     * @param  int      $end 
     * @access public
     * @return void
     */
    public function getItemExtraPie($type, $item, $begin, $end)
    {
        $charts  = array();
        $reports = $this->dao->select('*, sum(ip) as ip, sum(pv) as pv, sum(uv) as uv')->from(TABLE_STATREPORT)
            ->where('type')->eq($type)
            ->andWhere('item')->eq($item)
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->groupBy('extra')
            ->fetchAll('extra');

        $colors = $this->config->stat->chartColors;
        $this->loadModel('log');
        
        $i = 0;       
        foreach($reports as $extra => $report)
        {
            if(!isset($colors[$i])) $colors[$i] = '#333';
            $color[$extra] = isset($color[$extra]) ? $color[$extra] : $colors[$i];
            $i ++;

            $pv = new stdclass();
            $pv->value = $report->pv;
            $pv->color = $color[$extra];
            $pv->label = $report->extra;

            $uv = new stdclass();
            $uv->value = $report->uv;
            $uv->color = $color[$extra];
            $uv->label = $report->extra;

            $ip = new stdclass();
            $ip->value = $report->ip;
            $ip->color = $color[$extra];
            $ip->label = $report->extra;

            $charts['pv'][] = $pv;
            $charts['uv'][] = $uv;
            $charts['ip'][] = $ip;
        }
        return $charts;
    }

    /**
     * Get page report data.
     * 
     * @param  int    $domain 
     * @param  int    $begin 
     * @param  int    $end 
     * @param  int    $pager 
     * @access public
     * @return void
     */
    public function getPageReport($domain, $begin, $end, $pager)
    {
        return $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('type')->eq('domain')
            ->andWhere('item')->eq($domain)
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->orderBy('pv_desc')
            ->page($pager)
            ->fetchGroup('extra', 'timeValue');
    }

    /**
     * Get today report 
     * 
     * @access public
     * @return array 
     */
    public function getTodayReport()
    {
        $todayReport = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('timeType')->eq('day')
            ->andWhere('type')->eq('basic') 
            ->andWhere('item')->eq('total')
            ->andWhere('timeValue')->eq(date('Ymd'))
            ->fetch(); 

        return $todayReport;
    }

    /**
     * Get yesterday report 
     * 
     * @access public
     * @return array 
     */
    public function getYesterdayReport()
    {
        $yesterdayReport = $this->dao->select('*')->from(TABLE_STATREPORT)
            ->where('timeType')->eq('day')
            ->andWhere('type')->eq('basic') 
            ->andWhere('item')->eq('total')
            ->andWhere('timeValue')->eq(date('Ymd', strtotime("-1 day")))
            ->fetch();

        return $yesterdayReport;
    }

    public function getPageRank($mode = '', $begin = '', $end = '', $pager = null)
    {
        $pages = $this->dao->select('*, sum(pv) as pv')->from(TABLE_STATREPORT)
            ->where('type')->eq('url')
            ->andWhere('item')->ne('')
            ->beginIf($mode != 'all')
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->ge($begin)
            ->andWhere('timeValue')->le($end)
            ->fi()
            ->groupBy('item')
            ->orderBy('pv_desc')
            ->page($pager)
            ->fetchAll();

        return $pages;
    } 


    /**
     * get total quantity 
     * 
     * @param  string $field  uv or ip or pv 
     * @access public
     * @return void
     */
    public function getTotalQuantity($field)
    {
        return $this->dao->select($field)->from(TABLE_STATREPORT)
            ->where('type')->eq('basic')
            ->andWhere('item')->eq('total')
            ->andWhere('timeType')->eq('day')
            ->andWhere('timeValue')->eq(date('Ymd'))
            ->fetch($field);
    }
}
