MyConference Developer's Guide

This document aims for giving MyConference's developers an overview on the system architecture in order to ease development works.

* This is a very rough guide. Information within this guide are for illustration purpose only and some code examples may need to be modified for correct execution due to system version changes.

System Architecture

We use a framework based approach to develop our system. In this framework, components are divided our system into four categories. The first one is the Utility Classes. It is responsible for handling low level common routines like database query, access control, data input/output, HTML generation and XML processing. The next one is the Modules. They are built on top of the Utility Classes that perform the high level functions like user registration, paper submission and paper review. The third is the Presentation components. They act as the front end to interact with the user. Styling and layout information are managed by these components. The last one is the Configuration components. They are not program codes. They are mainly system configuration files that are in the form of XML.

During system installation, the utility class and the configuration file will be used to initialize the environment. Once users enter the system, they will first encounter the presentation components. Upon user requests, the presentation components dynamically load the corresponding modules to do some processing. The modules make use of the utility classes to perform the requested operation and return the result back to the presentation components. The presentation components finally, base on the styling and structural information, render the result back to the browser.

High Level System Flow

There are three main types of processing flow in the system, namely, Login, Module Invocation and Logout.

I - Login

Login is the process of user authentication. The system will check for the eligibility of the user to access the system. Whenever a user wants to access the system, he/she should go to the login.php of the system. The page will prompt for login name and password for the user to login. Once the user finishes entering the login information and clicks the login button, he/she will be directed to index.php. The details of the index.php will be discussed below.

II - Module Invocation

This is the major part of the system that a user will be using. User will be accessing all the modules through index.php. The flow of the index.php is mainly divided into three parts.

  • User Authentication

The index.php will first get an instance of the AccessController object and call the authenticate() method of it. The method checks for the login status of the current user. If the user have not logged in, it checks if the user have entered the correct login information. If correct login information is provided, it stores them in the php’s session variables, otherwise, it forces the user back to login.php.

  • Module Accessibility Check

After the authenticate() method successfully returns, the index.php will then instantiate a new ContentGenerator. The ContentGenerator object gathers the current invoking module’s information from HTTP GET/POST variables and checks for the eligibility of the user to access the current module. It prompts for access denied if the access is not granted according to the access configuration file.

  • Actual Request Handling

index.php will then trigger the request processing routine by invoking getMainMeun(), getModuleActionMenu(), getHeaderContent(), getMainContent() and getFooterContent() method of the ContentGenerator. The ContentGenerator calls the factory method of the Module class to get the current module object. It invokes the module objects to handle the user’s request. Finally the result will be returned back to the index.php for display.

III - Logout

Logout is the process which the user tells the system that he/she is leaving. In this process, the user will be directed to the logout.php. The logout.php gets an instance of the AccessController and call the logout() method of it. The logout() method destroy the session data and so the user will no longer marked as logged in. Any further module request will be forbidden automatically.

Component Details

XML Configuration Framework

XML Configuration Framework is a solution to manage complicated setting for a system. For examples and descriptions about MyConference's XML Configuration Framework, click Here.

Presentation Components

Presentation components stores style and structural information of the system.

Points to note:

  • The first line should be a line to tell the relative path of CseLib.php with respect to the current presentation component file (e.g. index.php):
    • $GLOBALS[“BasePath”] = “includes/”;
  • The following lines should be used to include CseLib.php, AccessController and ContentGenerator:
    require_once("includes/cseLib.php"); 
    CseLib::requirePageOnce(CseLib::getVar("AccessController"));
    CseLib::requirePageOnce(CseLib::getVar("ContentGenerator"));
  • Read the following examples and I am sure that you can get the rest.

login.php (Sample)

login.php is used to get username and password from external users.

  <?php
  $GLOBALS["BasePath"] = "includes/";
  
  require_once("includes/cseLib.php");
  $conf = CseLib::getConferenceInformation();
  ?>
  <html>
  <head>
  <title><?php echo $conf->getParam("name");?></title>
  </head>
  <body>
  <form action="index.php" method=POST>
  <center>
  <table>
  <tr><th><?php echo $conf->getParam("name");?> Login</th></tr>
  <tr><td>Username: <input type=text name=loginname size=20 value="ktchana@gmail.com"></td></tr>
  <tr><td>Password: <input type=password name=loginpassword size=20></td></tr>
  <tr><td><center><input type=submit value="Login"></center></td></tr>
  <tr><td><center><a href="userRegistration.php">Not yet registered? Register now!</a></center></td></tr>
  </table>
  </center>
  </form>
  </form>
  </body>
  </html>

index.php (Sample)

index.php is the core part of the presentation component. It will do the followings:

  • check user's login status (via AccessController::authenticate()).
  • create a new instance of ContentGenerator
  • get a list of user accessible module names to generate a main menu
  • trigger the request handling routine by calling
    1. ContentGenreator::getHeaderContent()
    2. ContentGenerator::getMainContent()
    3. ContentGenreator::getFooterContent()
  <?php
  
  $GLOBALS["BasePath"] = "includes/";
  
  require_once("includes/cseLib.php");
  CseLib::requirePageOnce(CseLib::getVar("AccessController"));
  CseLib::requirePageOnce(CseLib::getVar("ContentGenerator"));
  
  $accessController = AccessController::getAccessController();
  $accessController->authenticate();
  
  $cg = new ContentGenerator();
  $conf = CseLib::getConferenceInformation();
  $conferenceName = $conf->getParam("name");
  ?>
  <html>
  	<head>
  		<title><?php echo $conferenceName;?></title>
  		<?php echo CseLib::loadGlobalStyleSheet();?>
  		<?php
  		echo $cg->getHeaderContent();
  		?>
  	</head>
  	<body>
  		<center>
  			<table width=780 class=MainTable border=0>
  				<tr><td class=MainTableHeader align=left>
  					<center><img src="logo.jpg"></center><br>
  					<font size=2 color=#556677><b><?php echo $cg->getUserWelcomeMessage();?></b></font>
  				</td></tr>
  
  				</tr><td class=MainTableMainMenu align=center>
  					<?php
  					echo $cg->getMainMenu();
  					?>
  				</td></tr>
  
  				</tr><td class=MainTableModuleActionMenu align=center>
  					<?php
  					echo $cg->getModuleActionMenu();
  					?>
  				</td></tr>
  
  				</tr><td class=MainTableMainContent align=center>
  					<?php
  					echo $cg->getMainContent();
  					?>
  				</td></tr>
  
  				<tr><td class=MainTableFooterContent align=center>
  					<?php
  					echo $cg->getFooterContent();
  					?>
  	    			</td></tr>
  			</table>
  		</center>
  	</body>
  </html>

outside.php (Sample)

The purpose of outside.php is similar to index.php except that it is used to trigger functions that do not require user logon (e.g. user registration).

  <?php
  
  $GLOBALS["BasePath"] = "includes/";
  
  require_once("includes/cseLib.php");
  CseLib::requirePageOnce(CseLib::getVar("AccessController"));
  CseLib::requirePageOnce(CseLib::getVar("ContentGenerator"));
  
  $accessController = AccessController::getAccessController();
  $accessController->loginless();
  
  $cg = new ContentGenerator();
  $conf = CseLib::getConferenceInformation();
  $conferenceName = $conf->getParam("name");
  ?>
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <!-- DW6 -->
  <head>
  <!-- Copyright 2005 Macromedia, Inc. All rights reserved. -->
  <title><?php echo $conferenceName." - ".$cg->getModuleName();?></title>
  <link rel="stylesheet" href="emx_nav_glay.css" type="text/css" />
  
  
  <?php echo CseLib::loadGlobalStyleSheet();?>
  <?php
  echo $cg->getHeaderContent();
  ?>
  
  
  <style type="text/css">
  <!--
  .style1 {
  	color: #4C4C4C;
  	font-style: italic;
  }
  .style13 {color: #2E75D9}
  -->
  </style>
  
  </head>
  <body>
  
  <table width=100% align=center valign=top><tr><td>
  <center>
  <!--<body onmousemove="closesubnav(event);">
  <div class="skipLinks">skip to: <a href="#content">page content</a> | <a href="#pageNav">links on this page</a> | <a href="#globalNav">site navigation</a> | <a href="#siteInfo">footer (site information)</a> </div>-->
  
  <div id="masthead"> 
    <h1 class="style1" id="siteName" align="center"> ICONIP 2007 14th International Conference on Neural Information Processing</h1>
    
  	<div id="breadCrumb">
  	<embed src="iconip_banner.swf" width="845" height="125"></embed>
  	   <!-- <img src="iconip_head.jpg" width="845" height="135">-->
      <h1 class="style1">&nbsp;</h1>
  
       <h1 class="style1" align="center">Towards an Integrated Approach to the Brain &mdash; Brain-Inspired Engineering and Brain Science &mdash;</h1>
  
    	 <h1 class="style1" align="center">13-16 November, 2007, Kitakyushu, Japan</h1>
  	</div>
  
  </div>
  <!-- end masthead -->
  <div id="pagecell1">
    <!--pagecell1-->
  
    <div id="breadCrumb"> <a href="#"></a></div>
    <div id="pageNav">
  
  	<div id="sectionLinks"><a href="#"></a><a href="<?php echo CseLib::getVar("LoginPage");?>">Main Page</a><a href="#"></a></div>    
  
      <div class="relatedLinks">
        <h3>&nbsp;</h3>
      </div>
  
      <div id="advert"> <img src="iconip02.jpg" alt="KIT" width="140" height="100" />  </div>
      <div id="advert"></div>
  
    </div>
    
    <div id="content">
      <div class="feature">
        
  		<?php
  			/**************************************************************************************************************/
  			echo $cg->getModuleActionMenu();
  			echo "<br>";
  			echo $cg->getMainContent();
  			/**************************************************************************************************************/
  		?> 
    </div>
   
  <div id="siteInfo"><a href="mailto:secretary-ICONIP@brain.kyutech.ac.jp"> Contact Us</a> | &copy;2007 ICONIP 2007 Commities All Rights Reserved. </div>
  
  
  </div>
  <!--end pagecell1-->
  <br />
  
  
  
  <br>
  <?php
  	echo $cg->getFooterContent();
  ?>
  <br>
  
  </center>
  </td></tr></table>
  </body>
  </html>

paperDownload.php (Sample)

paperDownload.php do exactly the same as index.php except that it do not include style and structural information (i.e. HTML codes). It is used by functions that allow user to download files. Please make sure that no additional “Enters” (i.e. CR, LF) are inserted before and after <?php …. ?>. Otherwise, files downloaded by users will be incorrect.

  <?php
  
  $GLOBALS["BasePath"] = "includes/";
  
  require_once("includes/cseLib.php");
  CseLib::requirePageOnce(CseLib::getVar("AccessController"));
  CseLib::requirePageOnce(CseLib::getVar("ContentGenerator"));
  
  $accessController = AccessController::getAccessController();
  $accessController->authenticate();
  
  $cg = new ContentGenerator();
  $cg->getMainContent();
  ?>

Utility Classes

Utility Classes are the classes which encapsulate the low level operations of the system. They generally provide services that other components of the system will make use of.

In general, all utility classes are itself base classes with the exception of XMLObjects and XMLParser. We will focus on the class hierarchy of these two special classes in the following passage.

XML Objects

XMLObjects are used to represent the information given by an XML configuration file. It generalizes all the methods that other components will be using.

Here is the interface of an XMLObject:

  class XMLObject {
  	// set the type of an object in string
  	protected function setObjectType($type);
  
  	// return the object type in string
  	public function getObjectType();
  
  	// set the parameter $name = $value
  	public function setParam($name, $value);
  
  	// get the parameter named $name
  	public function getParam($name);
  
  	// return all parameters of the object
  	public function getAllParams();
  
  	// add a sub-element under this XMLObject
  	public function addElement(XMLObject $element);
  
  	// return a sub-element object with the $paramName = $value
  	public function getElementByParam($paramName, $value);
  
  	// return a sub-element with db_name = $dbname
  	public function getElementByDBName($dbname);
  
  	// return all the sub-elements
  	public function getElementList();
  
  	// clone the object
  	public function cloneObject();
  
  	// print all the parameters’ name and value
  	public function printAllParams();
  }

There are a lot of classes that directly inherit from XMLObject. Examples of them are EntityObject, FieldObject, MemberObject, DisplayObject, StyleObject, GroupObject, DataObject, ModuleObject, ConferenceObject and AccessRuleObject. They are responsible for different parts of the XML configuration module.

Let consider the first one, EntityObject. For the entity User, we may have the follow attributes:

Attribute (db_name)Type
reg_emailEmail
pwdPassword
firstnameString
lastnameString
area_of_interestSelect
countryDropDownMenu

After parsing the XML file, a new EntityObject (which is a subclass of XMLObject) will be created. It stores all the attributes in the form of FieldObjects. Each type of attribute will have a corresponding sub-class of FieldObject to store its information.

To be more concrete, let’s take the above User entity as an example. The objects created after parsing the entity configuration file are:

  EntityObject (sub-class of XMLObject)
  It contains the sub-elements:
  	EmailObject (sub-class of XMLObject)
  	PasswordObject (sub-class of XMLObject)
  	StringObject (sub-class of XMLObject)
  	StringObject (sub-class of XMLObject)
  	SelectObject (sub-class of XMLObject)
  	DropDownMenu (sub-class of XMLObject)

FieldObjects are the objects that responsible for managing the input, output, database interaction and HTML generation of an attribute. Each type of entity attribute corresponds to exactly one sub-class of FieldObject. All the classes under FieldObject will expose the same interface. Different type of FieldObject will react differently upon calling.

For example, an EmailObject may return the following with the getDisplayHTML() function call:

  <input type=text name='reg_email' maxlength='100' size='50' value='ktchana@gmail.com'>

However, calling the same function on a PasswordObject may have the following thing returned:

  <input type=password name='userpwd' maxlength='20' size='50' value=’’>

In this way, but the outside caller doesn’t need to care about which type of attribute it is as long as the object expose the same interface.

XML Parser

XMLParser is the base class of all different type of XML parsers. It provides some base implementation for parsing XML configuration files. However, different types of XML configuration file have to be parsed different and so each specific parser extends the base XMLParser class and override the methods that are needed to handle the differences.

Modules

We have written an abstract class Module that defined all the operations that a module has to implement. The interface of the Module class is:

  <?php
  
  /* Base class of all modules */
  abstract class module {
  	var $action;
  	
  	public static function getModule($moduleName) {
  		require_once("$moduleName.php");
  		return new $moduleName();
  	}
  
  	public function module() {
  	}
  
  	// called when installing the system, only once.
  	public function install();
  
  	public abstract function getModuleName();
  
  	public function getModuleActionList();
  
  	public function setModuleAction($maction);
  
  	public function getHeaderContent();
  
  	public function getMainContent();
  
  	public function getFooterContent();
  }
  
  ?>

Every module in the system must inherit from the Module class. Module::getModule() is very special method that acts as an object factory for the content generator to call in order to dynamically instantiate the module for processing. Under this hierarchy, the content generator only needs to gather the module information from the request and instantiate the corresponding one through this abstract method. It does not need to care about the actual module being loaded. This polymorphic behaviour allows us create new modules easily with minimal affections to the existing system codes. One example is that user can add new module to the system and register the module in the Module XML. The system will automatically know how to make use of the module and include it as part of the system.

Examples

New Module Development

The following example assume that you want to write a new module called “dataClustering”.

Steps to create a new module:

  • add a line in /cfg/module.xml, ordering does matter. It will affect the order of appearance of a module in the system menu.
  <module>dataClustering</module>
  • create a new file named “dataClustering.php”. Filename must be the same as the name written in module.xml. Start to write that module from the skeleton below (make sure the class name is the same as the filename [dataClustering]):
  <?php
  
  require_once("module.php");
  
  class dataClustering extends module {
  	public function getModuleName() {
  		return "";
  	}
  
  	public function getModuleActionList() {
  		// return an array of action and the corresponding display name for module action menu display
  		return array("dataclustering" => "Cluster Data!", "viewresult" => "View Clustering Result");
  	}
  
  	public function getHeaderContent() {
  		// type the code that you want to show in between the <head>..</head> region of a page
  	}
  
  	public function getMainContent() {
  		// type the code that you want to show in the main region of a page
  	}
  
  	public function getFooterContent() {
  		// type the code that you want to show at the bottom of a page
  	}
  }
  
  ?>
  • in order to make codes of MyConference align to the same standard, we recommend you to write getMainContent() in the following way:
  	public function getMainContent() {
  		$ret = "";
  		switch (strtolower($this->action)) {
  			case "dataclustering":
  				$ret = $this->dataClusteringAction();
  				break;
  			
  			case "viewresult":
  				$ret = $this->viewResultAction();
  				break;
  
  			case "confirminput":
  				$ret = $this->confirmInputAction();
  				break;
  
  			default:
  				$ret = $this->dataClusteringAction();
  				break;
  		}
  
  		return $ret;
  	}
  
  	private function dataClusteringAction() {
  		// type the code to handle request here, return anything that you want to display back to the user
  	}
  
  	private function viewResultAction() {
  		// type the code to handle request here, return anything that you want to display back to the user
  	}
  
  	private function confirmInputAction() {
  		// type the code to handle request here, return anything that you want to display back to the user
  	}
  
  • the next thing to do is to update access rules (/cfg/accessRules???.xml) for each phase so that you can control the usergroups (or particular users) to access the system in a particular conference phase.
  <module name="dataClustering" groups="USER-GROUPS" users="USERS">
  	<action name="dataclustering" groups="USER-GROUPS" users="USERS" />
  	<action name="viewresult" groups="" users="" loginless="true" />
  	<action name="confirminput" groups="USER-GROUPS" users="USERS"/>
  </module>
  
  USER-GROUPS - a list of user groups allowed to access this module (or action of a module), separated by ';'
  USERS - a list of user email allowed to access this module (or action of a module), separated by ';'
  loginless="true" - adding this attribute indicate this module (or action of a module) is accessible without login (via outside.php)

Using XML Framework to handle HTML Form Input/Output and Database Manipulation

This section will only talk about the sample usage of MyConference's XML Configuration Framework. See XML Configuration Module for detailed explanation for the XML file's schematic.

Getting input from users

Suppose we want to generate a form for user to input and send email:

  private function generateEmailSendingFormAction() {
  	$ret = "";
  
  	// get entity and display object for "Email"
  	// you have to create and register these 2 xml files in CseLib.php
  	// CseLib::setVar("EmailEntityXML", $basedir."$cfgDir/email.xml");
  	// CseLib::setVar("EmailDisplayXML", $basedir."$cfgDir/emailDisplay.xml");
  	$entity = CseLib::getEntityObject("Email");
  	$display = CseLib::getDisplayObject("Email");
  
  	// Get the current user's email address
  	$ac = AccessController::getAccessController();
  	$email = $ac->getUserInformation()->getElementByDBName("reg_email")->getValue();
  
  	// Set the email's "from address" to the current user's email address
  	// so that the generated HTML form will have a 
  	// default value of this user's email address
  	$entity->getElementByDBName("emailfrom")->setValue($email);
  
  	// Create a new FormGenerator
  	// (remember to include FormGenerator using CseLib::requirePageOnce()
  	$fg = new FormGenerator($entity, $display);
  
  	// set up optional parameters
  	$fg->setFormAction("index.php");
  	$fg->addHiddenField("moduleAction", "send");
  	$fg->addHiddenField("page", "email");
  	$fg->showFullForm(true);
  
  	// After setting up all the parameters needed, 
  	// you can obtain the HTML form by calling FormGenerator::genInputForm()
  	$ret .= $fg->genInputForm();
  
  	// return the code for display
  	return $ret;
  }

Database manipulation

Create database table for a particular entity (e.g. user)
  // get a database connection (see CseLib.php and
  // the utility class DatabaseConnector for details)
  $dbc = CseLib::getDatabaseConnection();
  
  // Get "User" entity object
  $userEntities = CseLib::getEntityObject("user");
  
  // Create a new QueryGenerator for the "User" entity
  $qg = new QueryGenerator($userEntities);
  
  // Generate create "User" entity table SQL
  $sql = $qg->genCreateTableSQL();
  
  // Execute the sql
  $r = $dbc->executeSQL($sql);
  
  // Check if it executed successfully
  if ($r->isQuerySuccessful()) {
  
  }
Insert a new record to a table (e.g. User)
  // Create a new RequestProcessor for "User" entity's record insertion
  // ("Delete" for deletion, "Modify" for modification)
  $rp = RequestProcessor::getRequestProcessor("User", "Insert");
  
  // Assume that you get the information from $_POST (HTTP POST request)
  $rp->setValueFromArray($_POST);
  
  // insert the record
  $r = $rp->processRequest();
  
  // Check if it executed successfully
  if ($r->isQuerySuccessful()) {
  
  }

References

 
fyp/ik0602/developer_guide.txt · Last modified: 2007/04/16 00:05 (external edit)     Back to top