<?php
/**
 * @package XCube
 * @version $Id: XCube_Root.class.php,v 1.1.2.4 2006/10/21 11:08:53 minahito Exp $
 */

require_once XOOPS_ROOT_PATH . "/core/XCube_HttpContext.class.php";

/**
 * This class offers the access course same as global variable for a logic in old mechanism.
 * This class does not let you depend on a main controller class name
 * You must not succeed to this class.
 *
 * @final
 */
class XCube_Root
{
	/**
	@access private
	*/
	var $mController = null;
	
	/**
	 * @access private ?
	 */
	var $mLanguageManager = null;

	var $mDelegateManager = null;
	
	var $mServiceManager = null;

	var $mRenderSystems = array();
	
	var $mSiteConfig = array();
	
	/**
	 * @access public
	 * @var XCube_AbstractPermissionProvider
	 */
	var $mPermissionManager = null;
	
	var $mRoleManager = null;
	
	var $mCacheSystem = null;
	
	/**
	 * @var XCube_HttpContext
	 */
	var $mContext = null;

	function XCube_Root()
	{
	}

	/**
	 * Return a object of XCube_Root as singleton.
	 * 
	 * @return XCube_Root
	 */
	function &getSingleton()
	{
		static $instance;
		
		if (!isset($instance))
			$instance = new XCube_Root();
		
		return $instance;
	}

	/**
	 * Load SiteConfig from plural files, and control set and override site config.
	 * 
	 * @return void
	 */
	function loadSiteConfig()
	{
		if (func_num_args() == 0) {
			die("FETAL: usage error: site setting config.");
		}

		$file = func_get_arg(0);
		if(!file_exists($file)) {
			die("FETAL: open error: site setting config.");
		}
		
		$this->setSiteConfig(parse_ini_file($file, true));

		//
		// Override setting.
		//
		if (func_num_args() > 1) {
			for ($i = 1; $i < func_num_args(); $i++) {
				$overrideFile = func_get_arg($i);
				
				if (file_exists($overrideFile)) {
					$this->overrideSiteConfig(parse_ini_file($overrideFile, true));
				}
			}
		}
	}
	
	/**
	 * Set site configs.
	 * 
	 * @param array $config
	 */
	function setSiteConfig($config)
	{
		$this->mSiteConfig = $config;
	}
	
	/**
	 * Override site config. SiteConfig is overrided by $config value. And, if 
	 * $config has new key, that key is set.
	 * 
	 * @param array $config
	 */
	function overrideSiteConfig($config)
	{
		foreach ($config as $_overKey=>$_overVal) {
			if (array_key_exists($_overKey, $this->mSiteConfig)) {
				$this->mSiteConfig[$_overKey] = array_merge($this->mSiteConfig[$_overKey], $_overVal);
			}
			else {
				$this->mSiteConfig[$_overKey] = $_overVal;
			}
		}
	}

	/**
	 * Return the value of site config that is defined by ini files.
	 * 
	 * @return mixed If the value specified by parameters is no, return null.
	 */
	function getSiteConfig()
	{
		//
		// TODO Check keys with using 'isset'
		//
		if (func_num_args() == 0) {
			return $this->mSiteConfig;
		}
		elseif (func_num_args() == 1) {
			if (isset($this->mSiteConfig[func_get_arg(0)])) {
				return $this->mSiteConfig[func_get_arg(0)];
			}
		}
		elseif (func_num_args() == 2) {
			if (isset($this->mSiteConfig[func_get_arg(0)][func_get_arg(1)])) {
				return $this->mSiteConfig[func_get_arg(0)][func_get_arg(1)];
			}
		}
		elseif (func_num_args() == 3) {
			if (isset($this->mSiteConfig[func_get_arg(0)][func_get_arg(1)])) {
				return $this->mSiteConfig[func_get_arg(0)][func_get_arg(1)];
			}
			else {
				return func_get_arg(2); //return 3rd param as a default value;
			}
		}

		return null;
	}

	/**
	 * Create controller with the rule, and call member function prepare().
	 * The class of creating controller is defined in ini.php files.
	 * 
	 * @return void
	 */
	function setupController()
	{
		//
		// [NOTICE]
		// We don't decide the style of SiteConfig.
		//
		$controllerName = $this->mSiteConfig['Cube']['Controller'];
		$this->mController =& $this->_createInstance($this->mSiteConfig[$controllerName]['class'], $this->mSiteConfig[$controllerName]['path']);
		$this->mController->prepare($this);
	}

	/**
	 * Return the instance of the controller.
	 * 
	 * @return XCube_Controller
	 */
	function &getController()
	{
		return $this->mController;
	}

	/**
	 * Set the instance of the language manager.
	 * 
	 * @param $languageManager XCube_LanguageManager
	 * @return void
	 */
	function setLanguageManager(&$languageManager)
	{
		$this->mLanguageManager =& $languageManager;
	}
	
	/**
	 * Return the instance of the language manager.
	 * 
	 * @return XCube_LanguageManager
	 */
	function &getLanguageManager()
	{
		return $this->mLanguageManager;
	}
	
	/**
	 * Set the instance of the delegate manager.
	 * 
	 * @param $delegateManager XCube_DelegateManager
	 * @return void
	 */
	function setDelegateManager(&$delegateManager)
	{
		$this->mDelegateManager =& $delegateManager;
	}
	
	/**
	 * Return the instance of the delegate manager.
	 * 
	 * @return XCube_DelegateManager
	 */
	function &getDelegateManager()
	{
		return $this->mDelegateManager;
	}
	
	/**
	 * Set the instance of the service manager.
	 * 
	 * @param $languageManager XCube_ServiceManager
	 * @return void
	 */
	function setServiceManager(&$serviceManager)
	{
		$this->mServiceManager =& $serviceManager;
	}
	
	/**
	 * Return the instance of the service manager.
	 * 
	 * @return XCube_ServiceManager
	 */
	function &getServiceManager()
	{
		return $this->mServiceManager;
	}

	/**
	 * Return the instance of the render system by the name. If the render
	 * system specified by $name doesn't exist, raise fatal error. This member
	 * function does creating the instance and calling prepare().
	 * 
	 * @todo
	 * @param $name string the registed name of the render system.
	 */
	function &getRenderSystem($name)
	{
		if (isset($this->mRenderSystems[$name])) {
			return $this->mRenderSystems[$name];
		}
		
		//
		// create
		//
		$chunkName = $this->mSiteConfig['RenderSystems'][$name];
		$this->mRenderSystems[$name] =& $this->_createInstance($this->mSiteConfig[$chunkName]['class'], $this->mSiteConfig[$chunkName]['path']);
		
		if (!is_object($this->mRenderSystems[$name])) {
			die("NO");
		}
		
		$this->mRenderSystems[$name]->prepare($this->mController);
		
		return $this->mRenderSystems[$name];
	}
	
	function setPermissionManager(&$manager)
	{
		$this->mPermissionManager =& $manager;
	}
	
	function &getPermissionManager()
	{
		return $this->mPermissionManager;
	}
	
	/**
	 * Sets the role manager object.
	 */
	function setRoleManager(&$manager)
	{
		$this->mRoleManager =& $manager;
	}
	
	/**
	 * Sets the HTTP-context object.
	 *
	 * @param XCube_Context $context
	 */
	function setContext(&$context)
	{
		$this->mContext =& $context;
	}
	
	/**
	 * Gets the HTTP-context object.
	 *
	 * @return XCube_Context
	 */
	function &getContext()
	{
		return $this->mContext;
	}

	/**
	 * Create the instance dynamic with the rule and the string parameters.
	 * First, load the file from $classPath. The rule is XOOPS_ROOT_PATH + 
	 * $classPath + $className + .class.php. Next, create the instance of the
	 * class if the class is defined rightly. This member function is called by
	 * other member functions of XCube_Root.
	 * 
	 * @access private
	 * @param $className string the name of class.
	 * @param $classPath string the path that $className is defined in.
	 * @return void
	 * @todo If the file doesn't exist, require_once() raises fatal errors.
	 */
	function &_createInstance($className, $classPath=null)
	{
		$ret = null;
		
		if ($classPath != null) {
			require_once XOOPS_ROOT_PATH . $classPath . "/" . $className . ".class.php";
		}
		
		if (class_exists($className)) {
			$ret =& new $className();
		}

		return $ret;
	}
}

?>