====== Better Navigation Template Details ======
===== Credit =====
The foundation of my Better Navigation template work has been borrowed from the work done by [[mailto:chris@knowledge.teevee|Chris]]. More info can be found [[http://wiki.jalakai.co.uk/dokuwiki|here]]. In particular, I reused the following:
* the idea to define the sidebar content in a specific wiki page
* the idea to have a sidebar page per namespace and look up the most appropriate one
* the way to use the stylesheet to position the sidebar
* the php and css code, as a starting point
I extended and adapted the implementation to achieve my goals.
===== Goals =====
I had a number of design goals with my Better Navigation template:
* Make sure all [[issues]] are addressed
* No changes to the core DokuWiki code
* Minimal changes to the default stylesheet, same philosophy and no tricks
===== Code implementation details =====
==== Introduction ====
The Better Navigation template uses some supporting php code. This has been placed in ''sidebar.php'' file in the ''sidebar'' directory. This file is automatically included in the ''main.php'' file in the same directory. The following sections describe the details for the php function.
==== Finding the master sidebar file ====
// recursive function to establish best sidebar file to be used
function getSidebarFN($ns, $file) {
// check for wiki page = $ns:$file (or $file where no namespace)
$nsFile = ($ns) ? "$ns:$file" : $file;
if (file_exists(wikiFN($nsFile))) return wikiFN($nsFile);
// remove deepest namespace level and call function recursively
// no namespace left, exit with no file found
if (!$ns) return '';
$i = strrpos($ns, ":");
$ns = ($i) ? substr($ns, 0, $i) : false;
return getSidebarFN($ns, $file);
}
The ''getSidebarFN'' function is used to lookup the wiki page that contains the sidebar content. It is the page called ''sidebar'' in the current namespace, or in the namespace "closest" to the current one.
==== Generating the sidebar xhtml ====
/**
* Returns xhtml for a virtual local sidebar file
* based on instructions from a master file
*
* Uses and creates a cachefile
*
* @author Jan Decaluwe
* by adapting the p_cached_xhtml function in dokuwiki
*
*/
function p_sidebar_cached_xhtml($localFile, $masterFile){
global $conf;
$cache = getCacheName($localFile.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.xhtml');
$purge = $conf['cachedir'].'/purgefile';
// check if cache can be used
$cachetime = @filemtime($cache); // 0 if not exists
if( @file_exists($masterFile) // does the source exist
&& $cachetime > @filemtime($masterFile) // cache is fresh
&& ((time() - $cachetime) < $conf['cachetime']) // and is cachefile young enough
&& !isset($_REQUEST['purge']) // no purge param was set
&& ($cachetime > @filemtime($purge)) // and newer than the purgefile
&& ($cachetime > @filemtime(DOKU_INC.'conf/dokuwiki.php')) // newer than the config file
&& ($cachetime > @filemtime(DOKU_INC.'conf/local.php')) // newer than the local config file
&& ($cachetime > @filemtime(DOKU_INC.'inc/parser/xhtml.php')) // newer than the renderer
&& ($cachetime > @filemtime(DOKU_INC.'inc/parser/parser.php')) // newer than the parser
&& ($cachetime > @filemtime(DOKU_INC.'inc/parser/handler.php')))// newer than the handler
{
//well then use the cache
$parsed = io_readfile($cache);
$parsed .= "\n\n";
}else{
$parsed = p_render('xhtml', p_cached_instructions($masterFile),$info); //try to use cached instructions
if($info['cache']){
io_saveFile($cache,$parsed); //save cachefile
$parsed .= "\n\n";
}else{
@unlink($cache); //try to delete cachefile
$parsed .= "\n\n";
}
}
return $parsed;
}
The ''p_sidebar_cached_xhtml_sidebar'' function returns the xhtml for the sidebar. This function has a degree of sophistication that warrants further explanation. As can be seen, the xhtml is cached based on a "local" filename, but the instructions come from a "master" file. In this way, the same instructions from a master sidebar file can generate different xhtml versions for the local sidebars. As the xhtml generation is influenced by the current page ''$ID'', this mechanism is used to accomplish one of my goals (see [[issues]]), namely that a navigation link to the current page should be highlighted.
Note that the plain text version of the local sidebar file doesn't actually have to exist - it can be a virtual file with a well-chosen file name.
==== The top-level function ====
function html_sidebar() {
global $ID;
global $ACT;
if ($ACT != 'show') return '';
// determine master sidebar file
$masterFile = getSidebarFN(getNS($ID), 'sidebar');
// open sidebar
echo("