Нодус:Кастомизация списка записей

Компонент: Nodus

С недавних пор в Нодусе появилась возможность кастомизировать списки записей (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), таким образом они не будут переданы родительскому мапперу, и ошибки не возникнет.

Вот и все, смотрим на наш преобразившийся список с нескрываемой радостью!

Если ничего не получилось, обновите Нодус до последней версии.

Метки: Нодус
26.06.2014
Все статьи