<?php
/*
 * This file is part of INQMAN
 *
 * Copyright(c) 2008 BULLHEAD,INC. ALL RIGHTS RESERVED.
 *
 * http://www.bullhead.co.jp/
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation;
 * either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

define('VIEW_KEY_PAGE_TITLE',      'page_title');
define('VIEW_KEY_ACL_FLAGS',       'acl_flags');
define('VIEW_KEY_FORM',            'form');
define('VIEW_KEY_FORM_INPUT',      'form_input');
define('VIEW_KEY_DATA_DETAIL',     'data_detail');
define('VIEW_KEY_DATA_LIST',       'data_list');
define('VIEW_KEY_PAGER',           'pager');
define('VIEW_KEY_ERROR_MESSAGES',  'error_messages');
define('VIEW_KEY_USER_INFO',       'user_info');
define('VIEW_KEY_FORRWARD_PARAMS', 'forward_params');

define('ACTION_PREFIX_KEY',        'action_prefix');
define('ACTION_PREFIX_NAME',       'action_name');
define('ACTION_PREFIX_CREATE',     'create_');
define('ACTION_PREFIX_MODIFY',     'modify_');
define('ACTION_PREFIX_DERIVATE',   'derivate_');

define('REQUEST_KEY_CURRENT_PAGE', 'start');
define('REQUEST_KEY_PER_PAGE',     'per_page');
define('REQUEST_KEY_FORWARD',      'forward');

define('ACL_GLOBAL_SERVICE_ID',    1);
define('ACL_RESOURCE_KEY_USER',         'user');
define('ACL_RESOURCE_KEY_SERVICE',      'service');
define('ACL_RESOURCE_KEY_INQUIRY',      'inquiry');
define('ACL_RESOURCE_KEY_UNACCEPT',     'unaccept');
define('ACL_RESOURCE_KEY_UNAPPROVE',    'unapprove');
define('ACL_RESOURCE_KEY_COMMENT',      'comment');
define('ACL_RESOURCE_KEY_REPLY',        'reply');
define('ACL_RESOURCE_KEY_MAILTEMPLATE', 'mail_template');
define('ACL_RESOURCE_KEY_EVENT',        'event');

define('ACL_PRIVILEGE_KEY_CREATE',      'create');
define('ACL_PRIVILEGE_KEY_READ',        'read');
define('ACL_PRIVILEGE_KEY_UPDATE',      'update');
define('ACL_PRIVILEGE_KEY_DELETE',      'delete');
define('ACL_PRIVILEGE_KEY_ACCEPT',      'accept');
define('ACL_PRIVILEGE_KEY_APPROVE',     'approve');
define('ACL_PRIVILEGE_KEY_SETUP',       'setup');
define('ACL_PRIVILEGE_KEY_SETLIMIT',    'setlimit');
define('ACL_PRIVILEGE_KEY_TAKECHARGE',  'takecharge');
define('ACL_PRIVILEGE_KEY_REFERENCE',   'reference');
define('ACL_PRIVILEGE_KEY_DERIVATION',  'derivation');
define('ACL_PRIVILEGE_KEY_MERGE',       'merge');
define('ACL_PRIVILEGE_KEY_SUSPEND',     'suspend');
define('ACL_PRIVILEGE_KEY_SOLUTION',    'solution');


define('ERROR_KEY_ACCESS_FORBIDDEN', 'access_forbidden');

abstract class AbstractController extends Bullhead_Controller_Action
{
    /**
     * 
     * @var Bullhead_Log
     */
    protected $_logger;
    
    /**
     * 初期設定を行う
     */
    public function init()
    {
        parent::init();
        $this->_prepareHelper();
        $this->_setupLogger();
        $this->_assignCommonValue();
    }
    
    /**
     * preDispatch
     * 
     * @access public
     */
    public function preDispatch()
    {
        //認証情報（ログイン済みか）をチェックする
        $userInfo = $this->_getUserInfo();
        
        if (null === $userInfo) {
            $forwardParams = array();
            
            //未ログインの場合、リクエストパラメータを保持してログイン画面に遷移させる
            foreach ((array) $this->getRequest()->getParams() as $key => $value) {
                $forwardParams[$key] = $value;
            }
            $this->_forward('index','account', null, array(REQUEST_KEY_FORWARD => $forwardParams));
        } else { 
            
            $this->view->assign(VIEW_KEY_USER_INFO, $userInfo);            
        }
    }
    
    /**
     * postDispatch
     * 
     * @access public
     * 
     */
    public function postDispatch()
    {
        //$this->_setupLayout();
        $this->view->setHelperPath(ROOT_DIR . '/library/Bullhead/View/Helper', 'Bullhead_View_Helper');
        $this->_prepareTemplate();
    }
    
	/**
	 * 設定ファイルを読み込む
	 * 
	 * @see Bullhead_Controller_Action
	 */
	protected function _prepareConfig()
	{
        $config = new Zend_Config_Ini(MOD_INQMAN_CONFIGS_DIR . '/config.ini.php', APPLICATION_RUNNING_MODE);
        return $config;
	}
	
	/**
	 * 翻訳ファイルを読み込む
	 * 
	 * @see Bullhead_Controller_Action
	 */
	protected function _prepareTranslate()
	{
		$translate = new Zend_Translate('csv', MOD_INQMAN_LANGUAGES_DIR, 'ja');
		return $translate;
	}
	
    /**
     * レイアウトテンプレートを設定する
     * 
     * @acess protected
     */
    protected function _prepareTemplate()
    {
        $response = $this->getResponse();
        $response->insert('header', $this->view->render('layout/header.phtml'));
        $response->insert('footer', $this->view->render('layout/footer.phtml'));
    }
    
    /**
     * ページャーオブジェクトの設定情報を取得する
     * 
     * リクエストパラメータから現在のページ番号と1ページ内の表示件数を取得し、オフセット値を算出して設定する。
     * 
     * @access protected
     * @return array ページャーオブジェクトの設定情報を連想配列で返す
     * 
     */
    protected function _getPagerParams()
    {
        $currentPage = $this->getRequest()->getParam(REQUEST_KEY_CURRENT_PAGE);
        if (empty($currentPage)) $currentPage = 1;
        
        $perPage = $this->getRequest()->getParam(REQUEST_KEY_PER_PAGE);
        if (!empty($perPage) && $this->_pagerParams['appoint_per_page']) {
            $this->_pagerParams['perPage'] = $perPage;
        }
        
        $offset = 0 + ($currentPage -1) * $this->_pagerParams['perPage'];
        $count = $this->_pagerParams['perPage'];
        $params = array($offset, $count);
        
        return $params;
    }
    
    /**
     * ページャーオブジェクトを生成し、VIEWに設定する
     * 
     * @access protected
     * 
     */
    protected function _preparePager($pagerParams=null)
    {
        if ($pagerParams == null) $pagerParams = $this->_pagerParams;
        
        $params = array_merge($pagerParams, $params);        
        $pager = Pager::factory($params);
        
        $this->view->assign('pager', $pager);
    }
    
    /**
     * 独自ヘルパーのパスを設定する
     * 
     */
    protected function _prepareHelper()
    {
        $this->view->setHelperPath('Bullhead/View/Helper', 'Bullhead_View_Helper');
    }
    
	/**
	 * ロギングオブジェクトを設定する
	 * 
	 */
    protected function _setupLogger()
    {
        $log_config   = $this->_config->log_files->controller_log;
        $save_dir     = $log_config->save_dir;
        $output_level = intval($log_config->output_level);
        
        $logger = new Bullhead_Log();
        $logger->addWriter(new Zend_Log_Writer_Stream(ROOT_DIR . $save_dir . 'controller.log'));
        $logger->addFilter(new Zend_Log_Filter_Priority($output_level));
        $this->_logger = $logger;
    }
    
	/**
	 * レイアウトファイルのディレクトリ設定を行う
	 * 
	 * @see Bullhead_Controller_Action
	 */
	protected function _setupLayout()
	{
		Zend_Layout::startMvc(array('layoutPath' => MOD_INQMAN_VIEWS_DIR . '/scripts/layout'));
	}
	
	/**
	 * データベース接続設定を行う
	 * 
	 * @see Bullhead_Controller_Action
	 */
	protected function _setupDatabase()
	{
        $db = Zend_Db::factory(Zend_Registry::get('config')->database);
        
        $db->query('set names utf8');//TODO MySQLか否かなの判定要
        Zend_Db_Table_Abstract::setDefaultAdapter($db);
	}

	/**
	 * ページタイトルを設定する
	 * 
	 * @param string $title
	 * @param boolean $by_key 引数$titleをページ名を表す翻訳キーとする場合はTRUE、そのままタイトルとする場合はFALSEを受け取る
	 */
	protected function _setupPageTitle($action, $controller, $module=null, $by_key=true)
	{
	    if ($by_key) {
	        $translate_key = "{$controller}.title.{$action}";
	        $title = "{$this->_translate->translate($translate_key)} {$this->_translate->translate('common.title.system')}"; 
	    }
	    $this->view->assign(VIEW_KEY_PAGE_TITLE, $title);
	}
	
	/**
	 * アクション共通のパラメータをVIEWに設定する
	 * 
	 * @access protected
	 */
	protected function _assignCommonValue()
	{
	    $this->view->assign('base', $this->_config->site->fqdn);
	}
	
    /**
     * 作成関連アクションの共通パラメータをVIEWに設定する
     * 
     * @access protected
     * 
     */
    protected function _assignCreateActionValue() {
        $this->view->assign(ACTION_PREFIX_KEY, ACTION_PREFIX_CREATE);
        $this->view->assign(ACTION_PREFIX_NAME, $this->view->translate('common.label.create'));
    }
    
    /**
     * 変更関連アクションの共通パラメータをVIEWに設定する
     * 
     * @access protected
     * 
     */
    protected function _assignModifyActionValue() {
        $this->view->assign(ACTION_PREFIX_KEY, ACTION_PREFIX_MODIFY);
        $this->view->assign(ACTION_PREFIX_NAME, $this->view->translate('common.label.modify'));
    }
    
    /**
     * 認証済みのユーザ情報を取得する
     * 
     * @access protected
     * @return object ユーザ情報をStandardObjectで返す
     * 
     */
    protected function _getUserInfo()
    {
        //認証クラスのインスタンスを取得
        $auth = Zend_Auth::getInstance();
        
        if ($auth->hasIdentity()) {
            $storage = $auth->getStorage();
            $user = $storage->read();
            return $user;
        }
        return null;
    }
    
    /**
     * アクセス制御情報を初期化する
     * @return Zend_Acl instance
     */
    protected function _prepareAcl()
    {
    }
    
    /**
     * アクセス制御をチェックする
     * 
     * 引数で渡されたアクセス権限（Role）名に対してアクセス可否のチェックを行う
     * Zend_ACL を用いる
     *
     * @param array $roles 権限名
     * @return boolean アクセスを許可する場合 TRUE を返す
     */
    protected function _checkAcl($resource_key, $privilege_key, $service_id, $authorities=null)
    {
        if ($authorities === null) {
            $authorities = array_keys($this->_getUserInfo()->roles);
        }
        
        $acl_model = new Inqman_AclModel();
        if (!$acl_model->checkAcl($resource_key, $privilege_key, $service_id, $authorities)) {
            throw new Exception($this->_translate->translate('error.message.access_forbidden'));
        }
    }
    
}
