<?php
/*
 * This file is part of the easy-CMS project.
 * easy-CMS 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 2 of the License, or
 * (at your option) any later version.
 *
 * easy-CMS 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 easy-CMS; if not, write to the Free Software
 * along with easy-CMS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * @package Core
 */
include_once('classes/core/CoreObject.class.php');
include_once('classes/core/FamilyManager.class.php');
include_once('classes/core/DBManipulatorsManager.class.php');
include_once('classes/core/ACL/ACL.class.php');
include_once('classes/core/ACL/ACLManager.class.php');
include_once('classes/core/users/User.class.php');
include_once('classes/core/users/UsersManager.class.php');
include_once('classes/core/groups/Group.class.php');
include_once('classes/core/groups/GroupsManager.class.php');
include_once('classes/core/frames/Frame.class.php');
include_once('classes/core/frames/FramesManager.class.php');
include_once('classes/core/pages/Page.class.php');
include_once('classes/core/pages/PagesManager.class.php');
include_once('classes/core/types/TypesManager.class.php');
include_once('classes/core/menus/MenusManager.class.php');
include_once('classes/core/menuNodes/MenuNodesManager.class.php');
include_once('classes/core/contents/ContentsManager.class.php');
include_once('classes/core/containers/ContainersManager.class.php');
include_once('classes/core/containersLists/ContainersListsManager.class.php');
include_once('classes/core/versions/ContentVersionsManager.class.php');
include_once('classes/core/CacheManager.class.php');
include_once('classes/core/HTMLManager.class.php');
include_once('classes/core/forms/FormsManager.class.php');


/**
 * Site object : easy-CMS main element
 *
 * @author	Cedric Francoys <cedric.francoys@easy-cms.org>
 * @version	Site.class, Thu Dec 02 20:47:30 CET 2004
 * @package	Core
 */
class Site extends CoreObject {

	/**
	 * @var object
	 */
	var $dbManipulator;

	/**
	 * @var object
	 */
  var $dbManager;

	/**
	 * @var object
	 */
	var $familyManager;

	/**
	 * @var object
	 */
	var $ACLManager;

	/**
	 * @var object
	 */
	var $usersManager;

	/**
	 * @var object
	 */
	var $groupsManager;

	/**
	 * @var object
	 */
	var $typesManager;

	/**
	 * @var object
	 */
	var $framesManager;

	/**
	 * @var object
	 */
	var $templatesManager;

	/**
	 * @var object
	 */
	var $pagesManager;

	/**
	 * @var object
	 */
	var $menusManager;

	/**
	 * @var object
	 */
	var $menuNodesManager;

	/**
	 * @var object
	 */
	var $containersListsManager;

	/**
	 * @var object
	 */
	var $containersManager;

	/**
	 * @var object
	 */
	var $contentsManager;

	/**
	 * @var object
	 */
  var $contentVersionsManager;

	/**
	 * @var object
	 */
	var $cacheManager;

	/**
	 * @var object
	 */
	var $formsManager;

	/**
	 * @var integer
	 */
	var $defaultPageId;
	var $defaultLangId;
	var $defaultDebugLevel;
	var $defaultMode;


	var $name;

	/**
	 * Class constructor.
	 * Initialize the Site object and the associated variables.
	 *
 	 * @param    integer  The default page (pid) of the site.
 	 * @param    string   The default mode in which the site is to be displayed.
 	 * @param    integer  The default language in which the site is to be displayed.
 	 * @return   void
	 */
	function Site($defaultPageId=1, $defaultMode=VIEW_MODE, $defaultLangId=1, $defaultDebugLevel=0) {
		parent::setClassName('Site');
		$this->debug('Site::Site, status : constructor invoked', 10, DBG_OPEN);

		// set the default values
		$this->defaultMode        = $defaultMode;
		$this->defaultPageId      = $defaultPageId;
		$this->defaultLangId      = $defaultLangId;
		$this->defaultDebugLevel  = DEBUG_LEVEL;

		// init the object used to communicate with the DBMS
		$this->dbManager = new DBManipulatorsManager(DB_CONNECTION_DBMS, DB_CONNECTION_HOST, DB_CONNECTION_DB, DB_CONNECTION_USER, DB_CONNECTION_PASS);

		$this->dbManipulator = &$this->dbManager->getDBManipulator();
		$this->dbManipulator->connect();

		// init the session if necessary
		if(strlen(session_id()) <= 0){
			ini_set('session.use_trans_sid','0');
			ini_set('url_rewriter.tags','');
			session_start();
		}

		// register vars that need to be persistent
		$this->registerVars();

		// we are displaying a page of the website, not a form nor an admin page
		if($this->getSubmittedVar('display', RENDER) == RENDER){
			// check the URL for easy navigation (allow use of back and forward buttons)
			$this->checkURL();
		}

		// special chars not allowed in the site name
		$specialChars = array(".", ":", ";", "/", "\\", "-", "_", "@");
		// the site name is based on the server name (DNS) and the root directory holding the web site (containing index.php)
		$this->name = str_replace($specialChars, "", $this->getHostName().$this->getScriptPath());
		$this->debug('Site::Site, status : object created', 10, DBG_CLOSE);
  }

	function getCurrentLangId() {
		$this->debug('Site::getCurrentLangId, status : function invoked', 10, DBG_OPEN);
		$lid = $this->getPersistentVar('lid', $this->getDefaultLangId());
		$this->debug('Site::getCurrentLangId, status : function completed', 10, DBG_CLOSE);
		return $lid;
	}

	function getDefaultLangId() {
		return $this->defaultLangId ;
	}

	function getDefaultMode() {
		return $this->defaultMode;
	}

	function getDefaultPageId() {
		return $this->defaultPageId ;
	}

	// todo
	function getRootPageId() {
		return 1;
	}

	// todo
	function getRootAclId() {
		return 1;
	}

 	/**
	 * The class destructor. !!At this time this function need to be called manually.!!
	 * Waiting for a better implementation of OOP mechanisms (with PHP 5).
	 *
	 * @return   void
	 */
	function siteDestructor()	{
		$this->debug('Site::siteDestructor, status : destructor invoked', 10, DBG_OPEN);
		$this->dbManipulator->disconnect();
		$now = date("D M j G:i:s Y");
		$this->debug('Site::siteDestructor, status : destructor completed', 10, DBG_CLOSE);
		$this->debug("Page generation completed on $now\n\n", 0);
		exit(1);
	}

	/**
	 * Gets Site Instance
	 *
	 * Returns a reference to the site instance. The site object is
	 * used as singleton.
	 *
	 * @static
	 * @return object
	 */
	function &getInstance()	{
		if(!isset($GLOBALS['site_instance'])) {	
			$GLOBALS['site_instance'] = new Site();
			$site = &$GLOBALS['site_instance'];
			$site->debug('Site::getInstance, status : new instance created', 10, DBG_OPEN);
		}
		else {
			$site = &$GLOBALS['site_instance'];
			$site->debug('Site::getInstance, status : function invoked', 10, DBG_OPEN);
		}
		$site->debug('Site::getInstance, status : function completed', 10, DBG_CLOSE);
		return $GLOBALS['site_instance'];
	}

	/**
	 * Gets DBManipulator
	 *
 	 * @return object
	 */
	function &getDBManipulator() {
		return $this->dbManipulator;
	}

  /**
	 * Gets Site Name
	 *
	 * The name of the site is a string (unique id) based on the host name
	 * and the path to easy-CMS scritps
	 *
 	 * @return string
	 * @deprecated
	 */
	function getName(){
		return $this->name;
	}

	/**
	 * Gets Site Name
	 *
	 * The name of the site is a string (unique id) based on the host name
	 * and the path to easy-CMS scritps
	 *
	 * @return string
	 */
	function getSiteName(){
		return $this->name;
	}

	/**
	 * Returns the name of the server hosting the easy-CMS scripts reside
	 *
	 * @return   string
	 */
	function getURL() {
		$this->debug('Site::getURL, status : function invoked', 10, DBG_OPEN);
		$url = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
		$this->debug('Site::getURL, status : function completed', 10, DBG_CLOSE);
		return $url;
	}

  /**
	 * Returns the name of the server hosting the easy-CMS scripts reside
	 *
	 * @return string
	 */
	function getHostName() {
		$this->debug('Site::getHostName, status : function invoked', 10, DBG_OPEN);
		$host_name = $_SERVER["SERVER_NAME"];
		$this->debug('Site::getHostName, status : function completed', 10, DBG_CLOSE);
		return $host_name;
	}

	/**
	 * Extracts the path of the current script (format is [dir1]/[dir2]/[dir3])
	 *
	 * @return string
	 */
	function getScriptPath() {
		$this->debug('Site::getScriptPath, status : function invoked', 10, DBG_OPEN);
		$dirName = dirname($_SERVER["PHP_SELF"]);
		// remove the first slash
		$script_path = substr($dirName, 1);
		$this->debug('Site::getScriptPath, status : function completed', 10, DBG_CLOSE);
		return $script_path;
	}

	/**
	 * Gets Script Name
	 *
	 * The filename of the script currently running
	 *
 	 * @return string
	 */
	function getScriptName() {
		$this->debug('Site::getScriptName, status : function invoked', 10, DBG_OPEN);
		$script_name = basename($_SERVER["PHP_SELF"]);
		$this->debug('Site::getScriptName, status : function completed', 10, DBG_CLOSE);
		return $script_name;
	}

    /**
	 * Gets Location
	 *
	 * The name of the site is a string (unique id) based on the host name
	 * and the path to easy-CMS scripts
	 * i.e. : http://machine.domain.extention/scriptpath/scriptname
	 *
 	 * @return string
	 */
	function getLocation() {
		$this->debug('Site::getLocation, status : function invoked', 10, DBG_OPEN);
		$scriptPath = $this->getScriptPath();
		$location = "http://".$this->getHostName();
		if(strlen($scriptPath)) {
			$location .= "/".$scriptPath;
		}
		$this->debug('Site::getLocation, status : function completed', 10, DBG_CLOSE);
		return $location."/".$this->getScriptName();
	}


	function redirectTo($location) {
		$sname = session_name();
		$sid = session_id();
		if( strlen($sid) < 1 ) {
		   header("Location: ".$location);
		   exit();
		}
		if( isset( $_COOKIE[$sname] ) || strpos($location, $sname."=".$sid) !== false ) {
		   header("Location: ".$location);
		   exit();
		}
		else {
			if( strpos( $location, "?" ) > 0 ) {
				$separator = "&";
			}
			else {
				$separator = "?";
			}
			$fixed = $location . $separator . $sname."=".$sid;
			header("Location: ".$fixed);
			exit();
		}
	}

	/**
	 * Returns the value of a submitted variable.
	 *
	 *
 	 * @param    string   The name of the variable for which we want the associated value.
 	 * @param    object   The value to assigned by default (if no value has been given).
 	 * @return   string
	 */
	function getSubmittedVar($var_name, $defaultValue = null) {
		$this->debug('Site::getSubmittedVar, status : function invoked', 10, DBG_OPEN);
		if(isset($_POST[$var_name])) {
			$value = $_POST[$var_name];
		}
		elseif(isset($_GET[$var_name])) {
			$value = $_GET[$var_name];
		}
		else {
      // explore the URI
      $uri_array = array();

			$vars = explode('?', $_SERVER['REQUEST_URI']);
			if(is_array($vars) && isset($vars[1])) {
  			$vars_array = explode('&', $vars[1]);
  			for($i = 0; $i < count($vars_array); ++$i) {
          if(!isset($vars_array[$i])) {
            break;
          }
          list($key, $value) = explode('=', $vars_array[$i]);
          $uri_array[$key] = $value;
  			}
			}

			if(isset($uri_array[$var_name])) {
			 $value = $uri_array[$var_name];
			}
			else {
        // var not found : set the default value
        $value = $defaultValue;
      }
		}
		$this->debug('Site::getSubmittedVar, status : function completed ('.$var_name.' = '.$value.')', 10, DBG_CLOSE);
		return $value;
	}

	function setSubmittedVar($var_name, $value) {
		$_POST[$var_name] = $value;
	}

	/**
	 * Returns the value of a persistent variable.
	 *
	 *
 	 * @param    string   The name of the variable for which we want the associated value.
 	 * @param    object   The value to assigned by default (if no value has been given).
 	 * @return   string
	 */
	function &getPersistentVar($var_name, $defaultValue = null){
		$this->debug('Site::getPersistentVar, status : function invoked', 10, DBG_OPEN);
		$value = $defaultValue;
		if(!isset($_SESSION[$var_name])){
			$this->debug("Site::getPersistentVar($var_name), variable unknown : setting default value($defaultValue).", 3);
		}
		else {
		  $value = $_SESSION[$var_name];
		}
		$this->debug('Site::getPersistentVar, status : function completed ('.$var_name.' = '.$value.')', 10, DBG_CLOSE);
		return $value;
	}

	/**
	* Assigns a value to a specified persistent var.
	*
 	*
	* @param    string    The name of the var.
 	* @param    object    The value we want the var to be assigned to.
	* @return   void
	*/
	function setPersistentVar($var_name, $value){
		$this->debug('Site::setPersistentVar, status : function invoked ('.$var_name.', '.$value.')', 10, DBG_OPEN);
		if(isset($var_name) && isset($value) && $value != null) {
			$_SESSION[$var_name] = $value;
		}
		$this->debug('Site::setPersistentVar, status : function completed', 10, DBG_CLOSE);
	}

	/**
	* Removes the specified persistent var.
	*
 	* @access   private
	* @param    string    The name of the var we want to remove.
	* @return   void
	*/
	function deletePersistentVar($varName){
		$this->debug('Site::deletePersistentVar, status : function invoked ('.$varName.')', 10, DBG_OPEN);
		if(isset($_SESSION[$varName])) {
			unset($_SESSION[$varName]);
		}
		$this->debug('Site::deletePersistentVar, status : function completed', 10, DBG_CLOSE);
	}

	/**
	* Removes all persistent vars.
	*
 	* @access   private
	* @return   void
	*/
	function deletePersistentVars(){
		$this->debug('Site::deletePersistentVars, status : function invoked', 10, DBG_OPEN);
		session_destroy();
		$this->debug('Site::deletePersistentVars, status : function completed', 10, DBG_CLOSE);
	}

	function getCurrentURL($includeVars=true) {
		$this->debug('Site::getCurrentURL, status : function invoked', 10, DBG_OPEN);

		$pid  = $this->getCurrentPageId();
		$lid  = $this->getCurrentLangId();
		$mode = $this->getCurrentMode();

		$url = $this->getLocation()."?pid=$pid&lid=$lid&mode=$mode";

		// add non-persistent vars to the URL
		// ? urlencode necessary
		if($includeVars) {
			// GET vars
			foreach($_GET as $key => $value){
				$new_part = "&{$key}={$value}";
				if(strlen($url.$new_part) > 1024) {
					break;
				}
				if($key != 'pid' && $key != 'lid') {
					$url .= $new_part;
				}
			}
			// POST vars
			// what for long POST vars ?
			foreach($_POST as $key => $value){
				$new_part = "&{$key}={$value}";
				if(strlen($url.$new_part) > 1024) {
					break;
				}
				if($key != 'pid' && $key != 'lid') {
					$url .= $new_part;
				}
			}
		}
		$this->debug('Site::getCurrentURL, status : function completed', 10, DBG_CLOSE);
		return $url;
	}

	/**
	 * Check if the URL encloses the pid (to be navigation friendly) and reloads the page if necessary.
	 *
	 * @access   private
	 */
	function checkURL() {
		$this->debug('Site::checkURL, status : function invoked', 10, DBG_OPEN);
		$pagesManager = &$this->getPagesManager();

		// check if the URL contains a page alias
		if($this->getSubmittedVar('resolve_alias', false)) {
			$langId = $this->getPersistentVar('lid', $this->getDefaultLangId());
			$langId = $this->getSubmittedVar('lid', $langId);
			$mode = $this->getPersistentVar('mode', $this->getDefaultMode());
			$mode = $this->getSubmittedVar('mode', $mode);
			$path = explode('/', $_SERVER['REQUEST_URI']);

			$test_path = $path[1];

			for($i = 1; isset($path[$i]) && (strlen($test_path) <= strlen($this->getScriptPath())); ++$i) {
				if(strlen($test_path) > 0) {
					$test_path .= '/';
				}
				$test_path .= $path[$i];
			}

			if(isset($path[$i])) {
				$pageAlias = $path[$i];

				if(($pos = strpos($pageAlias, '?')) !== false) {
					$pageAlias = substr($pageAlias, 0, $pos);
				}
				// redirect to the login page
				if($pageAlias == 'login') {
					header('HTTP/1.0 200 OK');
					header('Status: 200 OK');
					$url = $this->getLocation();
					$url = str_replace('index.php', 'login.php', $url);
					$this->redirectTo($url);
					exit();
				}
				else {
					// find this alias among other languages
					if($this->dbManipulator->languageExists($langId)) {
						if(($page = &$pagesManager->getPageByAlias($pageAlias, $langId)) == null) {
							$langs_array = $pagesManager->getLangsArray();
							foreach($langs_array as $other_lang_id => $lang_name) {
								if($other_lang_id == $langId) {
									continue;
								}
								if(($page = &$pagesManager->getPageByAlias($pageAlias, $other_lang_id)) != null) {
									$langId = $other_lang_id;
									break;
								}
							}
						}
					}
					if($page != null) {
						header('HTTP/1.0 200 OK');
						header('Status: 200 OK');
						$pid = $page->getPageId();
						$this->setPersistentVar('pid', $pid);
						$this->setPersistentVar('lid', $langId);
						$this->setPersistentVar('mode', $mode);
						$this->setSubmittedVar('pid', $pid);
						$this->setSubmittedVar('lid', $langId);
						$this->setSubmittedVar('mode', $mode);
					}
					else {
						//unexistent page
						header('HTTP/1.0 404 Not Found');
						print('<html><header><title>Page Not Found</title></header><body>Sorry but the page you requested was not found on this server.</body></html>');
						exit();
					}
				}
			}
			else {
				// no alias : should have been redirected to the default file by apache
				header('HTTP/1.0 200 OK');
				header('Status: 200 OK');
				$scriptPath = $this->getScriptPath();
				$url = 'http://'.$this->getHostName();
				if(strlen($scriptPath)) {
					$url .= '/'.$scriptPath;
				}
				$url .= '/index.php';
				$this->redirectTo($url);
				exit();
			}
		}
		else {
			// URL does not contain an alias
			$display = $this->getSubmittedVar('display', RENDER);
			// the pid must be in the url in order to be navigation friendly
			if($display == RENDER && $this->getScriptName() == "index.php") {
				if(($pid = $this->getPersistentVar('pid')) == null) {
					$this->setPersistentVar('pid', $this->defaultPageId);
				}
				if(($lid = $this->getSubmittedVar('lid')) != null) {
					$this->setPersistentVar('lid', $lid);
				}
				$pid  = $this->getCurrentPageId();
				$lid  = $this->getCurrentLangId();
				$url = $this->getCurrentURL();
				if(($page = &$pagesManager->getPage($pid)) == null) {
					$this->debug('Site::checkURL, error : unable to load requested page', 1);
				}
				elseif(FORCE_ALIAS_IN_URL) {
					// if the requested page have an alias modify the url
					$alias = $page->getPageAlias($lid);
					if(strlen($alias) > 0) {
						$scriptPath = $this->getScriptPath();
						$url = 'http://'.$this->getHostName();
						if(strlen($scriptPath)) {
							$url .= '/'.$scriptPath;
						}
						if($alias[0] != '/') {
							$alias = '/'.$alias;
						}
						$url .= $alias;
					}
				}
				// do we need rewriting ?
				if($this->getSubmittedVar('pid') == null || strlen($alias) > 0) {
					$this->redirectTo($url);
					exit();
				}
			}
		}
		$this->debug('Site::checkURL, status : function completed', 10, DBG_CLOSE);
	}

	/**
	 * Retrieves the actual value of a variable and stores it as persistent.
	 *
 	 * @access private
	 * @param  string $varName
	 * @param  mixed $defaultValue
	 * @return void
	 */
	function registerVar($var_name, $defaultValue) {
		$this->debug('Site::registerVar, status : function invoked ('.$var_name.', '.$defaultValue.')', 10, DBG_OPEN);
		$value = $defaultValue;
		if (($value = $this->getSubmittedVar($var_name)) == null){
			$value = $this->getPersistentVar($var_name, $defaultValue);
		}
		$this->setPersistentVar($var_name, $value);
		$this->debug('Site::registerVar, status : function completed', 10, DBG_CLOSE);
	}

	/**
	* Manage the registration of the site's variables.
	*
	*
 	* @access   private
	* @return   void
	*/
	function registerVars() {
    $this->debug('Site::registerVars, status : function invoked', 10, DBG_OPEN);
		// check if some actions are required
		if(($action = $this->getSubmittedVar("action")) != null){
			switch($action) {
				case LOGIN :
					// check if both user and password variables have been posted
					if(($userName = $this->getSubmittedVar("login")) != null && ($password = $this->getSubmittedVar("password")) != null){
						$usersManager = &$this->getUsersManager();
						if (($user = &$usersManager->getUser($usersManager->getUserId($userName, $password))) <= 0){
							//unknown user or mismatch error
							header("Location: login.php?error=1");
							exit();
						}
						else {
              // prevent disabled users to log out
						  if($user->getUserDisabled()) {
                $user = null;
                break;
						  }
							$lid = $user->getUserLangId();
							$homePageId = $user->getUserHomePageId();
							$this->setPersistentVar('user', $user);
							$this->setPersistentVar('user_id', $user->getUserId());
							$this->setPersistentVar('lid', $lid);
							// check if a redirection to user's homepage is necessary
							if($this->getPersistentVar('pid', $this->defaultPageId) != $homePageId) {
								$pagesManager = &$this->getPagesManager();
								if($pagesManager->pageExists($homePageId)) {
									$this->setPersistentVar('pid', $homePageId);
									$url = $this->getCurrentURL(false);
									$this->redirectTo($url);
									exit();
								}
							}
						}
					}
					else{
						$this->debug('Site::registerVars, warning : login process not initiated');
          }
					break;
				case LOGOUT :
						$this->deletePersistentVars();
					break;
				default :
					break;
			}
		}

		// some vars need to be persistent (pid, lid, mode, ... more to come)
		$this->registerVar('lid', $this->defaultLangId);
		$this->registerVar('debug', $this->defaultDebugLevel);
		$this->registerVar('pid', $this->defaultPageId);

		$pagesManager = &$this->getPagesManager();

		if(!$pagesManager->pageExists($this->getSubmittedVar('pid', $this->defaultPageId))){
			// page does not exist
			$this->setPersistentVar('pid', $this->defaultPageId);
		}

		if(($mode = $this->getSubmittedVar('mode')) == null){
			if(($mode = $this->getPersistentVar('mode')) == null) {
        $mode = $this->defaultMode;
      }
		}
    else {
      if($mode == EDIT_MODE) {
  			// only identified users can switch to edit mode
  			if ($this->getCurrentUserId() == USER_ID_ANONYMOUS) {
          $mode = VIEW_MODE;
  			}
      }
      elseif($mode != VIEW_MODE) {
        $mode = VIEW_MODE;
      }
    }

    $this->registerVar('mode', $mode);

    $this->debug('Site::registerVars, status : function completed', 10, DBG_CLOSE);
	}

	/**
	 * Returns a constant-string corresponding to the current mode
	 *
	 *
	 * @return   string
	 */
	function &getCurrentMode(){
    $this->debug('Site::getCurrentMode, status : function invoked', 10, DBG_OPEN);
		if(($mode = &$this->getPersistentVar("mode")) == null) {
			$mode = &$this->defaultMode;
		}
    $this->debug('Site::getCurrentMode, status : function completed', 10, DBG_CLOSE);
		return $mode;
	}

	/**
	 * @return integer
	 */
	function &getCurrentUserId() {
    $this->debug('Site::getCurrentUserId, status : function invoked', 10, DBG_OPEN);
    $user_id = USER_ID_ANONYMOUS;
		if(($user = &$this->getCurrentUser()) != null){
      $user_id = $user->getUserId();
		}
    $this->debug('Site::getCurrentUserId, status : function completed', 10, DBG_CLOSE);
		return $user_id;
	}

	/**
	 * @return object
	 */
	function &getCurrentUser() {
    $this->debug('Site::getCurrentUser, status : function invoked', 10, DBG_OPEN);
		$usersManager = &$this->getUsersManager();
		$userId = $this->getPersistentVar('user_id', 0);
		if(!$userId) {
			// create an anonymous user
			if (is_null($anonymousUser = &$usersManager->getUser(USER_ID_ANONYMOUS))) {
        $this->debug("Site::getCurrentUser, error : unable to load ANONYMOUS (id=".USER_ID_ANONYMOUS.")user.", 2);
			}
      else {
        $this->debug("Site::getCurrentUser, notice : unidentified user, switching to anonymous user", 8);
        $this->setPersistentVar('user', $anonymousUser);
        $this->setPersistentVar('user_id', USER_ID_ANONYMOUS);
        $user = &$anonymousUser;
      }
		}
		else {
			$user = &$usersManager->getUser($userId);
		}
    $this->debug('Site::getCurrentUser, status : function completed', 10, DBG_CLOSE);
		return $user;
	}

	function setCurrentUser(&$user) {
	}

	/**
	 * Gets Id of the current page
	 *
	 * @return integer
	 */
	function getCurrentPageId() {
    $this->debug('Site::getCurrentPageId, status : function invoked', 10, DBG_OPEN);
		$pid = $this->getPersistentVar('pid', $this->getDefaultPageId());
    $this->debug('Site::getCurrentPageId, status : function completed', 10, DBG_CLOSE);
		return $pid;
	}

	/**
	 * Gets Current Page
	 *
	 * @return object
	 */
	function &getCurrentPage($loadFrame=true, $loadAcl=true) {
    $this->debug('Site::getCurrentPage, status : function invoked', 10, DBG_OPEN);
		$pid = $this->getPersistentVar('pid');
		$pagesManager = &$this->getPagesManager();
    $page = null;

		if (!($page = $pagesManager->getPage($pid))) {
			$this->debug('Site::getCurrentPage, error : unable to get page #'.$pid, 1);
		}
		else {
  		if (!$page->getPageFrame()) {
  			$framesManager = &$this->getFramesManager();
  			$frame = &$framesManager->getFrame($page->getPageFrameId());
  			$page->setPageFrame($frame);
  		}

  		if (!$page->getPageAcl()) {
  			$aclManager = &$this->getACLManager();
  			$acl = &$aclManager->getACL($page->getPageAclId());
  			$page->setPageAcl($acl);
  		}
    }
    $this->debug('Site::getCurrentPage, status : function completed', 10, DBG_CLOSE);
		return $page;
	}

	/**
	 * Returns the html code of a given page object.
	 *
 	 * @param    object   A reference to the page object we want to be displayed.
 	 * @return   string
	 */
	function &generatePageHTML(&$page) {
    $this->debug('Site::generatePageHTML, status : function invoked', 10, DBG_OPEN);
    $html = '';
		// must be improved (multi-caching and user rights recognition)
		if(!is_object($user = &$this->getCurrentUser())) {
      // error : user object missing
      trigger_error('Site.generatePageHTML(), error :  missing object user', E_USER_ERROR);
		}
    else {
  		// check redirection
  		if(strlen($page->getPageLink()) > 0) {
  			// todo : test link validity
  			if($url=$page->getPageURL()) {
  				$this->redirectTo($url);
  				exit(0);
  			}
  		}

  		$langId = $this->getPersistentVar('lid');

  		// static environment
  		if ($user->getUserId() == USER_ID_ANONYMOUS) {
  			$cacheManager = &$this->getCacheManager();
  			// get the final HTML code from cache
  			$html = &$cacheManager->getHTML($page, $user, $langId);
  		}
  		// dynamic environment
  		else {
  			// get start time
  			$mtime = microtime();
  			$startTime = explode(" ", $mtime);
        $mode = $this->getCurrentMode();
  			$aclManager = &$this->getACLManager();

  			$acl = &$aclManager->getACL($page->getPageAclId());

  			$user = &$this->getCurrentUser();

  			if ($acl->userHasViewRight($user) && ($mode == EDIT_MODE || $page->isPublished())) {

  				$htmlManager = new HTMLManager($page->getPageTitle($langId),NORMAL_HEADER,'', $mode);

  				// add some meta tags
  				$htmlManager->addMeta("Description", $page->getPageDescription($langId));
  				$htmlManager->addMeta("Keywords", $page->getPageKeywords($langId));

  				$cmsPath = &$this->getScriptPath();

  				// add easy-CMS specific styles
  				if(strlen($cmsPath)) {
  					$htmlManager->addStyle("/$cmsPath/includes/html/styles/style.css");
          }
  				else {
  					$htmlManager->addStyle("/includes/html/styles/style.css");
          }

  				// add easy-CMS specific scripts
  				if(strlen($cmsPath)) {
  					$htmlManager->addScript("/$cmsPath/includes/html/scripts/scripts.js");
  					$htmlManager->addScript("/$cmsPath/includes/html/scripts/md5.js");
  					$htmlManager->addScript("/$cmsPath/includes/html/scripts/prototype.js");
  					$htmlManager->addScript("/$cmsPath/includes/html/scripts/effects.js");
  					$htmlManager->addScript("/$cmsPath/includes/html/scripts/glider.js");
          }
  				else {
  					$htmlManager->addScript("/includes/html/scripts/scripts.js");
  					$htmlManager->addScript("/includes/html/scripts/md5.js");
  					$htmlManager->addScript("/includes/html/scripts/prototype.js");
  					$htmlManager->addScript("/includes/html/scripts/effects.js");
  					$htmlManager->addScript("/includes/html/scripts/glider.js");
          }

  				// add page specific scripts
  				foreach($page->getHTMLScripts() as $script){
  					$fullPath = "/".REPOSITORY_FOLDER."/".SCRIPTS_FOLDER."/".$script;
  					if(strlen($cmsPath)) {
  						$fullPath = "/$cmsPath/".REPOSITORY_FOLDER."/".SCRIPTS_FOLDER."/".$script;
            }
  					$htmlManager->addScript($fullPath);
  				}

  				// add page specific styles
  				foreach($page->getHTMLStyles() as $style){
  					$fullPath = "/".REPOSITORY_FOLDER."/".STYLES_FOLDER."/".$style;
  					if(strlen($cmsPath))
  						$fullPath = "/$cmsPath/".REPOSITORY_FOLDER."/".STYLES_FOLDER."/".$style;
  					$htmlManager->addStyle($fullPath);
  				}

  				// add the page content
  				$htmlManager->addHTML($page->getHTMLBody($langId, $user, $mode));

  				// get end time
  				$mtime = microtime();
  				$endTime = explode(" ", $mtime);
  				$totaltime = round($endTime[1] + $endTime[0] - $startTime[1] - $startTime[0], 2);
  				$now = date("D M j G:i:s Y");
  				$htmlManager->addHTML("<!-- This page was generated on $now in $totaltime seconds -->");

  				// add debug informations
  				if($this->getSubmittedVar('debug') > 0 && $user->checkGroupMembership(GROUP_ID_ADMINS)) {
  					$debug = &Debug::getInstance();
  					$debugInfo = $debug->getReport();
  					$htmlManager->addHTML($debugInfo);
  				}

  				// get the resulting HTML code
  				$html = &$htmlManager->getHTML();
  			}
  			else {
  				$html = "<html><body>You don't have permissions to view this page or this page has not been published yet.<br /><br />Maybe you've been redirected to a wrong page. You may try to go to the <a href='index.php?pid=1'>homepage</a><br /><br />You could also try to switch to <a href=\"?mode=edit\">edit mode</a> or <a href=\"?action=logout\">logout</a> and <a href=\"login\">log on</a> as a different user.</body></html>";
  			}
  		}
		}
    $this->debug('Site::generatePageHTML, status : function completed', 10, DBG_CLOSE);
		return $html;
	}

	/**
	 * Returns the html code of a given form object
	 *
 	 * @param    object   The form object to display
 	 * @return   string
 	 * @deprecated
	 */
	function &generateFormHTML(&$form) {
    $this->debug('Site::generateFormHTML, status : function invoked', 10, DBG_OPEN);
		$html = '';
		if (($user = $this->getPersistentVar('user')) != null) {
			$htmlManager = &$form->getHTMLManager();
			$html = &$htmlManager->getHTML();
		}
    $this->debug('Site::generateFormHTML, status : function completed', 10, DBG_CLOSE);
		return $html;
	}

	/**
	 * Gets FamilyManager
	 *
	 * @return object
	 */
	function &getFamilyManager() {
    $this->debug('Site::getFamilyManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->familyManager)) {
			$this->familyManager = new FamilyManager($this);
		}
		$this->debug('Site::getFamilyManager, status : function completed', 10, DBG_CLOSE);
		return $this->familyManager;
	}

	/**
	 * Gets ACLManager
	 *
	 * @return object
	 */
	function &getACLManager() {
    $this->debug('Site::getACLManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->ACLManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->ACLManager = new ACLManager($dbManipulator);
		}
    $this->debug('Site::getACLManager, status : function completed', 10, DBG_CLOSE);
		return $this->ACLManager;
	}

	/**
	 * Gets UsersManager
	 *
	 * @return object
	 */
	function &getUsersManager() {
    $this->debug('Site::getUsersManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->usersManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->usersManager = new UsersManager($dbManipulator);
		}
    $this->debug('Site::getUsersManager, status : function completed', 10, DBG_CLOSE);
		return $this->usersManager;
	}

	/**
	 * Gets GroupsManager
	 *
	 * @return object
	 */
	function &getGroupsManager() {
    $this->debug('Site::getGroupsManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->groupsManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->groupsManager = new GroupsManager($dbManipulator);
		}
    $this->debug('Site::getGroupsManager, status : function completed', 10, DBG_CLOSE);
		return $this->groupsManager;
	}

	function &getTypesManager() {
    $this->debug('Site::getTypesManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->typesManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->typesManager = new TypesManager($dbManipulator);
		}
    $this->debug('Site::getTypesManager, status : function completed', 10, DBG_CLOSE);
		return $this->typesManager;
	}

	/**
	 * Gets FramesManager
	 *
	 * @return object
	 */
	function &getFramesManager() {
    $this->debug('Site::getFramesManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->framesManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->framesManager = new FramesManager($dbManipulator);
		}
    $this->debug('Site::getFramesManager, status : function completed', 10, DBG_CLOSE);
		return $this->framesManager;
	}

	/**
	 * Gets TemplatesManager
	 *
	 * @return object
	 */
	function &getTemplatesManager() {
    $this->debug('Site::getTemplatesManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->templatesManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$this->templatesManager = new TemplatesManager($dbManipulator);
		}
    $this->debug('Site::getTemplatesManager, status : function completed', 10, DBG_CLOSE);
		return $this->templatesManager;
	}

	/**
	 * Gets PagesManager
	 *
	 * @return object
	 */
	function &getPagesManager() {
    $this->debug('Site::getPagesManager, status : function invoked', 10, DBG_OPEN);
		if (!isset($this->pagesManager)) {
			$dbManipulator = &$this->getDBManipulator();
			$framesManager = &$this->getFramesManager();
			$aclManager = &$this->getACLManager();
			$menusManager = null; //&$this->getMenusManager();
			$containersListsManager = &$this->getContainersListsManager();
			$containersManager = &$this->getContainersManager();
			$this->pagesManager = new PagesManager($dbManipulator, $framesManager, $aclManager, $menusManager, $containersListsManager, $containersManager);
			$menusManager = &$this->getMenusManager();
			$this->pagesManager->setMenusManager($menusManager);
		}
    $this->debug('Site::getPagesManager, status : function completed', 10, DBG_CLOSE);
		return $this->pagesManager;
	}

	/**
	 * Gets MenuNodesManager
	 *
	 * @return object
	 */
	function &getMenuNodesManager() {
    $this->debug('Site::getMenuNodesManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->menuNodesManager)){
			$dbManipulator = &$this->getDBManipulator();
			$pagesManager = &$this->getPagesManager();
			$menusManager = &$this->getMenusManager();

			$this->menuNodesManager = new MenuNodesManager($dbManipulator, $pagesManager, $menusManager);
		}
    $this->debug('Site::getMenuNodesManager, status : function completed', 10, DBG_CLOSE);
		return $this->menuNodesManager;
	}

	/**
	 * Gets MenusManager
	 *
	 * @return object
	 */
	function &getMenusManager() {
    $this->debug('Site::getMenusManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->menusManager)){
			$dbManipulator = &$this->getDBManipulator();
			$aclManager = &$this->getACLManager();
			$langId = $this->getPersistentVar('lid');
			$pagesManager = &$this->getPagesManager();
			$templatesManager = &$this->getTemplatesManager();
			$menuNodesManager = null;
			$this->menusManager = new MenusManager($dbManipulator, $aclManager, $pagesManager, $menuNodesManager, $templatesManager, $langId);
			$menuNodesManager = &$this->getMenuNodesManager();
			$this->menusManager->setMenuNodesManager($menuNodesManager);
		}
		$this->debug('Site::getMenusManager, status : function completed', 10, DBG_CLOSE);
		return $this->menusManager;
	}

	/**
	 * Gets ContentsManager
	 *
	 * @return object
	 */
	function &getContentsManager() {
		$this->debug('Site::getContentsManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->contentsManager)){
			$aclManager = &$this->getACLManager();
			$typesManager = &$this->getTypesManager();
			//$langId = $this->getPersistentVar('lid');
			//$this->contentsManager = &new ContentsManager($this->dbManipulator, $aclManager, $typesManager, $langId);
			$this->contentsManager = new ContentsManager($this->dbManipulator, $aclManager, $typesManager);
		}
		$this->debug('Site::getContentsManager, status : function completed', 10, DBG_CLOSE);
		return $this->contentsManager;
	}

	/**
	 * Gets ContainersManager
	 *
	 * @return object
	 */
	function &getContainersManager() {
		$this->debug('Site::getContainersManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->containersManager)){
			$dbManipulator = &$this->getDBManipulator();
			$aclManager = &$this->getACLManager();
			$contentsManager = &$this->getContentsManager();
			$typesManager = &$this->getTypesManager();
			$templatesManager = &$this->getTemplatesManager();
			$this->containersManager = new ContainersManager($this->dbManipulator, $aclManager, $typesManager, $contentsManager, $templatesManager);
		}
    $this->debug('Site::getContainersManager, status : function completed', 10, DBG_CLOSE);
		return $this->containersManager;
	}

	/**
	 * Gets ContainersListsManager
	 *
	 * @return object
	 */
	function &getContainersListsManager() {
    $this->debug('Site::getContainersListsManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->containersListsManager)){
			$aclManager = &$this->getACLManager();
			$containersManager = $this->getContainersManager();
			$this->containersListsManager = new ContainersListsManager($this->dbManipulator, $aclManager, $containersManager);
		}
    $this->debug('Site::getContainersListsManager, status : function completed', 10, DBG_CLOSE);
		return $this->containersListsManager;
	}

	/**
	 * Gets ContentsVersionsManager
	 *
	 * @return object
	 */
	function &getContentVersionsManager() {
    $this->debug('Site::getContentVersionsManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->contentVersionsManager)){
			$typesManager = &$this->getTypesManager();
		  $this->contentVersionsManager = new ContentVersionsManager($this->dbManipulator, $typesManager);
    }
    $this->debug('Site::getContentVersionsManager, status : function completed', 10, DBG_CLOSE);
    return $this->contentVersionsManager;
  }

	/**
	 * Gets CacheManager
	 *
	 * @return object
	 */
	function &getCacheManager() {
    $this->debug('Site::getCacheManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->cacheManager)){
			$pagesManager = &$this->getPagesManager();
			$aclManager = &$this->getACLManager();
		  $this->cacheManager = new CacheManager($this->dbManipulator, $pagesManager, $aclManager);
    }
    $this->debug('Site::getCacheManager, status : function completed', 10, DBG_CLOSE);
    return $this->cacheManager;
  }

	/**
	 * Gets FormsManager
	 *
	 * @return object
	 */
	function &getFormsManager() {
    $this->debug('Site::getFormsManager, status : function invoked', 10, DBG_OPEN);
		if(!isset($this->formsManager)){
		  $this->formsManager = new FormsManager($this);
    }
    $this->debug('Site::getFormsManager, status : function completed', 10, DBG_CLOSE);
    return $this->formsManager;
  }

	// todo : see family.class.php
	function &getParentObject($object) {
    $this->debug('Site::getParentObject, status : function invoked', 10, DBG_OPEN);
		switch($object->getClassName()) {
			case content :
				$contentId = $object->getContentId();
				if($result = $this->dbManipulator->queryGetContainerIdFromContentId($contentId)){
					if($row = $this->dbManipulator->fetchArray($result)) {
						$containerId = $row['id'];
						$containersManager = &$this->getContainersManager();
						$result = &$containersManager->getContainer($containerId, false);
					}
				}
				else {
          trigger_error('Site.getParentObject(), error :  cannot find parent container for content ('.$contentId.')', E_USER_ERROR);
				}
				break;
			case container :
				$containerId = $object->getContainerId();
				// container in containersList
				if($result = $this->dbManipulator->queryGetContainersListIdFromContainerId($containerId)) {
					$row = $this->dbManipulator->fetchArray($result);
					if($row) {
						$containersListId = $row['id'];
						$containersListsManager = &$this->getContainersListsManager();
						return $containersListsManager->getContainersList($containersListId, false);
					}
					else {
						// container in page
						if($result = $this->dbManipulator->queryGetPageIdFromContainerId($containerId)) {
							$row = $this->dbManipulator->fetchArray($result);
							$pageId = $row['id'];
							$pagesManager = &$this->getPagesManager();
							$result = &$pagesManager->getPage($pageId, false, true, false, false);
						}
						else {
              trigger_error('Site.getParentObject(), error :  cannot find parent page for container ('.$containerId.')', E_USER_ERROR);
						}
					}
				}
				else {
          trigger_error('Site.getParentObject(), error :  cannot find parent containersList for container ('.$containerId.')', E_USER_ERROR);
				}
				break;
		}
    $this->debug('Site::getParentObject, status : function completed', 10, DBG_CLOSE);
    return $result;
	}
}
?>