J2.5

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:
{{incomplete}}{{review}}
+
==JRouter Modifications==
The Joomla! Router can be modified with additional rules by using the attatchXRules methods.  Ideally, this can be done from a system plugin so these rules can affect be used by others.
+
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 possibilities when adding rules would be that you want to augment the router functionality, or you want to replace it.
+
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.
    public function onAfterInitialize()
+
 
    {
+
{{JVer|2.5}}
      global $app;
+
<source lang="php">
    // should we  use $app = JFactory::getApplication('site'); ?
+
class plgSystemMyRouterAugmentor extends JPlugin
    // get the router
+
{
    $router = $app->getRouter();
+
/**
    // add my own rules
+
* @return  void
    // create a callback array to call the augmentRoute method of this object
+
*/
    $augmentCallback = array($this, 'augmentRoute ');
+
public function onAfterInitialise()
    // attach the callback to the router
+
{
    $router->attachBuildRule($myRouterCallback);
+
$app = JFactory::getApplication();
    }
+
 
    /**
+
// Get the router
    * @param  JRouterSite &$router  The Joomla Site Router
+
$router = $app->getRouter();
    * @param  JURI &$uri The URI to parse
+
 
    *
+
// Add my own rule:
    * @return  array  $vars The array of processed URI variables
+
 
    */
+
// Create a callback array to call the augmentRoute method of this object
    public function augmentRoute ($router, $uri)
+
$augmentRouteCallback = array($this, 'augmentRoute');
    {
+
 
      $vars = array();
+
// Attach the callback to the router
      // do something to the vars
+
$router->attachBuildRule($augmentRouteCallback);
      $vars['augment'] = 'succeeded';
+
}
      // in this case, now to any Joomla! component/module it will look like ?augment=succeeded was in the url
+
 
      return $vars;
+
/**
    }
+
* @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 {
+
 
    public function onAfterInitialize()
+
class plgSystemMyRouterReplacor extends JPlugin
    {
+
{
      global $app;
+
/**
      // should we  use $app = JFactory::getApplication('site'); ?
+
* @return  void
      // get the router
+
*/
      $router = $app->getRouter();
+
public function onAfterInitialise()
      // add my own rules
+
{
      // create a callback array to call the replaceRoute method of this object
+
$app = JFactory::getApplication();
      $augmentCallback = array($this, 'replaceRoute ');
+
 
      // attach the callback to the router
+
// Get the router
      $router->attachBuildRule($myRouterCallback);
+
$router = $app->getRouter();
    }
+
 
    /**
+
// Create a callback array to call the replaceRoute method of this object
    * @param  JRouterSite &$router  The Joomla Site Router
+
$replaceRouteCallback = array($this, 'replaceRoute');
    * @param  JURI &$uri The URI to parse
+
 
    *
+
// Attach the callback to the router
    * @return  array  $vars The array of processed URI variables
+
$router->attachBuildRule($replaceRouteCallback);
    */
+
}
    public function replaceRoute ($router, $uri)
+
 
    {
+
/**
      global $app;
+
* @param  JRouterSite &$router  The Joomla Site Router
      // should we  use $app = JFactory::getApplication('site'); ?
+
* @param  JURI         &$uri     The URI to parse
      $vars = array();
+
*
      // get the true router
+
* @return  array  The array of processed URI variables
      $siteRouter= $app->getRouter()
+
*/
    // to avoid a recursion trap, we need to make sure that only
+
public function replaceRoute($router, $uri)
    // the site router can call us!  We could have removed our own
+
{
    // rule the myRouter...but that would only work  
+
$app = JFactory::getApplication('site');
    // inside our own method!  If someone else is also
+
$vars = array();
    // doing the same thing, we would have an ugly little
+
 
    // recursion where they call parse which calls us
+
// Get the true router
    // and then we clone router and call parse which calls them
+
$siteRouter = $app->getRouter();
    // back, and forth and back and forth
+
 
    // friends don't let friends use recursion!
+
/**
    if (spl_object_hash($router) != spl_object_hash($siteRouter)) {
+
* to avoid a recursion trap, we need to make sure that only
      // oh no!  Abort, abort!
+
* the site router can call us!  We could have removed our own
      return $vars;
+
* rule the myRouter...but that would only work
      }
+
* inside our own method!  If someone else is also
      // we still want to clone the router passed to us, not the true router
+
* doing the same thing, we would have an ugly little
      // since the rules might be different
+
* recursion where they call parse which calls us
      $myRouter = clone $router;  
+
* and then we clone router and call parse which calls them
      //now use the power of Joomla! to parse this uri!
+
* back, and forth and back and forth
      $vars = $myRouter->parse($vars);
+
* friends don't let friends use recursion!
      //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 (spl_object_hash($router) != spl_object_hash($siteRouter))
      if ($menuId == 67) {
+
{
        // change the option to be a different component.
+
// Recursion detected -> abort!
        $vars['option'] == 'com_my_custom_component';
+
return $vars;
      }  
+
}
      // $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);
+
* we still want to clone the router passed to us, not the true router
      // if the router mode is RAW - integer 0, then _parseRawRoute will be called by JRouter
+
* since the rules might be different
      //$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
+
$myRouter = clone $router;
      // false or null would be a logical choice,  
+
 
      //but since the comparison is == not === false, null and 0/RAW are the same
+
// Now use the power of Joomla! to parse this uri!
      // therefore we defined our own constants.
+
$vars = $myRouter->parse($uri);
      // 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
+
// What is the menu id?  What is the airspeed velocity of an unladen swallow?
      // counting on checking for if mode > 0 will work
+
$menuId = isset($vars['itemId']) ? $vars['itemId'] : 0;
      // 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
+
// Please be smarter than this.  Load the menu and check the config.  Do something
      // already triggered the skip.
+
if ($menuId == 67)
      $mode = $router-getMode();
+
{
      if ($mode == JROUTER_MODE_RAW) {
+
// Change the option to be a different component.
        $router->setMode(ROUTER_MODE_SKIP_RAW);
+
$vars['option'] == 'com_my_custom_component';
      }
+
}
      if ($mode == JROUTER_MODE_SEF) {
+
 
        $router->setMode(ROUTER_MODE_SKIP_SEF);
+
/**
      }  
+
* $vars has both the merged values of what would have been calculated and our changes
      // return our custom variables
+
* So force the siteRouter to skip more processing - no reason to process it twice!
      return $vars;
+
* $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;
 +
}
 
}
 
}
  
{{JVer|2.5}}
+
</source>
{{license}}
+
 
 +
[[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.

Joomla 2.5

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.

Joomla 2.5

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;
	}
}