Вторник, 01 Апрель 2014 00:00

Как написать плагин для XMap. Joomla

Автор
Оцените материал
(0 голосов)

После очередного переноса своего компонента Cookbook на Joomla 3.* задался целью разработать плагин для компонента XMap. Дело в том, что этот самый компонент xmap формирует карту сайта только на основании меню и обрабатывает только известные для него объекты. Имеется ограниченное количество плагинов. Конечно же плагин для моего ненаглядного компонента они еще не разработали (вот мерзавцы!). Делать нечего, придется разрабатывать своими руками.

Описания конечно же не нашел. Изучил имеющиеся плагины. После двух дней мытарств удалось запустить плагин для 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() используется для того
            // чтобы на экран выводились читабельные символы. Этот вызов был необходим
            // так как название каталога содержит символы &quot;
            $node->name = htmlspecialchars_decode($cat->name);
            // Для каждого элемента прописываем его url, в данном случае что-то типа:
            // 'index.php?option=com_test&amp;view=catalog&amp;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); // Не забываем восстановить уровень вложенности!
    }        
}
Прочитано 2068 раз Последнее изменение Вторник, 01 Апрель 2014 16:33
Авторизуйтесь, чтобы получить возможность оставлять комментарии