Development Guide

Functions

General: Plugins and Plugin Slots

The plugin architecture has been introduced with ILIAS 3.10.0. ILIAS components (modules and services) can define plugin slots. Plugin slots define an interface for a set of possible plugins with similar characteristics. E.g. the test and assessment module of ILIAS will define a plugin slot for new question types. Another plugin slot will be defined by the internal ILIAS event handling service, to enable plugins to listen to all sorts of ILIAS events like the creation, update and deletion of new users or other resources.

Once a plugin slot is defined, plugins can be developed and deployed within the Customizing directory of ILIAS to extend or modify the behaviour of ILIAS. Plugins can use their own language files for user interface texts, use an own set of database tables to store data and use their own HTML template files.

Defining a Plugin Slot

This section describes what is needed to define a new plugin slot. If you are not a core developer, you will probably start with developing plugins for existing plugin slots. In this case you may skip this section.

Plugin slots are defined in components. ILIAS distinguishes between two major component types: modules and services. Modules implement repository resources that can be used in ILIAS, e.g. forums or tests. Services provide general functionalities used by other components, and example would be the news service.

To define a plugin slot you must declare it within the module.xml or service.xml file of your component. This is done with the pluginslots and pluginslot tags.
<?xml version = "1.0" encoding = "UTF-8"?>
<service xmlns="http://www.w3.org" version="$Id$"
id="evnt">
<baseclasses>
</baseclasses>
<objects>
</objects>
<pluginslots>
<pluginslot id="evhk" name="EventHook" />
</pluginslots>
</service>
The second step is to implement an abstract plugin class, derived from class ilPlugin (./Services/Component/classes/class.ilPlugin.php). The name of the class is derived from the name of the plugin slot: il<slot_name>Plugin. The class file must be located in the classes directory of the corresponding component.
include_once("./Services/Component/classes/class.ilPlugin.php");
 
/**
* Abstract parent class for all event hook plugin classes.
*
* @author Alex Killing <alex.killing@gmx.de>
* @version $Id$
*
* @ingroup ServicesEventHandling
*/

abstract class ilEventHookPlugin extends ilPlugin
{
/**
* Get Component Type
*
* @return string Component Type
*/

final function getComponentType()
{
return IL_COMP_SERVICE;
}
 
/**
* Get Component Name.
*
* @return string Component Name
*/

final function getComponentName()
{
return "EventHandling";
}
 
/**
* Get Slot Name.
*
* @return string Slot Name
*/

final function getSlot()
{
return "EventHook";
}
 
/**
* Get Slot ID.
*
* @return string Slot Id
*/

final function getSlotId()
{
return "evhk";
}
 
/**
* Object initialization done by slot.
*/

protected final function slotInit()
{
// nothing to do here
}
 
 
}
?>
This is it. The next DB update step should load the information into the DB. The slot should then be listed within the ILIAS administration in section "Modules, Services and Plugins".

The plugins will implement one non-abstract class that is derived from this class provided by the slot. You may add additional abstract or non-abstract functions that can be used or must be implemented by the plugins.

However these plugin final classes should not implement too much of the application logic of the plugin.

Using Plugins within the Components

There are some important rules how plugins should be used within a component.
Always check whether a plugin is active before you use it.
ILIAS provides a global helper object $ilPluginAdmin that gives you the information, whether a plugin is active or not. Use its static isActive($a_ctype, $a_cname, $a_slot_id, $a_pname) method to get this information.
function isActive($a_ctype, $a_cname, $a_slot_id, $a_pname)
{
global $ilPluginAdmin;
 
// check if DummyHook Plugin in Slot "evhk" of EventHandling service is active.
if ($ilPluginAdmin->isActive(IL_COMP_SERVICE, "EventHandling", "evhk", "DummyHook"))
{
// now use the plugin...
$plugin_obj = $ilPluginAdmin->getPluginObject(IL_COMP_SERVICE, "EventHandling",
"evhk", "DummyHook");
[...]
}
}
The $ilPluginAdmin helper object also provides a method to get all active plugins for a given plugin slot. Alternatively this information can be obtained from a corresponding plugin slot object.
// get active plugins of slot
$pl_names = $ilPluginAdmin->getActivePluginsForSlot($a_ctype, $a_cname, $a_slot_id);
 
// get same information using plugin slot object
$slot = new ilPluginSlot($a_c_type, $a_c_name, $a_slot_id);
$pl_names = $slot->getActivePlugins();
Your component must not stop working, if a plugin switches to inactive status.
You must not rely on the activity of a certain plugin. You must always implement code, that continues to work, even if a certain plugin suddenly becomes inactive.

In the worst case this could mean, that a larger resource of your component becomes "inactive", too. But this must happen in a controlled manner.

E.g. if the test module uses plugged in new question types within a test, it must check the activity of the corresponding plugins during the test run. It may put the whole test to an "inactive" or "offline" status and display an appropriate message to the user if necessary plugins are not active anymore.