-
Notifications
You must be signed in to change notification settings - Fork 1
DevelopModule
CM5 has a very flexible module system that is completely event driven. For the needs of the module, the author can reuse internal CM5 libraries, or even include a foreign framework (although it is not preferable). The interaction with the CM5 core is done in the form of events, where a module can be informed and optionally mangle data at different stages (fetching from database, rendering, etc)...
To create a module the following steps are needed:
- Create the folder of module.
- Provide the module.php file which describes module
- Provide a subclass of CM5_Module which declares the management interface of module.
Every module is organized under its own subfolder in the modules folder. The name of the folder must consist of lower case letters, numbers dashes (-) or hyphens (_). The internal structure of module is the author's decision. The only prerequisite is that it provides the file module.php which describes the module.
...
+ lib
+ modules
+ contactform
+ lib
-> module.php
+ revisions
+ install
-> module.php
+ foobar
+ lib
-> myclass.php
-> module.php
...
Every module must provide a module.php file. This file must return an associative array with module properties. The key values of this array are:
- class : The name of the class that implements the management interface of module.
- nickname: A small nickname, that must be the same as module's folder name.
- title: A human descriptive title of the module.
- description: An one line description of the module.
An example for the module foobar would be:
<?php
// Optionally include needed files
require_once __DIR__ . "lib/ModuleFoobar.php"
// Return the module description array
return array(
'class' => 'CM5_Module_Foobar',
'nickname' => 'foobar',
'title' => 'Foo Bar',
'description' => 'A module to foo and bar',
);
?>
Note: As this is the only file that is been included by the CM5 core, if you need to refer to classes or functions that exist in other files inside your module folder, you must include them manually here.
To actually interact with Core you have to provide a subclass of CM5_Module, and override any needed method. This is mandatory even for the most minimal module.
class CM5_Module_Foobar extends CM5_Module {
public function onInitialize(){
// Code to be run on every request
}
}
For more information about CM5_Module check in the next section.
As previously mentioned the interaction with Core is done through events, and the basic management of module (enable, disable, run, configuration ...) is done through the interface of CM5_Module.
Basic management interface is implemented by overriding or using methods of CM5_Module.
This function is called by the core when it needs to "wake up" a module that a page request is in the process. This function is executed early enough so that is a good place to put your event consuming code. If a page is cached, modules are not woke up so this function will not be called.
Exposed events by the CM5 Core that can be consumed are documented at API-events page.
If a user enables this module, Core will execute this function. It is the best place to put code that prepares the environment for the module. Some modules can create extra tables in database, indexes etc...
This is executed when a user disables the module. Here you can put code for cleaning up changes that was done on the environment.
CM5_Module also provides a way to optionally expose a configuration UI. When a module implements the configuration API, an extra "configure" button will be shown at administrators panel under the module's area. This button will navigate to a page with the configuration controls as described in the module.
If you want to provide a configuration, you need to implement this function and return an associative array with all fields. Each entry key is the nickname of the configuration field and each value is another associative array with field options.
Accepted field options are:
- label : A text to be shown near the UI control of this field.
- type: The type of field, acceptable values are (text, color, select, checkbox)
- optionlist: If the type can have options (like select), this is an array with all options that will be shown.
Example:
return array(
'bg-color' => array('type' => 'color', 'label' => 'Background Color'),
'fg-color' => array('type' => 'color', 'label' => 'Foreground Color'),
'show-title' => array('type' => 'checkbox', 'label' => 'Show title')
);
Sometimes you need to provide default values for each entry in the configuration. This can be done by returning an associative array, where key is the name of the config (as described in getConfigurableFields) and value the default one.
Example:
return array(
'bg-color' => '#FFFFFF',
'fg-color' => '#000000',
'show-title' => true
);
In the following subsections, you will find minimal examples showing same cases.
This module, listens for page requests and if the "/myfavorite/url" url is requested, it returns a document with content "Hello world from module!".
class CM5_Module_UrlInteract {
public function onEventPageRequest($event) {
$response = $event->arguments['response'];
if ($event->arguments['url'] == '/myfavorite/url') {
$event->filtered_value = true;
$response->document = "Hello World from module!"
}
}
public function onInitialize() {
$c = CM5_Core::getInstance();
$c->events()->connect('page.request', array($this, onEventPageRequest'));
}
}
This modules, adds an HTML footer at the end of all pages with the last updated date.
class CM5_Module_AddFooter {
public function onPagePostRender($event) {
$response = $resp = $event->filtered_value;
$page = $event->arguments['page'];
$lm = Output_DateFormat($page->lastmodified);
$response .= '<em> This page was last updated at' . $lm->human_diff() .'</em>'
}
public function onInitialize() {
$c = CM5_Core::getInstance();
$c->events()->connect('page.post-render', array($this, 'onPagePostRender'));
}
}