J2.5

Difference between revisions of "Creating a System Plugin to augment JRouter"

From Joomla! Documentation

(corrected coding style and variable names)
(3 intermediate revisions by 2 users not shown)
Line 12: Line 12:
 
{{JVer|2.5}}
 
{{JVer|2.5}}
 
<source lang="php">
 
<source lang="php">
  class plgSystemMyRouterAugmentor extends JPlugin {
+
class plgSystemMyRouterAugmentor extends JPlugin
    public function onAfterInitialise()
+
{
    {
+
/**
    $app = JFactory::getApplication();
+
* @return  void
    // get the router
+
*/
    $router = $app->getRouter();
+
public function onAfterInitialise()
    // add my own rules
+
{
    // create a callback array to call the augmentRoute method of this object
+
$app = JFactory::getApplication();
    $augmentCallback = array($this, 'augmentRoute');
+
 
    // attach the callback to the router
+
// Get the router
    $router->attachBuildRule($myRouterCallback);
+
$router = $app->getRouter();
    }
+
 
    /**
+
// Add my own rule:
    * @param  JRouterSite &$router  The Joomla Site Router
+
 
    * @param  JURI &$uri The URI to parse
+
// Create a callback array to call the augmentRoute method of this object
    *
+
$augmentRouteCallback = array($this, 'augmentRoute');
    * @return  array  $vars The array of processed URI variables
+
 
    */
+
// Attach the callback to the router
    public function augmentRoute ($router, $uri)
+
$router->attachBuildRule($augmentRouteCallback);
    {
+
}
      $vars = array();
+
 
      // do something to the vars
+
/**
      $vars['augment'] = 'succeeded';
+
* @param  JRouterSite $router  The Joomla site Router
      // in this case, now to any Joomla! component/module it will look like ?augment=succeeded was in the url
+
* @param  JURI         $uri     The URI to parse
      return $vars;
+
*
    }
+
* @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>
 
</source>
  
Line 47: Line 61:
 
{{JVer|2.5}}
 
{{JVer|2.5}}
 
<source lang="php">
 
<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 onAfterInitialise()
+
class plgSystemMyRouterReplacor extends JPlugin
    {
+
{
      $app = JFactory::getApplication();
+
/**
      // get the router
+
* @return  void
      $router = $app->getRouter();
+
*/
      // add my own rules
+
public function onAfterInitialise()
      // create a callback array to call the replaceRoute method of this object
+
{
      $augmentCallback = array($this, 'replaceRoute');
+
$app = JFactory::getApplication();
      // attach the callback to the router
+
 
      $router->attachBuildRule($myRouterCallback);
+
// Get the router
    }
+
$router = $app->getRouter();
    /**
+
 
    * @param  JRouterSite &$router  The Joomla Site Router
+
// Create a callback array to call the replaceRoute method of this object
    * @param  JURI &$uri The URI to parse
+
$replaceRouteCallback = array($this, 'replaceRoute');
    *
+
 
    * @return  array  $vars The array of processed URI variables
+
// Attach the callback to the router
    */
+
$router->attachBuildRule($replaceRouteCallback);
    public function replaceRoute ($router, $uri)
+
}
    {
+
 
      global $app;
+
/**
      // should we  use $app = JFactory::getApplication('site'); ?
+
* @param  JRouterSite &$router  The Joomla Site Router
      $vars = array();
+
* @param  JURI         &$uri     The URI to parse
      // get the true router
+
*
      $siteRouter= $app->getRouter()
+
* @return  array  The array of processed URI variables
    // to avoid a recursion trap, we need to make sure that only
+
*/
    // the site router can call us!  We could have removed our own
+
public function replaceRoute($router, $uri)
    // rule the myRouter...but that would only work  
+
{
    // inside our own method!  If someone else is also
+
$app = JFactory::getApplication('site');
    // doing the same thing, we would have an ugly little
+
$vars = array();
    // recursion where they call parse which calls us
+
 
    // and then we clone router and call parse which calls them
+
// Get the true router
    // back, and forth and back and forth
+
$siteRouter = $app->getRouter();
    // friends don't let friends use recursion!
+
 
    if (spl_object_hash($router) != spl_object_hash($siteRouter)) {
+
/**
      // oh no!  Abort, abort!
+
* to avoid a recursion trap, we need to make sure that only
      return $vars;
+
* the site router can call us!  We could have removed our own
      }
+
* rule the myRouter...but that would only work
      // we still want to clone the router passed to us, not the true router
+
* inside our own method!  If someone else is also
      // since the rules might be different
+
* doing the same thing, we would have an ugly little
      $myRouter = clone $router;  
+
* recursion where they call parse which calls us
      //now use the power of Joomla! to parse this uri!
+
* and then we clone router and call parse which calls them
      $vars = $myRouter->parse($vars);
+
* back, and forth and back and forth
      //what is the menu id?  what is the airspeed velocity of an unladen swallow?
+
* friends don't let friends use recursion!
      $menuId = ? isset($vars['itemId']) $vars['itemId'] : 0;
+
*/
      // Please be smarter than this.  Load the menu and check the config.  Do something
+
 
      if ($menuId == 67) {
+
if (spl_object_hash($router) != spl_object_hash($siteRouter))
        // change the option to be a different component.
+
{
        $vars['option'] == 'com_my_custom_component';
+
// Recursion detected -> abort!
      }  
+
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);
+
/**
      // if the router mode is RAW - integer 0, then _parseRawRoute will be called by JRouter
+
* we still want to clone the router passed to us, not the true router
      //$router->setMode(JROUTER_MODE_SEF);
+
* since the rules might be different
      // 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,  
+
$myRouter = clone $router;
      //but since the comparison is == not === false, null and 0/RAW are the same
+
 
      // therefore we defined our own constants.
+
// Now use the power of Joomla! to parse this uri!
      // SEF/RAW is a binary condition of either a positive integer or not a positive integer[0]
+
$vars = $myRouter->parse($uri);
      // 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
+
// What is the menu id?  What is the airspeed velocity of an unladen swallow?
      // and SKIP_RAW is -1, so anything counting on checking mode <=0 will work
+
$menuId = isset($vars['itemId']) ? $vars['itemId'] : 0;
      // if it is not 0 or 1, then we don't change it because something else
+
 
      // already triggered the skip.
+
// Please be smarter than this.  Load the menu and check the config.  Do something
      $mode = $router-getMode();
+
if ($menuId == 67)
      if ($mode == JROUTER_MODE_RAW) {
+
{
        $router->setMode(ROUTER_MODE_SKIP_RAW);
+
// Change the option to be a different component.
      }
+
$vars['option'] == 'com_my_custom_component';
      if ($mode == JROUTER_MODE_SEF) {
+
}
        $router->setMode(ROUTER_MODE_SKIP_SEF);
+
 
      }  
+
/**
      // return our custom variables
+
* $vars has both the merged values of what would have been calculated and our changes
      return $vars;
+
* 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>
 
</source>
  
 
[[Category:Tutorials]][[Category:Development]]
 
[[Category:Tutorials]][[Category:Development]]
 
[[Category:Plugin Development]]
 
[[Category:Plugin Development]]

Revision as of 05:18, 15 October 2013

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.

Quill icon.png
Content is Incomplete

This article or section is incomplete, which means it may be lacking information. You are welcome to assist in its completion by editing it as well. If this article or section has not been edited in several days, please consider helping complete the content.
This article was last edited by K.schroeder (talk| contribs) 10 years ago. (Purge)

Copyedit.png
This Page Needs Your Help

This page is tagged because it NEEDS REVIEW. You can help the Joomla! Documentation Wiki by contributing to it.
More pages that need help similar to this one are here. NOTE-If you feel the need is satistified, please remove this notice.


JRouter Hacking[edit]

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 will apply globally.

Here are 2 examples of hacking 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;
	}
}