<?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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
 
/**
 * @package    Core
 * @subpackage Users
 */

/**
 *
 */
include_once('classes/core/DBAccessorObject.class.php');
include_once('classes/core/DBManipulator.class.php');
include_once('classes/core/users/User.class.php');

/**
 * Manage the instances of User objects.
 *
 * @access     public
 * @author	   Cedric Francoys <cedric.francoys@easy-cms.org>
 * @version    Container.class,v 0.1
 * @package    Core
 * @subpackage Users
 */
class UsersManager extends DBAccessorObject {
	/**
	 * array of users object
	 *
	 * @access private
	 * @var    array
	 */
	var $usersTable;


	/**#@+
	 * @access public
	 */
	/**
	 * Constructor
	 *
	 * @param object $dbManipulator
	 */
  function UsersManager(&$dbManipulator) {
    $this->debug('UsersManager::UsersManager, status : function invoked', 10, DBG_OPEN);
		parent::DBAccessorObject($dbManipulator);
		$this->usersTable = array();
    $this->debug('UsersManager::UsersManager, status : function completed', 10, DBG_CLOSE);
  }
	
	/**
	 * Gets Users Table
	 *
	 * @return array
	 */
	function &getUsersTable()	{
		return $this->usersTable;
	}
	
	/**
	 * Loads User
	 *
	 * Loads given user into manager
	 *
	 * @param  integer $id User Id
	 * @param  boolean $loadGroupsMembershipList
	 * @return boolean
	 */
	function loadUser($id, $loadGroupsMembershipList=true) {
    $this->debug('UsersManager::loadUser, status : function invoked', 10, DBG_OPEN);
    $result = true;
		$usersIdList = (array)$id;
		$db = &$this->getDBManipulator();
		$cond = '`id` in ('.implode(',', $usersIdList).')';
		$res = $db->getRecord(USERS_TABLE, -1, $cond);

		if (!$res || !$db->getNumRows()) {
      $this->debug('UsersManager::loadUser, error : unable to get user ('.$id.')', 3);
			$result = false;
		}
		else {
  		while ($row = $db->fetchArray($res)) {
  			$userId       = $row['id'];
  			$userLogin    = $row['login'];
  			$userPassword = $row['password'];
  			$userLangId   = $row['lang_id'];
  			$firstname    = $row['firstname'];
  			$lastname     = $row['lastname'];
  			$email        = $row['email'];
  			$homePageId   = $row['home_page_id'];
  			$disabled     = $row['disabled'];

  			$user = &new User($userId, $userLogin, $userPassword, $userLangId);

        if(!is_numeric($homePageId)){
  				$params = substr(strstr($homePageId, '?'), 1);
  				$paramArray = explode('&', $params);
  				foreach($paramArray as $param) {
  					list($paramName, $paramValue) = explode('=', $param);
  					if(!(strncmp($paramName, 'pid', 3)) && is_numeric($paramValue)) {
  	        	$user->setUserHomePageId($paramValue);
              break;
  					}
  		    }
        }
        else {
          $user->setUserHomePageId($homePageId);
        }

        $user->setUserFirstname($firstname);
        $user->setUserLastname($lastname);
        $user->setUserEmail($email);
        $user->setUserDisabled($disabled);

  			$this->addUser($user);
  		}

  		if ($loadGroupsMembershipList) {
  			$this->loadGroupsMembershipList($usersIdList);
  		}
    }
    $this->debug('UsersManager::loadUser, status : function completed', 10, DBG_CLOSE);
		return $result;
	}
	
	/**
	 * Loads Groups Membership List
	 *
	 * @param  mixed $userId integer or indexed array
	 * @return boolean
	 */
	function loadGroupsMembershipList($userId) {
		$usersIdList = array();

		foreach ((array)$userId as $id) {
			if ($this->userExists($id)) {
				$usersIdList[] = $id;
			}
		}

		if (count($usersIdList) < 1) {
			return false;
		}

		$db = &$this->getDBManipulator();
		$cond = '`user_id` in ('.implode(',', $usersIdList).')';
		if ($res = $db->getRecord(GROUP_USERS_TABLE, -1, $cond)) {
			while ($row = $db->fetchArray($res)) {
				$userId = (int)$row['user_id'];
				$groupId = (int)$row['group_id'];
				$this->usersTable[$userId]->addGroupMembership($groupId);
			}
		}
		else {
			return false;
		}
		return true;
	}
	
	/**
	 * User Exists
	 *
	 * Checks if user is defined into manager
	 *
	 * @param  integer $userId
	 * @return boolean
	 */
	function userExists($userId) {
		return isset($this->usersTable[$userId]);
	}
	
	/**
	 * Returns New User
	 *
	 * @param  integer $userId
	 * @return object
	 */
	function &getNewUser() {
    $this->debug('UsersManager::getNewUser, status : function invoked', 10, DBG_OPEN);
		$user = &new User();
		$this->addUser($user);
    $this->debug('UsersManager::getNewUser, status : function completed', 10, DBG_CLOSE);
		return $user;
  }


	/**
	 * Sets User Into Manager
	 *
	 * @param  object $user
	 * @return boolean
	 */
	function setUser(&$user) {
		$userId = $user->getUserId();
		$this->usersTable[$userId] = &$user;
	}

	/**
	 * Gets User
	 *
	 * Checks if User object already is loaded. If not tries to load it then
	 * returns it
	 *
 	 * @param  integer $id User Id
 	 * @return object
	 */
  function &getUser($id) {
    $this->debug('UsersManager::getUser, status : function invoked', 10, DBG_OPEN);
    $user = null;
		if (!$this->userExists($id)) {
			if (!$this->loadUser($id)) {
				$this->debug('UserManager::getUser, error : unable to load user ('.$id.')', 2);
			}
			else {
        $user = &$this->usersTable[$id];
			}
		}
		else {
      $user = &$this->usersTable[$id];
		}
    $this->debug('UsersManager::getUser, status : function completed', 10, DBG_CLOSE);
		return $user;
  }

	/**
	 * Gets User Id
	 *
	 * @param  string  $login User Login
	 * @param  string  $password User Password
	 * @return integer 0 if error
	 */
  function getUserId($login, $password) {
    $this->debug('UsersManager::getUserId, status : function invoked ('.$login.', '.$password.')', 10, DBG_OPEN);
    $userId = 0;
		$db = &$this->getDBManipulator();
		$where = '`login` = '.$db->quoteSmart($login).' and `password`='.$db->quoteSmart($password);
		$res = $db->getRecord(USERS_TABLE, -1, $where);
		if (!$res || !$db->getNumRows()) {
      $this->debug('UsersManager::getUserId, error : unable to load user', 2);
		}
		else {
  		$row = $db->fetchArray($res);
  		$userId = (int)$row['id'];
    }
    $this->debug('UsersManager::getUser, status : function completed', 10, DBG_CLOSE);
		return $userId;
  }
	
	function getUsersArrayForDisplay($get_groups=false, $usersIdsArray=null) {
		$usersArray = array();
		
		$result = $this->dbManipulator->queryGetAllUsers($get_groups, $usersIdsArray);
		
		if (!$result) {
			return null;
		}
		
		while ($row = $this->dbManipulator->fetchArray($result)) {
			$userId = (int )$row['user_id'];
			$userLogin = $row['user_login'];
			$usersArray[$userId] = $userLogin;
		}
		
		return $usersArray;
	}
	
	/**
	 * Gets Languages
	 *
	 * Returns associative array of available languages
	 *
	 * @return array
	 * @todo discussion about the right place for this function (managers interface ? / dbManipulator ?)
	 */
	function getLangsArray() {
		$dbManipulator = &$this->getDBManipulator();
		$result        = $dbManipulator->getRecord(LANGUAGES_TABLE, -1, '', 'id', '`name`');
		if (!$result) {
			return null;
		}
		$langsArray = array();
		while ($row = $dbManipulator->fetchArray($result)) {
			$langId = (int )$row['id'];
			$langsArray[$langId] = $row['name'];
		}
		return $langsArray;
	}

	/**
	 * Stores User
	 *
	 * Adds or updates User in database
	 *
	 * @param  integer $userId User Id (must be loaded into manager)
	 * @return integer User Id or 0 if error
	 */
	function storeUser($userId) {
		$stored = 0;
		if($this->userExists($userId)){
			$db = &$this->getDBManipulator();
			$user = &$this->usersTable[$userId];
			$fields = array();
			$fields['login']         = $user->getUserLogin();
			$fields['password']      = $user->getUserPassword();
			$fields['lang_id']       = $user->getUserLangId();
			$fields['firstname']     = $this->html_encode($user->getUserFirstname());
			$fields['lastname']      = $this->html_encode($user->getUserLastname());
			$fields['email']         = $user->getUserEmail();
			$fields['home_page_id']  = $user->getUserHomePageId();
			$fields['disabled']      = $user->getUserDisabled();

			if(!$userId){
				$res = $db->addRecord(USERS_TABLE, $fields);
				if($res && $db->getAffectedRows()){
					$newUserId = $db->getLastId();
					$user->setUserId($newUserId);
			    $this->setUser($user);
          $stored = $newUserId;
				}
			}else{
				if($db->setRecord(USERS_TABLE, $userId, $fields)){
					$stored = $userId;
				}
			}
		}
		return $stored;
	}

	/**
	 * Remove User
	 *
	 * Remove a user from the DB
	 *
	 * @param  integer $id User Id
	 * @return boolean
	 */
	function removeUser($id) {
		if (!($user = &$this->getUser($id))) {
			$this->debug("UsersManager.removeUser, error : trying to remove unexisting user '$id'.", 3);
			return false;
		}
    $db = &$this->getDBManipulator();
    if(!($db->delRecord(USERS_TABLE, $id))) {
			$this->debug("UsersManager.removeUser, error : unable to query user removal for user '$id'.", 3);
			return false;
    }

		return true;
	}

	/**
	 * Stores Groups Membership List
	 *
	 * @param  integer $userId User Id (user must be loaded into manager)
	 * @return boolean
	 */
	function storeGroupsMembershipList($userId) {
		$user = &$this->getUser($userId);
		if (!$user) {
			return false;
		}
		$groupsIdList = $user->getGroupsMembershipList();
		if (count($groupsIdList)<1) {
			return true;
		}
		$db = &$this->getDBManipulator();
		$where = '';
		$res = $db->getRecord(GROUP_USERS_TABLE, $userId, $where, 'user_id');
		if (!$res) {
			return false;
		} elseif ($db->getNumRows()) {
			$currGroupsIdList = array();
			while ($row = $db->fetchArray($res)) {
				$groupId = (int)$row['group_id'];
				$currGroupsIdList[] = $groupId;
			}
			$addList = array_diff($groupsIdList, $currGroupsIdList);
			foreach ($addList as $groupId) {
				$record = array();
				$record['group_id'] = $groupId;
				$record['user_id']  = $userId;
				$db->addRecord(GROUP_USERS_TABLE, $record);
			}
			$delList = array_diff($currGroupsIdList, $groupsIdList);
			$where = '`user_id`='.$userId;
			foreach ($delList as $groupId) {
				$db->delRecord(GROUP_USERS_TABLE, $groupId, $where, 'group_id');
			}
		} else {
			foreach ($groupsIdList as $groupId) {
				$record = array();
				$record['group_id'] = $groupId;
				$record['user_id']  = $userId;
				$db->addRecord(GROUP_USERS_TABLE, $record);
			}
		}
		return true;
	}
	/**#@-*/
	
	/**#@+
	 * @access private
	 */
	/**
	 * Adds User Into Manager
	 *
	 * @param object $user
	 */
	function addUser(&$user) {
		$userId = $user->getUserId();
		$this->usersTable[$userId] = &$user;
	}
	/**#@-*/
	
	/**
	 * @author vinadelmar <vinadelmar@users.sourceforge.net>
	 * @since  2006-02-16
	 * @param  array $usersIdList
	 * @return mixed array or false if error
	 */
	/*
	function &getUsersName($usersIdList) {
		$sql = sprintf('SELECT usr.id AS uid, usr.login AS uname '
		              .'FROM %s usr '
		              .'WHERE usr.id IN(%s);'
		              ,USERS_TABLE, implode(',', $usersIdList));
		
		$dbManipulator = &$this->getDBManipulator();
		
		if (($qry = &$dbManipulator->sendQuery($sql))===false) {
			$this->debug("UsersManager::getUsersName(), error : query failure '{$sql}'.", 3);
			return false;
		}
		
		$usersName = array();
		
		while (($row = &$dbManipulator->fetchArray($qry))!==false) {
			$uid   = $row['uid'];
			$uname = $row['uname'];
			$usersName[$uid] = $uname;
		}
		
		$this->debug("UsersManager::getUsersName(), success : got users' name.", 9);
		return $usersName;
	}
	*/
	
	/**
	 * Loads All Users
	 *
	 * @author vinadelmar <vinadelmar@users.sourceforge.net>
	 * @deprecated
	 */
	/*
	function loadAllUsers($load_users_groups)
	{
		$dbManipulator = &$this->dbManipulator;
		
		$rst = $dbManipulator->queryGetAllUsers(!$load_users_groups);
		
		if (!$rst) {
			return false;
		}
		
		$row = $dbManipulator->fetchArray($rst);
		$prev_id       = (int )$row['user_id'];
		$prev_login    = $row['user_login'];
		$prev_password = $row['user_password'];
		$prev_langId   = (int )$row['user_lang_id'];
		$groups = array();
		
		$groupId = (int )$row['user_group_id'];
		
		if ($groupId) {
			$groups[] = $groupId;
		}

		while ($row = $dbManipulator->fetchArray($rst)) {
			$id       = (int )$row['user_id'];
			$login    = $row['user_login'];
			$password = $row['user_password'];
			$langId   = (int )$row['user_lang_id'];
			$groupId  = (int )$row['user_group_id'];

			if ($id != $prev_id) {
				if (empty($groups)) {
					$groups = null;
				}
					
				$this->usersTable[$prev_id] = &new User($prev_id, $prev_login, $prev_password, $prev_langId, $groups);
				
				$prev_id       = $id;
				$prev_login    = $login;
				$prev_password = $password;
				$prev_langId   = $langId;
				$groups        = array();
			}
			
			if ($groupId) {
				$groups[] = $groupId;
			}
		}
		
		if (empty($groups)) {
			$groups = null;
		}
		
		$this->usersTable[$prev_id] = &new User($prev_id, $prev_login, $prev_password, $prev_langId, $groups);
		
		return true;
	}
	*/
} 
?>
