Нодус:Кастомизация списка записей
С недавних пор в Нодусе появилась возможность кастомизировать списки записей (item'ов). Переопределить можно как столбцы таблицы, так и форму для фильтрации записей.
Нужно сказать, что переопределение идет на уровне типов данных, то есть при выводе списка записей только одного типа. Если вывести записи всех типов сразу, отобразятся поля и форма по умолчанию.
Переопределение столбцов таблицы
Для переопределения столбцов таблицы в классе Component_Nodus_Datatype существует метод admin_list_fields, который можно переопределить в классе нужного типа данных. В качестве параметра он принимает массив полей по умолчанию, а возвращать должен тот же массив, но уже модифицированный по вашему усмотрению.
Например, у нас есть список товаров, и мы хотим добавить в таблицу поля "Артикул" и "Цена". Сделать это можно так:
// app/components/Nodus/app/Datatype/My/Type.php class Component_Nodus_App_Datatype_My_Type extends Component_Nodus_Datatype implements Core_ModuleInterface { ... public function admin_list_fields($fields = array()) { $fields['code'] = array( 'caption' => 'Артикул', 'weight' => -550, ); $fields['price'] = array( 'caption' => 'Цена', 'weight' => -540, ); return $fields; } ... }
У каждого столбца, то бишь поля записи, есть свой вес. Чем меньше вес, тем раньше столбец будет выведен в таблице. Тут все по аналогии с полями для формы редактиорвания записи.
Столбцы по умолчанию, а также их вес, можно посмотреть в методе list_fields класса Component_Nodus_Admin_Items. Ну или поставить var_dump в своем методе, и посмотреть, что же там за поля такие пришли.
Формат модифицируемых полей соответствует формату стандартных полей CMS.Controller.Table. Что позволяет применять все допустимые параметры для кастомизации при настройке полей. Подробнее о параметрах в ст. CMS.Controller.Table: Стандартный контроллер администрирования таблиц (раздел: Настройка формы редактирования).
Для изменения содержимого столбцов (например, нужно вывести поле с привязкой к терминам таксономии) можно подписаться на событие nodus.admin.items.on_row. Первым параметром выбранного метода будет объект отображаемой записи, вторым - объект текущего админского контроллера.
// ../app/components/Nodus/app/Datatype/MyDatatype/Type.php class Component_Nodus_App_Datatype_MyDatatype_Type extends Component_Nodus_Datatype { ... public static function initialize() { parent::initialize(); Events::add_listener( 'nodus.admin.items.on_row', array(Component_Nodus::datatype('mydatatype'), 'on_row'), ); } public function on_row($row, $controller) { if ($row->datatype == 'mydatatype') { $item->taxonomy_field = ($term = Component_Nodus::taxonomy_term($item->taxonomy_field)) ? $term->field('title') : 'Нет'; } } ... }
Кастомизация формы для фильтрации записей
Таким же образом можно переопределить поля для формы фильтрации.
По умолчанию присутствует только одно текстовое поле "Поиск", и поиск ведется только по названию записи. Не густо.
Давайте добавим два поля для фильтрации по цене ("Цена от" и "Цена до"), а поиск будем вести не только по названию, но и по артикулу.
В классе Component_Nodus_Datatype есть метод admin_filters_form, переопределяем его в классе нашего типа данных.
// app/components/Nodus/app/Datatype/My/Type.php class Component_Nodus_App_Datatype_My_Type extends Component_Nodus_Datatype implements Core_ModuleInterface { ... public function admin_filters_form($fields = array()) { $fields['price_from'] = array( 'caption' => 'Цена от', 'style' => 'width: 100px;', 'weight' => -950, ); $fields['price_to'] = array( 'caption' => 'Цена до', 'style' => 'width: 100px;', 'weight' => -940, ); $fields['search']['caption'] = 'Поиск по названию и артикулу'; return $fields; } ... }
Здесь все аналогично, получаем список полей, модифицируем его и отдаем обратно. Поля по умолчанию смотрим в методе filters_form класса Component_Nodus_Admin_Items.
Все замечательно, у нас появилась форма с нужными нам полями. Но если попробовать отфильтровать записи по нашим новым полям, мы получим ошибку.
Это происходит потому, что каждому полю фильтра должен соответствовать свой метод в маппере (класс Component_Nodus_DB_Items). Полю price_from метод map_price_from и т.д. Но там их нет.
Не расстраивайтесь, это поправимо.
Все в том же классе Component_Nodus_Datatype есть метод mapper, который получает исходный маппер, модифицирует его и отдает обратно. Как вы уже наверное догадались, его нужно переопределить в классе нашего типа данных.
// app/components/Nodus/app/Datatype/My/Type.php class Component_Nodus_App_Datatype_My_Type extends Component_Nodus_Datatype implements Core_ModuleInterface { ... public function mapper($mapper, &$parms = array()) { if (isset($parms['price_from'])) { $mapper = $mapper->column_gte('price', $parms['price_from']); unset($parms['price_from']); } if (isset($parms['price_to'])) { $mapper = $mapper->column_lte('price', $parms['price_to']); unset($parms['price_to']); } if (isset($parms['search'])) { $s = "%{$parms['search']}%"; $where = array(); foreach(array('code', 'title') as $field) { $where[] = "$field like '$s'"; } $mapper = $mapper->where(implode(' OR ', $where)); unset($parms['search']); } return $mapper; } ... }
Как вы заметили, кроме самого маппера в этот метод передается еще и массив параметров $parms, это те самые значения, которые были введены в поля формы фильтрации. Причем массив этот передается по ссылке, а значит мы можем и его модифицировать. И мы пользуемся этой возможностью.
Проверяем наличие параметров для новых полей формы, и модифицируем маппер в соответствии с ними. После этого обязательно удаляем параметры (unset), таким образом они не будут переданы родительскому мапперу, и ошибки не возникнет.
Вот и все, смотрим на наш преобразившийся список с нескрываемой радостью!
Если ничего не получилось, обновите Нодус до последней версии.