Creating custom navigation with MidCOM

One frequent question I see on #midgard is how to customize the default navigation options shipping with the MidCOM template site. In my opinion, there are two options: Either stick with the existing navigation styles and customize via CSS, or roll your own in PHP.

MidCOM provides a wonderful tool called Navigation Access Point (NAP) for site designers want to create their own custom navigation systems. It provides a PHP programming interface for listing the site structure. First, a bit of NAP terminology:

Directory, or subtopic in the MidCOM site structure
Page, or article under a node
Both nodes and leaves under a given node
Root node
The first level node, or front page of MidCOM site

Constructing the navigation happens in two steps:

  1. Figure out where you are:
    $current_node = $GLOBALS["midcom_site"]['nap']->get_current_node();
  2. List the children of the node:
    $children = $GLOBALS["midcom_site"]['nap']->list_child_elements($current_node);

The $children array contains both nodes and leaves under the $current_node in NAP array format which you can then traverse:

foreach ($children as $child) {

As we're listing all child elements from the node instead of only nodes with list_nodes() or leaves with list_leaves() we next need to instantiate correct child type for display:

if ($child[MIDCOM_NAV_TYPE] == "node") {
    // This is a subtopic, instantiate it as node
    $node = $GLOBALS["midcom_site"]['nap']->get_node($child[MIDCOM_NAV_ID]);

    // Display the link in whatever way you want
    echo "<div><a href=\"".$node[MIDCOM_NAV_URL]."\">".$node[MIDCOM_NAV_NAME]);</a></div>\n";
   // This is where you would place a call for listing children of the node

} elseif ($child[MIDCOM_NAV_TYPE] == "leaf") {
    // This is an article (or event or some other document type)
    $leaf = $GLOBALS["midcom_site"]['nap']->get_leaf($child[MIDCOM_NAV_ID]);

    // Display the link
    echo "<div><a href=\"".$leaf[MIDCOM_NAV_URL]."\">".$leaf[MIDCOM_NAV_NAME]);</a></div>\n";

And there you have a very simple navigation listing of children under your current directory. You can easily modify this to list children of your root node by switching from get_current_node() method to get_root_node() method.

This example also doesn't check for possible content visibility settings. You can check for these using the MIDCOM_NAV_VISIBLE boolean in the node and leaf arrays.

In the other news, if you get error "Apache2(98)Address already in use: make_sock: could not bind to address" when restarting Apache after addition of a new VirtualHost with datagard, the problem is that you have multiple "Listen 80" directives in your Apache configuration. Comment out the one in /etc/midgard/apache/httpd.conf.

Figured this one when troubleshooting with Robert Guerra from Canada.

Read more Midgard posts.