Версия: 3.x
Выполняем действие с выбранными товарами в административной панели

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

В общем виде задача состоит в том, что необходимо в нашем участке кода получить ID выбранных товаров. Для примера, в данной статье мы будем устанавливать выбранным товарам флаг публичности в положение "видим".

Реализовывать данную задачу мы будем из нашего кастомного модуля ModuleName. Исходим из того, что простейший модуль создан и установлен в вашем магазине.

Сперва необходимо добавить кнопку действия в панель действий с товарами, для этого перехватим событие controller.exec.catalog-admin-ctrl.index. Это событие происходит сразу после формирования визуального хелпера RS::Controller::Admin::Helper::CrudCollection. В нем уже сформирована структура будущего раздела административной панели, в котором уже присутствует описание структуры дерева категорий слева, колонок таблицы справа, кнопок в верхней и нижней панелей инструментов. Наша задача добраться до нижней панели и добавить в неё кнопку.

Создаем обработчик события в файле config/handlers.inc.php

<?php
namespace ModuleName\Config;
/**
* Класс предназначен для объявления событий, которые будет прослушивать данный модуль.
*/
class Handlers extends \RS\Event\HandlerAbstract
{
function init()
{
//Подписываемся на обработку события
$this->bind('controller.exec.catalog-admin-ctrl.index');
}
/**
* Возвращает пункты меню этого модуля в виде массива
*
* @param \RS\Controller\Admin\Helper\CrudCollection $helper
* @return void
*/
public static function controllerExecCatalogAdminCtrlIndex(\RS\Controller\Admin\Helper\CrudCollection $helper)
{
//Сформируем URL обработчика действия.
//URL должен вести на контроллер в административной панели
// нашего модуля ModuleName\Controller\Admin\Tools, в котором у нас будет метод setVisible
$url = \RS\Router\Manager::obj()->getAdminUrl('setVisible', //Action контроллера
array(), //Доп. параметров нет
'modulename-tools'); //Имя административного контроллера
//Создаем объект кнопки
$button = new \RS\Html\Toolbar\Button\Button(null, t('Сделать публичными'), array(
'attr' => array(
'data-url' => $url,
'class' => 'crud-post' //Пользуемся микроразметкой административной панели. Сообщаем, что нужно отправить ID выбранных элементов на data-url
)
));
//Получаем нижнюю панель инструментов на странице со списком товаров в административной панели
$bottom_toolbar = $helper->getBottomToolbar(); //Здесь объект \RS\Html\Toolbar\Element
//Добавляем кнопку
$bottom_toolbar->addItem($button);
}
}
add_custom_product_action.jpg
Кастомная кнопка в панели инструментов

Как видно из примера выше, мы добавили произвольную кнопку в нижнюю панель инструментов и с помощью классов микроразметки наделили её способностью передавать POST запросом выбранные ID элементов в таблице.

Далее необходимо создать контроллер, который будет обрабатывать входящий запрос. Создаем файл controller/admin/tools.inc.php.

<?php
namespace ModuleName\Controller\Admin;
{
function actionSetVisible()
{
$ids = $this->url->post('chk', TYPE_ARRAY); //Получаем из POST ID отмеченных товаров или флажок "Все товары".
$controller = new \Catalog\Controller\Admin\Ctrl(); //Создаем экземпляр того контроллера, в котором мы выбирали товары
$real_product_ids = $controller->modifySelectAll($ids); //Получаем список ID товаров с учетом всех выбранных фильтров на странице контроллера
//Все, далее мы можем делать все что угодно с товарами, так как известны ID всех выбранных товаров в $real_product_ids
$process_product_api = new \ModuleName\Model\ProcessProductApi(); //Создаем объект нашего собственного API, в котором мы реализуем логику действий
$count = $process_product_api->setAllVisible($real_product_ids); //Отмечаем флаг публичности выбранным товарам
$this->result->setSuccess($count > 0); //Сообщим frontEnd'у, что операция выполнена успешно и следует обновить список товаров
if ($count) {
// Вернем команду административной панели: отобразить успешный стикер с надписью
return $this->result->addMessage(t('Обновлено %count товаров', array('count' => $count)));
} else {
// Вернем команду административной панели: отобразить ошибочный стикер с надписью
return $this->result->addEMessage(t('Все товары уже видимы'));
}
}
}

Так как на странице со списком товаров в административной панели можно не просто выбрать товары, а выбрать еще флажок "Выбрать товары на всех страницах", нам необходимо обработать такую ситуацию. Технически это будет выглядеть так: будет передан дополнительный параметр selectAll=on в POST запросе.

Если мы получаем такой параметр, то нужно связаться с контроллером, который выводил товары. Только он знает какие были установлены в тот момент фильтры, и только он может корректно вернуть все ID товаров. Соответственно мы связываемся с контроллером Catalog::Controller::Admin::Ctrl и вызываем у него метод modifySelectAll, который вернет нам готовый результат в виде ID всех выбранных товаров.

Придерживаемся принципа минималистичности контроллера и не пишем непосредственно логику действий здесь. Вместо этого вызываем метод setAllVisible у созданного нами класса ProcessProductApi. Рассмотрим его подробнее.

Создадим класс модели, в котором реализуем непосредственную логику обновления поля рublic у товаров, для этого создадим файл /model/processproductapi.inc.php со следующим содержимым:

<?php
namespace ModuleName\Model;
/**
* Класс, в котором мы реализуем собственную логику действий
*/
class ProcessProductApi
{
/**
* Устанавливает указанным товарвм флаг видимости
*
* @param array $product_ids массив со списком ID товаров
* @return int Возвращает количество обновленных записей
*/
function setAllVisible(array $product_ids)
{
if (!$product_ids) return 0; //Если пустой массив, то возвращает, что обработано 0 записей
//Выполняем запрос к БД
->update(new \Catalog\Model\Orm\Product())
->set(array(
'public' => 1
))
->whereIn('id', $product_ids)
->exec()
->affectedRows();
return $count;
}
}

Все готово. Проверяем работу. Выбираем два товара непубличных товара, нажимаем на кнопку "Сделать публичными", видим успешный стикер.

add_custom_product_action_sticker.jpg
Успешный стикер

В случае выполнения повторной попытки выполнить команду, видим красный стикер с ошибкой

add_custom_product_action_errsticker.jpg
Стикер с ошибкой