Difference between revisions of "Creating a System Plugin to augment JRouter"
From Joomla! Documentation
(Remove needs review and incomplete tags) |
|||
(24 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
− | + | ==JRouter Modifications== | |
− | The Joomla! Router can be modified with additional rules by using the | + | 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. |
− | 2 | + | 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== | ==Augmentation== | ||
− | class plgSystemMyRouterAugmentor extends JPlugin { | + | 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. |
− | + | ||
− | + | {{JVer|2.5}} | |
− | + | <source lang="php"> | |
− | + | 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; | ||
+ | } | ||
} | } | ||
+ | </source> | ||
==Replacement== | ==Replacement== | ||
+ | |||
+ | 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. | ||
+ | |||
+ | {{JVer|2.5}} | ||
+ | <source lang="php"> | ||
define('ROUTER_MODE_SKIP_SEF', 2); | define('ROUTER_MODE_SKIP_SEF', 2); | ||
define('ROUTER_MODE_SKIP_RAW', -1); | define('ROUTER_MODE_SKIP_RAW', -1); | ||
− | class plgSystemMyRouterReplacor extends JPlugin { | + | |
− | + | 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; | ||
+ | } | ||
} | } | ||
− | + | </source> | |
− | + | ||
+ | [[Category:Tutorials]][[Category:Development]] | ||
+ | [[Category:Plugin Development]] |
Latest revision as of 05:30, 1 April 2020
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;
}
}