Описания конечно же не нашел. Изучил имеющиеся плагины. После двух дней мытарств удалось запустить плагин для Cookbook, который вывел в карте сайта все рецепты и продукты.
Думаю, что я не единственный, кто может задаться целью написать плагин для xmap. Как результат работы публикую текст условного плагина для условного компонента com_test. Этот тестовый компонент работает с деревом каталогов (catalogs), в каждом из которых может содержаться некоторые статьи (items). Естественно, результат необходимо оформить в надлежащем пакете для установке, но это уже просто. Изучайте утановленные плагины. Там как раз все ясно.
В меню ссылка на каталог выглядит следующим образом:
<site>/index.php?option=com_test&view=catalog&id=<номерочек каталога>
Ниже приведенный текст плагина разворачивает эту ссылку в дерево каталогов и их статей. Текст документирован достаточными для понимания коментариями. Все лишнее я убрал. Возможно, текст можно еще упростить, но не думаю, что принципиально. В каком-то смысле - это минимальный плагин. За остальным - вперед, изучайте плагины для com_k2 или com_content!
<?php
/**
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @author Alexander Bushmelev (Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.)
*/
defined( '_JEXEC' ) or die( 'Restricted access' );
/**
* Обработка каталогов и элементов каталога
*
* Плагин для компонента XMap, который раскрывает каталог тестового компонента com_test из меню
*/
class xmap_com_test {
/**
* Эта функция вызывается перед тем как будет обработан элемент меню и используется
* для установки является ли данная ссылка контейнером или конечным элементом
* Эта функция обязательно должна быть реализована
*
* @param object Обрабатываемый элемент меню
* @param array массив параметров свойств элемента в карте
*
* @return void
* @since 1.2
*/
static function prepareMenuItem($node, &$params) {
/*
* Стандартные вызовы для получения информации о текущих параметрах элемента меню
* следующие четыре строчки стандартны и служат для получения значений id и view
*/
$link_query = parse_url($node->link);
parse_str(html_entity_decode($link_query['query']), $link_vars);
$view = JArrayHelper::getValue($link_vars, 'view', '');
$id = intval(JArrayHelper::getValue($link_vars, 'id', 0));
if ($view == 'testitem') {
if ($id) {
$node->uid = 'com_testi' . $id;
} else {
$node->uid = 'com_testi' . $view;
}
/*
* Устанавливаем, что этот элемент терминальный и не содержит в себе
* других элементов которые нужно обрабатывать
* Собственно, в этом весь смысл этой функции
*/
$node->expandible = false;
} elseif ($view == 'catalog') {
if ($id) {
$node->uid = 'com_testc' . $id;
} else {
$node->uid = 'com_testc' . $view;
}
/*
* Устанавливаем, что этот элемент является каталогом и должен
* обрабатыватья рекурсивно
* Собственно, в этом весь смысл этой функции
*/
$node->expandible = true;
}
}
/**
* Expands a com_test menu item. Эта функция вызывается для всех контейнеров
* Обязательная для реализации функция
*
* @param object карта сайта
* @param object Родительский элемент, к которому производится привязка
* @param array массив параметров свойств элемента в карте
*
* @return void
* @since 1.0
*/
static function getTree($xmap, $parent, &$params) {
// Добавляем описание используемых классов
require_once JPATH_SITE.'/components/com_test/models/catalog.php';
require_once JPATH_SITE.'/components/com_test/helpers/route.php';
// Следующие строки более или менее стандартные и служат для получения
// информации о view и id
$link_query = parse_url($parent->link);
if (!isset($link_query['query'])) {
return;
}
parse_str(html_entity_decode($link_query['query']), $link_vars);
$view = JArrayHelper::getValue($link_vars, 'view', 0);
$catid = intval(JArrayHelper::getValue($link_vars, 'id', 0));
// Устанавливаем значения параметров элемента карты сайта
// В данном случае тупо забиваем эти значения, но можно получить из описания
$params['cat_priority'] = 0.5;
$params['cat_changefreq'] = 'weekly';
$params['link_priority'] = 0.5;
$params['link_changefreq'] = 'weekly';
if ($view == 'catalog') { // Обрабатываем только каталоги
// Получаем объект каталог в зависимости от значения его идентификатора
// Если идентификатор отсутствует, то это корневой каталог
$catalog = ($catid? TestModelCatalog::loadCatalog($catid) : TestModelCatalog::getRoot());
// Вызываем внутреннюю рекурсивную функцию для обработки каталога
self::getCatalogTree($xmap, $parent, $params, $catalog->id);
}
}
/**
* Функция внутренняя, название ее не принципиально. Параметры как удобно, так
* и делаем. В данном случае это
*
* @param object карта сайта
* @param object Родительский элемент, к которому производится привязка
* @param array массив параметров свойств элемента в карте
* @param int идентификатор каталога
*
* Последний параметр выбран так как было удобнее. Первые три можно считать необходимыми
* Обращаем внимание, что параметр params передается по ссылке и может быть изменен
* по ходу обработки. Нам менять его значение в данном примере не нужно.
*
* @return void
*/
static function getCatalogTree($xmap, $parent, &$params, $catid) {
// Получаем все подкаталоги данного каталога
$children = TestModelCatalog::getSubcatalogList($catid);
// В данном примере каталоги не поддерживают информацию о времени их последнего
// изменения, поэтому используем текущее время
$modified = time();
$xmap->changeLevel(1); // Увеличивем уровень вложенности
foreach ($children as $cat) {
$node = new stdclass;
$node->id = $parent->id;
$node->uid = $parent->uid . 'c' . $cat->id;
// В данном месте функция htmlspecialchars_decode() используется для того
// чтобы на экран выводились читабельные символы. Этот вызов был необходим
// так как название каталога содержит символы "
$node->name = htmlspecialchars_decode($cat->name);
// Для каждого элемента прописываем его url, в данном случае что-то типа:
// 'index.php?option=com_test&view=catalog&id='.$catalogid
// для этого используется встроенный роутер компонента
$node->link = TestHelperRoute::getCatalogRoute($cat->id);
$node->priority = $params['cat_priority'];
$node->changefreq = $params['cat_changefreq'];
$node->expandible = true; // это контейнер!!!
$node->modified = $modified;
// Вызов $xmap->printNode($node) и приводит к появлению строчки на экране
if ($xmap->printNode($node) !== FALSE) {
// Рекурсивно обрабатываем подкаталоги подкаталога
self::getCatalogTree($xmap, $parent, $params, $cat->id);
}
}
// После обработки подкаталогов обрабатываем все терминальные элементы
// Все действия аналогичны обработке каталогов, кроме рекурсивной обработки
$items = TestModelCatalog::getItemList($catid);
foreach ($items as $item) {
$node = new stdclass;
$node->id = $parent->id;
$node->uid = $parent->uid . 'i' . $item->id;
$node->name = htmlspecialchars_decode($item->name);
$node->link = TestHelperRoute::getItemRoute($item->id);
$node->priority = $params['link_priority'];
$node->changefreq = $params['link_changefreq'];
$node->expandible = false;
$node->modified = $modified;
$xmap->printNode($node);
}
$xmap->changeLevel(-1); // Не забываем восстановить уровень вложенности!
}
}