Translations of this page?:

Event Handlers: Sample Code

eventCheck

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 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 it in a directory named eventCheck in lib/plugins.

<?php
 
if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'action.php');

 
class action_plugin_eventCheck extends DokuWiki_Action_Plugin { 

  
  /**
   * return some info
   */
  function getInfo(){
    return array(
		 'author' => 'Myron Turner',
		 'email'  => 'turnermm@my-provider.ca',
		 'date'   => '2007-09-18',
		 'name'   => 'Event Check',
		 'desc'   => 'Checks Events',
		 'url'    => 'http://www.mturner.org/htmlOKay'
		 );
  }
 

  /*
   * Register its handlers with the DokuWiki's event controller
   */
  function register(&$controller) {

       $events = array 
            (
            '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 $evt) {
        $controller->register_hook($evt, 'BEFORE', $this, 'write_event_before');    
        $controller->register_hook($evt, 'AFTER', $this, 'write_event_after');    
    }
 }


 function write_event_before (&$event, $param) {
         $this->write_event ($event, $param,'BEFORE');
 }
 function write_event_after (&$event, $param) {
        $this->write_event ($event, $param, 'AFTER');
 }
   
 function write_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 cache 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 expiry time in seconds; this is set in the Configuration Manager, and defaults to 24 hours
  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] are older than $event→data→depends[age] seconds then the cache will be refreshed. One of these files is 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, although I have never tried this myself, presumably it is possible to alter the age field to greater or lesser values.

The basic technique to refresh a page is this:

      $event->preventDefault();
      $event->stopPropagation();
      $event->result = false;

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.
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: 2008/11/07 21:50 by 70.103.232.219
 

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported

Imprint Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki
WikiForumIRCBugsDarcsXRefTranslate