Создание системного плагина для модификации JRouter
Переопределение 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;
}
}