4. Building website with henkari

4.1. Getting started

With it's default file handler Section 4.3.2 henkari does pretty much nothing different when comparing to an ordinary webserver. Usually the first thing to do is to register handlers for the filetypes you want henkari to be aware of. Builtin html-handler (see Section 4.3.3) with default directory and file handlers should be enough for small and moderate websites. You can register html handler by creating to your root directory a dothenkari (file named .henkari or _henkari) with the following content.

 <?php
 $hf =& handlerFactory::getInstance();
 $hf->registerHandler('text/html', 'htmlHandler');
 ?>

Now when you have html handler enabled on your website html files behave intelligetly with templates and you can start building your website.

4.2. Template system

Henkari uses templates from phplib. Phplib templates are ordinary html files with some "magical" markings. Words within curly braces are {markers} that are to be replaced with some content that is spesific to viewed page. These markers are called template variables.

Henkari automatically provides content for number of template variables (see Section 4.4). With those template variables known by henkari you can describe how your template should be used. i.e. Where to put page content, last modification time, table of contents, etc. The most important template variable is {content} which is replaced with the content of page. You should always have it in every template you create.

Name of the template file is _template.html and you may (but you are not required to) have one in each directory in your henkari webtree. First template encountered is used as master template. If another template is found when walking further along request path, it's nested in master template (if not explisitly set otherwise, see Section 3.3.2).

Master template is used directly, no modifications are done. In nesting operation master template's {content} -variable is replaced with the content of nested template's <body> tag.

References in templates must be written so that they don't break when pages in different directories are wrapped in the same template. Assume we have in webroot a stylesheet file style.css, template having

<link rel="stylesheet" type="text/css" href="style.css">

and also two pages, one in webroot and another in a directory under webroot. When the first page in webroot is requested everyting works fine, but on the second page stylesheet is not found because it's looked from the directory where the page is in. So we must use absolute address for stylesheet. At this point henkari helps us a little. There's a template variable {entrypoint_uri} which is automatically replaced with an address to henkari webroot. So we can write

<link rel="stylesheet" type="text/css" href="{entrypoint_uri}style.css">

4.3. Handlers

Henkari has a subsystem called "handler factory". It's given a filename and it decides which handler should that file be given to. Handlers provide the actual functionality. Handlers that you want to use, must be properly registered to handler factory. Henkari comes with a number of predefined handlers, but only default directory handler (see Section 4.3.1) and default file handler (see Section 4.3.2) are used unless you register more.

Next sections describe the handlers coming with henkari distribution.

4.3.1. Directories (dirHandler)

This is the default directory handler. It's used when filename given to handler factory points to a directory. In the real world it means that dirHandler is used until recursion reaches the requested file (if there is one) or another directory handler is registered. Assume we have site http://www.somesite.net/somepath/, entrypoint directory /entry/point/dir/ and request http://www.somesite.net/somepath/index.php/some/file.html coming in. Now /entry/point/dir/root/ and /entry/point/dir/root/some/ are given to dirHandler and /entry/point/dir/root/some/file.html by default to As-is file handler.

dirHandler is responsible of the most of henkari core functionality: Executing per-directory special file dothenkari (see Section 3.3.3), setting per-directory templates (see Section 4.2), interpreting per-directory special file dotindex (see Section 3.3.2), creating table of contents, menu and path (see Section 4.4.1)

4.3.2. Files "as-is" (asisHandler)

This is the default file handler. It's used when filename given to handler factory points to an ordinary file and no other handlers are registered to be responsible of handling that file. This handler just sets Content-type: http header to reflect the MIME-type of the file and sends the content of that file, which is pretty much what would (efectively) happen without henkari.

If you for example want to have a download-link and direct browsing (as described in Section 4.3.5) link to a gzip package, "intelliget" behavior of henkari is not desired. As-is file handler can be forced by giving a http get parameter asis value yes. (Append ?asis=yes to download url)

4.3.3. Html files (htmlHandler)

This handler makes henkari behave more intelligently with html files. When handled by htmlHandler, html files are embedded to page template (see Section 4.2), content of html file's <body> tag is appended to page content (which gets at it's turn to replace {content} template variable), content of html file's <title> tag is appended to page title and so on.

4.3.4. Php scripts (phpHandler)

This handler executes (with include()) a php script, buffers it's output and appends the output to page content. There are no special requirements to php scripts executed with phpHandler. There are a few minor limitations though. Script is not executed in global namespace as a plain php script without henkari would but in phpHandler::handle(). Remember to explisitely introduce global variables as global. If you want to bypass the template system you have to use UI::responseData and UI::addHeader() (see Section 5.3) to make your response work and have it correctly cached. I could look like this.

<?php
// Get user interface
$ui =& UI::getInstance();

// Set response content type
$ui->addHeader('Content-type: application/x-shockwave-flash');

// Set response data
$swf_data = create_some_nifty_flash();
$ui->responseData = $swf_data;
?>

Simple rule for generating your own response from within henkari means first retrieving instance of UI and replacing "header()" with "UI::addHeader()" and "echo" with "UI::responseData .=".

4.3.5. Packages (tarHandler, gzipHandler)

These two handlers make tar and gzip -packages behave exactly like directories. If a tar or gzip -package is requested, handler extracts the package to a temporary directory and recurses into it pretty much as directory handler would.

4.3.6. Ejsc scripts (ejscHandler)

This is an example of more advanced handler. It glues together a powerfull online geometric construction tool and a script compiler resulting remarkable ease of construction authoring. To learn more about these tools visit (JavaSketchpad homepage and read about Extended JavaSketchpad Construction Compiler from it's manual.

ejscHandler compiles requested script with ejscc and appends the result to template variable "construction". "Local" template scriptfile.ejsc.html is used if found and builtin default template otherwise. If script has preprocessor directives of the form

 #define DEFAULT_variablename variablevalue

Now template variable "variablename" is set to "variablevalue" if not overriden by http get or post -parameter which takes precendance. Default template has variables "string_name" (page title), "appletheight", "appletwidth", "codebase" (applet codebase, set default in config.php) and "construction" (place for JSP construction).

If you want to set, say page title form script, you put the following line in ejsc script file.

 #define DEFAULT_string_name MyTitle

You can change it's template behaviour with ejsc_template -parameter. It has the following possible values.

local

Local template (scriptfile.ejsc.html) is used (if found, otherwise default) and template is nested.

default

Default template is used and it's nested.

plain_local

As local but template is set root (no previously set templates are used).

plain_default

As default but template is set root.

4.3.7. Statement lists (statementlistHandler)

Simple way to set up true-false quiz. [FIXME: Complete this...]

4.4. Automatic template variables

Template variables (those strings in curly braces) get replaced by associated value if the data containing the variable is handled by template system. Package handlers and asisHandler don't use template system to produce their output (package handlers don't provide any output and asisHandler serves the plain file as it is).

Next chapters provide a brief but comprehensive description on the template variables that have automagical content.

4.4.1. Navigational elements

A separate "label mapper" is responsible of mapping filenames to viewed names. If dirHandler encounters a map or pseudo command in dotindex configuration file it adds a corresponding name mapping rule to label mapper. Default mapping is to remove file extension and leading number (if not configured otherwise), replace underscores with spaces and capitalize first letter. A few examples:

 a_file.txt --> A file
 03_directory --> Directory
 fancy_name_with_date_1.1.2000.html --> Fancy name with date 1.1.2000

All these automatic navigational elements use those mapped names for files and directories.

You can change the way these automatical elements render. Look for the available configuration items from lib/henkariConfig.php.

{TOC}

Table of contents reflects the underlying filesystem structure with exceptions described in dotindex -files (see Section 3.3.2). It folds automatically to form a minimal tree still having all the children of requested item visible.

{menu}

Menu contains parent and all the children of requested item. You can hide parent item from menu. Just put "hide \.\." in your dotindex.

{path}

Path contains (as it's name suggests) the path from main page up to and including the viewed page. All path items are links which point to correspondig pages.

4.4.2. Other automatic template variables

{entrypoint_uri}

Is replaced (a bit counter-intuitively) with an absolute path to root directory of this entrypoint. Assume you have henkari in henkari/ with no special tricks (url rewrite, etc.) under your personal webspace which is visible on http://www.myhost.com/~myself/ and mystyles.css in your henkari/root/css/ and you want to link it from you template with an absolute address so that it works in on every page. You can write {entrypoint_uri}/css/mystyles.css and henkari resolves it to /~myself/henkari/index.php/css/mystyles.css.

{this_uri}

Is replaced with an absolute path (see {entrypoint_uri}) to requested file.

{base_uri}

Is replaced with an absolute path (see {entrypoint_uri}) to the directory where requested file/directory resides.

{title}

Page title is placed here. Title is put together from pieces separated by $config->title->separator and pieces are taken from titles of nested templates in the order they appear (and from requested html file if htmlHandler was registered).

{content}

Page content is placed here.

{date_modified}

Is replaced with the last modification time of requested file/directory (if it exists). You can set date format in configuration.

4.5. Includes

There's a special form of template variable (wich isn't actually handled with template system, but it behaves the same way) called include.Includes look like this.

 {#include random_file.html}
 {#include /random/location/random_file.html}
 {#include http://randomhost/awesomereport.html}

Only whitespace allowed is the single space before filename. Two first examples are local files and the last one is a webpage. Local paths are taken relative to entrypoint directory. Content of the included file is assumed to be (x)html. <body> tag is searched and if it's found only its contents are used. Otherwise the whole file is included.

If you have fopen wrappers enabled on your php you can use ftp-paths and specify host port. If fopen wrappers are not availabe henkari uses builtin web retrieve which only supports http and port 80.

Note that only htmlHandler has this feature enabled. Includes work only in files handled by htmlHandler unless you define your own handler which uses this feature (see Section 5).

4.6. Builtin server side cache

Every query is mapped to $config->cachefile in $config->cachedir (which you can set in config.php. If cachefile is found (and cache is on, i.e. $config->cache = true, default is off) the file (along with its headers) is sent to browser and no handlers are created.

If you change website content and want the pages be refreshed you have to empty cache directory. If you only have changed single page you only have to delete cache files of that particular page. Name of cachefile is of the form

 henkaricache[requestpath].[crc]

Where [requestpath] is the requested path slashes (/) replaced with hashes (#) and [crc] is crc32 polynomial of serialized http parameters. So if you changed root/info/news.html you only have to issue the following command in cache directory

bash$ rm -f henkaricache#info#news.html.*

Cache is turned on from configuration where also the cachedir is set (as previously described). If you want to use cache (why not!) make sure that $config->cachedir exists and is writable by php. Note that sometimes server-side scripts (as php) are run with their owner/creator's account and sometimes with webserver's account. Find out wich one applies to your host and change cachedir's permissions to allow php-scripts to write there.