splitbrain/dokuwiki — pull request #396 by roverrobot (2013-10-22 07:38:55+00:00)
Title: A third attempt to modularize the actions

Again, this patch set is intended for discussion about how to modularize actions.

The main problem that this patch set tries to solve is that, currently, the core action handling code is sort of convoluted, there is a script actions.php for action handling, where all actions are lumped together, it is not quite easy to see how many actions are defines, and how they are defined. There is another set of rendering functions in another script html.php. To understand what an action does, one needs to refer to at least 4 functions to pick out pieces from each.

One resulting problem is that it is not very easy to define new actions or extend currently defined actions. In the core, one needs to tack into this convolution. In plugins, one needs to intercept the ACTION_ACT_PREPROCESS event, which has its own problems:
a) It does not easily resolve conflicts in action handling: what if two plugins define two different ways to acting on an action?
b) it also requires the understanding of the current convolution of action handling in the core to be sure how to correctly handle permission, handling, and rendering without interfering with the current logic.

This patch set addresses these problems by
1. Define an interface for action (command, or do=*, not the event handlers) handlers, that abstract away the logic for determining the permissions of an action, and the general logic of handling chains of actions and render the html output.
2. Separate the logics of each action into their own classes. Each handler needs to provide functions to specify:
a) the action that they can handle
b) the permission that is required for the action
c) how to handle the action, and what action should be performed in chain.
3. Separate action handling from rendering whenever that makes sense. A renderer needs to provide functiosn to specify
a) the action that they can render
b) how to render
4. Before an action is handled, a set of preprocessors can be defined to respond to this action are informed, so that they can customize the global data before handling an action. They just prepare data, and do not define the action logic.
5. After the handling of an action but before rendering, a set of post-processors can be defined to customize the global data for rendering. Again, they prepare data, and do no define the rendering logic.

These pre- and post-processors simplify the process of customizing the actions without redefining the handling and rendering logic. If the handling or rendering logic needs to be altered, one can simply extend the original handler or renderer class, and the child handler/renderer automatically replaces their parent handler/renderers.

To define new actions, put a script containing the definition of handler and renderer in inc/commands folder with the name of the action they respond to. To define/extend an action in a plugin, put a script containing the pre- or post-processors (or inherit from the handler/renderer class) with the same name of the action it handles, in the plugin's commands folder.

This patch set is based on a previous attempt (in my dokuwiki/actions branch). They main changes are
1. removed the original components structure.
2. lazy loading of actions. Now, only the script defining the action to be handled are loaded, all the other action handlers/renderers are left without being loaded.
3. the separation of handling, data pre- and post-processing, and rendering.

This seems to result in a slight performance boost from the master branch. By running
ab -n 10000 http://my-dokuwiki/
for 100 times and compute the average time, this patch set achieved 4.8646 seconds while the master finished in 4.8782 seconds. Not much, but definitely not a loss.

Any comments?