5. Extending

To extend henkari features you need at least basic programming skills and knowledge of php programming language (see http://www.php.net/).

Henkari is extended by creating your own php scripts which take advantage of henkari environment. Another more advanced way is to create and register your own handler(s) to be responsible of your own special files.

5.1. User defined handlers

Possibilities with handlers are next to infinite. You could for example have handler for files containing SQL, which would connect database, execute query and render the result to html table. More advanced one would be general image handler, which would verify that the type of requested image is found from Accept-Encoding header and if not, would try to convert requested image to one of the accepted types if possible.

User defined handler is a correct solution when you have multitude of files that must be somehow prepared for viewing. Need for special behavior in a single point on your website is easier to satisfy by simple php-script.

Creating your own handler starts (after you have decided that you really need it and this is the correct answer to problem in hand) with deciding where to put the physical file(s). If your handlers are strictly entrypoint spesific, you can create a directory for them under your entrypoint, for example lib_local/. If your handler could be used more widely consider making it GPL, (eventually) placing it in your lib/ and informing henkari author. Next is to devise a name. Naming convention for handlers is fooHandler where foo is the name of the thing this handler is intended to deal with. This will be the name of your handler class. Name the file containing the class fooHandler.class.php.

You define a handler by inheriting from abstractHandler and overriding handle(). The following is the classic done properly as henkari handler.

<?php 
class helloHandler extends abstractHandler {
  function handle() {
    $ui =& UI::getInstance();
    $hello = 'Hello World!';
    $ui-<pageTitle($hello);
    $ui-<appendToPage($hello);
  }
}
?>

This is of course pretty braindead handler, because it doesn't do anything with the file it was commanded to handle.

Your newly defined handler is put into action by registering it to be responsible of files of certain type. Let's given an example of it by putting our new handler to handle *.hello files. This is accomplished by registering a file type and a handler for it in dothenkari. Assume that guidelines given for placing and naming handlers have been followed.

<?php
$mi =& MIME::getInstance();
$mi-<bindExtensionToType('hello', 'application/x-hellotrigger');
$hf =& handlerFactory::getInstance();
$hf-<registerHandler('application/x-hellotrigger', 
                     'helloHandler', 
                     'lib_local/helloHandler.class.php');
?>

First we bind file extension hello to a fabricated mime type. The the mime type is registered to be handled with helloHandler which is defined in lib_local/helloHandler.class.php relative to the entrypoint. Now for example request for file say.hello results to a page saying "Hello World!" and your template neatly wrapped over it.

To learn more about the possibilities, read short interface descriptions (see Section 5.3) and read sources.

5.2. Your PHP scripts in henkari

In henkari php scripts work pretty much as one would expect. You have henkari environment available, output of script ends up to page content and so on. You only have to keep in mind that your php code is executed in handle() function of phpHandler, and not in global namespace as it normally would. This might change in future releases of php, so refer to php documentation to see how include() works.

5.3. Interfaces

This is short description of the interfaces of henkari core components. Useful member functions and properties are described.

5.3.1. UI

Don't instantiate this class! Call UI::getInstance() to obtain an instance. Remember to assign return value from getInstance() with referece assignment operator "=&".

tpl

An instance of phplib Template class. Set template variables using tpl->set_var($name, $value);.

labelMapper

An instance of henkariLabelMapper inherited from labelMapper. See interface description of labelMapper.

responseData

Holds the actual data to be sent in response to the recieved request. This becomes set only after handler recursion has been done. You can't check "what the page would look like" from here. If you want to bypass template system and all the nice features included, you can do it by setting the result data you want to this variable (and propably set headers too). asisHandler does this. Check an example from lib/asisHandler.class.php.

setTemplate($template, $override=false)

Set page template. The first variable is the template (itself, not filename). Template is set to be root template when no template was previously se or $override is true. More about templates in Section 4.2.

addHeader($h)

Adds a http header to response. Use this if your response is of different type than text/html. See lib/asisHandler.class.php as an example.

appendToPage($str, $var=false)

Appends given string to template variable. If no variable is given content is used.

pageTitle($str, $append=false)

Sets page title to be given string. If $append is true string is appended to variable, otherwise previous value is overriden. pageTitle('My Title', true); is equivalent to appendToPage('My Title', 'title');

isUndefined($variable)

Checks if template system contains variable of given name as undefined variable. In here "undefined" means that there's {varname} somewhere in template, page content, etc. but there's no defined value corresponding to that variable.

appendTo[TOC,Path,Menu]($uri, $label)

Add an item to navigational elements, table of contents, path or menu. Takes as parameters the address and visible text to be used in links.

5.3.2. labelMapper

setLabel($key, $label)

Sets the label of a key.

getLabel($key)

Returns the label corresponding to a key. If a label for requested key was explicitely set with setLabel() it's used. Otherwise label is obtained from defaultLabel().

defaultLabel($key)

Returns a default label for given key.

5.3.3. handlerFactory

Don't instantiate this class! Call handlerFactory::getInstance() to obtain an instance. Remember to assign return value from getInstance() with referece assignment operator "=&".

registerHandler($mime, $classname, $classfile='')

Registers class of given name to be responsible of handling the files of given type. If classfile is not explicitely given, the default policy lib/[classname].class.php is assumed.

createHandler($root_uri, $filename, $patharray)

Instantiates a handler for $filename and returns a reference to it. Remember to assign return value with referece assignment operator "=&". Other parameters are needed for handler instantiation. Read the description of abstractHandler interface to learn more about them.

5.3.4. abstractHandler

patharray

Request path from handled file to requested file. Stored in an array. For example random/path/file.html would be array("random", "path", "file.html").

filename

Actual file (or directory) to be handled.

root_uri

Base for references created by this handler. In other words items contained by the thing pointed by filename have root_uri as their base web address.

isDirectory

True if handled file is a directory. Defaults to false.

tmpdir

A directory where temporary files and directories created by this handler should be placed in.

createTmpDir()

Create a new temporary directory inside default temporary directory and set tmpdir to point to this newly created directory.

removeTmpDir()

Remove temporary directory created with createTmpDir(). If no new directory has been created this has no effect.

filecontents($file)

Returns the contents of given file. Return value is empty if file doesn't exist or it cannot be read.

parseNested($page)

Parse includes on given page. Read more from Section 4.5.

writePathEntry($trailing_slash = false)

Appends handled file to navigational element {path} (see Section 4.4). Trailing slash is appeded to directories. Behavior of this function can be controlled with $config->path->files configuration option. It has three possible values: 'none' (no files are shown in path) 'noindex' (index -files are hidden from path, default) 'all' (all files are shown in path). Directories are always shown.

handle()

Override this when you create your own handler.

5.3.5. MIME

Don't instantiate this class! Call MIME::getInstance() to obtain an instance. Remember to assign return value from getInstance() with referece assignment operator "=&".

generic_type

This mime type is returned when a mime type for file extension with no bindings is requested.

getMimeTypeByFilename($filename)

Returns an educated guess on mimetype based on filename.

getMimeTypeByExtension($extension)

Returns an educated guess on mimetype based on file extension.

bindExtensionToType($ext, $type)

Binds the given file extension to given mime type.