<?php
/* SVN FILE: $Id: view.php 617 2008-07-20 03:30:38Z 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
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @package         hitSuji
 * @version         $Revision: 617 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-07-20 12:30:38 +0900 (日, 20 7 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */

/**
 * Controllerクラス
 *
 * @category        hitSuji developer
 * @package         hitSuji
 * @copyright       Copyright (c) 2007 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 617 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-07-20 12:30:38 +0900 (日, 20 7 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */
class Controller extends RKT_Controller
{
    /**
     * ページタイプ
     * @var string
     */
    public $type = null;

    /**
     * テーブル名
     * @var string
     */
    public $table = null;

    /**
     * テーブル名配列
     * @var array
     */
    public $tables = null;

    /**
     * アカウント情報
     * @var array
     */
    protected $account = array('status'=> STATUS_GUEST);

    /**
     * 項目名配列
     * @var array
     */
    private $_columns = null;

    /**
     * manipドライバオブジェクト
     * @var object
     */
    private $_objmdr = null;

    /**
     * 置換変数
     * @var array
     */
    private $_vars = array();

    /**
     * 変数の初期化
     *
     * @abstract
     * @access protected
     * @return void
     */
    protected function initValue()
    {
        $this->objvew->setBaseFile('common/frame/xml.tpl');
    }

    /**
     * 実行処理
     *
     * @access public
     * @return void
     **/
    protected function action()
    {
        $this->_objmdr  = Model_Manip::factory($this->table);
        $this->_columns = $this->_objmdr->parseColumns();

        $this->_setForm();
        $this->_setExpression();
        $this->_setTables();
        $this->_setTable();

        /* View,Controller用パスの設定 */
        if (!empty($this->path)){
            $args       = explode('/', $this->path);
            $this->path = $args[1].DS.$args[2].DS.$args[3];
            if (!empty($args[4])){
                $this->path .= DS.$args[4];
            }
        }

        $complete = false;
        if (!empty($_POST['manip'])){
            $this->_setColumns();

            $this->_createModel();
            $this->_createView();
            $this->_createController();

            $this->objvew->assign('alert', $this->objrqt->getAlerts());
            $complete = true;
        }
        $this->objvew->assign('complete', $complete);
    }

    /**
     * 入力条件の設定
     *
     * @access protected
     * @return string   絞込み句
     **/
    protected function setCondition()
    {
        $this->conditions = array (
            'type'=> array(
                'type'=>     'string',
                'option'=>   array('required'=> true),
            ),
            'table'=> array(
                'type'=>     'string',
                'option'=>   array('required'=> true),
            ),
            'path'=> array(
                'type'=>     'string',
                'option'=>   array('required'=> false),
            ),
        );
    }

    /**
     * フォームタイプの設定
     *
     * @access private
     * @return string   絞込み句
     **/
    private function _setForm()
    {
        $forms = array (
            'direct'=>   _('Direct(default)'),
            'text'=>     _('Text form'),
            'textarea'=> _('Text area'),
            'select'=>   _('Select list'),
            'checkbox'=> _('checkbox button'),
            'redio'=>    _('redio button'),
            'date'=>     _('Date form'),
        );
        $this->objvew->assign('forms', $forms);
    }

    /**
     * 式の設定
     *
     * @access private
     * @return string   絞込み句
     **/
    private function _setExpression()
    {                        
        $forms = array (
            '='=>           '=',
            '&gt;'=>        '&gt;',
            '&gt;='=>       '&gt;=',
            '&lt;'=>        '&lt;',
            '&lt;='=>       '&lt;=',
            '!='=>          '!=',
            'LIKE'=>        'LIKE',
            'NOT LIKE'=>    'NOT LIKE',
            'IS NULL'=>     'IS NULL',
            'IS NOT NULL'=> 'IS NOT NULL',
        );
        $this->objvew->assign('operators', $forms);
    }

    /**
     * テーブルリストの設定
     *
     * @access private
     * @return string   絞込み句
     **/
    private function _setTables()
    {
        $result = $this->_objmdr->getTables();
        $pos    = strlen(DB_PREFIX);

        foreach ($result as $table){
            $table = substr($table, $pos);

            $this->tables[$table] = $table;
        }

        $this->objvew->assign('tables', $this->tables);
    }

    /**
     * テーブル情報の設定
     *
     * @access private
     * @return string   絞込み句
     **/
    private function _setTable()
    {
        $type2form = array (
            'string'=> 'text',
            'number'=> 'select',
            'date'=>   'date',
            'email'=>  'text',
            'uri'=>    'text',
        );
        
        $columns = array();
        foreach ($this->_columns as $column=> $info){
            $type = $info['default']? 'direct':$type2form[$info['type']];

            $columns[] = array(
                'column'=>    $column,
                'type'=>      $type,
                'reference'=> $this->_getReference($column)
            );
        }

        $this->objvew->assign('table', $this->table);
        $this->objvew->assign('columns', $columns);
    }

    /**
     * 参照元ファイル名の取得
     *
     * @access private
     * @return string   絞込み句
     **/
    private function _getReference($column)
    {
        if (!preg_match('/^'.REF_PREFIX.'/', $column)){
            return null;
        }

        $offset = strlen(DB_PREFIX);
        $pos    = strpos($this->table, '_', $offset);
        $table  = substr($this->table, 0, $pos);
        
        $name = substr($column, REF_PREFIX_LENGTH);
                
        return $table.'_'.$name;
    }

    /************************************************************/
    /**
     * 配列から文字列へ
     *
     * @access private
     * @return void
     */
    public function array2string($array)
    {
        if (empty($array)){
            return 'array()';
        }
        if (!is_array($array)){
            return 'array()';
        }

        $row = array();
        foreach ($array as $key=>$value){
            $row[] = "'".$key."'=>'".$value."'";
        }

        return 'array('.implode(',', $row).')';
    }

    /**
     * 項目の設定
     *
     * @access private
     * @return void
     */
    private function _setColumns()
    {
        $columns    = array();
        $references = array();
        $pos        = strlen(DB_PREFIX);

        foreach ($this->_columns as $key=>$value){
            if (!empty($_POST[$key])){
                $operator = $_POST['operator'][$key];
                $reference  = null;

                if (!empty($_POST['reference'][$key])){
                    $reference = $_POST['reference'][$key];
                    $reference = substr($reference, $pos);
                    $references[$key] = $_POST['reference'][$key];
                }
                $columns[] = array(
                    'column'=>      $key,
                    'key'=>         $_POST[$key],
                    'type'=>        $value['type'],
                    'pdo_type'=>    $value['pdo_type'],
                    'option'=>      $this->array2string($value['option']),
                    'required'=>    'FALSE',
                    'effect'=>      $value['effect'][1],
                    'reference'=>   $reference,
                    'operator'=>  $operator,
                );
            }
        } // foreach ($this->_columns as $key=>$value)
        $this->_vars['columns']    = $columns;
        $this->_vars['references'] = $references;
    }

    /**
     * テンプレート解析結果の取得
     *
     * @access privat
     * @param string $template
     * @return string
     */
    private function _getParsed($template)
    {
        ob_start();
        include VIEW_DIR.'admin'.DS.'developer'.DS.$template;
        $buffer = ob_get_contents();
        ob_end_clean();

        return $buffer;
    }

    /**
     * 連続削除処理
     *
     * @access private
     * @param string $path
     * @param integer $mode
     * @return boolean
     */
    private function _mkdirP($path, $mode=0755)
    {
        $dir    = dirname($path);
        $result = true;
        if (!file_exists($dir)){
            $result = mkdir($dir, $mode, true);
        }
        return $result;
    }

    /************************************************************/
    /**
     * Modelの作成実行
     *
     * @access private
     * @return void
     */
    private function _createModel()
    {
        $table  = substr($this->table, REF_PREFIX_LENGTH);

        $this->_vars['tbl_name']    = $table;
        $this->_vars['primary_key'] = $this->_objmdr->getPrimaryKey();
        $this->_vars['date']        = date('Y/m/d H:i:s');
        $this->_vars['extends']     = 'Model_View';
        $this->_vars['prefix']      = 'View_';

        $this->_setSqlColumns();

        /* ディレクトリの分割 */
        $dirs = array('');
        if (!empty($this->path)){
            $dirs = explode(DS, $this->path);
        }
        
        /* ファイル名の指定 */
        if ($dirs[0] == 'plugin'){
            $filename = PLUGIN_DIR.$dirs[1].DS.$dirs[2].DS.'models'.DS.'views'.DS.$table.'.php';
            $this->_mkdirP($filename);
        } else {
            $filename = MODEL_DIR.'views'.DS.$table.'.php';
        }

        if (file_exists($filename)){
            $this->_updateClass($filename);
        } else {
            $this->_createClass($filename, $table);
        }
    }

    /**
     * SQL用項目文字列設定
     *
     * @access private
     * @return void
     */
    private function _setSqlColumns()
    {
        $keys = array_keys($this->_columns);
        $bind = array();
        $sets = array();

        foreach ($keys as $key){
            $bind[] = ':'.$key;
            $sets[] = $key.'=:'.$key;
        }

        $this->_vars['cs_columns']   = implode(',', $keys);
        $this->_vars['bind_columns'] = implode(',', $bind);
        $this->_vars['set_columns']  = implode(', ', $sets);
    }

    /**
     * 新規ViewModelの作成
     *
     * @access private
     * @param string $filename
     * @param string $table
     * @return boolean
     */
    private function _createClass($filename, $table)
    {
        $buff  = "<?php\r\n";
        $buff .= $this->_getParsed('_header.tpl');
        $buff .= $this->_getParsed('_view.tpl');
        $buff .= "    /* <<<<<end */\r\n";
        $buff .= '} // class '.$table."\r\n";
        $buff .= "?>\r\n";

        /* ファイルの中身を取得 */
        $handle = fopen($filename, 'w');
        if (!is_resource($handle)) {
            return false;
        }
        $result = fwrite($handle, $buff);
        fclose($handle);
        
        return $result;
    }

    /**
     * ViewModelの更新
     *
     * @access private
     * @param string $filename
     * @return boolean
     */
    private function _updateClass($filename)
    {
        $anchor = array(
            'start>>>>>',
            '<<<<<end',
            '<<<<<*>>>>>'
        );

        /* ファイルの中身を取得 */
        $handle = fopen($filename, 'r');
        if (!is_resource($handle)) {
            return false;
        }

        $buff = array('', '', '');
        $pos = 0;
        while (!feof($handle)) {
            $line  = fgets($handle, 4096);
            $match = strpos($line, $anchor[$pos]);
            if ($match !== false){
                $pos++;
            }            
            $buff[$pos] .= $line;
        }
        fclose($handle);
        $buff[1] = $this->_getParsed('_view.tpl');

        /* ファイルの中身を取得 */
        $handle = fopen($filename, 'w');
        if (!is_resource($handle)) {
            return false;
        }
        $result = fwrite($handle, $buff[0].$buff[1].$buff[2]);
        fclose($handle);
        
        return $result;
    }

    /************************************************************/
    /**
     * Viewの作成実行
     *
     * @access private
     * @return boolean
     */
    private function _createView()
    {
        if (empty($this->path)){
            return false;
        }
        $dirs     = explode(DS, $this->path);

        /* ファイル名の指定 */
        if ($dirs[0] == 'plugin'){
            $filename = PLUGIN_DIR.$dirs[1].DS.$dirs[2].DS.'views'.DS.$dirs[3].'.tpl';
        } else {
            $filename = VIEW_DIR.$this->path.'.tpl';
        }

        if (file_exists($filename)){
            return false;
        }
        $buff = $this->_getParsed('view_list.tpl');
        
        /* ファイルの中身を取得 */
        $this->_mkdirP($filename);
        $handle = fopen($filename, 'w');
        if (!is_resource($handle)) {
            return false;
        }
        $result = fwrite($handle, $buff);
        fclose($handle);
        
        return $result;
    }

    /************************************************************/
    /**
     * Controllerの作成実行
     *
     * @access private
     * @return boolean
     */
    private function _createController()
    {
        $this->_vars['is_view'] = true;

        if (empty($this->path)){
            return false;
        }
        $dirs = explode(DS, $this->path);
        /* ファイル名の指定 */
        if ($dirs[0] == 'plugin'){
            $filename = PLUGIN_DIR.$dirs[1].DS.$dirs[2].DS.'controllers'.DS.$dirs[3].'.php';
        } else {
            $filename = CONTROLLER_DIR.$this->path.'.php';
        }

        if (file_exists($filename)){
            return false;
        }
        /* 継承するクラス名の設定 */
        $info = explode(DS, $this->path);
        $groups = array(
            'admin'=>     'Admin_Controller',
            'community'=> 'Community_Controller',
            'member'=>    'Member_Controller',
            'plugin'=>    'Plugin_Controller',
            'private'=>   'Private_Controller',
            'public'=>    'Public_Controller',
        );
        $group = empty($groups[$info[0]])? 'RKT_Controller':$groups[$info[0]];
        $this->_vars['Controller'] = $group;

        /* テンプレートの解析 */
        $buff  = "<?php\r\n";
        $buff .= $this->_getParsed('controller.tpl');
        $buff .= "\r\n?>\r\n";

        /* ファイルの中身を取得 */
        $this->_mkdirP($filename);
        $handle = fopen($filename, 'w');
        if (!is_resource($handle)) {
            return false;
        }
        $result = fwrite($handle, $buff);
        fclose($handle);
        
        return $result;
    }
} // class Controller