Wikka Menus

Last edited by NilsLindenberg:
Replaces old-style internal links with new pipe-split links.
Fri, 20 May 2016 07:38 UTC [diff]

This is an improved version of a module for creating and managing custom Wikka menus.
The module uses a dedicated wikka_menus table, in which the settings for several menus can be stored, along with their CSS selectors.
This version allows menus to be created, modified, (safely) renamed and (safely) deleted.
The output is an unordered list (<ul>) of menu items, which can then be formatted as a horizontal or vertical menu through the appropriate CSS style.

Beside adding links, Wikka administrators will be able to add items such as text, images and action-generated content (provided there are actions that do the job).
In order to use actions in WikkaMenus, the current system links that are present in the header and footer menu have to be 'modularized', i.e. saved as actions so as to let Wikka admins free to decide whether to display them or not.

See WikkaMenulets for more information on action-generated content for menu items

Why a menu table?
  1. it is much safer having a script modify single table entries than write into the Wikka configuration file (which contains all system settings).
  1. it is possible to create as many menus as needed, without cluttering up the system configuration, and store each menu in the table along with a CSS class/id that will determine its appearance on the page;

Here's how the menu interface looks like:

Menu Configuration

Please enter menu items on separate lines.
You can use on each line:
camelcase links like: PageIndex
forced links like: [[RecentChanges | What's new?]]
actions like: {{who}}

Menu: main_menu


Menu: logged_in_menu


Menu: footer_menu


Create a new menu
Menu name:
CSS class:


1. Create the table
Updated 2004-11-16: field names modified

You will need to change your wikka prefix, e.g. "wikka_", to match your configuration.
Menus are identified through their name which is unique, content is a \n-separated list of links, css_class is a CSS selector. Different menus can have the same css_class.
I removed the sample INSERT, since new menus can be built using the interface below

CREATE TABLE `wikka_menus` (
  `name` varchar(20) NOT NULL default '',
  `content` varchar(255) NOT NULL default '',
  `css_class` varchar(20) NOT NULL default '',
UNIQUE KEY `name` (`name`)

2. Add the menu functions in libs/Wakka.class.php
Updated 2004-11-17: more compact functions

function LoadMenu($name) {
    $content = $this->LoadSingle("SELECT * FROM ".$this->config["table_prefix"]."menus WHERE name = '".$name."'");
    return $content;

function LoadAllMenus() {
    $menurow = $this->LoadAll("SELECT * FROM ".$this->config["table_prefix"]."menus");
    return $menurow;

function SaveMenu($name, $content) {
    $this->Query("UPDATE ".$this->config["table_prefix"]."menus SET content ='".mysql_real_escape_string(trim(str_replace("\r", "", $content)))."' WHERE name = '".$name."' LIMIT 1");

function MenuExists($name) {
    if ($this->LoadMenu($name)){
        return true;

function RenameMenu($oldname, $newname) {
    $this->Query("UPDATE ".$this->config["table_prefix"]."menus SET name = '".$newname."' WHERE name = '".$oldname."' LIMIT 1");

function DeleteMenu($name) {
    $this->Query("DELETE FROM ".$this->config["table_prefix"]."menus WHERE name = '".$name."' LIMIT 1");

function CreateMenu($name, $css_class) {
    $this->Query("INSERT INTO ".$this->config["table_prefix"]."menus SET name = '".mysql_real_escape_string($name)."', content = '', css_class = '".mysql_real_escape_string($css_class)."'");

function TrimMenu($list) {
    foreach (explode("\n", $list) as $line) {
        $line = trim($line);
        $trimmed_list .= $line."\n";
    return $trimmed_list;

function PrintMenu($name) {
    if ($menurow = $this->LoadMenu($name)) {
        $menu = "<ul class=\"".$menurow["css_class"]."\">";
        foreach (explode("\n", $menurow["content"]) as $menuitem){          $menu .="<li>".$this->Format($menuitem)."</li>\n";
    $menu .= "</ul>\n";
    return $menu;

3. Create the menu configuration interface (action/menu.php)
Updated 2004-11-16: Menus can be now created, deleted, renamed and modified

//  Menu Configuration Interface
// Version 1.0

<h3>Menu Configuration</h3>
<br />

if ($this->IsAdmin()) {
    switch ($_POST["operation"]) {
    case "Create Menu":
        if ($this->MenuExists($_POST["newname"])) {
            echo $this->Format("<<**Sorry!** --- A menu named \"".$_POST["newname"]."\" already exists. --- Please choose another name<<::c::--- --- ");
        } else {
            $this->CreateMenu($_POST["newname"], $_POST["css"]);
            echo $this->Format("<<**Thanks!** --- Menu \"".$_POST["newname"]."\" has been created<<::c:: --- ");

    case "Delete Menu":
        echo $this->Format("<<**Confirmation required**<<::c:: --- Do you really want to delete **".$_POST["name"]."**? --- --- ");
        $formdelete =   '<input type="hidden" name="name" value="'.$_POST["name"].'" />'.
            '<input type="submit" name="operation" value="Confirm Deletion" style="width: 120px" accesskey="s" />'.
            '<input type="button" value="Cancel" onClick="history.back();" style="width: 120px" /><p>&nbsp;</p>';
        print $this->FormOpen("","","post");
        print $formdelete;
        print $this->FormClose();

    case "Confirm Deletion":
            echo $this->Format("<<**Thanks!** --- Menu \"".$_POST["name"]."\" has been deleted<<::c:: --- ");

    case "Rename Menu":
        if ($this->MenuExists($_POST["newname"])) {
            echo $this->Format("<<**Sorry!** --- A menu named \"".$_POST["newname"]."\" already exists. --- Please choose another name<<::c:: --- --- ");
        } else {
            echo $this->Format("<<**Confirmation required**<<::c:: --- Do you really want to rename **".$_POST["name"]."** as **".$_POST["newname"]."**? --- --- ");
            $formrename =  '<input type="hidden" name="oldname" value="'.$_POST["name"].'" />'.
                '<input type="hidden" name="newname" value="'.$_POST["newname"].'" />'.
                '<input type="submit" name="operation" value="Confirm Rename" style="width: 120px" accesskey="s" />'.
                '<input type="button" value="Cancel" onClick="history.back();" style="width: 120px" /><p>&nbsp;</p>';  
            print $this->FormOpen("","","post");
            print $formrename;
            print $this->FormClose();

    case "Confirm Rename":
        $this->RenameMenu($_POST["oldname"], $_POST["newname"]);
        echo $this->Format("<<**Thanks!** --- Menu has been renamed as \"".$_POST["newname"]."\"<<::c:: --- --- ");

    case "Update Menu":
        $this->SaveMenu($_POST["name"], $this->TrimMenu($_POST["content"]));
        echo $this->Format("<<**Menu configuration stored** --- Thanks for updating \"".$_POST["name"]."\"!<<::c:: --- --- ");

    // load stored menus and print menu forms
    echo $this->Format('Please enter menu items on separate lines. --- You can either use //""CamelCase"" links// like ##""PageIndex""## --- or //forced links// like: ##""[[http://www.mydomain.com | External Link]]""## --- --- --- ');
    $allmenus = $this->LoadAllMenus();
    foreach ($allmenus as $item) {
        $formarray[$item["name"]] = 'Menu: <strong>'.$item["name"].'</strong><br />'.
            '<input type="hidden" name="name" value="'.$item["name"].'" />'.
            '<textarea name="content" rows="6" cols="30">'.$item["content"].'</textarea><br />'.
            '<input type="submit" name="operation" value="Update Menu" style="width: 120px" accesskey="s" />'.
            '<input type="submit" name="operation" value="Delete Menu" style="width: 120px" /><br />'.
            '<input type="text" name="newname" value="'.$item["name"].'" style="width: 120px">'.
            '<input type="submit" name="operation" value="Rename Menu" style="width: 120px" /><p>&nbsp;</p>';
        print $this->FormOpen("","","post");
        echo $formarray[$item["name"]];

    // "Create menu" form
    $newmenuform = '<table><tr>'.
        '<td>Menu name:</td><td><input type="text" name="newname" value="new_menu_name" style="width: 120px"></td></tr>'.
        '<tr><td>CSS class:</td><td> <input type="text" name="css" value="css_class" style="width: 120px"><td></tr></table>'.
        '<input type="submit" name="operation" value="Create Menu" style="width: 120px" /><br />';
    echo $this->Format("== Create a new menu ==");
    print $this->FormOpen("","","post");
    echo $newmenuform;
} else {
    print("<em>Sorry, only Wikka Administrators can modify the Menu configuration.</em>");


4. Create the appropriare CSS styles

Here's a basic example for formatting a Wikka Menu as a horizontal menu. Change the CSS class (main_menu) to match the one you specified when creating a menu.

.main_menu {
	width: 100%;
	list-style-type: none;
.main_menu li {
	padding: 2pt;
	float: left;
	width: auto;
	margin-right: 3pt;
	text-align: center;
.main_menu .exttail {
	visibility: hidden;

5. Use the menus in your wiki pages

Once you've set the appropriate CSS styles, two different usages of custom Wikka Menus are possible:

You can either print your menus in the page header, by modifying actions/header.php as follows
Updated 2004-11-17: typo in previous version - sorry!

original actions/header.php
<?php echo $this->Link($this->config["root_page"]); ?> ::
        if ($this->GetUser()) {
            echo $this->config["logged_in_navigation_links"] ? $this->Format($this->config["logged_in_navigation_links"])." :: " : "";
            echo "You are ".$this->Format($this->GetUserName());
        } else {
            echo $this->config["navigation_links"] ? $this->Format($this->config["navigation_links"]) : "";

modified actions/header.php
if ($this->GetUser()) {
        echo $this->PrintMenu("logged_in_menu");
} else {
        echo $this->PrintMenu("main_menu");

or use them in the page body, through a simple action action/printmenu.php which can be called on the page with a syntax like {{printmenu name="main_menu"}}
Updated 2004-11-16: replaced $type with $name

//  Print Menu action
echo $this->PrintMenu($name);


To Do

-- DarTar

There are 40 comments on this page. [Show comments]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki