<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
class config
{
	static public $cached=false;
	
	static private $_cfg=array();
	
	static function init()
	{
		if ($data=@file_get_contents(LAB_PATH_DATA.'/cache/configs.obj')) {
			self::$_cfg=unserialize($data);
		}

		//если отключено кэширование
		if (!self::get('core.cache')) self::_init();

		//если включен режим отладки то кэширование отключаем
		if (self::get('core.debug_mode')) self::set('core.cache', false);
		
		if (self::get('core.cache') && !self::$cached && !$data) {
			self::_cache();
		}
		
		define('SECURECODE', self::get('core.secure_code'));
	}
	
	//получить значение настройки
	public static function get($key, $group_id=null)
	{
		list($key, $module, $group_id)=self::_parseConfigKey($key, $group_id);
		return self::_get($key, $module, $group_id, 'config');
	}
	
	//установить значение настройки
	public static function set($key, $value, $group_id=null)
	{
		list($key, $module, $group_id)=self::_parseConfigKey($key, $group_id);
		self::_set($key, $value, $module, $group_id, 'config');
	}
	
	//сохранить значение настройки
	public static function save($key, $value, $group_id=null)
	{
		list($key, $module, $group_id)=self::_parseConfigKey($key, $group_id);
		self::_save($key, $value, $module, $group_id, 'config');
	}
	
	//удалить значение настройки
	public static function delete($key=null, $group_id=IS_GUEST)
	{
		list($key, $module, $group_id)=self::_parseConfigKey($key, $group_id);
		return self::_delete($key, $module, $group_id, 'config');
	}
	
	//получить значение прав для группы
	public static function getAccess($key, $group_id)
	{
		list($key, $module, $group_id)=self::_parseAccessKey($key, $group_id);
		if ('core'==$module) return;
		return self::_get($key, $module, $group_id, 'access');
	}
	
	//установить значение прав для группы для текущей сессии
	public static function setAccess($key, $value, $group_id=null)
	{
		list($key, $module, $group_id)=self::_parseAccessKey($key, $group_id);
		if ('core'==$module) return;
		self::_set($key, $value, $module, $group_id, 'access');
	}
	
	//установить значение прав для группы на постоянной основе
	public static function saveAccess($key, $value, $group_id=null)
	{
		list($key, $module, $group_id)=self::_parseAccessKey($key, $group_id);
		if ('core'==$module) return;
		if ($value) self::_save($key, $value, $module, $group_id, 'access');
		else self::_delete($key, $module, $group_id, 'access');
	}
	
	public static function deleteAccess($key=null, $group_id=IS_GUEST)
	{
		list($key, $module, $group_id)=self::_parseAccessKey($key, $group_id);
		if ('core'==$module) return;
		self::_delete($key, $module, $group_id, 'access');
	}

	public static function cleanModule($module, $group_id=null)
	{
		if (!$module) $module=LabVars::$current_module['module'];
		Db::i()->query(
			"DELETE FROM ?_config WHERE module=?{ AND group_id=?}", $module, $group_id?$group_id:DBSIMPLE_SKIP
		);
	}
	
	protected static function _get($key, $module, $group_id, $type)
	{
		if ('core'==$module) {
			if (isset(self::$_cfg[$type][$group_id]['core'][$key]))
				return self::$_cfg[$type][$group_id]['core'][$key];
		} else {
			if (isset(self::$_cfg[$type][$group_id]['module'][$module][$key]))
				return self::$_cfg[$type][$group_id]['module'][$module][$key];
		}
		return null;
	}
	
	protected static function _set($key, $value, $module, $group_id, $type)
	{
		if ('core'==$module) {
			self::$_cfg[$type][$group_id]['core'][$key]=$value;
		} else {
			self::$_cfg[$type][$group_id]['module'][$module][$key]=$value;
		}
	}

	protected static function _save($key, $value, $module, $group_id, $type)
	{
		$value=is_object($value)?'':((is_array($value))?serialize($value):$value);
		if (!$value && $type=='access' && $group_id!=IS_GUEST) return self::_delete($key, $module, $group_id, $type);
		if ($value===null) $value='';
		Db::i()->query(
			"INSERT INTO ?_config (`type`, module, group_id, `key`, `value`)
			VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE `value`=?",
			$type, $module, $group_id, $key, $value, $value
		);
	}
	
	protected static function _delete($key=null, $module='core', $group_id=IS_GUEST, $type='config')
	{
		Db::i()->query(
			"DELETE FROM ?_config
			WHERE  module=? {AND `key`=? } {AND `type`=? } { AND group_id=?}",
			$module,
			$key?$key:DBSIMPLE_SKIP, //если не указан ключ, удаляем все ключи
			$type?$type:DBSIMPLE_SKIP, //если не указан тип, удаляем все настройки модуля
			$group_id?$group_id:DBSIMPLE_SKIP   //если не указана группа - удаляем настройки для всех групп
		);	
	}
	
	protected static function _parseConfigKey($string, $group_id=null)
	{
		if(!self::_get('separate_config', 'core', -1, 'config')) $group_id=IS_GUEST;
		
		if (strpos($string, '.')) {
			$keys = explode('.', $string);
			//если запрашивают глобальную настройку
			if ($keys[0]=='core') {
				$module='core';
				$group_id=IS_GUEST;
				$key=$keys[1];
			} elseif ($keys[0]=='module') {//если запрашивают настройку конкретного модуля
				if(!$group_id)	$group_id=User::i()->group_id;
				$module=$keys[1];
				$key=$keys[2];
			}
		} else {//если запрашивают настройку текущего модуля
			if (!$group_id) $group_id=User::i()->group_id;
			$module=LabVars::$current_module['module'];
			$key=$string;
		}
		
		return array($key, $module, $group_id);
	}
	
	protected static function _parseAccessKey($string, $group_id=null)
	{
		//если запрашивают настройку конкретного модуля
		if(!$group_id)	$group_id=User::i()->group_id;
		if (strpos($string, '.')) {
			$keys = explode('.', $string);
			$module=$keys[1];
			$key=$keys[2];
		} else {//если запрашивают настройку текущего модуля
			$module=LabVars::$current_module['module'];
			$key=$string;
		}
		
		return array($key, $module, $group_id);
	}
	
	protected static function _init()
	{
		$config = array();
		self::$_cfg=array();
		self::set('core.debug_mode', 'init');
		$config = parse_ini_file(LAB_PATH_DATA."/cms.ini", true);
		if (isset($config['version']) && is_array($config['version'])) self::update_old_config($config);

		foreach ($config as $k=>$v) {
			self::set('core.'.$k, $v);
		}

		if (!self::get('core.version') || version_compare(self::get('core.version'), '5.4', '>=')) {
			self::_initGlobalConfig();
			//убиваем соедиенение с БД, так как оно установлено в режиме отладки
			Db::destroy();
		}

		include LAB_PATH_KERNEL.'/install/revision.php';
		self::set('core.revision', $revision);
		self::set('core.branch', $branch);
	}
	
	protected static function _cache()
	{
		self::$cached=true;
		self::set('core.lastCacheReset', time());
		file_put_contents(LAB_PATH_DATA.'/cache/configs.obj', serialize(self::$_cfg));
		@chmod(LAB_PATH_DATA.'/cache/configs.obj', 0666);
	}
	
	protected static function _initGlobalConfig()
	{
		$tree=self::getGroupsTree();
		$configs=Db::i()->select(
			"SELECT `type`, module, `key`, `value`, group_id
			FROM ?_config c"
		);
		if ($configs) {
			foreach ($tree as $group_id=>$parents) {
				foreach ($parents as $parent_id) {
					foreach ($configs as $cfg) {
						if ($cfg['group_id']==$parent_id) {
							if ('core'==$cfg['module'])
								self::$_cfg[$cfg['type']][IS_GUEST]['core'][$cfg['key']]=self::_expandValue($cfg['value']);
							else
								self::$_cfg[$cfg['type']][$group_id]['module'][$cfg['module']][$cfg['key']]=self::_expandValue($cfg['value']);
						}
					}
				}
			}
		}
	}
	

	protected static function _expandValue($v)
	{
		//разворачиваем массивы, если таковые имеются
		if (strpos($v, 'a:')===0 && $array=unserialize($v)) return $array;
		//разворачиваем объекты, если таковые имеются
		if (strpos($v, 'O:')===0 && $array=unserialize($v)) return $array;
		return $v;
	}
	
	protected static function getGroupsTree()
	{
		$groups=User::getAllUserGroups();
		if ($groups) {
			foreach ($groups as $group_id=>$parent_id) {
				$tree[$group_id]=array($group_id);
				while (array_key_exists($parent_id, $groups)) {
					$tree[$group_id][]=$parent_id;
					$parent_id=$groups[$parent_id];
				}
				$tree[$group_id]=array_reverse($tree[$group_id]);
			}
		}
		return $tree;
	}
	
	public static function getCoreConfig()
	{
		return Db::i()->selectCol(
			"SELECT `key` AS ARRAY_KEY, value
			FROM ?_config
			WHERE type='config' AND group_id=? AND module='core'", IS_GUEST
		);
	}
	
	public static function asignToTpl()
	{
		if (self::get('core.separate_config')) $group_id=User::i()->group_id;
		else $group_id=IS_GUEST;
		Tpl::i()->assignByRef('_cfg', self::$_cfg['config'][$group_id]);
	}
	
	public static function getModuleData($group_id, $module_id)
	{
		$data['config']=isset(self::$_cfg['config'][$group_id]['module'][$module_id])?
			self::$_cfg['config'][$group_id]['module'][$module_id]:array();
		$data['access']=isset(self::$_cfg['access'][$group_id]['module'][$module_id])?
			self::$_cfg['access'][$group_id]['module'][$module_id]:array();
		return $data;
	}
	
	public static function setCurrentModuleConfig()
	{
		if (self::get('core.separate_config')) $group_id=User::i()->group_id;
		else $group_id=IS_GUEST;
		self::$_cfg['config'][$group_id]['current']
		=&self::$_cfg['config'][$group_id]['module'][LabVars::$current_module['module']];
	}
	
	public static function access($rules)
	{
		//если суперадмин, то все права у него есть.
		if (User::i()->isSuperАdmin()) return true;
		$group_id=User::i()->group_id;
		$rules=explode(",", $rules);
		foreach ($rules as $rule) {
			$rule=trim($rule);
			if (self::getAccess($rule, $group_id)) return true;
		}
		return false;
	}
	
	private static function update_old_config($cfg)
	{
		$ini=array();
		$ini['dblocation']=$cfg['mysql']['dblocation'];
		$ini['dbname']=$cfg['mysql']['dbname'];
		$ini['dbuser']=$cfg['mysql']['dbuser'];
		$ini['dbpasswd']=$cfg['mysql']['dbpasswd'];
		$ini['prefix']=$cfg['mysql']['prefix'];
		$ini['secure_code']=$cfg['secure']['code'];
		$ini['version']=$cfg['version']['current'];
		copy(LAB_PATH_DATA.'/cms.ini', LAB_PATH_DATA.'/cms.bak');
		write_ini_file(LAB_PATH_DATA.'/cms.ini', $ini);
		refresh('', '/');
	}
}
