Переопределение JRouter

Маршрутизатор Joomla! может быть изменен с дополнительными правилами, используя методы attatchBuildRules и attatchParseRules. В идеале это можно сделать из системного плагина, так что эти правила будут применяться глобально.

Вот 2 примера модификации JRouter используя правила и системный плагин. Один из них добавит результаты, возвращаемые JRouter, в то время как другой полностью заменит результаты, возвращаемые JRouter.

Добавление.

JRouter возвращает массив переменных, которые затем используются через API JInput для переопределения фактических переменных _GET/_POST/_REQUEST. Если вы просто хотите добавить возвращаемые переменные, то это просто.

class plgSystemMyRouterAugmentor extends JPlugin
{
	/**
	 * @return  void
	 */
	public function onAfterInitialise()
	{
		$app = JFactory::getApplication();

		// Получить роутер
		$router = $app->getRouter();

		// Добавить собственное правило:

		// Создать массив обратного вызова для вызова метода augmentRoute этого объекта
		$augmentRouteCallback = array($this, 'augmentRoute');

		// Прикрепить обратный вызов к роутеру
		$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();

		// Сделать что-нибудь с переменными
		$vars['augment'] = 'succeeded';

		/**
		 * В этом случае теперь любой компонент/модул Joomla! будет выглядеть, как будто параметр
		 * ?augment=succeeded был в URL
		 */
		return $vars;
	}
}

 



Замена.

JRouter возвращает массив переменных, которые затем используются через API JInput для переопределения фактических переменных _GET/_POST/_REQUEST. Если вы хотите полностью заменить эти переменные, это займет немного больше работы. В этом случае вам может потребоваться вызвать метод parse в песочнице, чтобы узнать, каковы были бы результаты. Затем вы можете добавить/удалить/изменить эти результаты. Наконец, прежде чем возвращать эти результаты в JRouter для самого сайта, вам нужно отметить JRouter, чтобы он не продолжал обрабатывать результаты.

define('ROUTER_MODE_SKIP_SEF', 2);
define('ROUTER_MODE_SKIP_RAW', -1);

class plgSystemMyRouterReplacor extends JPlugin
{
	/**
	 * @return  void
	 */
	public function onAfterInitialise()
	{
		$app = JFactory::getApplication();

		// Получить маршрутизатор
		$router = $app->getRouter();

		// Создать массив обратного вызова для вызова метода replaceRoute этого объекта
		$replaceRouteCallback = array($this, 'replaceRoute');

		// Прикрепить обратный вызов к маршрутизатору
		$router->attachBuildRule($replaceRouteCallback);
	}

	/**
	 * @param   JRouterSite  &$router  The Joomla Site Router
	 * @param   JURI         &$uri     URI для разбора
	 *
	 * @return  array  Массив обработанных переменных URI
	 */
	public function replaceRoute($router, $uri)
	{
		$app = JFactory::getApplication('site');
		$vars = array();

		// Get the true router
		$siteRouter = $app->getRouter();

		/**
		 * чтобы избежать рекурсивной ловушки, нам нужно убедиться,
		 * что только маршрутизатор сайта может вызвать это!  
		 * Мы могли бы убрать наше собственное правило  myRouter
		 * ...но это будет работать только внутри нашего собственного метода! 
		 * Если бы кто - то другой тоже делал то же самое, у нас была бы рекурсия, 
		 * где они вызывают parse, который вызывает нас, а затем мы 
		 * клонируем маршрутизатор и вызываем parse, который вызывает
		 * их туда - обратно!
		 */

		if (spl_object_hash($router) != spl_object_hash($siteRouter))
		{
			// Обнаружена рекурсия -> прервать!
			return $vars;
		}

		/**
		 * мы все еще хотим клонировать переданный нам маршрутизатор, 
		 * а не настоящий маршрутизатор, так как правила могут быть другими
		 */

		$myRouter = clone $router;

		// Теперь используем возможности Joomla! чтобы разобрать этот uri!
		$vars = $myRouter->parse($uri);

		// Есть ли идентификатор меню?  Если не - то 0
		$menuId = isset($vars['itemId']) ? $vars['itemId'] : 0;

		// Загрузите меню и проверить конфигурацию... И еще что ни будь...
		if ($menuId == 67)
		{
			// Изменить параметр option на другой компонент.
			$vars['option'] == 'com_my_custom_component';
		}

		/**
		 * $vars имеет как объединенные значения того, что было бы вычислено, так и наши изменения,
		 * так что заставьте siteRouter пропустить больше обработки - нет причин обрабатывать его дважды!  
		 * $router->setMode(JROUTER_MODE_RAW);
		 * если режим маршрутизатора RAW - integer 0, то _parseRawRoute будет вызван JRouter
		 * $router->setMode(JROUTER_MODE_SEF);
		 * если режим маршрутизатора SEF - integer 1, , то _parseSEFRoute будет вызван JRouter,
		 * если мы установим его на что-то, что НЕ является SEF или RAW, ничего не будет сделано с ним 
		 * false или null было бы логичным выбором,
		 *  но так как сравнение == не === false, null и 0/RAW - это одно и то же,
		 * поэтому мы определили наши собственные константы.
		 * SEF/RAW -это двоичное условие либо положительного целого числа, 
		 * либо не положительного целого числа [0],
		 * поэтому мы расширяем его так, что SKIP_SEF будет 2, 
		 * так что предложение if потерпит неудачу, 
		 * но все остальное, рассчитанное на проверку if mode > 0, будет работать, 
		 * а SKIP_RAW будет -1, так что все, что рассчитано на проверку mode <=0, будет работать, 
		 * если это не 0 или 1, то мы не меняем его, потому что что-то другое уже вызвало пропуск.
		 */

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