<?php

/**
 * 初期設定をするコントローラ
 *
 * LICENSE: ライセンスに関する情報
 *
 * @category   Setuco
 * @package    Admin
 * @subpackage Controller
 * @license    http://www.opensource.org/licenses/gpl-2.0.php GNU General Public License, version 2
 * @copyright  Copyright (c) 2010 SetucoCMS Project.(http://sourceforge.jp/projects/setucocms)
 * @link
 * @since      File available since Release 0.1.0
 * @author     Takayuki Otake suzuki-mar
 * @todo       フォーム処理をZenfFormに置き換える
 */

/**
 * Description of InstallController
 *
 * @author Takayuki Otake
 */
class Install_InstallController
    extends Setuco_Controller_Action_InstallAbstract
{

    protected $dbh;

    function init()
    {
        parent::init();
        $this->_session = new Zend_Session_Namespace('Setuco_Install_Service');
        $this->_initializeFormValidator = $this->_createInitializeFormValidator();
    }

    public function indexAction()
    {
        $inputValues = $this->_getAllParams();

        $template = 'index';
        if ($this->_request->isPost()) {
            $this->_setSession($inputValues);
            if (!$this->_initializeFormValidator->isValid($inputValues)) {
                $template = 'index';
            } else {
                if ($this->_getParam('submit')) {
                    $template = 'confirm';
                } else if ($this->_getParam('commit')) {
                    $this->_initialize($inputValues);
                    $this->_helper->redirector('finish', 'install', null); 
                }
            }
            $inputValues = $this->_initializeFormValidator->getValues();
            $this->view->errorForm = $this->_initializeFormValidator;
        } else {
            $template = 'index';
        }

        if ($template == 'index') {
            $defaultValues = $this->_getDefaultValues();
            foreach ($defaultValues as $key => $value) {
                if (empty($inputValues[$key])) {
                    $inputValues[$key] = $defaultValues[$key];
                }
            }
            unset($defaultValues);
        }

        $this->view->inputValues = $inputValues;
        return $this->render($template);

    }

    /**
     * データベースとの初期化
     *
     * @author Takayuki Otake
     */
    public function _initialize($validData)
    {
        $validData = $this->_initializeFormValidator->getValues();
        if (preg_match("/^http(s):\/\//", $validData['site_url']) === false) {
            $validData['site_url'] .= 'http://';
        }

        $fhr = fopen('../application/configs/application-sample.ini', 'r');
        $fhw = fopen('../application/configs/application.ini', 'w');
        while ($line = fgets($fhr)){
            $key = '';
            if (preg_match("/resources\.db\.params\.(.*?)(\s+)?\=(\s+)?\"(.*?)\"/", $line, $matches)){
                if ($matches[1] === 'host'){
                    $key = 'db_host';
                } elseif ($matches[1] === 'username') {
                    $key = 'db_user';
                } elseif ($matches[1] === 'password') {
                    $key = 'db_pass';
                } elseif ($matches[1] === 'dbname') {
                    $key = 'db_name';
                }

                if (!empty($key)){
                    $line = str_replace($matches[4], $validData[$key], $line);
                }
            }
            fwrite($fhw, $line);
        }
        fclose($fhr);
        fclose($fhw);

        try{
            $this->_dbConnect($validData);
            $this->dbh->query("SET NAMES utf8");
            $querys = $this->_getInitializeTablesSql();
            foreach ($querys as $query){
                if (!empty($query)){
                    $this->dbh->query($query);
                }
            }

            $sth = $this->dbh->prepare('UPDATE site SET name = ?, url = ?, comment = ? WHERE id = ?');
            $sth->execute(array($validData['site_name'], $validData['site_url'], $validData['site_comment'], 1));

            $sql = "UPDATE account set login_id = '{$validData['account_id']}', password = SHA1('{$validData['account_pass']}')";
            $this->dbh->query($sql);
        } catch (Zend_Exception $pe) {
            $dbh = null;
            throw new Setuco_Exception('update文の実行に失敗しました。' . $pe->getMessage());
        } catch (Exception $e) {
            throw new Setuco_Exception('エラーが発生しました。', $e->getMessage());
        }
        $dbh = null;


        $this->_helper->redirector('finish', 'install', null);
    }

    /**
     * SetucoCMSのセットアップ終了ページ
     *
     * @author Takayuki Otake
     */
    public function finishAction()
    {
        $_siteService = new Admin_Model_Site();
        $siteInfos = $_siteService->getSiteInfo();

        $siteInfos['url'] = preg_replace('/\/$/', '', $siteInfos['url']);

        $this->view->siteInfos = $siteInfos;
        Zend_Session::destroy();
    }

    /**
     * 
     *
     * @author Takayuki Otake
     */
    private function _dbConnect($params)
    {
        try {
            $this->dbh = new PDO("mysql:host={$params['db_host']}; dbname={$params['db_name']}",
                    $params['db_user'], $params['db_pass']);
        } catch (PDOException $e) {
            return false;
        }
        return true;
    }

    /**
     *
     *
     * @author Takayuki Otake
     */
    private function _getDefaultValues()
    {
        if ($_SERVER['SERVER_ADDR'] == '::1') {
            $addr = 'localhost';
        } else {
            $addr = $_SERVER['SERVER_ADDR'];
        }
        return array(
                'account_id' => '',
                'site_url' => 'http://' . $addr . $this->view->baseUrl('/'),
                'site_name' => 'サイト名を設定してください',
                'site_comment' => 'サイトの説明を設定してください。',
                'db_host' => 'localhost',
                'db_name' => '',
                'db_user' => '',
                'db_pass' => ''
                );
    }

    /*
     *
     * @author Takayuki Otake
     **/
    private function _setSession($values)
    {
        foreach ($values as $key => $value) {
            if (preg_match("/pass/", $key)) {
                unset($this->_session->$key);
            } else {
                $this->_session->$key = $values[$key];
            }
        }
    }

    /**
     *
     * @return array String
     * @author Takayuki Otake
     */
    private function _getSession()
    {
        foreach ($this->_getDefaultValues() as $key => $value) {
            $params[$key] = $this->_session->$key;
        }

        return $params;
    }

    /**
     *
     * @return Setuco_Form
     * @author Takayuki Otake
     */
    private function _createInitializeFormValidator()
    {
        $form = new Setuco_Form();

        $adminAccountIdElement = new Zend_Form_Element_Text('account_id', array(
                    'id' => 'account_id',
                    'required' => 'true',
                    'validators' => $this->_makeAdminAccountIdValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($adminAccountIdElement);

        $adminAccountPassElement = new Zend_Form_Element_Text('account_pass', array(
                    'id' => 'account_pass',
                    'required' => 'true',
                    'validators' => $this->_makeAdminAccountPasswordValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($adminAccountPassElement);

        $adminAccountPassCheckElement = new Zend_Form_Element_Text('account_pass_check', array(
                    'id' => 'account_pass_check',
                    'required' => 'true',
                    'validators' => $this->_makeAdminAccountPasswordValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($adminAccountPassCheckElement);

        $siteNameElement = new Zend_Form_Element_Text('site_name', array(
                    'id' => 'site_name',
                    'required' => 'true',
                    'validators' => $this->_makeSiteNameValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($siteNameElement);

        $siteCommentElement = new Zend_Form_Element_Text('site_comment', array(
                    'id' => 'site_comment',
                    'required' => 'true',
                    'validators' => $this->_makeSiteCommentValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($siteCommentElement);

        $siteUrlElement = new Zend_Form_Element_Text('site_url', array(
                    'id' => 'site_url',
                    'required' => 'true',
                    'validators' => $this->_makeSiteUrlValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($siteUrlElement);

        $dbHostElement = new Zend_Form_Element_Text('db_host', array(
                    'id' => 'db_host',
                    'required' => 'true',
                    'validators' => $this->_makeDbHostValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($dbHostElement);

        $dbNameElement = new Zend_Form_Element_Text('db_name', array(
                    'id' => 'db_name',
                    'required' => 'true',
                    'validators' => $this->_makeDbNameValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($dbNameElement);

        $dbUserElement = new Zend_Form_Element_Text('db_user', array(
                    'id' => 'db_user',
                    'required' => 'true',
                    'validators' => $this->_makeDbUserValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($dbUserElement);

        $dbPassElement = new Zend_Form_Element_Text('db_pass', array(
                    'id' => 'db_pass',
                    'required' => 'true',
                    'validators' => $this->_makeDbPassValidators(),
                    'filters' => array('StringTrim')
                    ));
        $form->addElement($dbPassElement);

        return $form;
    }

    /**
     * 
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeSiteNameValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('サイト名を入力してください。');
        $siteNameValidators[] = array($notEmpty, true);

        $stringLength = new Zend_Validate_StringLength(
                array(
                    'max' => 100
                    )
                );
        $stringLength->setEncoding("UTF-8");
        $stringLength->setMessage('サイト名は%max%文字以下で入力してください。');
        $siteNameValidators[] = array($stringLength, true);

        return $siteNameValidators;
    }

    /**
     * 
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeSiteCommentValidators()
    {
        $stringLength = new Zend_Validate_StringLength(
                array(
                    'max' => 300
                    )
                );
        $stringLength->setEncoding("UTF-8");
        $stringLength->setMessage('サイトの説明は%max%文字以下で入力しだください。');
        $commentValidators[] = array($stringLength, true);

        return $commentValidators;
    }

    /**
     * 
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeAdminAccountIdValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('管理者アカウントのログインIDを入力してください');
        $idValidators[] = array($notEmpty, true);

        return $idValidators;
    }

    /**
     * 
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeAdminAccountPasswordValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('管理者アカウントのパスワードを入力してください。');
        $passValidators[] = array($notEmpty);

        $stringLength = new Zend_Validate_StringLength(
                array(
                    'min' => 6,
                    'max' => 30
                    )
                );
        $stringLength->setMessage('パスワードは%min%文字以上%max%文字以下で入力してください。');
        $passValidators[] = array($stringLength);

        $confirmCheck = new Setuco_Validate_Match(
                array(
                    'check_key' => 'account_pass_check'
                    )
                );
        $confirmCheck->setMessage('パスワードとパスワード確認が一致しません。');
        $passValidators[] = $confirmCheck;

        $passwordCheck = new Setuco_Validate_Password();
        $passValidators[] = $passwordCheck;

        return $passValidators;
    }

    /**
     *
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeSiteUrlValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('接続するデータベースのアドレスを入力してください。');
        $urlValidators[] = array($notEmpty, true);

        return $urlValidators;
    }

    /**
     *
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeDbHostValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('接続するデータベースのアドレスを入力してください。');
        $hostValidators[] = array($notEmpty, true);

        return $hostValidators;
    }

    /**
     *
     * @return Zend_From
     * @author Takayuki Otake
     */
    private function _makeDbNameValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('');
        $nameValidators[] = array($notEmpty, true);

        return $nameValidators;
    }

    /**
     *
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeDbUserValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('');
        $userValidators[] = array($notEmpty);

        return $userValidators;
    }

    /**
     *
     * @return Zend_Form
     * @author Takayuki Otake
     */
    private function _makeDbPassValidators()
    {
        $notEmpty = new Zend_Validate_NotEmpty();
        $notEmpty->setMessage('');
        $passValidators[] = array($notEmpty);

        return $passValidators;
    }

    /**
     * SetucoCMSのデータベーススキーマ取得
     * 
     * @return String
     * @author Takayuki Otake
     */
    function _getInitializeTablesSql()
    {

        $query = '';
        $comment_flg = false;
        $fp = fopen('../sql/initialize_tables.sql', 'r');
        while ( $line = fgets($fp) ){
            // MySQLスキーマのファイル内を走査しつつ、コメントは除外して抽出
            if ( $comment_flg === true ){
                if ( preg_match("/\*\//", $line) ){
                    $comment_flg = false;
                }
            } else {
                if ( preg_match("/\/\*/", $line) ){
                    $comment_flg = true;
                } elseif ( preg_match("/^\-\-/", $line) ){
                    // コメント行は無視する
                } else {
                    $query .= $line;
                }
            }
        }
        fclose($fp);

        $querys = explode(";", $query);
        return $querys;
    }
}
