How to build a module

From EFrontWiki

Jump to: navigation, search

So you want to create your own eFront modules, to extend current functionalities to your own needs? This manual will help you learn all there is about the eFront modules system and will enable you to create your own eFront in a series of easy steps. All that is required from you is:

  • Basic PHP skills (well you wouldn’t be reading this tutorial otherwise)
  • Fundamental object-oriented understanding
  • Basic XML knowledge (for writing the module manifest)
  • Blindly obeying to the 3 golden rules of eFront modules

The rest is up to your creative imagination and programming skills.

Contents

[edit] Just a little theory

There are a few things we could tell about the eFront modules system. It is based upon the logic that the main responsibility of module programmers is to define the methods of an existing abstract base module class. The return values of these methods will be used by the core eFront system to display and manage your module. Some of those methods are mandatory, while others might be used or not. If your module does not use them, then they will return the default values as defined in the base class and the system will know that they have not been implemented for this module. Therefore, define only mandatory derived methods and only the derived methods that are required by your module in order to avoid unnecessary problems. Leave everything else alone!

If you are an experienced programmer, then you might figure out pretty easily how to write a module by reading the following chapter and studying the methods of the modules.class.php file, where the module base class exists. Otherwise, take a look at the step-by-step tutorial below:

Let’s get started!

[edit] Defining the module.xml manifest

We assume that you have downloaded and setup eFront and that you have an idea for an eFront module on your mind. Great! The first thing to do is write an XML description file called module.xml regarding your module.

<module>
	<title>Any title for the module </title>
	<author>For vanity reasons mainly </author>
	<date>For historians to know</date>
	<version>The version of your module</version>
	<description>A free-text description of the module </description>
	<className>the PHP class of the module – beware not to leave unintentionally spaces</className>
</module>


The className is the only of the six afore mentioned fields that is mandatory and that actually matters (ok, if you insist, the author one as well). If the students were also to see who the best student is, then the getPermittedRoles() function would change as:

getPermittedRoles method

public function getPermittedRoles() {
    return array("professor", “student”);
}

Well, believe it or not, this is all that is required for you to create the basis of your module. You needn’t even define a constructor class. (Note: Actually you shouldn’t define a constructor class). In fact, if you do not need to add or alter any table structures in the eFront database for your module to function correctly, then you might as well install the module right away. Of course, if no other methods are implemented, the module won’t do anything, but it will be recognized by eFront and you would be able to view the changes on your code on the eFront system, since programming in blind is always risky.

Before we move on to the installation part, we will have a brief view of how to incur any changes to the database.

[edit] Defining the className.class.php file

The className tells eFront that the base class of your module will be called className and will be defined in a file called className.class.php. For example, the module

module.xml manifest file for sample module frequently asked questions

<?xml version="1.0" ?>
<module>
	<title>Frequently asked questions </title>
	<author>Me</author>
	<date>Today which is the 24/02/2008</date>
	<version>1.214 beta </version>
	<description>Module letting users find out FAQ for a lesson</description>
	<className>module_faq</className>
</module>

should define class module_faq in a file called module_faq.class.php.

Note: This file as any other defined should use UTF-8 encoding.

Moreover, the definition of your class should be set to extend the abstract global class for eFront called eFrontModule. This is done as follows:

module_faq.class.php

<?php

class module_faq extends EfrontModule {
	// … Definition of the class here
}

?>

Note: the base class header file should NOT be included.

The base class you write should define two basic functions defined as “abstract” in the basic class:

  • public function getName(): which should return a string with how your module should be called. This shouldn’t necessary be the title you have defined in the module.xml file.
  • public function getPermittedRoles(): This function should return an array with all eFront roles that are involved in the module, meaning that they are to interact somehow with the module’s interface. The possible roles are strings: “administrator”, “professor” and “student”.

A sample implementation of those basic two functions, for a module called (with className) module_best_student, which shows the name of the student with the best grade in a lesson to its professor, would be the following:

module_best_student.class.php

<?php

class module_best_student extends EfrontModule {
    public function getName() {
        return “Best Lesson Student”;
    }

    public function getPermittedRoles() {
        return array("professor");
    }

}
?>

If the students were also to see who the best student is, then the getPermittedRoles() function would change as:

getPermittedRoles method

public function getPermittedRoles() {
    return array("professor", “student”);
}

Well, believe it or not, this is all that is required for you to create the basis of your module. You needn’t even define a constructor class. (Note: Actually you shouldn’t define a constructor class). In fact, if you do not need to add or alter any table structures in the eFront database for your module to function correctly, then you might as well install the module right away. Of course, if no other methods are implemented, the module won’t do anything, but it will be recognized by eFront and you would be able to view the changes on your code on the eFront system, since programming in blind is always risky.

Before we move on to the installation part, we will have a brief view of how to incur any changes to the database.

[edit] Changing the eFront database

You may define your module to setup the eFront database in three occasions: during its installation, its uninstalling and during system upgrade. The methods used for this reason are onInstall, onUninstall and onUpgrade respectively.

Database setup methods

 // What should happen on installing the module
    public function onInstall() {
        eF_executeNew("CREATE TABLE module_faq (
                          id int(11) NOT NULL auto_increment,
                          lessons_ID int(11) not null,
                          question text not null,
                          answer text not null,
                          PRIMARY KEY  (id)
                        );");
        return true;
    }

    // And on uninstalling the module
    public function onUninstall() {
        eF_executeNew("DROP TABLE module_faq;");
        return true;
    }

Note: Function eF_executeNew is a utility wrapper eFront DB-function that allows you to directly execute SQL queries on the eFront database. Make use of it!

[edit] Installing the module

After optionally designating the database setup functions (and more significantly the onInstall one), we suggest you install the module right away. Installation can take place from the administrator menu, namely from the “Modules” option at the administrator control panel. To install a module:

  • Create a zip file having all module files. The root of the zip directory should necessarily contain the module.xml manifest file and the className.class.php file, otherwise the module won’t be installed.

Note: It is suggested that the zip file has the same className as your module, in order to avoid any collision problems of modules with the same name.

  • Click “Add new module” link of the module administration page and upload the zipped file.

Note: If a module exists in the system with the same className, then your module will not be installed. Solution: Change the className Note: If the your module cannot be installed maybe there is a problem with the database script (if you provided one)

Now, if the module has been correctly installed, it should appear on the list of modules on the administrator module page. You can edit your module’s code by going to the www/modules/ folder, opening your own module folder and editing or inserting the files you want (or only the className.class.php one).

[edit] Module links

Methods related to module links are used to make links appear for the module, meaning to the module’s pages or to any other pages in the system the module author wants to.

• public function getSidebarLinkInfo(): This method returns an array of arrays of links that lets the system know of the way and the menu in which new links will appear on the left hand sidebar of eFront. The main structure is the following: array ( menu id => link array ), where:

  • menu id: "system" | "lessons" | "users" | "organization" | "tools" | “current_lesson" | "other"
  • link array: array( link )
  • link: array ( ‘id’ => …, ‘title’ => …., ’target’ => …
                  ‘eFrontExtensions’ => …,‘image’ => …);

Let’s explain each of those fields:

  • menu id: is the unique identifier of one of the existing eFront menus. These are shown on the table below:

If “Other” is set as menu id, then: - the title of the new menu should also be provided in a field called “title” - the links of the new menu should be provided in a field called “links”

Note: Up to 8 new custom eFront menus may be defined. If more than these are used, then all links of “Other” menu id will be put under the “Modules” menu.

  • link: an array with all necessary information for the link. These are:
    • íd: the unique id of the link within the module framework. This can be later used for highlighting purposes (see getLinkToHighlight() method)
    • title: the title of the link
    • image: the image that will appear next to the link. Note: remember to use $this->moduleBaseDir if you use pictures inside the module directory. Otherwise, use the relative path from the main www/ folder of eFront.
    • eFrontExtensions: allows you to alternatively use ‘png’ and ‘gif’ images instead of always the same image depending on the browser. This approach is followed throughout eFront and guarantees better icon appearances. Therefore, if this field is equal to 1, then
      • the image file provided should have no extension
      • two different image files with the same filename and different extension should be provided in the path set in the image field. One should be ‘png’ and the other ‘gif’
      • these files will appear alternatively according to the browser used

Now let’s see a sample implementation of the sidebar links method

Sample implementation of getSidebarLinkInfo () method

  
public function getSidebarLinkInfo () {
        $currentUser = $this -> getCurrentUser();
	  // professors should see a link in the lessons menu	
        if ($currentUser -> getType() == "professor") {

           $link_of_menu_lessons = array (
                              'id' => 'other_link_id1',
                              'title' => “Lesson link title”,
                              'image' => $this -> moduleBaseDir . 'images/image16',
                              'eFrontExtensions' => '1',      //no extension provided up
                              'link'  => $this -> moduleBaseUrl .
                                            "&module_operation=lesson_related");

           return array (‘lessons’ => array ($link_of_menu_lessons) );

// and admins should see a link in the users menu and in a newly defined menu
   } else if ($currentUser -> getType()  == “administrator”) {

	//link using relative path to the eFront images folder 
            $link_of_menu_users = array (
                                'id'    => 'users_link_id1',
                               'title' => “Users link title”,
                               'image' => 'images/16x16/pens.png',
                               'link'  => $this -> moduleBaseUrl .
                                             "&module_op=user_related");

            $link_of_menu_other = array (
                               'id'    => 'other_link_id1',
                               'title' => “Other link title”,
                               'image' => 'images/16x16/pens',
                               'eFrontExtensions' => '1',   //no extension provided up
                               'link'  => $this -> moduleBaseUrl .
                                             "&module_op=user_related");

            return array (‘users’ => array ($link_of_menu_users),
                                 ‘other’ => array (‘title’ => “Module menu”, 
                                                            ‘links’=> array ($link_of_menu_other)));

   }
}

The sample should be self – explanatory. Just note again the how variables $this -> moduleBaseUrl and $this -> moduleBaseDir are used, and how the module urls do not use ‘ctg’ or ‘op’ (but in this case “module_op”). These three observations indicate how the three golden rules are applied in this case as well.

  • public function getCenterLinkInfo ():

This method returns an array of arrays of links that lets the system know of any new links on the administrator control panel of eFront. Most of the fields as the link of the previous chapter are provided here as well, namely ‘title’, ‘image’ and ‘link’. The ‘id’ and ‘eFrontExtensions’ are not used.

  • public function getLessonLinkInfo ():

This method returns an array of arrays of links that lets the system know of any new links on the professor or student lesson control panel. Most of the fields as the link of the previous chapter are provided here as well, namely ‘title’, ‘image’ and ‘link’. The ‘id’ and ‘eFrontExtensions’ are not used.

  • public function getNavigationLinks():

This method returns an array of links that defines the navigational links that may appear on the top of the right side eFront frame, when module pages are displayed. These links are divided by default with the “>>” character. Only ‘title’ and ‘link’ fields are provided.

Sample implementation of getNavigationLinks () method

public function getNavigationLinks() {
       return array ( array ('title' => "Main Page" , 
                                       'link'  => $this -> moduleBaseUrl),
                             array ('title'=> “Sub Page 1", 
                                        'link'  => $ths -> moduleBaseUrl ."&mod_op=sub"));
}

  • public function getLinkToHighlight ():

This method defines how left sidebar links might be highlighted according to current (module related) url. It returns the ‘id’ of the link that should be highlighted, as this id was defined in the getSidebarLinkInfo() method.

Sample implementation of getLinkToHighlight () method

public function getLinkToHighlight() {
            if (isset($_GET['management'])) {
                return 'management_link';
            } else {
                return ‘default_module_link';
            }
}

We assume here that links with id 'management_link' and ‘default_module_link' have been defined.

[edit] Setting module environment

The eFront module’s system offers further possibilities for increasing the appearance customization and functionalities of modules. This is accomplished with methods that allow you to define a ‘css’ file for your module, a ‘js’ file or language files.

[edit] CSS file

You might define a custom css file for your module with the method:

  • public function getModuleCSS ():

This method should return the filename of the css file corresponding to the module. It is a good idea to use a module specific namespace in your css so as to avoid collision with existing classes. Note: Do not forget to use the $this->moduleBaseDir variable in the filename definition.

[edit] CSS file

You might define a custom css file for your module with the method:
  • public function getModuleCSS ():

This method should return the filename of the css file corresponding to the module. It is a good idea to use a module specific namespace in your css so as to avoid collision with existing classes. Note: Do not forget to use the $this->moduleBaseDir variable in the filename definition.

[edit] Javascript file

You might define a custom js file for your module with the method:

  • public function getModuleJs ():

This method should return the filename of a js file containing all Javascript functions that might be needed by your module. Bear in mind that name collisions are an important issue in Javascript and therefore, you suggest you use your className as a prefix to every function you define. Note: Do not forget to use the $this->moduleBaseDir variable in the filename definition.

[edit] Getting/setting eFront environmental variables

A series of methods is derived from the base eFrontModule class in order to provide all necessary runtime information to the module’s programmer. Most of these methods return objects whose methods may also be used by your modules. These are:

  • public function getCurrentUser():

Returns an Object of class eFrontUser that corresponds to the user currently using the system. For more information on that class we recommend the documentation on the user.class.php file.

  • public function getCurrentLesson():

Returns an Object of class eFrontLesson that corresponds to the lesson currently selected in the system. For more information on that class we recommend the documentation on the lesson.class.php file.

  • public function getSmartyVar():

This method’s usage has already been demonstrated above. It returns the global smarty variable that is used by the smarty displaying system.

Besides those methods there exists the

  • public function setMessageVar ( $message , $message_type ):

This method is used to define the global message variable, for the message to appearing on the top of the right eFront frame. We have

    • $message: any string to appear
    • $message_type: ‘success’ or ‘failure’, which will define whether the background of the message will be green or yellow respectively.

Finally, eFront allows you to make use of any of the Javascript libraries used by the system like the prototype/scriptaculous one, with the use of the following method:

  • public function addScripts ():

This method returns an array with the names of the Javascript library files as they appear in the www/js/ directory of the eFront menu. For example:

Sample implementation of addScripts method

public function addScripts () {
	return array (“EfrontScripts”, 
                                 “ajax”, 
                                 “scriptaculous/scriptaculous”, 
                                 “scriptaculous/prototype) ;
}

will include the eFront Javascript libraries:
- www/js/EfrontScripts.js
- www/js/ajax.js
- www/js/scriptaculous/scriptaculous.js
- www/js/scriptaculous/prototype.js

It should be evident by now what string is required to be put into the array for the correct script library to be loaded.

[edit] Triggering events

The last series of methods involves the triggering of module related actions on specific predetermined actions that take place within the eFront framework. The current version of eFront modules system supports events triggered on:

  • public function onNewUser ($login):

This method is used to define courses of action to be taken right after a new user with login = $login is entered into the system. This means all newly registered information is available.

  • public function onDeleteUser ($login):

This method is used to define courses of action to be taken right before user with login = $login is deleted from the system. This means all information, that will be shortly after deleted, is still available

  • public function onNewLesson ($lessonId):

This method is used to define courses of action to be taken right after a new lesson with id = $lessonId is entered into the system. This means all newly registered information is available.

  • public function onDeleteLesson ($lessonId):

This method is used to define courses of action to be taken right before lesson with id = $lessonId is deleted from the system. This means all information, that will be shortly after deleted, is still available

[edit] Putting it all together

Now, that we have a good overview of how eFront modules can be defined, let’s go and create a sample module. This module should return to the professor a list of the three most students with the highest score in the current lesson.

Step 0: Design

Q: How shall the module be called? A: Highest ranking students

Q: Who will use the module? How? A: The professor. A sub-window will show the best student on his lesson control panel. We will also provide an independent page with the list.

Q: Will we need any changes to the database? A: No

Step 1: Write the module manifest

module.xml manifest file for sample module frequently asked questions

<?xml version="1.0" ?>
<module>
	<title>Highest ranking students</title>
	<author>Me</author>
	<date>27/05/2008</date>
	<version>1.0 </version>
	<description>Module showing the highest ranking students of a lesson
            </description>
	<className>module_highest_rank</className>
</module>

Step 2: Create the module_highest_rank.class.php file and save it as UTF-8, following the design step answers define the basic two methods:

module_highest_rank.class.php – version 1

<?php

class module_highest_rank extends eFrontModule {

    public function getName() {
        return "Highest ranking students";
    }

    public function getPermittedRoles() {
        return array("professor");
    }
}
?>

Step 3: Zip files module.xml and module_highest_rank.class.php into a zip file called module_highest_rank.

Step 4: Install the module by logging into the eFront system as administrator and selecting the “Modules” link of the control panel.

Step 5: Go to the eFront base directory and then to www/modules/module_last_logged/ directory. Open file module_last_logged.class.php

Since we want to create a control panel module for the professor we are going to use the getLessonModule (or it in conjunction with getLessonModuleTpl) as explained above (paragraph 5.3).

At this point we assume that the eFront SQL interface and database is known to the programmer, so we will directly implement the getLessonModule code.

module_highest_rank.class.php – version 2

<?php

class module_highest_rank extends eFrontModule {

    public function getName() {
        return "Highest ranking students";
    }

    public function getPermittedRoles() {
        return array("professor");
    }

    public function getLessonModule() {
// Get the current lesson information
        $currentLesson = $this -> getCurrentLesson();

// Get the best student information from the eFront database
        $best_student = eF_getTableData("users_to_lessons join users on users.login = users_to_lessons.users_login", "name, 
surname, login, score", "users.user_type = 'student' and lessons_id = '".$currentLesson -> lesson['id']."'","","score");

// Return the HTML code to appear
        return "<table width ='550' height='80' bgcolor='#EFEFEF'>
                    <tr><td><img src='images/32x32/user1_new.png' /></td><td>My best student is <b>".$best_student[0]['surname']. 
" " . $best_student[0]['name'] . "</b> with score “ . $best_student[0][‘score’] . “%</td></tr></table>";
    }
}
?>

The resulting lesson control panel for the professor is the following

Step 6: Add a link to the main module page under the current lesson menu on the sidebar.

module_highest_rank.class.php – version 2

    public function getSidebarLinkInfo() {
            $link_of_menu_clesson = array (array ('id' => 'module_best_link',
                                                  'title' => ‘Best student page’,
                                                  'image' => 'images/16x16/star_yellow',
                                                  'eFrontExtensions' => 1,
                                                  'link’ => $this -> moduleBaseUrl ));

            return array ( "current_lesson" => $link_of_menu_clesson);
    }

Step 7: Create the code for the main – independent module page

We put the almost the same code as in the getLessonModule() method.

public function getModule() {

        $currentLesson = $this -> getCurrentLesson();
        $best_student = eF_getTableData("users_to_lessons join users on users.login =
                         users_to_lessons.users_login", "name, surname, login, score",
                         "users.user_type = 'student' and lessons_id = '".$currentLesson -> 
                          lesson['id']."'","","score");

        return "<html><body><table width ='100%' height='80' bgcolor='#EFEFEF'>
                    <tr><td><img src='images/32x32/user1_new.png' /></td><td>My best
                    student is <b>".$best_student[0]['surname']. " " . $best_student[0]['name'] 
                    . "</b> with score “ . $best_student[0][‘score’] .  “%</td></tr></table>
                   </body></html>";

}

Moreover we will define the getLinkToHighlight() method to enable the highlighting of the link we have defined in the previous step. We only have one module page, and therefore this method should always return the id of the same link.

public function getLinkToHighlight() {
        return 'module_best_link';
}

Finally, we may define the navigational links for our module page with the getNavigationLinks method. We will define two links, one for the Home page of the lesson and one for our module page.

public function getNavigationLinks() {
       return array ( array ('title' => "Lesson Home Page" , 
                                       'link' => “professor.php?ctg=control_panel”),
                             array ('title'=> “Best Student", 
                                        'link'  => $ths -> moduleBaseUrl );
}

These three methods lead to the following final main module page

Future steps: These steps more or less wrap up the fundamental notions behind eFront module programming. Following the same steps, defining the well-known derived methods of your choice and blindly obeying to three golden rules will enable you to create from obscenely trivial to extremely complicated modules. Just as a reminder of the last:

Rule I: Any urls related with your module’s main-independent pages should begin with the $this->moduleBaseUrl string.
Rule II: You might have your pages using any $_GET/$_POST variables you like except from ‘ctg’ and ‘op’
Rule III: Any files in the module’s directory must be referenced as existing in the $this->moduleBaseDir directory. 
Any further paths inside that directory may be referenced normally.
Views
Personal tools
Navigation