MediaWiki custom navigation menu (old style)

InfoDabble > Tech Notes > MediaWiki > MediaWiki custom navigation menu (old style)
Jump to: navigation, search
No longer used. Use DynamicFunctionsEx for #userid: and MediaWiki:Sidebar instead.

The navigation bar provides links to the most important locations in the wiki and supplies site administrators with a place to add a persistent collection of links. For instance, most wikis will link to their main page and some useful tools.

MediaWiki provides a standard mechanism to customize the navigation bar: Manual:Navigation bar.

The standard method is perfect for a static menu, but I wanted to provide a different menu if the user is logged in. Unfortunately, there doesn't seem to be a standard MediaWiki Variable for the user state, so we need to use code.

[edit] Checking if the user is logged in

The Raskin Center has a nice discussion of how they customized their wiki: Hacked Mediawiki Files:

"Besides moving around the order of the sidebars, the big change involved checking whether the user is logged in. This is done using a php hack (there ought to be a better way to do this):"

## Create a variable that is true (0) if the user is logged in.
$logged_in = 1;
if (sizeof($this->data['personal_urls']) > 1)
{
     $logged_in = 0;
}

[edit] Extending the Code

[edit] How the navigation menu is built

The navigation menu starts with an outline in the main message file. From MessagesEn.php:

/* The sidebar for MonoBook is generated from this message. Lines that do not 
begin with * or ** are discarded, furthermore lines that do begin with ** and do not 
contain | are also discarded, but don't depend on this behaviour for future releases. 
Also note that since each list value is wrapped in a unique XHTML id it should only 
appear once and include characters that are legal XHTML id names. */
$messages = array(
'sidebar' => '
* navigation
** mainpage|mainpage
** portal-url|portal
** currentevents-url|currentevents
** recentchanges-url|recentchanges
** randompage-url|randompage
** helppage|help
** sitesupport-url|sitesupport',

During initialization, this is parsed into a language- and site-specific data array:

$this->data['sidebar'] = {
  ["navigation"]=>
  array(7) {
    [0]=> array(4) {
      ["text"]=>    string(9) "Main Page"
      ["href"]=>    string(30) "/wiki/index.php/Main_Page"
      ["id"]=>       string(10) "n-mainpage"
      ["active"]=> bool(false)
    }
    [1]=> array(4) {
      ["text"]=>    string(16) "Community portal"
      ["href"]=>    string(48) "/wiki/index.php/Wiki:Community_Portal"
      ["id"]=>       string(8) "n-portal"
      ["active"]=> bool(false)
    }
    [2]=> array(4) {
      ["text"]=>    string(14) "Current events"
      ["href"]=>    string(35) "/wiki/index.php/Current_events"
      ["id"]=>       string(15) "n-currentevents"
      ["active"]=> bool(false)
    }
    [3]=> array(4) {
      ["text"]=>    string(14) "Recent changes"
      ["href"]=>    string(42) "/wiki/index.php/Special:Recentchanges"
      ["id"]=>       string(15) "n-recentchanges"
      ["active"]=> bool(false)
    }
    [4]=> array(4) {
      ["text"]=>    string(11) "Random page"
      ["href"]=>    string(35) "/wiki/index.php/Special:Random"
      ["id"]=>       string(12) "n-randompage"
      ["active"]=> bool(false)
    }
    [5]=> array(4) {
      ["text"]=>    string(4) "Help"
      ["href"]=>    string(34) "/wiki/index.php/Help:Contents"
      ["id"]=>       string(6) "n-help"
      ["active"]=> bool(false)
    }
    [6]=> array(4) {
      ["text"]=>    string(9) "Donations"
      ["href"]=>    string(44) "/wiki/index.php/Wiki:Site_support"
      ["id"]=>       string(13) "n-sitesupport"
      ["active"]=> bool(false)
    }
  }
};

The data array is ultimately used in the skin class to build the navigation menu:

<!-- Navigation Menu -->
<div id="p-navigation">
    <?php foreach ($this->data['sidebar'] as $bar => $cont) { ?>
          <ul>
          <?php foreach($cont as $key => $val) { ?>
               <li id="<?php echo htmlspecialchars($val['id']) ?>" <?php if ( $val['active'] ) { ?> class="active" <?php } ?>>
               <a href="<?php echo htmlspecialchars($val['href']) ?>"><?php echo htmlspecialchars($val['text']) ?></a>
               </li>
          <?php } ?>
          </ul>
     <?php } ?>
</div> <!-- End of Navigation Menu -->

The final HTML looks like this:

<!-- Navigation Menu -->
<div id="p-navigation">
    <ul>
        <li id="n-mainpage" >       <a href="/wiki/index.php/Main_Page">Main Page</a></li>
        <li id="n-portal" >             <a href="/wiki/index.php/Wiki:Community_Portal">Community portal</a></li>
        <li id="n-currentevents" > <a href="/wiki/index.php/Current_events">Current events</a></li>
        <li id="n-recentchanges" ><a href="/wiki/index.php/Special:Recentchanges">Recent changes</a></li>
        <li id="n-randompage" >   <a href="/wiki/index.php/Special:Random">Random page</a></li>
        <li id="n-help" >               <a href="/wiki/index.php/Help:Contents">Help</a></li>
        <li id="n-sitesupport" >     <a href="/wiki/index.php/Wiki:Site_support">Donations</a></li>
   </ul>
</div> <!-- End of Navigation Menu -->

[edit] Customized site navigation menu

While it's easy to customize the navigation menu in a custom skin, a more generic approach is helpful. A relatively clean way to do this is to use the existing MediaWiki markup extension support.

MediaWiki extensions live in the extensions/ subdirectory in the MediaWiki installation. To create your own extension, first create a new file called YourExtensionName.php in this directory containing the following template code:

<?php
 
$wgExtensionFunctions[] = "wfCustomMenus";
 
function wfCustomMenus() {
	global $wgParser;
}
 
?>

Note that, unlike a regular parser extension, no rendering callback is registered.

All it takes to install the extension is adding a single line to the end of your LocalSettings.php file (above the "?>"):

require_once 'extensions/CustomMenus.php';

and you are ready to go. Go to the sandbox and see if it works.


SkinTemplate.php 161:

$tpl = $this->setupTemplate( $this->template, 'skins' );

Line 458:

$tpl->set( 'sidebar', $this->buildSidebar() );
$tpl->set( 'nav_urls', $this->buildNavUrls() );

Skin.php 1587:

function buildSidebar() {

Here's the basic extension function. It's crude in that it overwrites the global message cache, but it works.

<?php
 
$wgExtensionFunctions[] = "wfCustomMenus";
 
function wfCustomMenus() {
	global $wgLang;
 
	# The following line is necessary to load the message cache
	$message = $wgLang->getMessage( 'sidebar' );
 
	$wgLang->messages[ 'sidebar' ] = '
* navigation
** mainpage|mainpage
** Apollo_17_Flight_Journal|Flight Journal
** Category:Apollo_Flight_Journal_-_notes|AFJ Notes
** Special:Categories|Categories
** Special:Allpages|All Pages
** Special:Newpages|New Pages
** recentchanges-url|recentchanges
** helppage|help';
 
}
 
?>