Location: PHPKode > projects > Community Learning Network > cln/lib/CLN/Cln_Room.php
<?php
/*
 * Room Class
 *
 * Copyright (c) 2003-4 St. Christopher House
 *
 * Developed by The Working Group Inc.
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * @version $Id: Cln_Room.php,v 1.212 2005/01/22 20:15:19 cbooth7575 Exp $
 *
 */


require_once('Cln_Module.php');

class Cln_Room extends Cln_Module
{


	/*
	 *
	 * Class Attributes:  Cln_Room
	 *
	 * 		The attributes for this class are:
	 *
	 *		TBD
	 *
	 */
	var $roomId;
	var $roomLookId;
	var $template;
	var $stylesheet;
	var $childrenNodes;


	/***********************************************************************************
	 *
	 * Externally accessed methods
	 *
	 **********************************************************************************/

	/*
	 *
	 * Function:  Cln_Room()
	 *
	 * 		Class Constructor
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function Cln_Room($roomId, $passedData = FALSE)
	{
		d('RoomId: ' . $roomId . ': Cln_Room Constructor');
		$this->roomId = $roomId;
		
		if ($passedData && isset($passedData['roomLookId'])) {
			$this->roomLookId = $passedData['roomLookId'];
		}
		else {
			$this->roomLookId = 'NEW';
		}

		if ($passedData && isset($passedData['childrenNodes'])) {
			$this->childrenNodes = $passedData['childrenNodes'];
		}

		$this->template = CLN_DEFAULT_TEMPLATE;
		$this->stylesheet = CLN_DEFAULT_STYLESHEET;
	}


	/*
	 *
	 * Function: getContent()
	 *
	 * sources the template.
	 * any given templates expects to have certain contants defined,
	 * but they are not necessary
	 *
	 * @access public
	 * @return bool	  TRUE on success or FALSE on failure
	 *
	 */
	function getContent()
	{

		d('RoomId: ' . $this->roomId . ': Cln_Room getContent');
		global $PAGEID, $ROOMID;

		// *************************
		// Make the content

		// Set up Header here, so that it can be used by modules like Newsletter
		// :NOTE: this has been moved below for the module's stylesheet loading
		// this means that newsletter's email will be missing the page's stylesheet
		// until we fix that
		//$this->loadHeader();

		// If they're attempting to edit something and they are allowed then do that.
		if (isset($_REQUEST['editKoId']) && is_numeric($_REQUEST['editKoId'])) {
			d('Room: Attempting Edit');
			$editKoId = $_REQUEST['editKoId'];

			// If they're editing the room
			if ($editKoId == $this->_super->koId) {
				d('Room: Editing Current Room');
				$_SESSION['ProcessManager']->push('editRoom', Array('koId' => $editKoId));
				$GLOBALS['CLN_CONTENT'] = $this->_super->getEditContent();
			}
			// Else if they're editing the Page
			else if ($editKoId == $_SESSION['Page']->koId) {
				d('Room: Editing Current Page');
				$_SESSION['ProcessManager']->push('editPage', Array('koId' => $editKoId));
				$GLOBALS['CLN_CONTENT']= $_SESSION['Page']->getEditContent();
			}
			// Else if they're editing the KO in session
			else if (isset($_SESSION['KO']) && $editKoId == $_SESSION['KO']->koId) {
				d('Room: Editing current session KO');
				$_SESSION['ProcessManager']->push('editBlock', Array('koId' => $editKoId));
				$GLOBALS['CLN_CONTENT'] = $_SESSION['KO']->getEditContent();
			}
			// Else if they're editing a room, but not the room in session (ie. they're adding a room to a room)
			else if ($originalRoom = $_SESSION['ProcessManager']->getCurrentData('currentRoomObject')) {
				d('Room: Editing a room that is being unserialized from the PM');
				unset($_SESSION['Room']);
				$_SESSION['Room'] = unserialize($originalRoom);

				$GLOBALS['CLN_CONTENT'] = $_SESSION['Room']->getEditContent();
			}
			// Else if they're editing another KO
			else {
				d('Room: Editing some other KO, not the one in session');
				$_SESSION['ProcessManager']->push('editBlock', Array('koId' => $editKoId));
				if (isset($_SESSION['KO'])) {
					unset($_SESSION['KO']);
				}
				$_SESSION['KO'] = & new $GLOBALS['classes']['ko']['classname']($editKoId);
				$_SESSION['Module_Loader']->clearLoadList();
	   			$_SESSION['Module_Loader']->addToLoadList($_SESSION['KO']->modId);
				$GLOBALS['CLN_CONTENT'] = $_SESSION['KO']->getEditContent();
			}
		}

		// Else they're trying to add something
		else if (isset($_REQUEST['editKoId']) && $_REQUEST['editKoId'] == 'NEW') {
			d('Room: They\'re trying to add a NEW something');
			// If they're just adding it now
			if (isset($_REQUEST['modId'])) {
				d('Room: Just adding it now');
				$modId = $_REQUEST['modId'];

				// They are adding a Room
				if ($modId == 1) {
					d('Room: It\'s a Room they\'re adding');
					// For a NEW room that is just starting, unset the current session object
					if ($this->_super->koId != 'NEW') {
						d('Room: The room in session is wrong, so unsetting it, and creating a NEW one');
						unset($_SESSION['Room']);
						$_SESSION['Room'] = & new $GLOBALS['classes']['ko']['classname']('NEW', $modId);
					}
					$GLOBALS['CLN_CONTENT'] = $_SESSION['Room']->getEditContent();
				}
				// They are adding a Page
				else if ($modId == 2) {
					d('Room: It\'s a Page they\'re adding');
					// For a NEW page that is just starting, unset the current session object
					if ($_SESSION['Page']->koId != 'NEW') {
						d('Room: The page in session is wrong, so unsetting it, and creating a NEW one');
						unset($_SESSION['Page']);
						$_SESSION['Page'] = & new $GLOBALS['classes']['ko']['classname']('NEW', $modId);
					}
					$GLOBALS['CLN_CONTENT'] = $_SESSION['Page']->getEditContent();
				}
				// Else, they are adding a Block
				else {
					d('Room: It\'s a Block they\'re adding, unset and creating new');
					// If they're just getting here, create the Session KO object
					unset($_SESSION['KO']);
					$_SESSION['KO'] = & new $GLOBALS['classes']['ko']['classname']('NEW', $modId);
					$_SESSION['Module_Loader']->clearLoadList();
					$_SESSION['Module_Loader']->addToLoadList($_SESSION['KO']->modId);
					$GLOBALS['CLN_CONTENT'] = $_SESSION['KO']->getEditContent();
				}
			}
			// Else they are in the process of adding it already
			else {
				d('Room: They\'re in the middle of adding something NEW');
				// Find out what they're working on by checking the ProcessManager
				switch ($_SESSION['ProcessManager']->getCurrentProcess()) {
					case 'addRoom':
						d('Room: It\'s a room');
						$GLOBALS['CLN_CONTENT'] = $_SESSION['Room']->getEditContent();
					break;

					case 'addPage':
						d('Room: It\'s a page');
						$GLOBALS['CLN_CONTENT'] = $_SESSION['Page']->getEditContent();
					break;

					case 'addBlock':
						d('Room: It\'s a block');
						$GLOBALS['CLN_CONTENT'] = $_SESSION['KO']->getEditContent();
					break;
				}
			}
		}

		// Else they just want to see the content
		else {
			// Clear any record locks for this user, if they are logged in
			clearRecordLocks();
			d('Room: No editing going on, just content viewing');
			// special request for my house
			if(isset($GLOBALS['MYHOUSE']) && isset($_REQUEST['userProcess'])) {
				switch ($_REQUEST['userProcess']) {
					case 'myProfile':
					case 'myShortcuts':
					case 'confirmAccount':
					case 'register':
					case 'getPassword':
						$GLOBALS['CLN_CONTENT'] = $_SESSION['User']->getContent();
					break;

					default:
						// Get the modId, define the class path, instantiate it, and get the content
						if (isset($_GET['userModId'])) {
							$modId = $_GET['userModId'];
							$className = $_SESSION['Module_Loader']->getModuleClassname($modId);
							$classPath = $_SESSION['Module_Loader']->getModulePath($modId);
							$modPath = dirname($classPath)."/";
							$pathConstant = "MOD_".strtoupper($className)."_PATH";
							if(!defined($pathConstant)) define($pathConstant,$modPath);
							include_once($classPath);
							$module = & new $className();
							
							$GLOBALS['CLN_CONTENT'] = $module->getMyHouseContent();
						}
						else {
							$GLOBALS['CLN_CONTENT'] = $_SESSION['User']->getContent();
						}
					break;
				}
			} else {
				// If it's not an admin page, clear the Process Stack,
				// and push this page onto it
				if (!isset($GLOBALS['PAGETYPE']) || $GLOBALS['PAGETYPE'] != 'Admin') {
					$_SESSION['ProcessManager']->clearStack();
					$_SESSION['ProcessManager']->push('viewPage', Array('roomKoId' => $ROOMID, 'pageKoId' => $PAGEID, 'url' => $_SERVER['REQUEST_URI']));
				}

				// Get the page's content
				$GLOBALS['CLN_CONTENT'] = $_SESSION['Page']->getContent();
			}
		}
		
		
		$this->loadHeader();

		// *************************
		// Fill the other template variables appropriately

		$GLOBALS['CLN_BROWSE_EDIT_BUTTONS'] = $this->getBrowseEdit();

		$GLOBALS['CLN_LOGIN_FORM'] = $this->getLoginForm();
		$GLOBALS['CLN_LOGOUT_BUTTON'] = $this->getLogoutButton();
		$GLOBALS['CLN_MYHOUSE_BUTTON'] = $this->getMyHouseButton();
		$GLOBALS['CLN_JOIN_BUTTON'] = $this->getJoinButton();
		$GLOBALS['CLN_NEW_PASSWORD_BUTTON'] = $this->getNewPasswordButton();

		// for older templates - can be removed after dom changes all the templates...
		$GLOBALS['CLN_LOGIN'] = '<div id="userBort">'.$GLOBALS['CLN_BROWSE_EDIT_BUTTONS']
						.'<span id="userProfile userJoin">'.$GLOBALS['CLN_LOGIN_FORM']
						.$GLOBALS['CLN_MYHOUSE_BUTTON'].' '.$GLOBALS['CLN_JOIN_BUTTON'].' '
						.$GLOBALS['CLN_NEW_PASSWORD_BUTTON'].' '.$GLOBALS['CLN_LOGOUT_BUTTON']
						.'</span><br class="clear"/></div>';


		$GLOBALS['CLN_NAVBAR'] = $this->_super->currentPart['object']->getSideNavigation();
		$GLOBALS['CLN_MAINNAV'] = $this->_super->currentPart['object']->getMainNavigation();
		$GLOBALS['CLN_BREADCRUMB'] = $this->_super->currentPart['object']->getBreadcrumb();
		$GLOBALS['CLN_LANG_CONTROLLER'] = $this->getInterface('langController');
		$GLOBALS['CLN_USER_ERROR'] = clnGetUserError();
		$GLOBALS['CLN_USER_MESSAGE'] = clnGetUserMessage();
		$GLOBALS['CLN_TITLE'] = $this->_super->currentPart['title'] .  ' : ' . $GLOBALS['CLN_PAGE_TITLE'];
		$GLOBALS['CLN_ROOM_TITLE'] = $this->_super->currentPart['title'];

		// :NOTE: this is needed - i've fixed the compliancy issue by putting the comment outside of the condition, which itself is a comment
		// this line is need to make sure multiple columns in IE float properly - dwc
		$GLOBALS['CLN_FOOTER'] .= '<!-- fixes IE problem with layouts - adjusts width for layoutColumn -->'
								 .'<!--[if IE 6]>'
								 .'<script language="javascript" type="text/javascript" src="'.CLN_CLEAN_URL_BASE.'lib/CLN/interfaces/Room/IE.js"></script>'
								 .'<![endif]-->';

		// overlib support
		//$GLOBALS['CLN_HEADER'] .= '<script type="text/javascript" src="' . CLN_CLEAN_URL_BASE . 'lib/overlib/overlib.js"><!-- overLIB (c) Erik Bosrup --></script>' . "\n";
		//$GLOBALS['CLN_FOOTER'] = '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>';

		// *************************
		// Load the template
		ob_start();
		includeLangFile('./template/' . $this->template . '/mainTemplate');
		$completePage = ob_get_contents();
		ob_end_clean();
		return $completePage;

	}


	/*
	 *
	 * Function:  getEditContent()
	 *
	 * 		Returns the edit form for this module
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getEditContent($override = FALSE)
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room getEditContent');
		// Figure out the subprocess we're on
		if (isset($_GET['subprocess'])) {
			$this->currentSubprocess = $_GET['subprocess'];
		}
		if (!isset($this->currentSubprocess)) {
			$this->currentSubprocess = 'EditDetails';
		}

		// Load the language files needed
		includeLangFile('lib/CLN/lang/Room-Process');

		d('RoomId: ' . $this->roomId . ': Cln_Room getEditContent -> currentSubprocess = ' . $this->currentSubprocess);

		switch ($this->currentSubprocess) {

		case 'EditDetails':
			// If they have submitted the form, deal with it
			if (isset($_POST['editRoomDetails'])) {
				// Capture the form data

				// :COMMENT: i've started to work out how to rename the Untitled rooms and pages - dwc
				// the issue seems to be hinged on every room knowing it's parent's children (ie. siblings).  if we knew
				// then, as well as could control them, we'd be in fine shape to simply change it
				//
				//$parent =& new $GLOBALS['classes']['ko']['classname']();
				//$parent->loadPartObject(0);
				//PEAR::raiseError($_POST['koMetadataTitle'].print_r($this->childrenNodes,TRUE), E_USER_NOTICE);

				$this->template = $_POST['roomEditTemplate'];
				$this->stylesheet = $_POST['roomEditStylesheet'];
				$this->loadHeader();
				$this->setOtherLooksInMemory();

				// Validate the data
				if (!$this->validateDetails()) {
					$this->currentSubprocess = 'EditDetails';
					return $this->getInterface('EditDetails');
				}

				// Otherwise, there are no errors, continue
				else {
					if ($this->roomId != 'NEW') {
						$this->saveModuleData();
					}

					if (!$override) {
						PEAR::raiseError('The information for this room has been updated successfully.', E_USER_NOTICE);
						return FALSE;
					}
					else {
						return $this->getInterface('EditDetails');
					}
				}
			}

			// Else, they're just getting here, display the form
			else {
				$this->currentSubprocess = 'EditDetails';
				return $this->getInterface('EditDetails');
			}
		break;

		case 'EditNavigation':
			// If they have submitted the form, deal with it
			if (isset($_POST['submitChanges']) || isset($_POST['up']) || isset($_POST['down'])) {

				// If the data doesnt' capture properly, show it again
				if (!$this->captureEditNavigation()) {
					$this->currentSubprocess = 'EditNavigation';
					return $this->getInterface('EditNavigation');
				}

				// Otherwise, there are no errors, continue
				else {

					// If the user is changing node order show it again
					if(isset($_POST['up']) || isset($_POST['down'])) {
						$this->currentSubprocess = 'EditNavigation';
						return $this->getInterface('EditNavigation');
					}
					// Esle the User is done, leave the edit navigation screen
					else {
						PEAR::raiseError('The changes to the navigation have been processed successfully. Take a look at the navigation bar on the left side to make sure. '
										 .'If you changed the file/folder name, you will need to go to that page and check the URL (location of this page) to confirm the change. '
										 .'Remember that people in view mode will not see your changes until they are published.', E_USER_NOTICE);
						return FALSE;
					}
				}
			}
			// User is trying to cancel out of edit navigation
			else if(isset($_POST['cancelChanges'])) {
				PEAR::raiseError('Action cancelled', E_USER_NOTICE);
				return FALSE;
			}
			// User is trying to delete a node
			else if(isset($_POST['deleteNode'])) {
				PEAR::raiseError('The delete function is current not active from here', E_USER_NOTICE);
				return FALSE;
			}

			// Else, they're just getting here, display the form
			else {
				$this->currentSubprocess = 'EditNavigation';
				return $this->getInterface('EditNavigation');
			}
		break;

		case 'AddSubRoom';
			d('RoomId: ' . $this->roomId . ' AddSubRoom');

			// If they want to add a new room
			if (isset($_POST['addNewRoom'])) {

				// Make the new room
				$newRoom = & new $GLOBALS['classes']['ko']['classname']('NEW', '1');

				// Give it roles
				$newRoom->roles = $this->_super->roles;

				// Load the room object, set title, template, stylesheet and save it all
				$newRoom->loadPartObject(0);
				$newRoom->loadMetadata();
				$newRoom->currentPart['title'] = 'Room';
				$newRoom->currentPart['object']->template = $this->template;
				$newRoom->currentPart['object']->stylesheet = $this->stylesheet;
				$newRoom->save();

				// Give the new page a title that includes the KO, so the
				// filename will use that by default
				$newRoom->currentPart['title'] = 'Room' . $newRoom->koId;
				$newRoom->save();

				// Add the new room to this room
				$newRoomNodeName = $this->addRoomToRoom($newRoom->koId);
				PEAR::raiseError('A new room has been successfully added to the room you were just in, and you have been brought to the Control Panel for the new room. Edit it here.', E_USER_NOTICE);

				// Give the new page a better temporary title :TODO: this isn't working, and I can't really figure out why.
				//$newRoom->currentPart['title'] = 'New Room';
				//$newRoom->save();

				// Save if this is an existing room
				if ($this->roomId != 'NEW') {
					$this->saveModuleData();
				}

				// Push the process
				$this->subprocess = 'EditNavigation';
				$_SESSION['ProcessManager']->push('editRoom', Array('koId' => $newRoom->koId,
																	'editProcess' => 'Content'));

				// Figure out the path for this new room
				$newPath = getNodePath($this->_super->koId, TRUE);
				if(!empty($newPath)) {
					$newPath = $newPath.'/'.$newRoomNodeName . '/index.php';
				}
				else {
					$newPath = $newRoomNodeName . '/index.php';
				}

				// Reinitialize the session room object
				unset($_SESSION['Room']);
				$_SESSION['Room'] = & new $GLOBALS['classes']['ko']['classname']($newRoom->koId);

				// Go to the new room process
				$_SESSION['ProcessManager']->goToCurrentProcess($newPath);

			}

			// Else if they want to copy a room
			else if (isset($_POST['copyRoom'])) {
				$this->currentSubprocess = 'CopyRoomFromKB';

				// Create the search, and set it's default values
				include_once('Cln_KB_Search.php');
				$search = new Cln_KB_Search();
				$search->includedModules = Array(1);
				$search->customWheres = Array('ko.koId != ' . $this->_super->koId);

				// Run the search. We don't need to check anythign here, because that happens below
				return $search->getContent();
			}

			// Else if they want to link to an existing room
			else if (isset($_POST['linkToRoom'])) {
				$this->currentSubprocess = 'LinkToRoomInKB';

				// Create the search, and set it's default values
				include_once('Cln_KB_Search.php');
				$search = new Cln_KB_Search();
				$search->includedModules = Array(1);
				$search->customWheres = Array('ko.koId != ' . $this->_super->koId);

				// Run the search. We don't need to check anythign here, because that happens below
				return $search->getContent();
			}

			// Else they're just getting here
			else {
				d('RoomId: ' . $this->roomId . ' Add new room NOT clicked');
				$this->currentSubprocess = 'AddSubRoom';
				return $this->getInterface('AddSubRoom');
			}
		break;

		case 'CopyRoomFromKB':
			// Create the search, and set it's default values
			include_once('Cln_KB_Search.php');
			$search = new Cln_KB_Search();
			$search->includedModules = Array(1);
			$search->customWheres = Array('ko.koId != ' . $this->_super->koId);
			$search->run();

			if ($search->isComplete()) {
				// Get the linked roomId
				$copiedRoomKoId = $search->userResult;

				$newRoom = & new $GLOBALS['classes']['ko']['classname']('NEW',1);
				$newRoom = $newRoom->copy($copiedRoomKoId);

				// Give it roles
				$newRoom->roles = $this->_super->roles;

				// Save the new room
				$newRoom->save();

				// Add the new room to this room
				$newRoomNodeName = $this->addRoomToRoom($newRoom->koId, FALSE, TRUE);
				PEAR::raiseError('A copy of that room has been successfully added to the room you were just in, and you have been brought to the Control Panel for the copied room. Edit it here.', E_USER_NOTICE);

				// This is maybe not the right place for this.  i think what we want to
				// be doing is having the Room object take care of it's subpages and rooms.
				$copiedRoom = new $GLOBALS['classes']['ko']['classname']($copiedRoomKoId);
				$copiedRoom->loadPartObject(0);
				$childrenNodes = $copiedRoom->currentPart['object']->childrenNodes;

				$indexFileSet = FALSE;
				foreach($childrenNodes as $childNode) {
					if($childNode['modId'] == 1) {
						d('adding roomtoroom: ' . $childNode['koId']);
						$newRoom->currentPart['object']->addRoomToRoom($childNode['koId'], FALSE, TRUE);
					} else {
						d('adding pagetoroom: ' . $childNode['koId']);
						if (!$indexFileSet) {
							$newRoom->currentPart['object']->addPageToRoom($childNode['koId'], $childNode->nodeName, TRUE);
							$indexFileSet = TRUE;
						}
						else {
							$newRoom->currentPart['object']->addPageToRoom($childNode['koId'], $childNode->nodeName);
						}
					}
				}
				$newRoom->save();

				// Save if this is an existing room
				if ($this->roomId != 'NEW') {
					$this->saveModuleData();
				}

				$this->subprocess = 'EditNavigation';
				$_SESSION['ProcessManager']->push('editRoom', Array('koId' => $newRoom->koId,
																	'editProcess' => 'Content'));

				// Figure out the path for this new room
				$newPath = getNodePath($this->_super->koId, TRUE);
				if(!empty($newPath)) {
					$newPath = $newPath.'/'.$newRoomNodeName . '/index.php';
				}
				else {
					$newPath = $newRoomNodeName . '/index.php';
				}

				// Reinitialize the session room object
				unset($_SESSION['Room']);
				$_SESSION['Room'] = & new $GLOBALS['classes']['ko']['classname']($newRoom->koId);

				// Go to the new room process
				$_SESSION['ProcessManager']->goToCurrentProcess($newPath);
			}
			else {
				// Return the interface
				$this->currentSubprocess = 'CopyRoomFromKB';
				return $search->getInterface();
			}
		break;

		case 'LinkToRoomInKB':

			// Create the search, and set it's default values
			include_once('Cln_KB_Search.php');
			$search = new Cln_KB_Search();
			$search->includedModules = Array(1);
			$search->customWheres = Array('ko.koId != ' . $this->_super->koId);
			$search->run();

			if ($search->isComplete()) {
				// Get the linked roomId
				$roomKoId = $search->userResult;

				$newRoomName = $this->addRoomToRoom($roomKoId, FALSE, TRUE);
				PEAR::raiseError('The room you chose has been linked into this room.', E_USER_NOTICE);

				// Only save now for existing rooms, not new
				if ($this->roomId != 'NEW') {
					$this->saveModuleData();
				}
				$this->currentSubprocess = 'EditNavigation';
				return $this->getInterface('EditNavigation');
			}
			else {
				// Return the interface
				$this->currentSubprocess = 'LinkToRoomInKB';
				return $search->getInterface();
			}
		break;

		case 'DeleteSubRoom':
			// Have they chosen one?
			if (isset($_POST['selectRoom']) && isset($_POST['subroomId'])) {
				$this->currentSubprocess = 'DeleteSubroomConfirmation';
				return $this->getInterface('DeleteSubroomConfirmation');
			}
			// Or didn't they choose
			else if (isset($_POST['selectRoom']) && !isset($_POSST['subroomId'])) {
				PEAR::raiseError('You need to select a sub-room to delete', E_USER_WARNING);
				$this->currentSubprocess = 'DeleteSubRooom';
				return $this->getInterface('SelectRoom');
			}
			// Or are the just getting here
			else {
				$this->currentSubprocess = 'DeleteSubRooom';
				return $this->getInterface('SelectRoom');
			}
		break;

		case 'DeleteSubroomConfirmation':
			// If they've submitted the form
			if (isset($_POST['DeleteSubroomConfirmation'])) {
				// Are we deleting it completely from the KB?
				if (!empty($_POST['deleteFromKB']) && $_POST['deleteSubroomKoId']) {
					d('deleting subroom: '.$_POST['deleteSubroomKoId']);

					// Delete the room
					$deletedRoom = new $GLOBALS['classes']['ko']['classname']($_POST['deleteSubroomKoId']);
					$deletedRoom->delete();

					// remove this room and the KO
					$this->deleteNode($_POST['deleteSubroomKoId']);
					$this->saveNodes();

					PEAR::raiseError('The sub-room you selected has has been removed from this room and also removed completely from the Knowledge Base. You should make sure to publish this room now.', E_USER_NOTICE);
					return FALSE;
				}
				// Or just from this room
				else {
					if($this->deleteNode($_POST['deleteSubroomKoId'])) {
						$this->saveNodes();
						PEAR::raiseError('The sub-room you chose has been removed from this room. You should publish to make the changes live.', E_USER_NOTICE);
					} else {
						PEAR::raiseError('There was a problem removing the sub-room from this room.', E_USER_ERROR);
					}

					return FALSE;
				}
			}
			// Else if they're cancelling the delete
			else if (isset($_POST['cancel'])) {
				return FALSE;
			}
			// Or they're just getting here
			else {
				$this->currentSubprocess = 'DeleteSubroomConfirmation';
				return $this->getInterface('DeleteSubroomConfirmation');
			}
		break;

		case 'AddPage':
			// If they want to add a new page
			if (isset($_POST['addNewPage'])) {

				// Make the new page
				$_SESSION['Page'] = & new $GLOBALS['classes']['ko']['classname']('NEW', '2');

				// Give it roles
				$_SESSION['Page']->roles = $this->_super->roles;

				// Load the page object, set title, and save it all
				$_SESSION['Page']->loadPartObject(0);
				$_SESSION['Page']->loadMetadata();
				$_SESSION['Page']->currentPart['title'] = 'Page-ko';
				$_SESSION['Page']->save();

				// Give the new page a title that includes the KO, so the
				// filename will use that by default
				$_SESSION['Page']->currentPart['title'] = 'Page' . $_SESSION['Page']->koId;
				$_SESSION['Page']->save();

				// Add the new page to this room
				$newPageNodeName = $this->addPageToRoom($_SESSION['Page']->koId);
				PEAR::raiseError('A new page has been successfully added to this room and you have been brought to the Control Panel for the new page. When you are ready to make your changes public, be sure to:<ul><li>Publish the room</li><li>Check to see whether your new page has been published</li><li>Check to be sure that all the blocks on your new page have been published.</li></ul>', E_USER_NOTICE);

				// Give the new page a better temporary title
				$_SESSION['Page']->currentPart['title'] = 'New Page';

				// Save if this is an existing room
				if ($this->roomId != 'NEW') {
					$this->saveModuleData();
				}

				// Push the process
				$this->currentSubprocess = 'EditNavigation';
				$_SESSION['ProcessManager']->push('editPage', Array('koId' => $_SESSION['Page']->koId,
																	'editProcess' => 'Content'));

				// Figure out the path for this new page
				$newPath = getNodePath($this->_super->koId, TRUE);
				if(!empty($newPath)) {
					$newPath = $newPath.'/'.$newPageNodeName;
				}
				else {
					$newPath = $newPageNodeName;
				}

				// Go to the page process
				$_SESSION['ProcessManager']->goToCurrentProcess($newPath);
			}

			// Else if they want to copy a page
			else if (isset($_POST['copyPage'])) {
				$this->currentSubprocess = 'CopyPageFromKB';

				// Create the search, and set it's default values
				include_once('Cln_KB_Search.php');
				$search = new Cln_KB_Search();
				$search->includedModules = Array(2);
				$search->customWheres = Array('ko.koId != ' . $this->_super->koId);

				// Run the search. We don't need to check anythign here, because that happens below
				return $search->getContent();
			}

			// Else if they want to link to an existing page
			else if (isset($_POST['linkToPage'])) {
				$this->currentSubprocess = 'LinkToPageInKB';

				// Create the search, and set it's default values
				include_once('Cln_KB_Search.php');
				$search = new Cln_KB_Search();
				$search->includedModules = Array(2);

				// Run the search. We don't need to check anythign here, because that happens below
				return $search->getContent();
			}

			// Else display add page interface
			else {
				return $this->getInterface('AddPage');
			}
		break;

		case 'CopyPageFromKB':
			// Create the search, and set it's default values
			include_once('Cln_KB_Search.php');
			$search = new Cln_KB_Search();
			$search->includedModules = Array(2);
			$search->run();

			if ($search->isComplete()) {
				// Get the pageId
				$pageKoId = $search->userResult;

				$_SESSION['Page'] = & new $GLOBALS['classes']['ko']['classname']('NEW',2);
				$_SESSION['Page'] = $_SESSION['Page']->copy($pageKoId);

				// inherit roles from parent
				$_SESSION['Page']->roles = $this->_super->roles;

				$_SESSION['Page']->save();

				// Add the page
				$newPageNodeName = $this->addPageToRoom($_SESSION['Page']->koId);
				PEAR::raiseError('A copy of the page you selected has been successfully added to this room and you have been brought to the Control Panel for the copied page. When you are ready to make your changes public, be sure to:<ul><li>Publish the room</li><li>Check to see whether your new page has been published</li><li>Check to be sure that all the blocks on your new page have been published.</li></ul>', E_USER_NOTICE);

				// Save if this is an existing room
				if ($this->roomId != 'NEW') {
					$this->saveModuleData();
				}

				// Push the process
				$this->currentSubprocess = 'EditNavigation';
				$_SESSION['ProcessManager']->push('editPage', Array('koId' => $_SESSION['Page']->koId,
																	'editProcess' => 'Content'));

				// Figure out the path for this new page
				$newPath = getNodePath($this->_super->koId, TRUE);
				if(!empty($newPath)) {
					$newPath = $newPath.'/'.$newPageNodeName;
				}
				else {
					$newPath = $newPageNodeName;
				}

				// Go to the page process
				$_SESSION['ProcessManager']->goToCurrentProcess($newPath);
			}
			else {
				// Return the interface
				$this->currentSubprocess = 'CopyPageFromKB';
				return $search->getInterface();
			}
		break;

		case 'LinkToPageInKB':

			// Create the search, and set it's default values
			include_once('Cln_KB_Search.php');
			$search = new Cln_KB_Search();
			$search->includedModules = Array(2);
			$search->run();

			if ($search->isComplete()) {
				// Get the pageId
				$pageKoId = $search->userResult;

				$newNodeName = $this->addPageToRoom($pageKoId);
				PEAR::raiseError('A link to the page you chose has been added to this room.', E_USER_NOTICE);
				// Forward them to the new page
				$nodeName = getNodePath($this->_super->koId, TRUE);
				if(!empty($nodeName)) {
					$nodeName = $nodeName.'/'.$newNodeName;
				} else {
					$nodeName = $newNodeName;
				}

				$go_to = appendToURL(cleanURL($nodeName),'editKoId=' . $this->_super->koId . '&amp;editProcess=Panel', TRUE);
				clnRedirect($go_to);
				exit;
			}
			else {
				// Return the interface
				$this->currentSubprocess = 'LinkToPageInKB';
				return $search->getInterface();
			}
		break;

		case 'DeletePage':
			// Have they chosen one?
			if (isset($_POST['selectPage']) && isset($_POST['pageId'])) {
				$this->currentSubprocess = 'DeletePageConfirmation';
				return $this->getInterface('DeletePageConfirmation');
			}
			// Or didn't they choose
			else if (isset($_POST['selectPage']) && !isset($_POSST['pageId'])) {
				PEAR::raiseError('You need to select a page to delete', E_USER_WARNING);
				$this->currentSubprocess = 'DeletePage';
				return $this->getInterface('SelectPage');
			}
			// Or are the just getting here
			else {
				$pages = $this->getNodes(2, NULL, NULL);
				if (count($pages) > 1) {
					$this->currentSubprocess = 'DeletePage';
					return $this->getInterface('SelectPage');
				}
				else {
					PEAR::raiseError('There is only one page in this room, and you can\'t delete the index page', E_USER_WARNING);
					return FALSE;
				}
			}
		break;

		case 'DeletePageConfirmation':
			// If they've submitted the form
			if (isset($_POST['DeletePageConfirmation'])) {
				// Are we deleting it completely from the KB?
				if (!empty($_POST['deleteFromKB']) && $_POST['deletePageKoId']) {

					d('deleting page: '.$_POST['deletePageKoId']);

					// Delete the page
					$deletedPage = new $GLOBALS['classes']['ko']['classname']($_POST['deletePageKoId']);
					$deletedPage->delete();

					// remove this room and the KO
					$this->deleteNode($_POST['deletePageKoId']);
					$this->saveNodes();

					PEAR::raiseError('The page you selected has has been removed from this room and also removed completely from the Knowledge Base. You should make sure to publish this room now.', E_USER_NOTICE);
					return FALSE;
				}
				// Or just from this room
				else {
					if($this->deleteNode($_POST['deletePageKoId'])) {
						$this->saveNodes();
						PEAR::raiseError('The page you selected has has been removed from this room. You should make sure to publish this room now.', E_USER_NOTICE);
					} else {
						PEAR::raiseError('There was a problem removing that page from this room', E_USER_ERROR);
					}

					return FALSE;
				}
			}
			// Else if they're cancelling the delete
			else if (isset($_POST['cancel'])) {
				return FALSE;
			}
			// Or they're just getting here
			else {
				$this->currentSubprocess = 'DeletePageConfirmation';
				return $this->getInterface('DeletePageConfirmation');
			}
		break;

		default:
			return FALSE;
		break;

		}
	}


	/*
	 *
	 * Function:  loadModuleData()
	 *
	 * 		loads all the relevant data about a room into the object
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function loadModuleData()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room loadModuleData');

		if ($this->roomId != 'NEW' && is_numeric($this->roomId)) {
			$sql = sprintf("SELECT room.roomLookId, look.template, look.stylesheet
							FROM `%s` as room, `%s` as look
							WHERE room.roomLookId = look.roomLookId
							AND roomId = '%s'",
							ROOM_TABLE, ROOM_LOOK_TABLE, $this->roomId);

			$db = &Cln_Db::singleton(MAIN_CLN_DSN);
			$result = $db->query($sql);

			if (PEAR::isError($result))	 {
				PEAR::raiseError("Error on room select: $sql", E_ERROR);
				return FALSE;
			}
			else {
				$room = $result->fetchRow(DB_FETCHMODE_OBJECT);
				$this->roomLookId = $room->roomLookId;
				$this->template = stripslashes($room->template);
				$this->stylesheet = stripslashes($room->stylesheet);

				$this->loadNodes();
				return TRUE;
			}
		}
		else {
			return TRUE;
		}
	}


	/*
	 *
	 * Function:  getPublishData()
	 *
	 * Should return an array of all the data from an object that is needed by another
	 * object to publish it.
	 *
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getPublishData()
	{
		$returnVal['template'] = $this->template;
		$returnVal['stylesheet'] = $this->stylesheet;
		$returnVal['childrenNodes'] = $this->childrenNodes;

		return $returnVal;
	}


	/*
	 *
	 * Function: getNewTranslationData()
	 *
	 * To get general stuff that is needed when creating a translation version
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getNewTranslationData()
	{
		$data['roomLookId'] = $this->roomLookId;
		$data['childrenNodes'] = $this->childrenNodes;
		return $data;
	}


	/*
	 *
	 * Function:  publish()
	 *
	 * Should take an array of all the data from an object that is needed by another
	 * object to publish it.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function publish($publishData = FALSE)
	{
		if ($publishData) {
			$this->template = $publishData['template'];
			$this->stylesheet = $publishData['stylesheet'];
			$this->childrenNodes = $publishData['childrenNodes'];
		}

		return $this->saveModuleData();
	}


	/*
	 *
	 * Function:  delete()
	 *
	 * 		Deletes this room
	 *			- must delete children first
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function delete()
	{
		d('Cln_Room delete: roomId: ' . $this->roomId);

		$db = &Cln_Db::singleton(MAIN_CLN_DSN);
		$sql = sprintf("DELETE FROM %s WHERE roomId = '%s'", ROOM_TABLE, $this->roomId);
		$result = $db->query($sql);

		if (PEAR::isError($result))	 {
			PEAR::raiseError(ADMIN_EM_DB_ERROR_DELETE , E_USER_ERROR);
			PEAR::raiseError("Error on room delete: $sql", E_ERROR);
			return FALSE;
		}
		else {
			$sql = sprintf("DELETE FROM %s WHERE roomLookId = '%s'", ROOM_LOOK_TABLE, $this->roomLookId);
			$result = $db->query($sql);

			$sql = sprintf('DELETE FROM `%s` WHERE parentId = %d',
						ROOM_NODE_TABLE, $this->_super->koId);

			$result = $db->query($sql);
			return TRUE;
		}
	}

	/*
	 *
	 * Function:  saveModuleData()
	 *
	 * 		Saves the KO
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function saveModuleData()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room saveModuleData');

		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		// ********
		// Deal with the roomLook first

		// If it's a new room look
		if ($this->roomLookId == 'NEW') {
			// Get the next ID
			$this->roomLookId = $db->nextId(ROOM_LOOK_TABLE);

			// Write the SQL
			$sql = sprintf("INSERT INTO `%s` (roomLookId, template, stylesheet, created) VALUES ('%s', '%s', '%s', NOW())",
							ROOM_LOOK_TABLE, $this->roomLookId, addslashes($this->template), addslashes($this->stylesheet));


		}

		// Else it's an existing room
		else {
			$sql = sprintf("UPDATE %s SET template = '%s', stylesheet = '%s'
							WHERE roomLookId = '%s'",
							ROOM_LOOK_TABLE,  addslashes($this->template), addslashes($this->stylesheet), $this->roomLookId);
		}

		// Do the query
		$result = $db->query($sql);
		if (PEAR::isError($result))	 {
			PEAR::raiseError('ADMIN_EM_DB_ERROR_INSERT', E_USER_ERROR);
			PEAR::raiseError("Error on room look insert/update: $sql", E_ERROR);
			return FALSE;
		}

		// **********
		// Then deal with the main room info

		// If it's a new room
		if ($this->roomId == 'NEW') {
			// Get the next ID
			$this->roomId = $db->nextId(ROOM_TABLE);

			// Write the SQL
			$sql = sprintf("INSERT INTO `%s` (roomId, roomLookId, created) VALUES ('%s', '%s', NOW())",
							ROOM_TABLE, $this->roomId, $this->roomLookId);

		}

		// Else it's an existing room
		else {
			$sql = sprintf("UPDATE %s SET roomLookId = '%d'
							WHERE roomId = '%s'",
							ROOM_TABLE,  $this->roomLookId, $this->roomId);
		}

		// Do the query
		$result = $db->query($sql);
		if (PEAR::isError($result))	 {
			PEAR::raiseError('ADMIN_EM_DB_ERROR_INSERT', E_USER_ERROR);
			PEAR::raiseError("Error on room insert / update: $sql", E_ERROR);
			return FALSE;
		}
		else {
			if (!$this->saveNodes()) {
				PEAR::raiseError('Error on saving nodes', E_ERROR);
			}
			else {
				$this->updateModified();
				return $this->roomId;
			}
		}
	}


	/*
	 *
	 * Function:  addPageToRoom()
	 *
	 * 		Adds a new page to this room
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function addPageToRoom($pageKoId, $pageFilename = FALSE, $indexPage = FALSE)
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room addPageToRoom');
		// If there is no filename, generate one
		if (!$pageFilename) {
			$pageFilename = $this->generateUniqueNodeName($pageKoId, TRUE);
		}

		if ($indexPage) {
			$pageFilename = 'index.php';
		}

		// Add the page to the navigation
		$this->addNode($pageKoId, $pageFilename);

		return $pageFilename;
	}


	/*
	 *
	 * Function:  addRoomToRoom()
	 *
	 * 		Adds a new room to this room, and if it is an existing room, it copies all the pages there as well.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function addRoomToRoom($newRoomKoId, $newRoomFolderName = FALSE, $existing = FALSE)
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room addRoomToRoom');

		if(!is_numeric($newRoomKoId)) {
			PEAR::raiseError('inside addRoomToRoom: $newRoomKoId must be a number', E_ERROR);
			return FALSE;
		}

		// Generate a folder name
		if (!$newRoomFolderName) {
			$newRoomFolderName = $this->generateUniqueNodeName($newRoomKoId);
		}
		d('------> testing: '.$existing,1);
		// If the room doesn't exist yet, create a default index page.
		if (!$existing) {
			d('creating new default page for new room',1);
			// Create a default index page in new room
			$page = & new $GLOBALS['classes']['ko']['classname']('NEW', 2);
			$page->roles = $this->_super->roles;
			$page->loadPartObject(0);
			$page->loadMetadata();
			$page->currentPart['title'] = 'Your New Page';

			$page->save();

			$room = & new $GLOBALS['classes']['ko']['classname']($newRoomKoId);
			$room->loadPartObject(0);
			$room->loadMetadata();
			$room->currentPart['object']->addPageToRoom($page->koId, 'index.php');
			$room->save();
		}

		// Add the room to the navigation
		$this->addNode($newRoomKoId,$newRoomFolderName);

		return $newRoomFolderName;
	}


	/***********************************************************************************
	 *
	 * Node-related Methods (include subroom/page methods)
	 *
	 **********************************************************************************/

	/*
	 *
	 * Function:  loadNodes()
	 *
	 * 		Loads the info from the DB about the nodes of this object, and stores it in memory as $this->nodes
	 *
	 * @access public
	 * @return bool		TRUE or FALSE
	 *
	 */
	function loadNodes()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room loadNodes');
		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		$this->childrenNodes = Array();

		$sql = sprintf('SELECT ko.koId, ko.title, ko.modId, ko.lang, node.nodeName, node.ordering, node.visible
						FROM %s, %s AS node WHERE node.parentId = %d
						AND ko.koId = node.koId AND node.status = %d
						AND ko.status = node.status ORDER by ordering',
						KO_TABLE, ROOM_NODE_TABLE, $this->_super->koId,
						$this->_part['status']);

		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		$result = $db->query($sql);

		while($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
			$ordering = $row['ordering'];
			$this->childrenNodes[$ordering]['koId'] = $row['koId'];
			$this->childrenNodes[$ordering]['visible'] = $row['visible'];
			$this->childrenNodes[$ordering]['modId'] = $row['modId'];
			$this->childrenNodes[$ordering]['nodeName'] = $row['nodeName'];
			
			$lang = $row['lang'];
			
			/*if(ereg("My House",$row['title'])) {
				ereg("User([0-9]*)",$row['nodeName'],$regs);
				$userId = $regs[1];
				$row['title'] = "test ".$userId." ".$_SESSION['User']->getUserName($userId);
				$this->currentPart['object']->title = $row['title'];
			}*/
			$this->childrenNodes[$ordering]['title'][$lang] = $row['title'];
		}

		return TRUE;
	}


	/*
	 *
	 * Function: saveNodes()
	 *
	 * 		save all the nodes
	 *
	 * @access public
	 * @return Bool		TRUE or FALSE
	 *
	 */
	function saveNodes()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room saveNodes');

		// Only save nodes if this koId is set, and if we're dealing
		// with the correct part. This has caused problems in the past because in
		// ko->createLivePart saveModuleData is called before the current part is set
		// properly.
		if (is_numeric($this->_super->koId) && $this->_super->currentPart['objectId'] == $this->roomId) {
			$db = &Cln_Db::singleton(MAIN_CLN_DSN);

			// First delete all the nodes
			d('RoomId: ' . $this->roomId . ': Deleting all nodes', 3);
			d('RoomId: ' . $this->roomId . ': _super->koId is ' . $this->_super->koId);
			d('RoomId: ' . $this->roomId . ': _super->currentPart[\'status\'] is ' . $this->_super->currentPart['status']);
			d('RoomId: ' . $this->roomId . 'super dump:');
			$sql = sprintf('DELETE FROM %s WHERE parentId = %d
							AND status = %d',
							ROOM_NODE_TABLE, $this->_super->koId, $this->_super->currentPart['status']);
			d('RoomId: ' . $this->roomId . ': SQL: ' . $sql);
			$result = $db->query($sql);
			if (PEAR::isError($result)) {
				PEAR::raiseError('Unable to delete from '.ROOM_NODE_TABLE.' table: '.$sql, E_ERROR);
				return FALSE;
			}

			// Then resave all the nodes

			// If there aren't any nodes, you can't save anything yet!
			if (count($this->childrenNodes) == 0) {
				return TRUE;
			}

			$sql = sprintf('INSERT INTO %s (koId, parentId, status, nodeName, ordering, visible, created) VALUES', ROOM_NODE_TABLE);


			foreach($this->childrenNodes as $nodeOrder => $node) {
				$values[] = sprintf(" (%d, %d, %d, '%s', %d, %d, NOW())",
							$node['koId'], $this->_super->koId, $this->_super->currentPart['status'],
							$node['nodeName'], $nodeOrder, $node['visible']);
			}
			$sql .= join(', ',$values);
			d('RoomId: ' . $this->roomId . ": Saving nodes: {$sql}");

			$result = $db->query($sql);
			if (PEAR::isError($result)) {
				PEAR::raiseError('Unable to insert into '.ROOM_NODE_TABLE.' table: '.$sql, E_ERROR);
				return FALSE;
			}
		}
		$this->updateModified();
		return TRUE;
	}


	/*
	 *
	 * Function:  addNode()
	 *
	 * 		Adds a block to the node table for reference
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function addNode($koId, $nodeName)
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room addNode');

		// Fill in the basic stuff
		$newOrder = count($this->childrenNodes) + 1;
		$this->childrenNodes[$newOrder]['koId'] = $koId;
		$this->childrenNodes[$newOrder]['visible'] = 1;
		$this->childrenNodes[$newOrder]['nodeName'] = $nodeName;

		// Then query the DB to get the additional stuff
		$db = &Cln_Db::singleton(MAIN_CLN_DSN);
		$sql = sprintf('SELECT modId, title, lang FROM `%s` WHERE koId = %d AND status = %d',
						KO_TABLE, $koId, $this->_part['status']);
		$result = $db->query($sql);

		while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
			$this->childrenNodes[$newOrder]['modId'] = $row['modId'];
			$lang = $row['lang'];
			$this->childrenNodes[$newOrder]['title'][$lang] = $row['title'];
		}

		// Then save the nodes
		$this->saveNodes();
	}


	/*
	 *
	 * Function:  changeNodeOrder()
	 *
	 * 		Change the order of the node
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function changeNodeOrder($nodeOrder, $direction)
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room changeNodeOrder');

		$currentCount = count($this->childrenNodes);

		// Make sure they're not moving one too high, or too low
		if ($direction == 'up' && $nodeOrder == 1) {
		  	return FALSE;
		}
		else if ($direction == 'down' && $nodeOrder == $currentCount) {
			return FALSE;
		}

		// Figure out which one it's switching with
		if ($direction == 'up') {
			$newOrder = $nodeOrder - 1;
		}

		if ($direction == 'down') {
			$newOrder = $nodeOrder + 1;
		}

		// Perform the swap
		$this->childrenNodes['temporary'] = $this->childrenNodes[$nodeOrder];
		unset($this->childrenNodes[$nodeOrder]);
		$this->childrenNodes[$nodeOrder] = $this->childrenNodes[$newOrder];
		$this->childrenNodes[$newOrder] = $this->childrenNodes['temporary'];
		unset($this->childrenNodes['temporary']);
		ksort($this->childrenNodes);

		// And save the nodes
		$this->saveNodes();
	}


	/*
	 *
	 * Function:  updateNodeName()
	 *
	 * 		renames a node
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function updateNodeName($nodeOrder, $newNodeName)
	{
		foreach ($this->childrenNodes as $order => $data) {
			if ($order != $nodeOrder && $data['nodeName'] == $newNodeName) {
				// This is a duplicate name, don't allow it
				PEAR::raiseError('One of the filenames you chose was a duplicate, which isn\'t allowed.', E_USER_WARNING);
				return FALSE;
			}
		}
		$this->childrenNodes[$nodeOrder]['nodeName'] = $newNodeName;
		$this->saveNodes();
		return TRUE;
	}


	/*
	 *
	 * Function:  updateNodeVisibility()
	 *
	 * 		changes a node's visibility
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function updateNodeVisibility($nodeOrder, $newVisibility)
	{
		$this->childrenNodes[$nodeOrder]['visible'] = $newVisibility;
		$this->saveNodes();
		return TRUE;
	}


	/*
	 *
	 * Function:  deleteNode()
	 *
	 * 		Delete's a node
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function deleteNode($nodeKoId, $status = 0)
	{
		d('roomId: ' . $this->roomId . ': deleteNode: '.$nodeKoId.' '.$this->_super->koId,1);

		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		$sql = sprintf('DELETE FROM `%s` WHERE koId = %d AND parentId = %d AND status = %d',
						ROOM_NODE_TABLE, $nodeKoId, $this->_super->koId, $status);

		$result = $db->query($sql);

		if (PEAR::isError($result))	 {
			PEAR::raiseError(ADMIN_EM_DB_ERROR_DELETE, E_USER_ERROR);
			PEAR::raiseError("Error deleting node: $sql", E_ERROR);
			return FALSE;
		} else {
			// Delete the node and while at it fix the order of nodes after it
			$nodeFound = FALSE;
			foreach ($this->childrenNodes as $nodeNumber => $nodeInfo) {
				if ($nodeFound) {
					$newNodeNumber = $nodeNumber - 1;
					$this->childrenNodes[$newNodeNumber] = $nodeInfo;
					unset($this->childrenNodes[$nodeNumber]);
				}
				else if ($nodeInfo['koId'] == $nodeKoId) {
					unset($this->childrenNodes[$nodeNumber]);
					$nodeFound = TRUE;
				}
			}
			return TRUE;
		}
	}


	/*
	 *
	 * Function: getNodes()
	 *
	 * 		Returns arrays of the nodes based on what is passed - modId, visibility and language
	 *
	 * @access public
	 * @return Array of Objects		children nodes
	 *
	 */
	function getNodes($modId = NULL, $visibility = NULL, $language = NULL)
	{
		$returnNodes = Array();

		// Loop through the childrenNodes for this room, seeing if we should return each row according to
		// the passed values
		foreach ($this->childrenNodes as $nodeOrder => $node) {
			$captureNode = FALSE;

			// Check if the modId is being requested, and if so, that it's the same
			if (!is_null($modId) && $node['modId'] == $modId) {
				$captureNode = TRUE;
			}

			// Check that the visibility is being requested, and if so that it's the same
			if (!is_null($visibility) && $node['visible'] == $visibility) {
				$captureNode = TRUE;
			}

			// If neither modId or visibility is being requested, keep it
			if (is_null($modId) && is_null($visibility)) {
				$captureNode = TRUE;
			}

			// If we've passed so far, go through, and get the line, captureing proper language if requested
			if ($captureNode == TRUE) {
				if (!is_null($language)) {
					$titles = $node['title'];
					unset($node['title']);
					$availableLanguages = Array();
					foreach ($titles as $lang => $title) {
						$availableLanguages[] = $lang;
					}
					$langToUse = whichLanguage($availableLanguages);
					$node['title'][0] = $titles[$langToUse];
					$node['title'][$langToUse] = $titles[$langToUse];
				}
				$returnNodes[$nodeOrder] = $node;
			}
		}
		return $returnNodes;
	}


	/*
	 *
	 * Function: filterNodesForLang()
	 *
	 * 		filters nodes of the wrong languages
	 * 		  - objects in array must have lang and koId properties
	 *
	 * @access public
	 * @return Array of Objects		children nodes
	 *
	 */
	function filterNodesForLang($nodes)
	{
		foreach($nodes as $node) {
			$languageSets[($node->koId)][] = $node->lang;
		}

		$keepChildren = array();

		if(isset($languageSets) && isset($nodes)) {
			foreach($languageSets as $koId => $availableLanguages) {
				$useThisLang[$koId] = whichLanguage($availableLanguages);
			}

			for($i=0;$i<count($nodes);$i++) {
				$node = $nodes[$i];
				//print $node->lang.' == '.$useThisLang[($node->koId)].'<br />';
				if($node->lang == $useThisLang[($node->koId)]) {
					$keepChildren[] = $nodes[$i];
				}
			}
		}

		return $keepChildren;
	}


	/*
	 *
	 * Function:  generateUniqueNodeName()
	 *
	 * 		Generates a unique nodename to be used in this room that is based upon
	 *		the object's title, and is available.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function generateUniqueNodeName($koId, $isPage = FALSE, $x = FALSE)
	{
		// Create the page object and get it's fixed filename
		$theKO = & new $GLOBALS['classes']['ko']['classname']($koId);
		$theKO->loadPartObject(0);
		$filename = $this->fixFilename($theKO->currentPart['title']);

		// Make the full name to test, incrementing if needed
		if (!$x) {
			$nameToTest = $filename;
			$x = 1;
		}
		else {
			$nameToTest = $filename . '_' . $x;
			$x++;
		}

		// If it's a page, append .php to it
		if ($isPage) {
			$nameToTest .= '.php';
		}

		// Get the children
		$modId = $isPage ? 2 : 1;
		$childrenNodes = $this->getNodes($modId, NULL, NULL);

		// Assume the nodeName isn't taken
		$nameIsAvailable = TRUE;

		// Loop through the children
		foreach($childrenNodes as $nodeOrder => $childNode) {

			// If the node name is taken, make the name unavailable
			if(strtolower($nameToTest) == strtolower($childNode['nodeName'])) {
				$nameIsAvailable = FALSE;
			}
		}

		if($nameIsAvailable) {
			return $nameToTest;
		}
		else {
			return $this->generateUniqueNodeName($koId, $isPage, $x);
		}

	}


	/*
	 *
	 * Function:  fixFilename()
	 *
	 * 		Fixes the filename of an object, from the title, it generates a safe one.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function fixFilename($filename)
	{
		$filename = ucwords(strtolower($filename));
		$filename = ereg_replace('[^[:alnum:]]', '', $filename);
		if (strlen($filename) > 20) {
			$filename = substr($filename, 0, 20);
		}
		return $filename;
	}


	/*
	 *
	 * Function:  captureEditNavigation()
	 *
	 * 		Captures the data submitted by the EditNavigation form, and deals with it appropriately
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function captureEditNavigation()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room captureEditNavigation');

		$status = TRUE;

		// Check for page node name changes
		if(isset($_POST['pageNodeName']) && is_array($_POST['pageNodeName'])) {
			foreach($_POST['pageNodeName'] as $nodeOrder => $newNodeName) {
				$newNodeName .= '.php';
				if($newNodeName != $this->childrenNodes[$nodeOrder]['nodeName']) {
					if(!$this->updateNodeName($nodeOrder, $newNodeName)) {
						PEAR::raiseError('Unable to rename page', E_WARNING);
						$status = FALSE;
					}
				}
			}
		}


		// Check for room node name changes
		if(isset($_POST['roomNodeName']) && is_array($_POST['roomNodeName'])) {
			foreach($_POST['roomNodeName'] as $nodeOrder => $newNodeName) {
				if($newNodeName != $this->childrenNodes[$nodeOrder]['nodeName']) {
					if(!$this->updateNodeName($nodeOrder, $newNodeName)) {
						PEAR::raiseError('Unable to rename room', E_WARNING);
						$status = FALSE;
					}
				}
			}
		}

		// Check for visibility changes
		foreach ($this->childrenNodes as $nodeOrder => $node) {
			// If they're turning it on
			if ($node['visible'] == 0 && isset($_POST['nodeVisibility'][$nodeOrder])) {
				if(!$this->updateNodeVisibility($nodeOrder, 1)) {
					PEAR::raiseError('Unable to update visibility', E_WARNING);
					$status = FALSE;
				}
			}
			// Or if they're turning it off
			else if ($node['visible'] == 1 && !isset($_POST['nodeVisibility'][$nodeOrder])) {
				if(!$this->updateNodeVisibility($nodeOrder, 0)) {
					PEAR::raiseError('Unable to update visibility', E_WARNING);
					$status = FALSE;
				}
			}
		}

		if(isset($_POST['up'])) {
			// This is not really a loop as there is only one
			// element in the array
			foreach ($_POST['up'] as $nodeOrder => $garbage) {
				$this->changeNodeOrder($nodeOrder, 'up');
			}
		}

		if(isset($_POST['down'])) {
			// This is not really a loop as there is only one
			// element in the array
			foreach ($_POST['down'] as $nodeOrder => $garbage) {
				$this->changeNodeOrder($nodeOrder, 'down');
			}
		}

		return $status;
	}


	/***********************************************************************************
	 *
	 * Template/Display related Methods
	 *
	 **********************************************************************************/

	/*
	 *
	 * Function: getMainNavigation()
	 *
	 * Creates and returns the main navigation bar for the site
	 *
	 * @access public
	 * @return HTML formatted navigation bar
	 *
	 */
	function getMainNavigation()
	{
		//d('RoomId: ' . $this->roomId . ': Cln_Room getMainNavigation');
		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		// this is needed for IE to open the menus
		$mainNav  = "<!-- BEGIN MAIN NAVIGATION -->\n";
		$mainNav .= '<div id="dropDown">' . "\n";
		$mainNav .= ' <ul id="nav">' . "\n";


		// create 'Home' button
		$sql = sprintf('SELECT ko.koId, ko.modId, ko.title, ko.lang, node.nodeName
						FROM %s, %s AS node WHERE node.parentId = 0
						AND ko.koId = node.koId AND node.status = %d
						AND ko.status = node.status AND node.visible = 1 ORDER by ordering',
						KO_TABLE, ROOM_NODE_TABLE, $this->_super->currentPart['status']);

		$result = $db->query($sql);


		if (!PEAR::isError($result))	 {
			while($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
				$rootNodes[] = $row;
			}
			$rootNodes = $this->filterNodesForLang($rootNodes);
		}

		if(!empty($rootNodes[0])) {
			if ($GLOBALS['path'] == 'index.php') {
				$attributes = 'class="current"';
			}
			else {
				$attributes = '';
			}
		 	$mainNav .= '   <li ' . $attributes . ' id="homeLink"><a href="' . cleanURL($rootNodes[0]->nodeName) . '" >'.$rootNodes[0]->title."</a></li>\n";
		}

		// construct rest of menu
		$sql = sprintf('SELECT ko.koId, ko.modId, ko.title, ko.lang, node.nodeName
						FROM %s, %s AS node WHERE node.parentId = 1
						AND ko.koId = node.koId AND node.status = %d
						AND ko.status = node.status AND node.visible = 1 ORDER by ordering',
						KO_TABLE, ROOM_NODE_TABLE, $this->_super->currentPart['status']);

		$result = $db->query($sql);


		if (!PEAR::isError($result))	 {
			while($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
				// filter everything but rooms
				if($row->modId != 1) continue;
				$sql2 = sprintf('SELECT ko.koId, ko.title, ko.modId, ko.lang, node.nodeName
								FROM %s, %s AS node WHERE node.parentId = %d
								AND ko.koId = node.koId AND ko.status = %d
								AND ko.status = node.status AND node.visible = 1 ORDER by ordering',
								KO_TABLE, ROOM_NODE_TABLE, $row->koId, $this->_super->currentPart['status']);

				$result2 = $db->query($sql2);
				while($row2 = $result2->fetchRow(DB_FETCHMODE_OBJECT)) {
					// filter everything but rooms
					if(CLN_DROP_DOWN_MENU_HIDE_PAGES && $row2->modId != 1) continue;
					$row->childrenNodes[] = $row2;
				}
				$parentNodes[] = $row;
			}
		}

		if(!empty($parentNodes)) {
			// now filter by lang
			$parentNodes = $this->filterNodesForLang($parentNodes);
			for($i=0;$i<count($parentNodes);$i++) {
				if(isset($parentNodes[$i]->childrenNodes)) {
					$parentNodes[$i]->childrenNodes = $this->filterNodesForLang($parentNodes[$i]->childrenNodes);
				}
			}

			// now construct the menus
			foreach($parentNodes as $parentNode) {
				// display only rooms for top level
				if($parentNode->modId == 1) {
					if (strpos($GLOBALS['path'], $parentNode->nodeName) === 0) {
						$attributes = 'class="current"';
					}
					else {
						$attributes = '';
					}
					$mainNav .= '   <li ' . $attributes . '>';
					$mainNav .=	'<a href="' . cleanURL($parentNode->nodeName) . '/index.php">' . $parentNode->title . "</a>\n";

					if(defined('CLN_SHOW_DROP_DOWN_MENU') && CLN_SHOW_DROP_DOWN_MENU) {
						if(isset($parentNode->childrenNodes)) {
							$mainNav .=	"    <ul>\n";
							foreach($parentNode->childrenNodes as $childNode) {
								$mainNav .= '      <li>';
								// i've left the check for .php, in case we allow pages to be shown in the main nav - dwc
								if(substr($childNode->nodeName,-4) != '.php' && substr($childNode->nodeName,-1) != '/') {
									$childNode->nodeName .= '/';
								}
								$mainNav .= '<a href="' . cleanURL($parentNode->nodeName . '/' . $childNode->nodeName) . '">';
								$mainNav .= $childNode->title . "</a></li>\n";
							}
							$mainNav .= "    </ul>\n";
						}
					}

					$mainNav .= "   </li>\n";
				}
			}
		}

		$mainNav .= " </ul>\n";
		$mainNav .= "</div>\n";
		$mainNav .= "<!-- END MAIN NAVIGATION -->\n";

		return $mainNav;
	}


	/*
	 *
	 * Function:  getBreadcrumb()
	 *
	 * 		Adds a breadcrumb to this room
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getBreadcrumb()
	{
		//d('RoomId: ' . $this->roomId . ': Cln_Room getBreadcrumb');
		$nodePaths = split('/',dirname($GLOBALS['path']));

		$db = &Cln_Db::singleton(MAIN_CLN_DSN);

		// ignore final breadcrumb koId, since it is always a page
		array_pop($GLOBALS['breadcrumb']);

		if(count($GLOBALS['breadcrumb']) == 0) {
			$urlParts = array('<a href="'.CLN_BASE_URL.'">Home</a>');
		} else {
			$urlParts = array('<a href="'.CLN_BASE_URL.'">Home</a>');
			$status = $_SESSION['editMode'] == 'edit' ? 0 : 1;
			for($i=0;$i<count($GLOBALS['breadcrumb']);$i++) {
				$sql = sprintf('SELECT koId, title, lang FROM %s WHERE koId = %d
								AND status = %d',
								KO_TABLE, $GLOBALS['breadcrumb'][$i]['koId'], $status);

				$result = $db->query($sql);

				$nodes = array();

				if (!PEAR::isError($result))	 {
					while($row = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
						// ignore CLN_USERS_ROOM nodePoint, so it does not appear in breadcrumb
						if($GLOBALS['breadcrumb'][$i]['nodeName'] != CLN_USERS_ROOM) {
							$nodes[] = $row;
						}
					}
				}

				$nodes = $this->filterNodesForLang($nodes);

				if(isset($nodes[0])) {
					if(count($nodePaths) > 0) $tmpPath[] = array_shift($nodePaths);

					if($i+1 < count($GLOBALS['breadcrumb'])) {
						$urlParts[] = '<a href="' . cleanURL(join('/',$tmpPath)) . '/">'.$nodes[0]->title."</a>\n";
					} else {
						$urlParts[] = '<a class="lastBreadcrumb" href="' . cleanURL(join('/',$tmpPath)) . '/">'.$nodes[0]->title."</a>\n";
					}
				}
			}
		}

		return join(' &gt; ',$urlParts);
	}


	/*
	 *
	 * Function: getSideNavigation()
	 *
	 * Creates and returns the navigation bar that displays on the left
	 *
	 * @access public
	 * @return HTML formatted navigation bar
	 *
	 */
	function getSideNavigation()
	{
		// d('RoomId: ' . $this->roomId . ': Cln_Room getSideNavigation');

		// Preload some data
		$thisNodePath = getNodePath($this->_super->koId, TRUE);
		$childrenNodes = $this->getNodes(NULL, TRUE, TRUE);

		// Build the nav
		$navBar = "\n<!-- START SIDE NAVIGATION -->\n"
				 ."<div id=\"sideMenu\">\n <ul class=\"sideMenuNav\">\n";

		$navBar .= '  <li class="thisRoom">' . $this->_super->currentPart['title'] . "</li>\n";

		// :TODO: this does not address multiple languages yet.  the real plan is to create an admin module
		// which will enable us to make these pages using the system tools
		if(isset($GLOBALS['MYHOUSE']) && $GLOBALS['MYHOUSE'] && count($GLOBALS['breadcrumb']) == 3) {
			$myHouseNavigation = array(
				array(
					'koId' => 'PROFILE',
					'modId' => '2',
					'title' => array('My Profile'),
					'url' => appendToURL(cleanURL('MyHouse/index.php'), 'userProcess=myProfile')
				),
				array(
					'koId' => 'SHORTCUTS',
					'modId' => '2',
					'title' => array('My Shortcuts'),
					'url' => appendToURL(cleanURL('MyHouse/index.php'), 'userProcess=myShortcuts')

				)
			);

			// Get all the modules that have a virtual locker component, and get that component from them
			$sql = sprintf('SELECT class, path FROM `%s`
							WHERE hasMyHousePart = 1',
							MODULE_TABLE);
			$result = &Cln_Db::singleton(MAIN_CLN_DSN, $sql);

			if (!PEAR::isError($result))	 {
				while($moduleInfo = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
					$className = $moduleInfo->class;
					include_once($moduleInfo->path);
					$myHouseNavigation[] = call_user_func(array($className, 'getMyHouseNavItem'));
				}
			}

			// set active page
			foreach($myHouseNavigation as $myHouseNodes) {
				if(str_replace('&AMP;', '&', strtoupper($myHouseNodes['url'])) == strtoupper('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'])) {
					$thisPageKoId = $myHouseNodes['koId'];
				}
			}

			$childrenNodes = array_merge($childrenNodes,$myHouseNavigation);
		}

		if(!isset($thisPageKoId)) {
			$thisPageKoId = $_SESSION['Page']->koId;
		}

		if(isset($childrenNodes) && is_array($childrenNodes)) {
			foreach ($childrenNodes as $nodeOrder => $node) {
				$navBar .= '   <li class="';

				// If it's the page we're currently on
				if($node['koId'] == $thisPageKoId) {
					$navBar .=  'thisPage">'.$node['title'][0] . '</li>' . "\n";
				}

				// Else it's another page
				else {
					if($node['modId'] == 1) {
						$navBar .= 'roomLink';
					}
					else {
						$navBar .= 'pageLink';
					}

					if(!isset($node['url'])) {
						// Build the link
						if(!empty($thisNodePath)) {
							$nodePath = $thisNodePath.'/'.$node['nodeName'];
						}
						else {
							$nodePath = $node['nodeName'];
						}

						if($node['modId'] == 1) {
							$nodePath .= '/';
						}
						$node['url'] = cleanURL($nodePath);
					}

					$navBar .=  '"><a href="' . $node['url'] . '">';
					$navBar .=  $node['title'][0] . '</a></li>' . "\n";
				}
			}
		}

		$navBar .= "  </ul>\n</div>\n"
				  ."<!-- END SIDE NAVIGATION -->\n";

		return $navBar;
	}


	/*
	 *
	 * Function: loadHeader()
	 *
	 * Returns the stylesheets HTML code that is needed.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function loadHeader() {
		// Set up Header here, so that it can be used by modules like Newsletter
		$GLOBALS['CLN_HEADER'] = '<link rel="stylesheet" href="' . CLN_CLEAN_URL_BASE . 'styles/master.css" type="text/css" />' . "\n";
		$GLOBALS['CLN_HEADER'] .= '<script type="text/javascript" src="' . CLN_CLEAN_URL_BASE . 'lib/CLN/general.js"></script>' . "\n";

		// CODE HERE TO LOAD IN VARIOUS NAVIGATION JAVSCRIPTS BASED ON CONFIG CONSTANT SETTINGS
		if(defined('CLN_SHOW_DROP_DOWN_MENU') && CLN_SHOW_DROP_DOWN_MENU) {
			$GLOBALS['CLN_HEADER'] .= '<script src="' . CLN_CLEAN_URL_BASE . 'lib/CLN/interfaces/Room/mainNavigation.js" language="javascript"';
			$GLOBALS['CLN_HEADER'] .= 'type="text/javascript"></script>' . "\n";
		}

		$GLOBALS['CLN_HEADER'] .= $this->loadStyleSheets();
		$GLOBALS['CLN_HEADER'] .= '<link rel="stylesheet" href="' . CLN_CLEAN_URL_BASE . 'styles/print.css" type="text/css" media="print" />' . "\n";
	
		return $GLOBALS['CLN_HEADER'];
	}


	/*
	 *
	 * Function: loadStylesheets()
	 *
	 * Returns the stylesheets HTML code that is needed.
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function loadStylesheets() {
		//d('RoomId: ' . $this->roomId . ': Cln_Room loadStylesheets');
		
		$otherStyles = '';
		if(isset($GLOBALS['Stylesheets'])) {
			foreach($GLOBALS['Stylesheets'] as $stylesheet) {
				$href = $stylesheet['href'];
				$rel = $stylesheet['rel'];
				$media = $stylesheet['media'];
				$type = $stylesheet['type'];
				if(!isset($existingStyle[$href])) {
					$otherStyles .= ' <link rel="'.$rel.'" href="'.$href.'" media="'.$media.'" type="'.$type.'" />'."\n"; 
					$existingStyle[$href] = TRUE;
				}
			}
		}
		
		$mainStylesheet = '';
		$alternateStylesheet  = '';
		$templatePath = CLN_CLEAN_URL_BASE . 'template/' . $this->template . '/';

		foreach ($GLOBALS['CLN_TEMPLATES'][$this->template]['StyleSheets'] as $stylesheet => $name) {
			if($stylesheet == $this->stylesheet) {
				$mainStylesheet = ' <link rel="stylesheet"  href="' . $templatePath . 'styles/' . $stylesheet . '.css" type="text/css" media="screen" />'."\n";
			} else {
				$alternateStylesheet .= ' <link rel="alternative stylesheet" title="'.$name.'" href="' . $templatePath . 'styles/' . $stylesheet . '.css'.'" type="text/css" />'."\n";
			}
		}
		
		$allStylesheets = $otherStyles.$mainStylesheet.$alternateStylesheet;
		
		return $allStylesheets;
	}


	/***********************************************************************************
	 *
	 * Miscellaneous Methods
	 *
	 **********************************************************************************/


	/*
	 *
	 * Function: setOtherLooksInMemory()
	 *
	 * Makes an attempt to cycle through the other looks in memory that are the same, and updates their looks
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function setOtherLooksInMemory()
	{
		d('RoomId: ' . $this->roomId . ': Cln_Room setOtherLooksInMemory');
		$currentStatus = $this->_super->currentPart['status'];

		if (isset($this->_super->parts) ) {
			foreach ($this->_super->parts as $key => $part) {
				if ($part['status'] == $currentStatus) {
					if ($part['objectId'] != $this->roomId && is_object($part['object'])) {
						$otherObjectId = $part['objectId'];
						$this->_super->parts[$otherObjectId]['object']->template = $this->template;
						$this->_super->parts[$otherObjectId]['object']->stylesheet = $this->stylesheet;
					}
				}
			}
		}
	}


	/*
	 *
	 * Function:  validateDetails()
	 *
	 * 		Validates the details data and returns FALSE with errors, or TRUE
	 *
	 * @access public
	 * @return Boolean 		TRUE or FALSE
	 *
	 */
	function validateDetails()
	{
		return TRUE; // :ONEDAY: Any validation required?
	}


	/*
	 *
	 * Function:  getEditPanelGeneral()
	 *
	 * 		Returns the general edit panel components
	 *
	 * @access public
	 * @return String 		$message
	 *
	 */
	function getEditPanelGeneral()
	{
		$generalParts[0]['title'] = 'Edit Navigation';
		$generalParts[0]['description'] = 'Edit the navigation--changing the order of the navigation bar on the left side, and renaming files if needed';
		$generalParts[0]['subprocess'] = 'EditNavigation';

		$generalParts[1]['title'] = 'Add a Sub-room';
		$generalParts[1]['description'] = 'Add a room inside this room';
		$generalParts[1]['subprocess'] = 'AddSubRoom';
		$generalParts[1]['requiresSaving'] = TRUE;

		$generalParts[2]['title'] = 'Add a Page';
		$generalParts[2]['description'] = 'Add a page to this room';
		$generalParts[2]['subprocess'] = 'AddPage';
		$generalParts[2]['requiresSaving'] = TRUE;

		$generalParts[3]['title'] = 'Delete a Sub-room';
		$generalParts[3]['description'] = 'Delete a room that is inside this room';
		$generalParts[3]['subprocess'] = 'DeleteSubRoom';
		$generalParts[3]['requiresSaving'] = TRUE;

		$generalParts[4]['title'] = 'Delete a Page';
		$generalParts[4]['description'] = 'Delete a page from this room';
		$generalParts[4]['subprocess'] = 'DeletePage';
		$generalParts[4]['requiresSaving'] = TRUE;

		return $generalParts;
	}


	/*
	 *
	 * Function:  getEditPanelLanguages()
	 *
	 * 		Returns the language specific edit panel components
	 *
	 * @access public
	 * @return String 		$message
	 *
	 */
	function getEditPanelLanguages()
	{
		$specificParts[0]['title'] = 'Edit Details';
		$specificParts[0]['description'] = 'Edit the title, the templates, etc.';
		$specificParts[0]['subprocess'] = 'EditDetails';

		return $specificParts;
	}


	/*
	 *
	 * Function:  getInterface()
	 *
	 * 		Returns the edit form for this module
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getInterface($formName)
	{
		ob_start();
		include('lib/CLN/interfaces/Room/' . $formName . '.html');
		$form = ob_get_contents();
		ob_end_clean();
		return $form;
	}


	/*
	 *
	 * Function:  getBrowseEdit()
	 *
	 * 		Returns the browse/edit buttons
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getBrowseEdit()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			if ($_SESSION['editMode'] == 'browse')  {
				$form = $this->getInterface('BrowseModeButton');
			}
			else if ($_SESSION['editMode'] == 'edit') {
				$form = $this->getInterface('EditModeButton');
			}
		}
		else {
			$form = '';
		}

		return $form;
	}


	/*
	 *
	 * Function:  getLoginForm()
	 *
	 * 		Returns the login form
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getLoginForm()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			$form = '';
		}
		else {
			$form = $this->getInterface('LoginForm');
		}

		return $form;
	}


	/*
	 *
	 * Function:  getLogoutButton()
	 *
	 * 		Returns the logout form
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getLogoutButton()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			$form = $this->getInterface('LogoutButton');
		}
		else {
			$form = '';
		}

		return $form;
	}


	/*
	 *
	 * Function:  getMyHouseButton()
	 *
	 * 		Returns the user's My House link
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getMyHouseButton()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			$form = $this->getInterface('MyHouseButton');
		}
		else {
			$form = '';
		}

		return $form;
	}


	/*
	 *
	 * Function:  getJoinButton()
	 *
	 * 		Returns the join the system button
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getJoinButton()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			$form = '';
		}
		else {
			$form = $this->getInterface('JoinButton');
		}

		return $form;
	}


	/*
	 *
	 * Function:  getNewPasswordButton()
	 *
	 * 		Returns the new password button
	 *
	 * @access public
	 * @return TBD
	 *
	 */
	function getNewPasswordButton()
	{
		if ($_SESSION['User']->isLoggedIn()) {
			$form = '';
		}
		else {
			$form = $this->getInterface('NewPasswordButton');
		}

		return $form;
	}


} // END Class Cln_Room

?>
Return current item: Community Learning Network