====== 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 ===== {{fyp:ik0602:system_architecture.jpg|}} 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. {{fyp:ik0602:moduleflow.jpg|}} === 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 [[fyp:ik0602:7.xml_configuration_tools|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 echo $conf->getParam("name");?>
getParam("name");?> Login
Username:
Password:
Not yet registered? Register now!
=== 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 - ContentGenreator::getHeaderContent() - ContentGenerator::getMainContent() - ContentGenreator::getFooterContent() authenticate(); $cg = new ContentGenerator(); $conf = CseLib::getConferenceInformation(); $conferenceName = $conf->getParam("name"); ?> <?php echo $conferenceName;?> getHeaderContent(); ?>

getUserWelcomeMessage();?>
getMainMenu(); ?>
getModuleActionMenu(); ?>
getMainContent(); ?>
getFooterContent(); ?>
=== 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). loginless(); $cg = new ContentGenerator(); $conf = CseLib::getConferenceInformation(); $conferenceName = $conf->getParam("name"); ?> <?php echo $conferenceName." - ".$cg->getModuleName();?> getHeaderContent(); ?>

ICONIP 2007 14th International Conference on Neural Information Processing

getModuleActionMenu(); echo "
"; echo $cg->getMainContent(); /**************************************************************************************************************/ ?>
Contact Us | ©2007 ICONIP 2007 Commities All Rights Reserved.


getFooterContent(); ?>
=== 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 . Otherwise, files downloaded by users will be incorrect. 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_email|Email| |pwd|Password| |firstname|String| |lastname|String| |area_of_interest|Select| |country|DropDownMenu| 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: However, calling the same function on a PasswordObject may have the following thing returned: 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: 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. dataClustering * 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]): "Cluster Data!", "viewresult" => "View Clustering Result"); } public function getHeaderContent() { // type the code that you want to show in between the .. 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. 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 [[fyp:ik0602:7.xml_configuration_tools|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:4.reference_resources|References]]