====== 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 [[devel:events_list|Events List]]. The **eventCheck** [[xref>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''. */ 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 [[devel:caching|several documented ways]] to disable the use of cached pages, without disabling caching altogether. The most flexible is a 'BEFORE' handler for the [[devel:event:parser_cache_use|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 [[event_objects#parser_cache_use|dokuwiki\Cache\CacheParser Object]]. The file being processed is identified by two of the **data** fields, ''%%$event->data->file%%'' and ''%%$event->data->page%%'': - **file** holds the full path of the file being fetched. - **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: - **age**: the max age allowed for the cached version before it is considered expired. - **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:
Then you can check the $_REQUEST array for "refresh" and when it's present refresh the page. ====Headers and Footers==== Using [[devel:event:tpl_act_render|TPL_ACT_RENDER]], it's possible to add text to the top and bottom of a wiki page. TPL_ACT_RENDER is signalled by [[xref>tpl_content()]], which is called from ''main.php'' to output the wiki page to the browser: 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.((See the sample [[event_objects#tpl_act_render|TPL_ACT_RENDER object]].)) 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.((The page can be determined from ''$_REQUEST['id']'' and the IP from ''$_SERVER['REMOTE_ADDR']''.)) ====Content Modification==== There are several events which give handlers a chance to modify the text: * [[devel:event:parser_wikitext_preprocess|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. * [[devel:event:renderer_content_postprocess|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]''. * [[devel:event:io_wikipage_write|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 [[devel:action_plugins#Examples]] section of the Action Plugin development docs.