<?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/>.
 */


/**
 * サービス管理のロジッククラス
 *
 */
class Inqman_ServiceModel extends Inqman_AbstractDao
{
    protected $_name = 'm_service';
    
    /**
     * サービスIDで指定したサービス情報を取得する
     * 
     * @access public
     * @param integer $serviceId サービスID
     * @return mixed サービス情報を連想配列で返す
     * 
     */
    public function getOneService($service_id)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                     ->from(array('s'=>'m_service'))
                     ->where('s.id=?', $service_id)
                     ->where('s.deleted<>1')
        ;
        $this->_logger->info('Inqman_ServiceModel->getOneService : ' . $select->__toString());
        
        return $db->fetchRow($select);
    }
    
    /**
     * ユーザが利用できる（役割を持つ）サービスを取得する
     * 
     * @access public
     * @param integer $user_id
     * @return mixed
     */
    public function getEnableServices($user_id)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                     ->from(array('au'=>'t_acl_user'), array())
                     ->joinInner(array('aa'=>'t_acl_authority'), 'au.authority_id=aa.id', array('service_id'))
                     ->joinInner(array('s'=>'m_service'), 'aa.service_id=s.id')
                     ->where('au.user_id=?', $user_id)
                     ->where('s.enable=1')
                     ->where('s.deleted<>1')
                     ->group('aa.service_id')
                     ->order('aa.service_id asc')
        ;
        $this->_logger->info('Inqman_ServiceModel->getEnableServices : ' . $select->__toString());
        
        return $db->fetchAll($select);
    }
    
    /**
     * ユーザが利用できる（役割を持つ）サービスをKEY=ID,VALUE=NAMEの配列で取得する
     * 
     * @access public
     * @param integer $user_id
     * @return array
     */
    public function getEnableServiceOptions($user_id) {
        
        $services = $this->getEnableServices($user_id);
        
        $options = array();
        foreach ($services as $service) {
            $options[$service['service_id']] = $service['name'];
        }
        
        return $options;
    }
    
    /**
     * 全てのサービスをKEY=ID,VALUE=NAMEの配列で取得する
     * 
     * @param boolean $is_enable 無効なサービスも取得する場合はTRUE
     * 
     */
    public function getAllServiceOptions($is_enable=false)
    {
        $criteria = array();
        if ($is_enable) $criteria = array('enable'=>2);
        else $criteria = array('enable'=>1);
        
        $services = $this->findService('id asc', null, null, $criteria);
        
        $options = array();
        foreach ($services as $service) {
            $options[$service['id']] = $service['name'];
        }
        
        return $options;
    }
    
    /**
     * 検索する
     * 
     * @access public
     * @param mixed $order
     * @param integer $page ページ番号
     * @param integer $rp 1ページあたりの表示件数
     * @param mixed $criteria 検索条件
     */
    public function findService($order=null, $page=null, $rp=null, $criteria=null)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
            ->from(array('s' => 'm_service'))
            ->where('s.deleted<>1')
        ;
        
        if ($order !== null) {
            foreach ((array) $order as $str) {
                $select->order($str);
            }
            $select->order($this->_primary[1] . " asc");
        }
        
        if ($page !== null && $rp !== null) {
            $select->limitPage($page, $rp);
        }
        
        $select = $this->_buildFindQuery($select, $criteria);
        
        $this->_logger->info('Inqman_ServiceModel->find : ' . $select->__toString());
        
        return $db->fetchAll($select);
    }
    
    /**
     * データ件数を得る
     * 
     * @access public
     * @param mixed $criteria 検索条件
     */
    public function getTotalSize($criteria=null)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
            ->from(array('s' => 'm_service'), 'count(*)')
            ->where('s.deleted<>1')
        ;
        
        $select = $this->_buildFindQuery($select, $criteria);
        
        $this->_logger->info('Inqman_ServiceModel->getTotalSize : ' . $select->__toString());
        
        return $db->fetchOne($select);
    }
    
    /**
     * 検索条件からSQLを生成する
     * 
     * @access protected
     * @param select Zend_DB_Select
     * @param criteria mixed
     * @return string SQLを返す
     */
    protected function _buildFindQuery($select, $criteria)
    {
        //検索条件の設定
        foreach ((array) $criteria as $field => $cond) {
            
            switch ($field) {
            case 'enable':
                if($cond === 0) {
                    $select->where("enable=?", 0);
                }
                else if ($cond === 1) {
                    $select->where("enable=?", 1);
                }
                   
//                if ($cond['mtd']=='equal' && !empty($cond['val'])) {
//                    $select->where("i.subject=?", $cond['val']);
//                } elseif($cond['mtd']=='like' && !empty($cond['val'])) {
//                    $value = $cond['val'];
//                    $select->where("i.subject like ?", "%{$value}%");
//                }
                break;  
            default:
                break;
            }
        }
        return $select;
    }
    
    /**
     * サービス固有の設定情報を取得する
     * 
     * @access public
     * @param integer $service_id サービスID
     * @return array 設定情報を連想配列で返す
     */
    public function getServiceSettings($service_id)
    {
        $db = $this->getAdapter();
        $select = $db->select()
                ->from('t_service_setting')
                ->where('service_id=?', $service_id)
                ->order('id asc')
        ;
        $this->_logger->info('Inqman_ServiceModel->getServiceSettings : ' . $select->__toString());
        
        return $db->fetchAll($select);
    }
    
    /**
     * サービス固有の設定情報を更新する
     * 
     */
    public function updateServiceSettings($service_id, $settings)
    {
        try {
            $db = $this->getAdapter();
            $db->beginTransaction();
            foreach ((array)$settings as $id => $setting) {
                if ($id == 0 && !empty($setting['pop3_host']) && !empty($setting['pop3_user'])) {
                    unset($setting['delete']);
                    $setting['service_id'] = $service_id;
                    $db->insert('t_service_setting', $setting);
                } else if ($setting['delete'] == 1) {
                    $where = $db->quoteInto('id=?', $id);
                    $db->delete('t_service_setting', $where);
                } else {
                    unset($setting['delete']);
                    $where = $db->quoteInto('id=?', $id);
                    $db->update('t_service_setting', $setting, $where);
                }
            }
            $db->commit();
        } catch(Exception $e) {
            $this->_logger->err($e->getMessage());
            throw $e;
        }
    }
    
    /**
     * サービスコードが重複していないかチェックする
     * 
     * @access public
     * @param string $code
     * @return boolean 重複していない場合はTRUE、重複している場合はFALSEを返す
     */
    public function checkDuplicateCode($code, $is_modify=false)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                ->from('m_service', 'count(*)')
                ->where('code=?', $code)
        ;
        $this->_logger->info($select->__toString());
        
        $result = $db->fetchOne($select);
        
        if ($is_modify == false && $result > 0) {
            return false;
        } elseif ($is_modify == true && $result > 1) {
            return false;
        }
        return true;
    }
    
    /**
     * 問い合わせ受付用メールアドレスが重複していないチェックする
     * 
     * @access public
     * @param string $inquiry_mailaddress
     * @return boolean 重複していない場合はTRUE、重複している場合はFALSEを返す
     */
    public function checkDuplicateInquiryMailaddress($inquiry_mailaddress, $is_modify=false)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                ->from('m_service', 'count(*)')
                ->where('inquiry_mailaddress=?', $inquiry_mailaddress)
        ;
        $this->_logger->info($select->__toString());
        
        $result = $db->fetchOne($select);
        
        if ($is_modify == false && $result > 0) {
            return false;
        } elseif ($is_modify == true && $result > 1) {
            return false;
        }
        return true;
    }
    
    /**
     * コメント受付用メールアドレスが重複していないチェックする
     * 
     * @access public
     * @param string $inquiry_mailaddress
     * @return boolean 重複していない場合はTRUE、重複している場合はFALSEを返す
     */
    public function checkDuplicateCommentMailaddress($comment_mailaddress, $is_modify=false)
    {
        $db = $this->getAdapter();
        
        $select = $db->select()
                ->from('m_service', 'count(*)')
                ->where('comment_mailaddress=?', $comment_mailaddress)
        ;
        $this->_logger->info($select->__toString());
        
        $result = $db->fetchOne($select);
        
        if ($is_modify == false && $result > 0) {
            return false;
        } elseif ($is_modify == true && $result > 1) {
            return false;
        }
        return true;
    }
    
    /**
     * サービス情報をデータベースに登録する
     * 
     * @access public
     * @param mixed $values 登録するサービス情報
     * 
     */
    public function createService($values)
    {
        $db = $this->getAdapter();
        $db->beginTransaction();
        
        //サービスを登録
        $values['create_datetime'] = date("Y-m-d H:i:s", time());
        $db->insert('m_service', $values);
        
        //追加されたサービスIDとサービス名を取得
        $service_id = $db->lastInsertId();
        $service_name = $values['name'];
        
        //マスタから初期登録を行う役割情報を取得
        $rows = $db->fetchAssoc($db->select()->from('m_acl_role')->where('initial_giving=?',1));
        
        foreach ((array) $rows as $row) {
            //サービス名＋役割名で権限情報を登録
            $values = array(
                'name'            => $service_name . $row['name'],
                'role_id'         => $row['id'],
                'service_id'      => $service_id,
                'enable'          => 1,
            );
            $db->insert('t_acl_authority', $values);
            $authority_id = $db->lastInsertId();
            
            //役割に親子関係が設定されている場合は、権限情報にも親子関係を設定
            if (!empty($row['parent_id'])) {
                $parent_id = $db->fetchOne(
                        $db->select()
                           ->from('t_acl_authority', 'id')
                           ->where('service_id=?', $service_id)
                           ->where('role_id=?', $row['parent_id'])
                );
                $db->insert('l_authority_parent', array('authority_id'=>$authority_id, 'parent_id'=>$parent_id));
            }
        }
        $db->commit();
    }

    /**
     * サービス情報を更新する
     * 
     */
    public function updateService($service_id, $values)
    {
        try {
            $db = $this->getAdapter();
            $db->beginTransaction();
            
            $where = $db->quoteInto('id=?', $service_id);
            $values['update_datetime'] = date("Y-m-d H:i:s", time());
            $db->update('m_service', $values, $where);
            
            //マスタから初期登録を行う役割情報を取得
            $rows = $db->fetchAssoc($db->select()->from('m_acl_role')->where('initial_giving=?',1));
            
            $service_name = $values['name'];
            $values = array();
            foreach ((array) $rows as $row) {
                //サービス名＋役割名で権限情報を更新
                $values = array(
                    'name'       => $service_name . $row['name'],
                );
                $where = array($db->quoteInto('role_id=?', $row['id']),
                               $db->quoteInto('service_id=?', $service_id));
                $db->update('t_acl_authority', $values, $where);
            }
            
            $db->commit();
        } catch (Exception $e) {
            $db->rollBack();
            $this->_logger->err($e->getMessage());
            throw $e;
        }
    }
    
    /**
     * サービス情報を削除する
     * 
     */
    public function deleteService($service_id)
    {
        $db = $this->getAdapter();
        try {
            $db->beginTransaction();
            
            //サービス情報は論理削除
            $where = $db->quoteInto('id=?', $service_id);
            $values = array(
                    'code'                => 'DELETED'.$service_id,
                    'inquiry_mailaddress' => 'DELETED'.$service_id,
                    'comment_mailaddress' => 'DELETED'.$service_id,
                    'enable'              => '0',
                    'deleted'             => '1',
                    'delete_datetime'     => date("Y-m-d H:i:s", time()),
            );
            $db->update('m_service', $values, $where);
            
            //サービス固有の設定情報を削除
            $where = $db->quoteInto('service_id=?', $service_id);
            $db->delete('t_service_setting', $where);
            $db->delete('t_service_event',   $where);
            $db->delete('t_mailtemplate',    $where);
            
            //権限情報を削除
            $select = $db->select();
            $select->from('t_acl_authority', 'id')->where('service_id=?', $service_id);
            $result = $db->fetchCol($select);
            $inwhere = "authority_id in (" . implode(',', $result) .")";
            $db->delete('t_acl_user', $inwhere);
            $db->delete('t_acl_authority', $where);
            
            $db->commit();
        } catch (Exception $e) {
            $db->rollBack();
            $this->_logger->err($e->getMessage());
            throw $e;
        }
    }
    
}
