DokuWiki

It's better when it's simple

User Tools

Site Tools


devel:event_handlers_code

Event Handlers: Sample Code

eventCheck Plugin

eventCheck is a plugin that dumps output on all events, as they are being fired, to a file called eventcheck.txt in your main DokuWiki directory, labeling the 'BEFORE' and 'AFTER' phases of each event. A great deal of data accumulates in a very short time, so you may eventually want to exclude any events you are not currently interested in.

A good way to use this plugin is to check its output against the descriptions of the event objects in the DokuWiki Events List.

The eventCheck register() method registers all current DokuWiki events in both 'BEFORE' and 'AFTER' modes. This code illustrates that one plugin can accommodate multiple event handlers and that, where convenient, the same callbacks can be used for more than one handler. To use this plugin place the action.php file in a directory named eventcheck in lib/plugins.

lib/plugins/eventcheck/action.php
<?php
 
use dokuwiki\Extension\ActionPlugin;
use dokuwiki\Extension\Event;
use dokuwiki\Extension\EventHandler;
 
/**
 * @author Myron Turner <turnermm@my-provider.ca>
 */
class action_plugin_eventcheck extends ActionPlugin { 
 
 
    /**
     * Register its handlers with the DokuWiki's event controller
     */
    public function register(EventHandler $controller) {
 
        $events = [
            'ACTION_HEADERS_SEND', 'HTML_PAGE_FROMTEMPLATE', 
            'HTML_PROFILEFORM_INJECTION', 'HTML_REGISTERFORM_INJECTION', 
            'IO_NAMESPACE_CREATED', 'IO_NAMESPACE_DELETED', 
            'IO_WIKIPAGE_READ', 'IO_WIKIPAGE_WRITE', 'PARSER_CACHE_USE',
            'PARSER_HANDLER_DONE','PARSER_WIKITEXT_PREPROCESS',
            'RENDERER_CONTENT_POSTPROCESS', 'TPL_ACT_RENDER',
            'TPL_CONTENT_DISPLAY', 'TPL_METAHEADER_OUTPUT'
        ];
 
        foreach($events as $event) {
            $controller->register_hook($event, 'BEFORE', $this, 'writeEventBefore');
            $controller->register_hook($event, 'AFTER', $this, 'writeEventAfter'); 
        }
    }
 
    /**
     * Handle write action before event
     *
     * @param Event $event event object by reference
     * @param mixed $param empty optional 5th parameter of register_hook()
     * @return void
     */
    public function writeEventBefore (Event $event, $param) {
        $this->writeEvent ($event, $param,'BEFORE');
    }
 
    /**
     * Handle write action after event
     *
     * @param Event $event event object by reference
     * @param mixed $param empty optional 5th parameter of register_hook()
     * @return void
     */
    public function writeEventAfter (Event $event, $param) {
        $this->writeEvent ($event, $param, 'AFTER');
    }
 
    /**
     * Write event information to file
     * 
     * @param Event $event event object by reference
     * @param mixed $param empty
     * @param string $advise the advise the hook receives
     */
    protected function writeEvent (Event $event, $param = null, $advise) {     
        $filename = DOKU_INC . 'eventcheck.txt';
        if (!$handle = fopen($filename, 'a')) {
            return;    
        }
 
        $somecontent = "\n --- $advise ---\n";
        $somecontent .= "\$_REQUEST: " . print_r($_REQUEST, true) . "\n";
        $somecontent .= print_r($event, true) . "\n";
 
        fwrite($handle, $somecontent);
        fclose($handle);
    }
}

Some Practical Solutions

Caching

There are several documented ways to disable the use of cached pages, without disabling caching altogether. The most flexible is a 'BEFORE' handler for the PARSER_CACHE_USE event. It enables you to set up conditions which will force a page to be refreshed. The conditions are necessary; otherwise you might end up by-passing the cache altogether.

The data field of the PARSER_CACHE_USE event is a dokuwiki\Cache\CacheParser Object. The file being processed is identified by two of the data fields, $event->data->file and $event->data->page:

  1. file holds the full path of the file being fetched.
  2. page holds the name of the page, in namespace format

Of particular importance for modifying the caching process is the depends array ($event->data->depends), which has two elements:

  1. age: the max age allowed for the cached version before it is considered expired.
  2. files: the files on which the page depends; they are preset in inc/cache.php and are the same for all pages

If any of the files in $event->data->depends[files] were modified more recently than the cache file then the cache will be refreshed. One of these files is the local wiki configuration file, local.php –which explains why one of the techniques recommended to refresh the cache is to update the timestamp on local.php:

touch local.php

It is possible to add files to the depends['files'] array and it is also possible to alter the age field to lesser values (or greater values, though this should be done with care as some other part of dokuwiki is suggesting the cache should be refreshed at the earlier age).

The basic technique to refresh a page is this:

$event->preventDefault();   // stop dokuwiki carrying out its own checks
$event->stopPropagation();  // avoid other handlers of this event, changing our decision here
$event->result = false;     // don't use the cached version

To do the reverse, that is to force the use of a cached page, set result to true:

$event->result = true;

It's possible to add a refresh button to your toolbar:

<form class="button" method="get" action="doku.php">
    <div class="no">
        <input type="hidden" name="do" value="show" />
        <input type="hidden" name="refresh" value="yes" />
        <input type="hidden" name="id" value="<?php echo $ID; ?>" />
        <input type="submit" value="Refresh" class="button"  />
    </div>
</form>

Then you can check the $_REQUEST array for “refresh” and when it's present refresh the page.

Headers and Footers

Using TPL_ACT_RENDER, it's possible to add text to the top and bottom of a wiki page. TPL_ACT_RENDER is signalled by tpl_content(), which is called from main.php to output the wiki page to the browser:

<!-- wikipage start -->
<?php tpl_content() ?>
<!-- wikipage stop -->

While this event is in effect, the text is held in a buffer outside of its reach and cannot be modified. However, anything written to standard output (echo, print) will appear either above or below the page, depending on whether it has originated in the BEFORE or AFTER phase of the handler. The headers and footers appear on the screen but do not get written to the page files. This makes them ideal for outputting messages on the fly. When the user is editing a page, the header will appear above the standard instructions: “Edit the page and hit Save. See syntax . . . ” During a login session, it will appear above the Login title. What action is currently being processed can be determined from the data field ($event->data), which holds the name of the current action–edit, show, login, etc.1)

TPL_ACT_RENDER provides a powerful option. You can stop the page from being printed to the screen by making the following calls:

$event->preventDefault()
$event->stopPropagation()

The page will not appear on the screen, but any text output from the handler will, enabling you to substitute your own message for the page. Assume, for instance, that certain pages can be viewed only by users from particular IP addresses, who may not be registered with your DokuWiki. You can substitute for the page a message indicating that this page is not available for viewing.2)

Content Modification

There are several events which give handlers a chance to modify the text:

  • PARSER_WIKITEXT_PREPROCESS: here $event->data holds the complete text as marked up in DokuWiki syntax. The modified text will appear in the browser, but it is not saved to disk.
  • RENDERER_CONTENT_POSTPROCESS: here the marked up text has been converted to XHTML. As in the above, the modified text appears in browser but is not saved to disk. The text is found in data[1].
  • IO_WIKIPAGE_WRITE: this event writes the text with modifications to disk. At the same time, the text, with any modifications, is returned to the browser. The text is in DokuWiki format and is found in $event->data[0][1]; event->data[0][0] holds the absolute path of the file.

More examples

See also the Examples section of the Action Plugin development docs.

1)
See the sample TPL_ACT_RENDER object.
2)
The page can be determined from $_REQUEST['id'] and the IP from $_SERVER['REMOTE_ADDR'].
devel/event_handlers_code.txt · Last modified: 2023-09-02 13:53 by Klap-in

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki