Прежде всего, хочу отметить, что данная статья не является полноценным руководством по написанию компонента для Joomla 2.5, она лишь освещает узкую часть данного вопроса. Статья предназначена для разработчиков компонентов для Joomla или тех, кто хочет этим заняться. Достаточно подробный процесс создания компонента описан на сайте документации по Joomla тут. В этой статье я опишу то, чего я не нашел в указанном руководстве, а именно подробного описания добавления собственных иконок и сопутствующей им логики для компонента Joomla 2.5.

Для начала покажу пример того, как я реализовал несколько иконок в тулбаре для компонента, разработкой которого сейчас занимаюсь:

toolbar1
Как видно из рисунка, помимо стандартных иконок "Опубликовать", "Удалить" и т.д. я добавил в панель компонента собственные - "Сделать новинками", "Отменить новинки", "Рекомендовать", "Снять рекомендации".

Начнём с того, что перейдем в каталог /administrator/components/имя_компонента. Нам понадобится включить стили для задания иконок, поэтому если Вы еще не подключили файл стиля в админ-части Вашего компонента, самое время это сделать. Лично я предпочитаю создавать отдельную папку css в корне административной части компонента, внутри которой создаю файл стилей с именем компонента, например com_mycomp.css (пусть в нашем примере компонент называется mycomp, а каталог под него - com_mycomp)

Далее, я добавляю включение этого файла стилей во входной точке административной части компонента. Это файл mycomp.php. В этом файле, получается стандартный контроллер админ-части компонента и ему передается управление. Но сейчас нам это не особо важно, просто добавим в начало этого файла следующее подключение файла стилей:

$document = JFactory::getDocument();
$document->addStylesheet(JURI::root(true)."/administrator/components/com_mycomp/css/com_mycomp.css");


Такое включение позволит видеть в области администрирования Joomla все стили, которые мы зададим для нашего компонента. Далее переходим к редактированию самого файла com_mycomp.css и добавляем туда 2 стиля для задания иконок для наших собственных кнопок:

.icon-32-recommend {background-image: url(../../../../media/com_megashop/images/recommend-32x32.png);}
 
.icon-32-unrecommend {background-image: url(../../../../media/com_megashop/images/unrecommend-32x32.png);}



В моём случае, как видим, это два стиля для кнопки "Рекомендовать" (класс.icon-32-recommend) и для кнопки "Снять рекомендации" (класс.icon-32-unrecommend). Оба стиля содержат единственное CSS-свойствоbackground-image, которое указывает на местоположение нужной нам иконки размером 32x32 px. Согласно официальному руководству по разработке компонентов для Joomla принято все иконки и медиафайлы, прилагаемые к компоненту хранить в каталоге /media/имя_компонента/images. Именно туда мы и помещаем обе иконки для наших кнопок.

Теперь, когда иконки подготовлены, стили для иконок заданы, а сам файл стиля подключен в главном файле компонента, самое время добавить в панель наши кнопки. Для этого переходим в каталог views и далее в каталог нужного нам представления. В своём компоненте мне нужно было добавить кнопки для представления products, которое должно отображать список товаров. В Вашем случае это может быть любой view, который предназначен для отображения списка Ваших объектов. Находим файл view.html.php этого представления, а в нём функциюaddToolBar. У меня она выглядит примерно так:

protected function addToolBar()
{
    JToolBarHelper::title(JText::_('COM_MYCOMP_TAB_PRODUCTS'), 'products');
    JToolBarHelper::publishList( $task = 'products.publish', $alt = JText::_('JTOOLBAR_PUBLISH') );
    JToolBarHelper::unpublishList( $task = 'products.unpublish', $alt = JText::_('JTOOLBAR_UNPUBLISH') );
// ...
}


Теперь в эту функцию в нужное нам место добавим два вызова для создания собственных кнопок:

JToolBarHelper::custom( 
                        $task = 'products.recommend',
                        $icon = 'recommend.png', 
                        $iconOver = '', 
                        $alt = JText::_('COM_MYCOMP_PRODUCTS_RECOMMEND'), 
                        $listSelect = true, $x = false 
                        );
JToolBarHelper::custom( 
                        $task = 'products.unrecommend', 
                        $icon = 'unrecommend.png', 
                        $iconOver = '', 
                        $alt = JText::_('COM_MYCOMP_PRODUCTS_UNRECOMMEND'), 
                        $listSelect = true, 
                        $x = false 
                        );

Здесь есть несколько нюансов, на которые нужно обратить внимание. Во-первых, может смутить, почему в качестве параметра$iconмы передаем "recommend.png" и "unrecommend.png", ведь файлы иконок из каталога media/наш_компонент у нас называются совсем по-другому! Всё дело в том, что Joomla сама распарсит имя файла иконки и по нему поймет какой стиль включить для элемента кнопки в админ-области - соответственно для recommend.png Joomla включит стиль.icon-32-recommend, а для unrecommend.png - стиль .icon-32-unrecommend.

Следующий нюанс - параметр $listSelect. Мы передаем в него true, и это значит, что после нажатия на нашу кнопку в админ-области движок Joomla будет проверять признак выделенности хотя бы одного из наших объектов в списке - с помощью соответствующего ему чекбокса. Т.е. кнопка будет работать только при выбранных объектах.

Также стоит обратить внимание на первый параметр $task. Например, для кнопки "Рекомендовать"  мы передаём следующее: $task = 'products.recommend'. Эта нотация с разделением через точку, появившаяся в Joomla после версии 1.5, означает буквально следующее: найти контроллер с именем products и вызвать в нём метод (task) с именем recommend. Ну тут понятное дело - кнопка должна ведь что-то делать, вот в контроллер мы и должны разместить логику по обработке нажатия на кнопку.

Создаём (или обновляем) контроллер

Итак, идем в каталог controllers в админ-области нашего компонента и создаём (если еще не создан) контроллер для обработки нашего нажатия. Напомню, в моём случае представление, куда мы добавляем кнопки, называется products ("товары"), поэтому и контроллер должны создать с таким же именем - т.е. файл контроллера у меня products.php. В Вашем случае имя view и контроллера может быть другое. Итак, файл контроллера products.php для компонента с именем mycomp выглядит у меня следующим образом:


// Запрет доступа к данному файлу извне приложения (напрямую)
defined('_JEXEC') or die('Restricted access');
 
// Импорт библиотеки controlleradmin Joomla
jimport('joomla.application.component.controlleradmin');
 
class MyCompControllerProducts extends JControllerAdmin {
    public function __construct($config = array()) {
        parent::__construct($config);
        $this->registerTask('unrecommend', 'recommend');
    }
 
    public function getModel($name = 'Products', $prefix = 'MyCompModel') {
       $model = parent::getModel($name, $prefix, array('ignore_request' => true));
        return $model;
    }
 
    public function recommend() {
        JSession::checkToken() or die(JText::_('JINVALID_TOKEN'));
        // Получить элементы для рекомендации из запроса
        $cid = JRequest::getVar('cid', array(), '', 'array');
        $data = array('recommend' => 1, 'unrecommend' => 0);
 
        $task = $this->getTask();
        $value = JArrayHelper::getValue($data, $task, 0, 'int');
 
        if (empty($cid)) {
            JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED'));
        }
        else {
            // Получить соответствующую модель
            $model = $this->getModel();
            // Убедиться, что id элементов - это целые числа
            JArrayHelper::toInteger($cid);
 
            // Вызываем метод recommend в модели
            if (!$model->recommend($cid, $value))
            {
                JError::raiseWarning(500, $model->getError());
            } else {
                if ($value == 1) {
                    $ntext = $this->text_prefix . '_N_ITEMS_RECOMMENDED';
                } elseif ($value == 0) {
                    $ntext = $this->text_prefix . '_N_ITEMS_UNRECOMMENDED';
                }
                $this->setMessage(JText::plural($ntext, count($cid)));
            }
        }
        $this->setRedirect( JRoute::_('index.php?option=' . $this->option . '&view=' . $this->view_list , false) );
    }
}

В конструкторе вызываем метод registerTask, который регистрирует еще один task с именем unrecommend. Это позволяет не дублировать код метода recommend и не создавать еще одну функцию - все действия по "рекомендации" продукта и "снятия с рекомендации" будут у нас делаться аналогично стандартным джумловским "публиковать" и "снять с публикации", только вызываться для них будет наш метод recommend. Сам метод получает массив с именем cid, передаваемый в наш контроллер из запроса, после того как мы нажали на нашу кнопку. В массиве содержится ID всех элементов, которые мы выделили в интерфейсе области администрирования перед нажатием на кнопку. Далее, мы получаем текущий task, переданный контроллеру (у нас это может быть как recommend, так и unrecommend). После того, как task получен, в зависимости от него получаем целочисленное представление действия в переменную $value (1 = рекомендовать товар, 0 = снять товар с рекомендации):

$task = $this->getTask();
$value = JArrayHelper::getValue($data, $task, 0, 'int');

Далее - проверяем, что массив $cid непуст (т.е. данные пришли), после чего получаем модель для наших товаров и вызываем её метод recommend:

if (empty($cid)) {
            JError::raiseWarning(500, JText::_($this->text_prefix . '_NO_ITEM_SELECTED'));
        }
        else {
            // Получить соответствующую модель
            $model = $this->getModel();
            // Убедиться, что id элементов - это целые числа
            JArrayHelper::toInteger($cid);
 
            // Вызываем метод recommend в модели
            if (!$model->recommend($cid, $value))
            {
                JError::raiseWarning(500, $model->getError());
            } else {
                if ($value == 1) {
                    $ntext = $this->text_prefix . '_N_ITEMS_RECOMMENDED';
                } elseif ($value == 0) {
                    $ntext = $this->text_prefix . '_N_ITEMS_UNRECOMMENDED';
                }
                $this->setMessage(JText::plural($ntext, count($cid)));
            }

На этом все действия с контроллером для обработки нажатия на кнопку завершены и переходим к последнему этапу - обновление модели для наших продуктов.

Создаем (или обновляем) модель компонента

Модели располагаются в каталоге models административной части компонента. Мы должны найти модель для наших объектов (или создать её), а затем добавить туда код, который будет делать изменения уже в самой базе данных. В моем случае файл модели называется products.php и я добавил туда обработчик для нашей кнопки - методrecommend, который вызываю из контроллера. Также нам нужно убедиться, что в модели определен методgetTable, который получает таблицу для нашего объекта:

public function getTable($type = 'Product', $prefix = 'MyCompTable', $config = array()) {
    $return = JTable::getInstance($type, $prefix, $config);
    return $return;
}
 
function recommend(&$pks, $value = 1) {
    $pks = (array) $pks;
    $table = $this->getTable();
    foreach ($pks as $i => $pk) {
        if ($table->load($pk)) {
            $table->recommended = $value;
            $table->store();
        }
    }
    return true;
}