Page 1 of 2
The Joomla menu system is very easy to use but the menu items are stored in the database and cannot be easily changed according to the state of the system. Normally this doesn't matter but recently it was brought to my attention the fact that the Login menu item on our site didn't change to Logout when the user was logged in - even though when you clicked on it you were taken to a logout page.
This isn't a huge problem but it can be embarrassing when a fellow programmer points out that your site doesn't do what other sites appear to do without effort.
So I set to solving the problem....
First a quick reminder of how the Joomla menu system works. All menus are created by the mainmenu module which is loaded into any position on the page you want the menu to display. You can have as many mainmenu modules as you like and hence, despite its name, not all of the menus it renders are "main".
The menu module always generates the same sort of HTML which is then made to look different with the use of suitable styles.
For example, if you create a menu with three items - item1,item2 and item3 the HTML generated is basically:
To make the menu work it also generates an anchor tag around each item with a link to the web page that clicking on the item transfers the user to. This makes the actual generated HTML more like:
The HTML generated for the administrative menu on our site is:
<li id="current" class="active item8">
You can see that it follows the structure described above with the addition of some id and class attributes.
In this particular case what we want to do is change Login i.e. item8 to Logoff when the user is signed in and this cannot be done using the standard facilities provided by the mainmenu module because it stores the menu items in the database and there is no way to generate these of the fly.
So how can we change the menu item as the page is rendered?
There are a number of ways of doing this and perhaps the most satisfying would be to create a custom mainmenu module - dynamicmenu module say and build in the general facility for menu items to be rendered by PHP code. However this would take quite some effort and for a one off change represents a big investment.
My first thought about other ways of achieving the same result was to add to the PHP contained in the site template. The idea is that the PHP in the site template is run as the page is being constructed and can test for things like the user's logged on state.
The only problem is that tackling the problem this way means writing PHP to modify HTML that other PHP code has generated. This isn't too difficult in that you can retrieve the HTML generated so far within the template but in this case it does us no good.
The reason is that the template is rendered in two distinct stages.
- The first stage reads the template and executes any PHP code it contains to create a template that has nothing but HTML and some Joomla tags.
- The second stage reads the partially rendered template and replaces any Joomla tags with the output of any modules that are to be loaded.
If you think about this for a minute you can see that at the point any PHP code in the template is executed the output of the modules and in particular the output of the menu module we are interested in changing isn't in the partially rendered template.