The "Tech. Arch."

Architecting Forward ::>

DokuWiki, Plug It In, Plug It In …

Recently I have spent a good amount of personal and quality time with DokuWiki. I found it to be a very powerful and extensible platform primarily due to it plugin architecture. The plugins I have found the most useful are tag and topic. I am documenting the technical patterns and supporting frameworks of our enterprise architecture and the tag mechanism allows me to classify the content in a way that makes it very easy to reference with topic plugin.

When documenting frameworks I realized I wanted to not only provide code snippets but also reference to actual source code. Since .NET produces an XML documentation file for each class (providing you have been supplying the information in your code) I was interested in creating a plugin that would make it easy to include the documentation inside the wiki. So I started to dig into how to create a plugin. Luckily since some existing plugins are simple and well-documented the process was easier than I thought.

Here is how to create a simple plugin, around the now canonical (or should I say infamous?) hello world.

Approach:

The overall approach consists of the following steps:

  • defining the syntax (i.e. keywords and format) for our plugin:
~~hello message~~
  • tell Dokuwiki to call our plugin when the keyword is encountered
  • handle the custom display

Steps:

Let’s get started:

  • Create a new folder named after your plugin (e.g. myplugin) under \lib\plugin
  • Create a file named syntax.php in that folder
  • Define the class for your plugin:

class syntax_plugin_hello extends DokuWiki_Syntax_Plugin {

}

  • Add the getInfo function to the class to provide some metatadata about your plugin

function getInfo(){
return array(
'author' => 'Philippe Monnet',
'email'  => 'pmonnet@pulte.com',

'date'   => '2008-06-28',
'name'   => 'Hello Plugin',
'desc'   => 'Says hello',
'url'    => 'http://architecture/doku.php?id=technicalarchitecture:frameworks:dokuwiki:helloplugin:overview',
);
  • Add the getType and getPType as follows:

function getType(){ return 'substition'; }
function getPType(){ return 'block'; }
  • Add a new getSort function indicating the sort level of your plugin (in the list of plugins)
  function getSort(){ return 700; }
  • Let’s define the syntax of our tag with the following format in a new function named **connectTo** with a parameter of **($mode)**
function connectTo($mode) {
$this->Lexer->addSpecialPattern('~~hello .*?~~', $mode, 'plugin_hello');
}

This function will essentially register a pattern route for the syntax we defined and will route the request to our plugin.

  • Define the handle function responsible for parsing the tag:
  function handle($match, $state, $pos, &$handler){
$match = substr($match, 8, -2); // strip markup (from after ~~hello  i.e. position 8 to before ~~ i.e. -2 from the end
return array(trim($match)); #message
} 
  • Finally we need to define the render function for our tag:
  function render($mode, &$renderer, $data)
{
if ($data === false) return false;
$message = $data;
if ($mode == 'xhtml')
{
// prevent caching to ensure the included pages are always fresh
$renderer->info['cache'] = false;

// and render
$renderer->doc .= $message;
$renderer->doc .= DOKU_LF;
return true;
}

return false;
}

Example:

~~hello Hi there, fellow wiki readers !

Results:
Hi there, fellow wiki readers !

Recap:
A simple content-oriented plugin requires the following:

Artifact Purpose
Subclass of DokuWiki_Syntax_Plugin Encapsulates the behavior of the plugin
getInfo function Describes the plugin
getType function Should mostly always return ‘substitution’
getPType function Should mostly always return ‘block’
getSort function Should return a number
connectTo function Connects your plugin to the Dokuwiki engine so that it can handle the tag
handle function Parses the syntax of a tag when encountered on a page
render function Renders the output of the plugin

More complex plugins can be developed:

  • action-oriented: i.e. executing the tag performs an action on the site (e.g. may persist data). Example: the tag plugin.
  • administration-oriented: i.e. they will be available from the Admin page. Example the usermanager plugin.

So that’s it. I was able to create my csharpdoc plugin after that example and get it up and running in the wiki. Ah if only DokuWiki was written in Ruby instead of PHP … ;-)

June 29th, 2008 Posted by | plugin, Wiki | no comments