<?php
/* SVN FILE: $Id: View.php 340 2008-05-11 01:45:48Z bb_yujiro $ */
/**
 * テーブル一覧表示
 *
 * PHP versions 5
 *
 *      hitSuji : Social Network Service <http://rakuto.net/rktSNS/>
 *      Copyright (c) 2007 Yujiro Takahashi
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 340 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-05-11 10:45:48 +0900 (日, 11 5 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */

/**
 * テーブル一覧表示クラス
 *
 * @category        Model::View
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 340 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-05-11 10:45:48 +0900 (日, 11 5 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */
class Model_View extends RKT_Model
{
    /**
     * 外部入力
     * @var array
     */
    public $requests = array();

    /**
     * 表示するページ
     * @var integer
     */
    protected $page = 0;

    /**
     * DATA取得開始行数
     * @var integer
     */
    protected $offset = 0;

    /**
     * 最大DATA取得行数
     * @var integer
     */
    protected $limit = LIMIT_ROWS;

    /**
     * 最大DATA取得可能行数
     * @var integer
     */
    protected $maxrow = null;

    /**
     * 取得する項目
     * @var string
     */
    protected $field = '*';

    /**
     * FROM句の保存
     * @var string
     */
    protected $from = null;

    /**
     * WHERE句の保存
     * @var array
     */
    protected $where = null;

    /**
     * GROUP句の保存
     * @var string
     */
    protected $group = null;

    /**
     * ORDER句の保存
     * @var string
     */
    protected $order = null;

    /**
     * ORDERリスト
     * @var array
     */
    protected $order_list = null;

    /**
     * オフセット値の設定
     *
     * @access public
     * @param integer $offset DATA取得開始行数
     * @return void
     */
    public function setPage($page)
    {
        $this->page   = is_numeric($page)? $page:1;
        if ($this->page > 1){
            $this->offset = ($this->page-1) * $this->limit;
        } else {
            $this->offset = 0;
        }
    }

    /**
     * リミット値の設定
     *
     * @access public
     * @param integer $limit DATA取得行数
     * @return void
     */
    public function setLimit($limit)
    {
        $this->limit = is_numeric($limit)? $limit:0;
        $this->setPage($this->page);
    }

    /**
     * オーダーラベルの取得
     *
     * @access public
     * @return array
     */
    public function setOrderLabel()
    {
        return array();
    }

    /**
     * オーダー設定
     *
     * @access public
     * @param string $order DATA取得行数
     * @return void
     */
    public function setOrder($order)
    {
        $this->order = $order;
    }

    /**
     * 条件の取得
     *
     * @access private
     * @return void
     */
    public function catchRequest()
    {
        foreach ($this->column as $column){
            if ($column['input'] == RKT_Model::INPUT_CHATCH){
                if ($this->objrqt->catchValidate($column['key'], $column)){
                    $value = $this->objrqt->getRequest($column['key']);
                    $this->requests[$column['key']] = $value;
                    if ($value != ''){
                        $pos = stripos($column['operator'], 'LIKE');
                        if ($pos === false){
                            $where  = $column['column'].' '.$column['operator'].' ';
                            $where .= $this->objdb->quote($value);
                        } else {
                            $keywords = explode(' ', $value);
                            foreach ($keywords as $keyword){
                                $keyword = '%'.$keyword.'%';
                                $keys[]  = 
                                    $column['column'].' '.$column['operator'].' '.
                                    $this->objdb->quote($keyword);
                            }
                            $where = '('.implode(' AND ',$keys) .') ';
                        }
                        $this->where[] = $where;
                    } // if (!is_null($value))
                } // if ($this->objrqt->catchValidate($key, $column))
            } // if ($column['input'] == RKT_Model::INPUT_CHATCH)
        } // foreach ($this->column as $key=>$column)

        /* 並び順 */
        $column = array(
            'type'=>       'number',
            'pdo_type'=>   PDO::PARAM_INT,
            'option'=>     array(),
            'required'=>   FALSE,
            'effect'=>     array('RKT_Request', 'multiStripTags'),
        );
        $this->requests['order'] = 1;
        if ($this->objrqt->catchValidate('order', $column)){
            $order = $this->objrqt->getRequest('order');
            $this->order = empty($this->order_list[$order])? $this->order:$this->order_list[$order];
            $this->requests['order'] = $order;
        }
        
        /* オフセット */
        $column = array(
            'type'=>       'number',
            'pdo_type'=>   PDO::PARAM_INT,
            'option'=>     array(),
            'required'=>   FALSE,
            'effect'=>     array('RKT_Request', 'multiStripTags'),
        );
        if ($this->objrqt->catchValidate('page', $column)){
            $page = $this->objrqt->getRequest('page');
            $this->setPage($page);
        }
    }

    /**
     * WHERE文の設定
     *
     * @access public
     * @param string $key
     * @param string $value
     * @param string $operator
     * @return void
     */
    public function setValue($key, $value, $operator='=')
    {
        $expression = $key.' '.$operator.' '.$this->objdb->quote($value);
        if ($operator == '&'){
            $expression = RKT_DB::bitFlag($expression);
        }
        $this->where[] = $expression;
    }

    /**
     * 項目の設定
     *
     * @access public
     * @param string $field
     * @return void
     */
    public function setField($field)
    {
        $this->field = $field;
    }

    /**
     * 条件値の取得
     *
     * @access public
     * @param string $key
     * @return mixed
     */
    public function getValue($key)
    {
        return empty($this->requests[$key])? null : $this->requests[$key];
    }

    /**
     * 最大取得可能行数の取得
     *
     * @access public
     * @return integer 最大取得可能行数
     */
    public function getMaxRow()
    {
        return $this->maxrow;
    }

    /**
     * ページ情報配列の設定
     *
     * @access public
     * @return void
     */
    public function getInfo()
    {
        if ($this->maxrow === null) {
            $this->_setMaxRow();
        }

        $pages = array();
        $pages['self']   = getUrlSelf();
        $pages['maxrow'] = $this->maxrow;
        $pages['page']   = $this->page;
        $pages['prev']   = $this->page - 1;
        $pages['next']   = $this->page + 1;
        $pages['param']  = $this->requests;

        $pages['max_page']  = ceil($this->maxrow / $this->limit);
        $pages['prev_bool'] = true;
        $pages['next_bool'] = true;
        if ($pages['prev'] < 0){
            $pages['prev_bool'] = false;
        }
        if ($pages['next'] >= $pages['max_page']){
            $pages['next_bool'] = false;
        }

        if (isSet($pages['param']['page'])){
            unset($pages['param']['page']);
        }

        return $pages;
    }

    /**
     * DBからデータ読み込み
     *
     * @access public
     * @return array
     */
    public function getValues()
    {
        if ($this->maxrow === null) {
            $this->_setMaxRow();
        }
        $offset = ($this->maxrow < $this->offset) ? 0:$this->offset;
        $where = '';
        if (is_array($this->where)){
            $where = 'WHERE '.implode(' AND ', $this->where) .' ';
        }

        /* SELECT文の生成 */
        $sql =
            'SELECT '.
                $this->field.' '.
                $this->from.
                $where.' ';
        if (!empty($this->group)){
            $sql .= 'GROUP BY '.$this->group.' ';
        }
        if (!empty($this->order)){
            $sql .= 'ORDER BY '.$this->order.' ';
        }

        /* OFFSET処理：DBタイプによる分岐 */
        $driver = $this->objdb->getAttribute(PDO::ATTR_DRIVER_NAME);
        if ($driver === 'mysql'){
            $sql .= 'LIMIT '.$offset.', '.$this->limit;
        } else {
            $sql .= 'LIMIT '.$this->limit.' ';
            $sql .= 'OFFSET '.$offset;
        }

        /* データの取得 */
        $stmt = $this->objdb->prepare($sql); 
        $stmt->execute(); 
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

        return $result;
    }

    /**
     * 変数の初期化
     *
     * @abstract
     * @access protected
     * @return void
     */
    protected function initValue()
    {
        $this->from = 'FROM '.DB_PREFIX.$this->tbl_name.' ';
    }

    /**
     * 最大取得可能行数の設定
     *
     * @access private
     * @return void
     */
    private function _setMaxRow()
    {
        $driver = $this->objdb->getAttribute(PDO::ATTR_DRIVER_NAME);
        $where  = '';
        if (is_array($this->where)){
            $where = 'WHERE '.implode(' AND ', $this->where) .' ';
        }
        $distinct = array(
            'mysql'=> 'DISTINCT ',
            'sqlite'=> '',
            'pgsql'=> '',
        );

        /* Group By による分岐 */
        if (empty($this->group)){
            $sql = 'SELECT count(*) as maxrow '.$this->from.$where;
        } else {
            $pos = strpos($this->group, ',');
            $pos = empty($pos)? strlen($this->group):$pos;
            $field = substr($this->group, 0, $pos);
            $count = 'count('.$distinct[$driver].$field.') as maxrow ';

            if ($driver !== 'mysql'){
                $sql = 'SELECT count(ct) as maxrow FROM '.
                       '(SELECT '.$count.' '.$this->from.$where.
                       ' GROUP BY '.$field.') as max_row';
            } else {
                $sql = 'SELECT '.$count.' '.$this->from.$where.' GROUP BY '.$field;
            } // if ($this->type !== 'mysql')
        } // if (empty($this->group))

        /* SELECT文の生成 */
        $stmt = $this->objdb->prepare($sql);
        $stmt->execute(); 
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        $stmt->closeCursor();
        $this->maxrow = empty($result['maxrow'])? 0:$result['maxrow'];
    }
} // Model_Viewの終了
?>
