Skip to content

Dokuwiki plugins

hamstar edited this page Sep 11, 2012 · 7 revisions

This page will show you how to make a Dokuwiki plugin. You are expected to have a working knowledge of PHP and how get and post work.

See also: https://www.dokuwiki.org/development

File Structure

You should use the plugin wizard to generate you a skeleton plugin. It is most likely that you will want an action plugin to do stuff to the system which is what this how to will focus on. You should read the rest of page before generating a plugin to get a better idea of the wizard.

  • The plugins reside in /var/lib/dokuwiki/lib/plugins/.

Action plugins

Action plugins are based around an action (i.e. a request) generating an event. The Dokuwiki plugin system allows you to hook into the action and do something before or after the event.

Basic plugin structure

The classname should be action_plugin_<plugin-name> and should extend DokuWiki_Action_Plugin where <plugin-name> is the same as the folder name it resides in.

You will need a method called register(&$controller) which will register your plugin with the controller by telling it when to run the plugin (using hooks).

See this example from the autobackup plugin:

public function register(Doku_Event_Handler &$controller) {

  $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_action_act_preprocess');
  $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'handle_tpl_content_display');
  $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handle_tpl_act_unknown');
  $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call_unknown');   
}

As you can see, you register a hook using the register_hook($hook, $when, $class, $method) method:

  • $hook is the event to hook to to run
  • $when is when to run it ('BEFORE' or 'AFTER' the event takes place)
  • $class is the class holding the method you want to run
  • $method is the method in that class to run

The $method that is called needs to accept a parameter passed by reference called &$event. This is an event object that holds data relevant to the event that just happened. For certain hooks that event object holds data you can modify before it is sent to the page. Like so:

public function handle_tpl_content_display(Doku_Event &$event, $param) {
  $event->data .= "this text will be displayed on every page";
}

There are also ways to inspect what page you are currently so you will only add that text to like the user profile page or any page in the namespace braincase.

Lets inspect a couple of hooks (or events) that you would most likely use:

This event allows you to do something before (or after) the current event take place. $_GET['do'] is available in $event->data.

public function handle_action_act_preprocess(Doku_Event &$event, $param) {

  global $USERINFO; // get access to the userinfo

  switch ( $event->data ) {
    case 'admin': # was the request doku.php?do=admin ?
      Logger::info("security: {$USERINFO['name']} accessed the admin panel ");
      break;
  }
}

This event allows you to get the XHTML content about to be printed to the page by looking in $event->data. You'll probably only want to modify the XHTML before this hook.

public function handle_tpl_content_display(Doku_Event &$event, $param) {
  
  $this->_add_file_icons_to_download_links( $event );
}

Split this function out to keep the handle_ methods nice and clean:

private function _add_file_icons_to_download_links( &$event ) { // pass by reference
  
  $text = $event->data;
  // .. add links here
  $event->data = $text;
}

This event is called when the action (e.g. $_GET['do']) does not have a page to display for it. This is a good place to catch stuff for custom actions you've setup. $event->data contains the XHTML you want to print to the page (if need be there are ways to access the markdown to xhtml parser).

public function handle_tpl_act_unknown(Doku_Event &$event, $param) {
  
  $event->data = $this->_build_backup_form();
}

This event is run when value of $_GET['call'] (stored in $event->data to be OOP) to ajax.php is unknown to Dokuwiki. This is a good place to catch stuff that you send to ajax.php page (e.g. data from ajax scripts).

public function handle_ajax_call_unknown(Doku_Event &$event, $param) {
  
  global $INPUT;

  switch ( $event->data ) {
    case "autocomplete":
      if ( !$INPUT->post->has("name") )
        return; # TODO: return an error

      $names = $this->_get_possible_names( $INPUT->post->str("name") );
      echo json_encode( 'names' => $names );
      break;
  }
}

The Environment

There is some stuff you can access in the dokuwiki environment. Unfortunately it is mostly globals which is somewhat bad programming practice but there are ways to do this in an object oriented way.

  • $INPUT is a class for handling input from user (and is escaped and validated before you access it). You can check if $INPUT has a field by doing $INPUT->post->has("do") and get that field by doing $INPUT->post->str("do").

  • $INFO contains information about the current page and user

  • $USERINFO holds just the information for the user

OOP it

To get around using globals so much only call the globals in the handle_ method. Then pass them (you shouldn't need to edit them so not by reference) to objects that you create.

public function handle_tpl_content_display(Doku_Event &$event, $param) {
  
  global $USERINFO;
  global $INPUT;
  global $INFO;

  $mfc = MyFancyClass($USERINFO, $INPUT, $INFO);
  $mfc->do_stuff();
  $event->data.= $mfc->get_stuff();
}
Clone this wiki locally