TannerRitchie Web Applications

Advanced Web Application Development in the GTHA

Joomla – prevent it from displaying per-page modules in results

There are a few things I don’t like about Joomla. Well there are quite a lot of things I don’t like about Joomla, although the love-hate is roughly equal to my view of Drupal. They’re powerful tools, but you sometimes feel you waste roughly as much time unpicking another developer’s idea of what makes sense as you save time by using the CMS.

So, this might be useful to somebody.

Joomla’s new Smart Search added in Joomla 2.5, like the standard search before, styles its result pages according to the page the search is called from. So, if you start a search on the home page, and your home page includes lots of custom modules only suitable to appear on the home page, Joomla will stick them right onto the end (or start) of your search results, creating an unholy mess.

How to stop it? Googling suggested various things to do with hidden menus. Basically, create a hidden menu with the search module on it, and then switch modules off. That this is the ‘official’ way to do something says everything you need to know about the menu approach Joomla employs. Menus are central to how Joomla works. If something is not mentioned on a menu somewhere, then there are many things that Joomla won’t let you do. When things aren’t in menus (as much stuff isn’t), things get tough.

In any case, I couldn’t get this workaround to work – maybe I missed something key, but my view is, if it doesn’t leap out at me after 20 minutes then it’s bad design. A ‘pretend’ menu that exists only to prevent an unwelcome behaviour doesn’t seem optimal.

So, that forces you into template overrides as the way to fix the problem. Template overrides means you can override any bit of HTML output in Joomla core by copying it to your template and putting in in the directory JOOMLA_INSTALL/templates/templatename/html/mod_modulename/default.php. Great, but you can’t override files that the template file calls, only the template file itself. In this case, what needed to happen was for the following hidden form field to be removed, because it was responsible for Joomla insisting on styling results like the home page:

<input type="hidden" name="Itemid" value="123" />

In short, if Itemid 123 in the database has a whole load of modules enabled, they will be shown in the search results because of this line. The hidden input needs to die.

But the hidden input is created, not in a template file, but a helper file …

JOOMLA/modules/mod_finder/helper.php

Since that can’t be overwritten, you basically need to copy this entire static object in that file,

    public static function getGetFields($route = null)
    {
        $fields = null;
        $uri = JURI::getInstance(JRoute::_($route));
        $uri->delVar('q');

        // Create hidden input elements for each part of the URI.
        // Add the current menu id if it doesn't have one
        $needId = true;
        foreach ($uri->getQuery(true) as $n => $v)
        {
            $fields .= '<input type="hidden" name="' . $n . '" value="' . $v . '" />';
            if ($n == 'Itemid') {
                $needId = false;
            }
        }
        if ($needId) {
            //$fields .= '<input type="hidden" name="Itemid" value="' . JFactory::getApplication()->input->get('Itemid', '0', 'int') . '" />';
            $fields .= '<input type="hidden" name="Itemid" value="999999"/>';
        }
        return $fields;
    }

And rewrite it to be an old school PHP function in the template override file called
JOOMLA/templates/mytemplate/html/mod_finder/default.php

This is what I created to prevent the Itemid ever being sent to the search page:

function getGetFields($route = null)
    {
        $fields = null;
        $uri = JURI::getInstance(JRoute::_($route));
        $uri->delVar('q');

        // Create hidden input elements for each part of the URI.
        // PREVENT MENU ID MESSING UP SEARCH DISPLAY

        foreach ($uri->getQuery(true) as $n => $v)
        {
            if ($n != 'ItemId')
            $fields .= '<input type="hidden" name="' . $n . '" value="' . $v . '" />';
        }

        return $fields;
    }

Then you need to finally replace this line in the same file:

<?php echo modFinderHelper::getGetFields($route); ?>

with this one:

<?php echo getGetFields($route);?>