Set up a module in Sahana

Contents

Introduction

Using the following steps, you will be able to set up a new module in Sahana. This module in particular will show you how to create forms in Sahana as well as do some basic database querying. The main purpose of the module created herein is to allow the display of different greetings different languages.

Overview of Sahana Modules

Sahana is a modular and extensible system. Different software components, or modules, each reside in their own folder in the mod/ directory. Each module has a "short name", which is the name of the module's folder, and is used to refer to the module in code. For example, the Volunteer Management module's short name is "vm". Sahana comes with many modules pre-installed. You can see this by looking at the contents of the mod/ folder of a fresh install.

$ ls mod
cms    cs   gis    hr    mpr  or    rms   skel  vm
admin  cr   dvr    home  ims  msg   pref  rs    sync  vol

The skel module is the "skeleton module", a simple module that serves as an example and a framework to module developers. It contains code to display a simple message, populate Sahana's menu navigation system, and display an HTML form with various types of inputs. The skeleton module is a good place to start when creating a new module.

Within the skeleton module there are 3 files:

$ ls mod/skel
admin.inc   conf.inc   main.inc

When Sahana loads a module, it looks for the main.inc file in the module's folder. The admin.inc and conf.inc files store administration and configuration info about the module. It's not strictly necessary to have these files, but it's a good convention.

The bulk of the skeleton module is contained in main.inc. This file contains several functions:

shn_skel_mainmenu()
shn_skel_default()
shn_skel_mio()
shn_skel_mit()
shn_skel_report()
shn_skel_form()

The naming convention in Sahana is to name functions with shn_{module name}_{function name}(). This is to prevent colliding function names for different modules, as they share the same namespace.

The shn_skel_mainmenu() and shn_skel_default functions are special. The mainmenu() function is called by Sahana to populate the navigation menu on the left side of the page, and the default() function is the function that gets called when a module is first loaded.

The other functions are used by the skeleton module to demonstrate menus and forms. shn_skel_form() uses Sahana's built-in form generating functions to create a form with several input types.

We can use the examples in the skeleton module to create our own hello module.

Create the Necessary Database Tables with phpMyAdmin

First launch phpMyAdmin and log in with you username and password to view a list of database tables. Select the database that has been created already with Sahana Installation or create a new one on phpMyAdmin with two database tables called 'hello_greeting' and 'hello_language'. This can be done by scrolling down to the end of the page and typing in the name of the tables and the number of fields they would have in the given form fields. The 'hello_greeting' table should contain two attribues, namely 'id' and 'name'. In this case, for example, the name of the table could be 'hello greeting' and the number of fields could be 2 referring to the 'id' and 'name' attributes. The 'id' is the primary key and is a unique three letter abbreviation for the name of the language to be dealt with. Once the table is created, the name for the fields and the data type that would be stored in these fields should be input. So 'id' would be CHAR and 'name' would be VARCHAR. PhpMyAdmin also has a form field where you can specify the maximum length of the data to be input. The length for 'id' input can be 2 characters while 'name' can be as long as 30. Once the setup is done, you can use the edit button to input values for the 'id' and the 'name'.

The other table 'hello_greeting' should have three attributes - 'language', 'greeting_type', and 'greeting'. Here, the 'language' and the 'greeting' are the primary keys. So for each language identified by the 'language' attribute, there are different greeting types and the actual greetings in the corresponding languages.The fields, their data types and their exact text can be setup in a similar manner as described for the 'hello_language' table.

Create the Necessary PHP code

First you must create a new directory for the Sahana module. We will call this module 'hello', so create a new directory in your Sahana 'mod' folder called 'hello'. Sahana will recognize your module as 'hello' from here on out.

The two files that you must create can be downloaded here:

Media:hello.tar

The two main files in every Sahana module are the 'conf.inc' and 'main.inc' files. The 'conf.inc' file is simple and contains some basic information about the menu item for your module. You really only need two lines of actual code in this file:


<?

/**
 * Gives the nice name of the module
 */

$conf['mod_hello_name'] = _("Hello World");

/**
 * Gives the priority order in the main menu when listed
 */

$conf['mod_hello_menuorder'] = 21;

?>

As the comments describe, the first names the module in the menu and the second gives the order of the module's menu item in the entire menu.

The 'main.inc' file is a bit more involved, and contains the main functionality for this module. The very first thing we have to do is include various files from the Sahana library. You can do so as follows:

include_once $global['approot'].'/inc/lib_menu.inc';
include_once $global['approot'].'/inc/lib_form.inc';
include_once $global['approot'].'/inc/lib_validate.inc';
include_once $global['approot'].'/inc/lib_errors.inc';
include_once($global['approot'].'/inc/lib_log.inc');

Other than the includes, we must create a few important functions. The first is the one that takes care of the menu for this module:

/**
 * This function allows you to override the mainmenu. This is often done
 * to include the modules own menu.
 *
 * @access public
 * @return void
 */

function shn_hello_mainmenu()
{
    global $global;
    $module = $global['module'];

    // Create the module menu
    shn_mod_menuopen(_('Hello World'));
    shn_mod_menuitem('default',_('Home'));
    shn_mod_menuclose();

    // include the main menu so that the user can navigate outside the module
    include $global['approot'].'/inc/handler_mainmenu.inc';
}

Notice how the function's name is shn_<module_name>_mainmenu, where <module_name> is the name of our module.

The next function we must create is the shn_hello_default() function, which creates the form to choose various languages and greetings. We will create three inputs that will be identified by the browser and by the server as 'name', 'language', and 'greeting', which correspond to the name of the user, the language he or she selects, and the type of greeting that will be displayed. When we open the form, we give it the name 'say_hello', which means that to act on our form, we must create a function called shn_hello_say_hello(), or more generally, shn_<module_name>_<form_name>().


/**
 * This function displays the default page of the module when it is selected, displaying
 * the form to allow various greetings.
 *
 * @access public
 * @return void
 */
 
function shn_hello_default()
{
    /*
     * Display the title for the module
     */

    ?>
    <div id="home">
    <h2><?= _('Multilingual Hello'); ?></h2>
    
    <?
    
    /*
     * Store the global database object for later querying
     */
    
    global $global;
    $db = $global['db'];
    
    /*
     * Create a blank array and fill it with the various languages that are stored
     * in the database table 'hello_language'
     */
    
    $languages = array();
    $result = $db->Execute("select id, name from hello_language");
    
    while(!$result->EOF)
    {
            $languages[$result->fields['id']] = $result->fields['name'];
            $result->moveNext();
    }
    
    /*
     * Create a blank array and fill it with the various greetings that are possible
     * from the 'hello_greeting' table
     */
    
    $greetings = array();
    $result = $db->Execute("select distinct greeting_type from hello_greeting");
    
    while(!$result->EOF)
    {
            $greetings[$result->fields['greeting_type']] = $result->fields['greeting_type'];
            $result->moveNext();
    }
    
    /*
     * Create the HTML form that, depending on what is chosen, will display the corresponding
     * greeting in the corresponding language.
     */
    
    shn_form_fopen("say_hello", null,array('req_message'=>true));
        shn_form_fsopen("Hello");
        shn_form_text("Your name","name",null,array("req"=>true, "help"=>"testing help"));
        shn_form_select($languages,"Language", "language",$select_opts = "", $extra_opts = null);
        shn_form_select(
        $greetings,"Greeting", "greeting",$select_opts = "", $extra_opts = null);
        shn_form_submit("Submit", $submit_opts = null);
        shn_form_fsclose();
    shn_form_fclose();
    
    ?>
    </div>
    <?
}

The last function we must add is the shn_hello_say_hello() function, which acts on the inputs from the previous function's form. Once we get to this point, the browser will have passed to the server the 'name', 'language', and 'greeting' inputs, which we can retrieve from the global PHP $_REQUEST variable, which is an index-based array that has an input's name for each key and the input's value for each value.

It's important to note that there are two ways that inputs from forms are passed from browser to server: GET and POST. In GET, the browser sends the server the information via the URL, and in POST, the browser sends the server the information via the HTTP request. So, with POST there is more privacy, and Sahana uses POST for all of its forms. Once the variables are passed to the server, we can retrieve them from the global $_GET or $_POST index-based arrays, which contains an input's name for each key and its corresponding value for each value. $_GET contains the GET inputs, and $_POST contains the POST inputs. Alternatively, we can simply use the previously-mentioned $_REQUEST array, which combines the $_GET and $_POST arrays.


/**
 * This function acts on the inputs from the form created on the default page. Based on the 
 * name, language, and greeting, it will output the appropriate response preceeding the user's
 * name. 
 *
 * @access public
 * @return void
 */

function shn_hello_say_hello()
{
        /*
         * First get the information from the form
         */
         
	$name = $_REQUEST['name'];
	$language = $_REQUEST['language'];
	$greeting_type = $_REQUEST['greeting'];

        /*
         * Get the global database object and get the appropriate greeting from the database
         * based on the inputs.
         */
         
        global $global;
        $db = $global['db'];
        
        $result = $db->Execute("select greeting from hello_greeting where greeting_type = '$greeting_type' and language = '$language'");
	$greeting = $result->fields['greeting'];
	echo "<h1>$greeting</h1>";
	echo "$greeting, $name!";
	echo '<br /><br /><a href="?mod=hello">Back</a>';
}

Related Links