Creating a System Plugin to augment JRouter
From Joomla! Documentation
The "J2.5" namespace is a namespace scheduled to be archived. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.
JRouter Modifications[edit]
The Joomla! Router can be modified with additional rules by using the attatchBuildRules and attatchParseRules methods. Ideally, this can be done from a system plugin so these rules will apply globally.
Here are 2 examples of modifying JRouter using rules and a System Plugin. One will augment the results returned by JRouter while the other will completely replace the results returned by JRouter
Augmentation[edit]
JRouter returns an array of variables which are then used through the API by JInput to override the actual _GET/_POST/_REQUEST variables. If you merely want to augment the variables being returned, then this is straightforward.
class plgSystemMyRouterAugmentor extends JPlugin
{
/**
* @return void
*/
public function onAfterInitialise()
{
$app = JFactory::getApplication();
// Get the router
$router = $app->getRouter();
// Add my own rule:
// Create a callback array to call the augmentRoute method of this object
$augmentRouteCallback = array($this, 'augmentRoute');
// Attach the callback to the router
$router->attachBuildRule($augmentRouteCallback);
}
/**
* @param JRouterSite $router The Joomla site Router
* @param JURI $uri The URI to parse
*
* @return array The array of processed URI variables
*/
public function augmentRoute($router, $uri)
{
$vars = array();
// Do something to the vars
$vars['augment'] = 'succeeded';
/**
* In this case, now to any Joomla! component/module it will look like
* ?augment=succeeded was in the url
*/
return $vars;
}
}
Replacement[edit]
JRouter returns an array of variables which are then used through the API by JInput to override the actual _GET/_POST/_REQUEST variables. If you want to completely replace these variables, this takes a bit more work. In this case you may need to call the parse method in a sandbox to find out what would have been the results. You can then add/delete/modify those results. Finally, before returning those results to JRouter for the site itself, you need to flag JRouter so it doesn't continue to process the results.
define('ROUTER_MODE_SKIP_SEF', 2);
define('ROUTER_MODE_SKIP_RAW', -1);
class plgSystemMyRouterReplacor extends JPlugin
{
/**
* @return void
*/
public function onAfterInitialise()
{
$app = JFactory::getApplication();
// Get the router
$router = $app->getRouter();
// Create a callback array to call the replaceRoute method of this object
$replaceRouteCallback = array($this, 'replaceRoute');
// Attach the callback to the router
$router->attachBuildRule($replaceRouteCallback);
}
/**
* @param JRouterSite &$router The Joomla Site Router
* @param JURI &$uri The URI to parse
*
* @return array The array of processed URI variables
*/
public function replaceRoute($router, $uri)
{
$app = JFactory::getApplication('site');
$vars = array();
// Get the true router
$siteRouter = $app->getRouter();
/**
* to avoid a recursion trap, we need to make sure that only
* the site router can call us! We could have removed our own
* rule the myRouter...but that would only work
* inside our own method! If someone else is also
* doing the same thing, we would have an ugly little
* recursion where they call parse which calls us
* and then we clone router and call parse which calls them
* back, and forth and back and forth
* friends don't let friends use recursion!
*/
if (spl_object_hash($router) != spl_object_hash($siteRouter))
{
// Recursion detected -> abort!
return $vars;
}
/**
* we still want to clone the router passed to us, not the true router
* since the rules might be different
*/
$myRouter = clone $router;
// Now use the power of Joomla! to parse this uri!
$vars = $myRouter->parse($uri);
// What is the menu id? What is the airspeed velocity of an unladen swallow?
$menuId = isset($vars['itemId']) ? $vars['itemId'] : 0;
// Please be smarter than this. Load the menu and check the config. Do something
if ($menuId == 67)
{
// Change the option to be a different component.
$vars['option'] == 'com_my_custom_component';
}
/**
* $vars has both the merged values of what would have been calculated and our changes
* So force the siteRouter to skip more processing - no reason to process it twice!
* $router->setMode(JROUTER_MODE_RAW);
* if the router mode is RAW - integer 0, then _parseRawRoute will be called by JRouter
* $router->setMode(JROUTER_MODE_SEF);
* if the router mode is SEF - integer 1, then _parseSEFRoute will be called by JRouter
* if we set it to something which is NOT SEF or RAW, nothing is done to it
* false or null would be a logical choice,
* but since the comparison is == not === false, null and 0/RAW are the same
* therefore we defined our own constants.
* SEF/RAW is a binary condition of either a positive integer or not a positive integer[0]
* so we extend that so SKIP_SEF becomes 2 so the if clause will fail, but anything else
* counting on checking for if mode > 0 will work
* and SKIP_RAW is -1, so anything counting on checking mode <=0 will work
* if it is not 0 or 1, then we don't change it because something else
* already triggered the skip.
*/
$mode = $router->getMode();
if ($mode == JROUTER_MODE_RAW)
{
$router->setMode(ROUTER_MODE_SKIP_RAW);
}
if ($mode == JROUTER_MODE_SEF)
{
$router->setMode(ROUTER_MODE_SKIP_SEF);
}
// Return our custom variables
return $vars;
}
}