<?php
/**
 * 設定ファイル操作マネージャー
 *
 * PHP versions 5
 *
 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
 *
 * @package    Magic3 Framework
 * @author     平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
 * @copyright  Copyright 2006-2009 Magic3 Project.
 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
 * @version    SVN: $Id: configManager.php 1460 2009-01-22 13:34:21Z fishbone $
 * @link       http://www.magic3.org
 */
require_once(M3_SYSTEM_INCLUDE_PATH . '/common/core.php');

class ConfigManager extends Core
{
	private $configFile = 'siteDef.php';		// 設定ファイル名
    private $defParam = array();				// 定義項目
	
	/**
	 * コンストラクタ
	 */
	function __construct()
	{
		// 親クラスを呼び出す
		parent::__construct();
		
		$this->defParam['M3_SYSTEM_ROOT_URL'] = '';
		$this->defParam['M3_DB_CONNECT_DSN'] = '';
		$this->defParam['M3_DB_CONNECT_USER'] = '';
		$this->defParam['M3_DB_CONNECT_PASSWORD'] = '';
		
		// 設定値取得
		if (defined('M3_SYSTEM_ROOT_URL')) $this->defParam['M3_SYSTEM_ROOT_URL'] = M3_SYSTEM_ROOT_URL;				// ルートURL
		if (defined('M3_DB_CONNECT_DSN')) $this->defParam['M3_DB_CONNECT_DSN'] = M3_DB_CONNECT_DSN;					// 接続先ＤＢ
		if (defined('M3_DB_CONNECT_USER')) $this->defParam['M3_DB_CONNECT_USER'] = M3_DB_CONNECT_USER;				// 接続ユーザ
		if (defined('M3_DB_CONNECT_PASSWORD')) $this->defParam['M3_DB_CONNECT_PASSWORD'] = M3_DB_CONNECT_PASSWORD;	// パスワード
	}
	/**
	 * 設定ファイルのフルパス
	 *
	 * @return string			設定ファイルフルパス
	 */
	public function configFilePath()
	{
		return $this->gEnv->getIncludePath() . '/' . $this->configFile;
	}
	/**
	 * 設定ファイルが作成可能かどうか
	 *
	 * @return bool				true=可能、false=不可
	 */
	public function isConfigFileWritable()
	{
		if (file_exists($this->gEnv->getIncludePath() . '/' . $this->configFile) && is_writable($this->gEnv->getIncludePath() . '/' . $this->configFile)){
			return true;
		} else if (is_writable($this->gEnv->getIncludePath())){// ディレクトリが書き込み可能か
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 設定ファイルディレクトリが書き込み可能かどうか
	 *
	 * @return bool				true=可能、false=不可
	 */
	public function isConfigDirWritable()
	{
		if (is_writable($this->gEnv->getIncludePath())){// ディレクトリが書き込み可能か
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 定義値チェック
	 *
	 * 設定ファイルに最小限必要な設定が行われているかどうか確認
	 *
	 * @return bool		true=定義完了、false=定義未完
	 */
	public function isConfigured()
	{
		if ((defined('M3_SYSTEM_ROOT_URL') && strlen(trim(M3_SYSTEM_ROOT_URL)) > 0) &&				// ルートURL
				(defined('M3_DB_CONNECT_DSN') && strlen(trim(M3_DB_CONNECT_DSN)) > 0) &&			// 接続先ＤＢ
				(defined('M3_DB_CONNECT_USER') && strlen(trim(M3_DB_CONNECT_USER)) > 0) &&			// 接続ユーザ
				defined('M3_DB_CONNECT_PASSWORD')){													// パスワード(空の場合あり)			
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 設定ファイルの作成
	 *
	 * @param string $msg		エラーメッセージ
	 * @return bool				true=成功、false=失敗
	 */
	function updateConfigFile(&$msg)
	{
		// 設定ファイルのフルパス
		$configFilePath = $this->gEnv->getIncludePath() . '/' . $this->configFile;
		
		// 現在の設定ファイルを読み込む
		if (!($file = @fopen($configFilePath, "r"))){
			$errMsg = '設定ファイルのオープンに失敗しました ファイル=' . $configFilePath;
 			$this->gLog->error(__METHOD__, $errMsg);
			$msg = $errMsg;
 			return false;
		}
		$content = @fread($file, filesize($configFilePath));
		@fclose($file);
		
		// 引数で渡ってきた値を再設定する。コメント行は処理しない。
		foreach($this->defParam as $key => $val){
			if (preg_match("/^[ \t]*define\([ \t]*[\"']" . $key . "[\"'][ \t]*,[ \t]*[\"'].*[\"'][ \t]*\)/m", $content)){
				$content = preg_replace("/^[ \t]*define\([ \t]*[\"']" . $key . "[\"'][ \t]*,[ \t]*[\"'].*[\"'][ \t]*\)/m",
					"define('" . $key . "', '" . addslashes($val) . "')", $content);
			} else {
				$errMsg = '設定ファイルにキーが見つかりません key=' . $key;
				$this->gLog->error(__METHOD__, $errMsg);
				$msg = $errMsg;
				return false;
			}
		}
		
		// テンポラリファイルに保存
		if (!($tmpFilename = tempnam(M3_SYSTEM_WORK_DIR_PATH, "m3_"))){
			$errMsg = 'テンポラリファイルの作成に失敗しました ディレクトリ=' . M3_SYSTEM_WORK_DIR_PATH;
 			$this->gLog->error(__METHOD__, $errMsg);
			$msg = $errMsg;
 			return false;
		}
		if (!($tmpFHandle = fopen($tmpFilename, "w"))){
			$errMsg = 'テンポラリファイルのオープンに失敗しました ファイル=' . $tmpFilename;
 			$this->gLog->error(__METHOD__, $errMsg);
			$msg = $errMsg;
			
			// 作成した設定ファイルを削除
			unlink($tmpFilename);
 			return false;
		}
		fwrite($tmpFHandle, $content);
		fclose($tmpFHandle);
		
		// 現在の設定ファイルとテンポラリファイルを入れ替え
		$tmpConfigFilePath = $configFilePath . '_tmp';
		if (!rename($configFilePath, $tmpConfigFilePath)){
			$errMsg = '設定ファイルを退避できません';
			$this->gLog->error(__METHOD__, $errMsg);
			$msg = $errMsg;
			
			// 作成した設定ファイルを削除
			unlink($tmpFilename);
			return false;
		}
		if (!rename($tmpFilename, $configFilePath)){
			$errMsg = '設定ファイルを作成できません';
			$this->gLog->error(__METHOD__, $errMsg);
			$msg = $errMsg;
			
			// 作成した設定ファイルを削除
			unlink($tmpFilename);
			
			// 設定ファイルを戻す
			rename($tmpConfigFilePath, $configFilePath);
			return false;
		}
		
		// 古い設定ファイルを削除
		unlink($tmpConfigFilePath);
		return true;
	}
	/**
	 * システムのルートURL
	 */
	public function setSystemRootUrl($name)
	{
		$this->defParam['M3_SYSTEM_ROOT_URL'] = $name;
	}
	/**
	 * システムのルートURL
	 */
	public function getSystemRootUrl()
	{
		return $this->defParam['M3_SYSTEM_ROOT_URL'];
	}
	/**
	 * 接続先ＤＢ情報
	 */
	public function setDbConnectDsn($name)
	{
		$this->defParam['M3_DB_CONNECT_DSN'] = $name;
	}
	/**
	 * 接続先ＤＢ情報
	 */
	public function getDbConnectDsn()
	{
		return $this->defParam['M3_DB_CONNECT_DSN'];
	}
	/**
	 * 接続先ＤＢ情報を取得
	 */
	public function getDbConnectDsnByList(&$dbType, &$hostname, &$dbname)
	{
		// DB種別を取得
		$dsn = self::getDbConnectDsn();
		$pos = strpos($dsn, ':');
		if ($pos === false){
			$dbtype = '';
			$pos = -1;
		} else {
			$dbtype = trim(substr($dsn, 0, $pos));
		}
		// ホスト名、DB名を取得
		$hostname = '';
		$dbname = '';
		$dsnParams = explode(";", substr($dsn, $pos+1));
		for ($i = 0; $i < count($dsnParams); $i++){
			list($key, $value) = explode("=", $dsnParams[$i]);
			$key = trim($key);
			$value = trim($value);
			if ($key == 'host'){
				$hostname = $value;
			} else if ($key == 'dbname'){
				$dbname = $value;
			}
		}
		return true;
	}
	/**
	 * 接続ユーザ
	 */
	public function setDbConnectUser($name)
	{
		$this->defParam['M3_DB_CONNECT_USER'] = $name;
	}
	/**
	 * 接続ユーザ
	 */
	public function getDbConnectUser()
	{
		return $this->defParam['M3_DB_CONNECT_USER'];
	}
	/**
	 * 接続パスワード
	 */
	public function setDbConnectPassword($name)
	{
		$this->defParam['M3_DB_CONNECT_PASSWORD'] = $name;
	}
	/**
	 * 接続パスワード
	 */
	public function getDbConnectPassword()
	{
		return $this->defParam['M3_DB_CONNECT_PASSWORD'];
	}
}
?>
