Development Guide

OrgUnit Extension Plugin

This plugin Slot is available strating from ILIAS 5.2

The goal of the repository object plugin slot is to implement new objects in the organisational units tree. For example you can add: reports, overlays, etc.

Please make sure that you have read the general plugin implementation documentation.

This slot is defined by the Repository Service of ILIAS and named "RepositoryObject". This means all plugins have to be installed into directories at:

Customizing/global/plugins/Modules/OrgUnit/OrgUnitExtension/<Plugin_Name>

The ID of the Repository Service Component is "OrgUnit", the ID of the slot is "orguext". These are used as prefixes together with your plugin id for database tables and for language variable identifiers:

DB Table / Language VariablePrefixes: orgu_orguext_<Plugin_ID>_

The organisational unit extension plugin slot strongly relies on the repository object plugin slot. The API is almost the same, the only differences are:
  • The export of orgunit extension objects is not yet supported.
  • The orgunit extension plugin slot has additional helper methods for org unit specific funcitonality like:
    • Get employees and superiors of the current OrgUnit (recursive).
    • Get the path to this orgunit, or get the subtree of this orgunit.

Plugin Directory Structure

A orgu extension plugin has the following file/directory structure:

<PluginName> (Directory)
classes (Directory)
class.il<PluginName>Plugin.php
class.ilObj<PluginName>.php
class.ilObj<PluginName>Access.php
class.ilObj<PluginName>GUI.php
class.ilObj<PluginName>ListGUI.php
lang (Directory)
ilias_<LangKey>.lang
sql (Directory)
dbupdate.php
templates (Directory)
images (Directory)
...
tpl...html
plugin.php

Plugin Files

We will now have a detailed look on all mandatory files and an example implementation. The name of the plugin is "Example", so its location will be at:

Customizing/global/plugins/Services/Repository/RepositoryObject/Example

plugin.php

All plugins must include a plugin.php file.

<?php
$id = 'xsre';
$version = '0.0.1';
$ilias_min_version = '5.0.0';
$ilias_max_version = '5.2.999';
$responsible = 'Oskar Truffer';
$responsible_mail = 'ot@studer-raimann.ch';
?>

The plugin id is also used as an internal object type ID. All ILIAS objects are internally represented by a type ID, e.g. "glo" for glossaries, "orgu" for OrgUnits or "chat" for chats. This sets additional constrains on the plugin id:

The plugin ID must have a length of three or four characters. The plugin ID must start with an "x". Type IDs starting with "x" are reserved for plugins and will not be used by future ILIAS repositor objects.

classes/class.il<PluginName>Plugin.php

<?php
 
require_once "Modules/OrgUnit/classes/Extension/class.ilOrgUnitExtensionPlugin.php";
 
class ilTestOrgUnitExtensionPlugin extends ilOrgUnitExtensionPlugin {
 
/**
* Get Plugin Name. Must be same as in class name il<Name>Plugin
* and must correspond to plugins subdirectory name.
*
* Must be overwritten in plugin class of plugin
*
* @return string Plugin Name
*/

function getPluginName() {
return "TestOrgUnitExtension";
}
 
protected function uninstallCustom() {
// TODO: Implement uninstallCustom() method.
}
 
/**
* returns true iff the plugin shows up in the navigation tree.
* @return bool
*/

public function showInTree() {
return true;
}
}

The implementation of the plugin class is quite easy. It must be derived from ilRepositoryObjectPlugin. Most likely you will only have to replace the two occurrences of "OrgUnitExtension" by your plugin name in the code above. The uninstallCustom method can be overriden if you need to delete some custom databases in case the plugin gets removed from ILIAS again.

classes/class.ilObj<PluginName>.php

This is the main application class of the orgunit extension. It is derived from iliOrgUnitExtension wich derives ilObjectPlugin which is derived from ilObject2 which again derives from ilObject. All ILIAS repository objects implement a class that is derived from ilObject2. Please have a look at the general architecure to understand the separation of responsibilities between application and GUI classes. Also have a look at the guidelines about database handling.

<?php
 
require_once "Modules/OrgUnit/classes/Extension/class.ilOrgUnitExtension.php";
 
class ilObjTestOrgUnitExtension extends ilOrgUnitExtension {
 
protected function initType() {
 
 
$this->setType("xsre");
}
}

If you need to make any entries in a database upon creation or duplication of an object please visit the repository object plugin page. The OrgUnit Extension handles the CRUD operations in the exact same way!

You must overwrite at least the following abstract method:
  • initType()
    • The initType() method must set the same ID as the plugin ID.

sql/dbupdate.php

If you need to make any entries in a database upon creation or duplication of an object please visit the repository object plugin page. The OrgUnit Extension handles the db updates in the exact same way!

classes/class.ilObj<PluginName>GUI.php

This one is the major user interface class for your repository object. See the basic architectur for responsibilities of user interface classes.

The flow of control between user interface classes is handled by a controller object called $ilCtrl. Every request is targeted to a command that is executed in one user interface class, but involves a larger number of user interface classes that generate the HTML that is responded to the browser of the user. The $ilCtrl class forwards the flow of control to most of the user interface classes involved in a request (sometimes GUI classes call other GUI classes directly to get certain HTML snippets).

<?php
 
require_once "Modules/OrgUnit/classes/Extension/class.ilOrgUnitExtensionGUI.php";
 
/**
* User Interface class for example repository object.
* ...
* @ilCtrl_isCalledBy ilObjTestOrgUnitExtensionGUI: ilRepositoryGUI, ilAdministrationGUI, ilObjPluginDispatchGUI
* @ilCtrl_Calls ilObjTestOrgUnitExtensionGUI: ilPermissionGUI, ilInfoScreenGUI, ilObjectCopyGUI, ilCommonActionDispatcherGUI
*/

class ilObjTestOrgUnitExtensionGUI extends ilOrgUnitExtensionGUI {
 
/**
* @var ilObjTestOrgUnitExtension
*/

public $object;
 
/**
* Functions that must be overwritten
*/

public function getType() {
return "xsre";
}
 
public function performCommand($cmd) {
switch ($cmd) {
case "show":
$this->checkPermission("read");
$this->$cmd();
break;
default:
throw new Exception("The command $cmd is not valid for this class.");
}
}
 
/**
* Cmd that will be redirected to after creation of a new object.
*/

function getAfterCreationCmd() {
return "show";
}
 
protected function show() {
global $tpl;
 
$tpl->addJavaScript("https://code.highcharts.com/highcharts.js");
 
// Object Org Unit
$html = "<h3>Rekursiv from {$this->object->getOrgUnit()->getTitle()}:</h3><hr>superiors:<ul>";
 
// Superiors and employees
$sups = $this->object->getSuperiors(true);
$emps = $this->object->getEmployees(true);
foreach ($sups as $supId) {
$user = new ilObjUser($supId);
$html .= "<li>{$user->getPublicName()}</li>";
}
 
$html .= "</ul>";
$html .= "employees:<ul>";
 
foreach ($emps as $empId) {
$user = new ilObjUser($empId);
$html .= "<li>{$user->getPublicName()}</li>";
}
 
$html .= "</ul>";
 
// Path
$html .= "<hr /> Path <br />" . implode(" > ", $this->object->getOrgUnitPathTitles());
$html .= "<hr />";
 
// Subtree
$subtree = $this->object->getOrgUnitSubtree(true, "orgu");
$html .= "Subtree: <br /><ul>";
foreach ($subtree as $item) {
$html .= "<li>" . $item['title'] . "</li>";
}
$html .= "</ul>";
 
$pl = new ilTestOrgUnitExtensionPlugin();
$chart = $pl->getTemplate("tpl.pie_chart.html");
 
 
$types[] = array(
"name" => 'Superiors',
"y" => (int)count($sups),
);
 
$types[] = array(
"name" => 'Employees',
"y" => (int)count($emps),
);
 
 
$series = array(
'name' => 'name',
'colorByPoint' => true,
'data' => $types
);
$json = json_encode($series);
 
$chart->setCurrentBlock("block");
$chart->setVariable("TITLE", "What's the Ratio");
$chart->setVariable("ID", "highchart" . rand(1, 99999999));
$chart->setVariable("SERIES", $json);
$chart->parseCurrentBlock();
$tpl->setContent($html . $chart->get());
}
 
function getStandardCmd() {
return "show";
}
}

Your class must be derived from ilOrgUnitExtensionGUI which is an extension of ilObjectPluginGUI and ilObjectGUI. There are some important comment lines in the header starting with @ilCtrl_isCalledBy and @ilCtrl_Calls.

Do not remove the comment lines starting with * @ilCtrl_isCalledBy and * @ilCtrl_Calls. Without them your plugin will not work.

There are some abstract functions that must be implemented:
  • getType()
    • You must return the plugin ID here.
  • performCommand()
    • This central method calls all command related methods and checks the permissions.
  • getAfterCreationCmd()
    • After creation of a new object, the user is redirected to this command.
  • getStandardCmd()
    • This command is used, as a target for permanent links.

Please notice the way the performCommand() method handles incoming commands, especially how commands are grouped per permission that is needed to execute the command. This code ensures that no command is executed without the appropriate permission to do so. Please do not add a "default" branch to this switch structure, since it would make the whole setting less secure.

You should also overwite the setTabs() method that defines the set of tabs occuring on the screen. You must include the info and permission tab within this function.

The standard template is already initialized with title/icon/locator when performCommand() is called. All you need to do is to generate the HTML output and to pass it to $tpl->setContent(...). The example uses the ILIAS form class to generate a HTML form.

classes/class.ilObj<PluginName>Access.php

If you need to make any access related actions (e.g. check if an object is online) please visit the repository object plugin page. The OrgUnit Extension handles the access in the exact same way!

Container objects like categories, courses or group must create instances of access classes of all types of objects that are occuring on the screen. This can cost a lot of memory if the access classes create instances of large objects. Please avoid this and use small methods that access your database tables directly within the access class.

classes/class.ilObj<PluginName>ListGUI.php

The ListGUI classes are used to present the object in container listings, e.g. in a course or in a category. The class defines the commands that should be available already on the container level (usually displayed as an "Action" drop-down list) and properties that should be displayed under the title and the description.

<?php
 
require_once "Modules/OrgUnit/classes/Extension/class.ilOrgUnitExtensionListGUI.php";
 
/**
* Class ilObjTestOrgUnitExtensionListGUI
*
* @author Oskar Truffer <ot@studer-raimann.ch>
*/

class ilObjTestOrgUnitExtensionListGUI extends ilOrgUnitExtensionListGUI {
 
function getGuiClass() {
return "ilObjTestOrgUnitExtensionGUI";
}
 
/**
* @return array return an array with 3 keys: permission,
*/

function initCommands() {
return array
(
array(
"permission" => "read",
"cmd" => "show",
"default" => true)
);
}
 
function initType() {
$this->setType("xsre");
}
}
The following abstract methods must be overwritten in this class:
  • initType()
    • You must set the type to your plugin ID here.
  • getGuiClass()
    • This returns the GUI class, that handles the commands. Usually this is the main GUI class of your plugin.
  • initCommands()
    • This returns all commands that should be listed within container objects like categories or courses. One command should be flagged as "default" command ("default" => true). This one is put behind the title link.

Additionally you can overwrite the getProperties() method and provide property/value pairs that should be listed within the container listing.

Container objects like categories, courses or group must create instances of ListGUI classes of all types of objects that are occuring on the screen. This can cost a lot of memory if the access classes create instances of large objects. Please avoid this and use your corresponding access class to get any information from the database.

lang/ilias_<LangKey>.lang

Some general information on how internationalization is handled in plugins can be found in the main plugin documentation.

obj_xexo#:#Example
objs_xexo#:#Examples
obj_xexo_duplicate#:#Copy
objs_xexo_duplicate#:#Copy Example
obj_xexo_select#:#Select Example
xexo_add#:#Add Example
xexo_new#:#Add New Example
xexo_read#:#Read access to Example
xexo_write#:#Edit Example
xexo_delete#:#Delete Example
xexo_visible#:#Example is visible
xexo_edit_permission#:#Change permission settings
crs_create_xexo#:#Create Example
grp_create_xexo#:#Create Example
fold_create_xexo#:#Create Example
root_create_xexo#:#Create Example
cat_create_xexo#:#Create Example

The lang file must contain the entries listed above. Replace "xexo" with your plugin ID.

Download Full Example

The example plugin can be found here:

https://github.com/ILIAS-eLearning/TestOrgUnitExtension

Please report any bugs to our bug tracker.