

Данная статья повествует о темизации вьюсов пятой версии Друпала. Темизация для шестой ветки будет расписана позже. Оставайтесь с нами ;)
С выходом релиз-кандидатов модулей Views 2 и CCK 2 для шестой версии друпала, стоит уже серьезно задуматься о переходе на Drupal 6.
Чтобы дать толчок этому процессу, я решил окончательно раскрыть тему темизации этих модулей, сначала, для пятой ветки, а затем и для шестой.
Итак, начнем с темизации вьюсов.
Наверное, первым камнем преткновения разработчика, познавшего начальные прелести Друпала, является темизация модуля Views. Этот процесс содержит минимум документации, так что, порой, некоторые начинающие разработчики вообще не догадываются, что с вьюсами можно что-то делать.
В поставку модуля Views входит модуль Views Theme Wizard. Включив этот модуль, вы получите инструмент быстрого создания простых шаблонов темизации вьюсов:

Данный способ предполагает темизацию только вьюсов List-типа. Если у вас табличные, тизеровые или какие-то другие вьюсы — данный подход ничем вам не поможет.
Но не стоит отчаиваться, так как в модуле Views заложена уйма методов темизации. Рассмотрим все варианты.
В модуле можно найти замечательнуй функцию theme_views_view, а немного порыскав в коде, можно еще и найти ее вариации:
// изменения будут затрагивать только вьюсу с названием VIEW_NAME и типом VIEW_TYPE
// function phptemplate_views_view_VIEW_TYPE_VIEW_NAME($view, $type, $nodes, $level = NULL, $args = NULL) { ... }
// изменения будут затрагивать только вьюсу с названием VIEW_NAME, любого типа
// function phptemplate_views_view_VIEW_NAME($view, $type, $nodes, $level = NULL, $args = NULL) { ... }
// изменения будут затрагивать все вьюсы
function phptemplate_views_view($view, $type, $nodes, $level = NULL, $args = NULL) {
$num_nodes = count($nodes);
if ($type == 'page') {
drupal_set_title(filter_xss_admin(views_get_title($view, 'page')));
views_set_breadcrumb($view);
}
if ($num_nodes) {
$output .= views_get_textarea($view, $type, 'header');
}
if ($type != 'block' && $view->exposed_filter) {
$output .= views_theme('views_display_filters', $view);
}
$plugins = _views_get_style_plugins();
$view_type = ($type == 'block') ? $view->block_type : $view->page_type;
if ($num_nodes || $plugins[$view_type]['even_empty']) {
if ($level !== NULL) {
$output .= "<div class='view-summary ". views_css_safe('view-summary-'. $view->name) ."'>". views_theme($plugins[$view_type]['summary_theme'], $view, $type, $level, $nodes, $args) . '</div>';
}
else {
$output .= "<div class='view-content ". views_css_safe('view-content-'. $view->name) ."'>". views_theme($plugins[$view_type]['theme'], $view, $nodes, $type) . '</div>';
}
$output .= views_get_textarea($view, $type, 'footer');
if ($type == 'block' && $view->block_more && $num_nodes >= $view->nodes_per_block) {
$output .= theme('views_more', $view->real_url);
}
}
else {
$output .= views_get_textarea($view, $type, 'empty');
}
if ($view->use_pager) {
$output .= theme('pager', '', $view->pager_limit, $view->use_pager - 1);
}
if ($output) {
$output = "<div class='view ". views_css_safe('view-'. $view->name) ."'>$output</div>\n";
}
return $output;
}
Таким образом, мы получаем очень гибкий способ темизации, приктически любой вьюсы. Рассмотрим примеры.
Этот код очень похож на то, что генерирует модуль Views Theme Wizard, за исключением того, что данный код не пытается подключать внешние шаблоны, как это делает мастер. Если вам все же нужно подключить внешний шаблон, напомню, что это делается функцией _phptemplate_callback().
// вариация с именем вьюсы:
// function phptemplate_views_view_list_VIEW_NAME($view, $nodes, $type) { ... }
function phptemplate_views_view_list($view, $nodes, $type) {
$fields = _views_get_fields();
// составление строк списка
foreach ($nodes as $node) {
$item = '';
foreach ($view->field as $field) {
if (!isset($fields[$field['id']]['visible']) && $fields[$field['id']]['visible'] !== FALSE) {
if ($field['label']) {
$item .= "<div class='view-label ". views_css_safe('view-label-'. $field['queryname']) ."'>" . $field['label'] . "</div>";
}
// темизация отдельного поля
$item .= "<div class='view-field ". views_css_safe('view-data-'. $field['queryname']) ."'>" . views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view) . "</div>";
}
}
$items[] = "<div class='view-item ". views_css_safe('view-item-'. $view->name) ."'>$item</div>\n"; // l($node->title, "node/$node->nid");
}
if ($items) {
return theme('item_list', $items);
}
}
// вариация с именем вьюсы:
// function phptemplate_views_view_table_VIEW_NAME($view, $nodes, $type) { ... }
function phptemplate_views_view_table($view, $nodes, $type) {
$fields = _views_get_fields();
// составление строк таблицы
foreach ($nodes as $node) {
$row = array();
foreach ($view->field as $field) {
if ($fields[$field['id']]['visible'] !== FALSE) {
// темизация отдельного поля
$cell['data'] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view);
$cell['class'] = "view-field ". views_css_safe('view-field-'. $field['queryname']);
$row[] = $cell;
}
}
$rows[] = $row;
}
// вывод таблицы
return theme('table', $view->table_header, $rows);
}
// вариация с именем вьюсы:
// function phptemplate_views_view_teasers_VIEW_NAME($view, $nodes, $type) { ... }
function phptemplate_views_view_teasers($view, $nodes, $type) {
return views_theme('views_view_nodes', $view, $nodes, $type, true);
}
// вариация с именем вьюсы:
// function phptemplate_views_view_nodes_VIEW_NAME($view, $nodes, $type, $teasers = false, $links = true) { ... }
function phptemplate_views_view_nodes($view, $nodes, $type, $teasers = false, $links = true) {
foreach ($nodes as $n) {
$node = node_load($n->nid);
$output .= node_view($node, $teasers, false, $links);
}
return $output;
}
Этот код дает представление о том, как темизировать списки нод, но что если нужно темизировать сами ноды когда они появляются во вьюсах? Все довольно таки просто. В шаблонах node[-node_type].tpl.php нужно вставить такой код:
<?php global $current_view; ?>
<?php if ($current_view->name == 'viewname') { ?> // измените для вашего случая
// здесь вставлять свой код
<?php }; ?>
Думаю, здесь пояснения излишни.
Довольно редко используемое, summary-представление вьюсы, можно использовать, когда в вашей вьюсе используются аргументы. Возьмем к примеру, стандартную вьюсу taxonomy_term. Если в настройках аргумента выбрать в поле "Умолчания" правило "Summary", то при показе этой вьюсы без аргумента, все будет выглядеть примерно так:

Код темизации summary-представления:
// вариация с именем вьюсы:
// function phptemplate_views_summary_VIEW_NAME($view, $type, $level, $nodes, $args) { ... }
function phptemplate_views_summary($view, $type, $level, $nodes, $args) {
foreach ($nodes as $node) {
$items[] = views_get_summary_link($view->argument[$level]['type'], $node, $view->real_url) . " (" . $node->num_nodes . ")";
}
if ($items) {
$output .= theme('item_list', $items);
}
return $output;
}
Темизация отдельных полей вьюшек — еще плотнее завешена покровом тайны, потому что явного вызова этих функций в коде модуля Views нет нигде. Однако, они существуют:
// вариация с именем поля:
// function phptemplate_views_handle_field_FIELD_NAME($fields, $field, $data) { ... }
// вариация с именем вьюсы и поля:
// function phptemplate_views_handle_field_VIEW_NAME_FIELD_NAME($fields, $field, $data) { ... }
function phptemplate_views_handle_field($fields, $field, $data) {
$info = $fields[$field['fullname']];
if ($field['handler'] && function_exists($field['handler'])) {
return $field['handler']($info, $field, $data->$field['queryname'], $data);
}
if ($info['handler'] && is_string($info['handler']) && function_exists($info['handler'])) {
return $info['handler']($info, $field, $data->$field['queryname'], $data);
}
return check_plain($data->$field['queryname']);
}
Примечание: FIELD_NAME это не привычное название поля (типа field_image или field_mytext). Правильное значние FIELD_NAME находится в переменной $field['queryname'], поэтому, чтобы понять как назвать конкретную функцию, назовите ее сначала просто phptemplate_views_handle_field, а затем, в ее начале вставьте команду print_r($field['queryname']). Она и выведет корректное название (названия бывают довольно таки страшные, как node_data_field_image_field_image_fid, но не следует этого боятся, просто вставляйте это в название функции вместо FIELD_NAME).
Все фильтры во вьюсах можно сделать доступными для пользовательского ввода. В этом случае, за темизацию формы фильтра отвечает следующий код:
// вариация с именем вьюсы:
// phptemplate_views_filters_VIEW_NAME($form) { ... }
function phptemplate_views_filters($form) {
$view = $form['view']['#value'];
foreach ($view->exposed_filter as $count => $expose) {
$row[] = drupal_render($form["op$count"]) . drupal_render($form["filter$count"]);
$label[] = $expose['label'];
}
$row[] = drupal_render($form['submit']);
$label[] = '';
return drupal_render($form['q']) . theme('table', $label, array($row)) . drupal_render($form);
}
Не могу не упомянуть о возможности темизировать ссылку "More", которая появляется в блочных вьюсах когда элементов в списке больше, чем может вместить блок:
function phptemplate_views_more($url) {
return "<div class='more-link'>" . l(t('more'), $url) . "</div>";
}
Есть еще одна функция темизации, о которой я не упоминал. Но она используется только в случае программной вставки вьюшки в страницу (например так print(theme('view','current_user_buddys'));), а именно:
function phptemplate_view($view_name, $limit = NULL, $use_pager = NULL, $type = 'embed', $view_args = array()) {
if ($view = views_get_view($view_name)) {
$use_pager = isset($use_pager) ? $use_pager : $view->use_pager;
$limit_default = ($type == 'block') ? $view->nodes_per_block : $view->nodes_per_page;
$limit = isset($limit) ? $limit : $limit_default;
return views_build_view($type, $view, $view_args, $use_pager, $limit);
}
}
# | beerman
А как темизировать поле image в случае табличного представления, чтобы в таблицу не пихались все картинки этого поля, а только, к примеру, первая?
Полагаю, через phptemplate_views_handle_field_VIEW_NAME_FIELD_NAME($fields, $field, $data) { ... }
В точности код не скажу, надо смотреть по обстановке. Прийдется поиграться с переменной $data
# | Лера Мулина
Извините за, может быть, слишком простой вопрос:
то есть эти изменения надо вписать в views.module, чтобы иметь возможность темизировать views через css? А если их не прописать, то изменения во views через css нельзя делать?
Я правильно поняла?
Эти функции добавляются в template.php файл вашей темы. Ними можно поменять вывод в html, потому что бывает так, что нужное попросту не размечено CSS классами.
# | Лера Мулина
то есть если прописать эти функции, то для этих элементов появляются классы?
# | beerman
темизация ССК имеет функцию
function phptemplate_field_node_data_field_FIELDNAME_fid(&$node, &$field, &$items, $teaser, $page) {
...
return _phptemplate_callback('field', $variables, array('field-'. $field['field_name']));
}
при вставке кода print $field['field_name']; перед возвратом, получаю имя поля типа node_data_field_FIELDNAME.field_FIELDNAME_fid
т.е., как я понимаю, имя файла темизации должно быть вида field-node_data_field_FIELDNAME.field_FIELDNAME_fid.tpl.php так?
но он не цепляется.
учитель, колитесь ;)
# | beerman
нифига не там я его получал. а функция вызывается только при просмотре ноды... пойду views_handle поковыряю
# | KCEOH
Опечатка
назовите ее сначала ghjcnj phptemplate_views_handle_field
Пошел курить на тему табличных вьюсов и творить на своём сайте :)
Здравствуйте.
Возможно ли при выводе тизерной вьюсы добавить классы odd и even?
Можно ли где-то найти пример.
Большое спасибо
function phptemplate_views_view_nodes($view, $nodes, $type, $teasers = false, $links = true) {
$odd = TRUE;
foreach ($nodes as $n) {
$odd = !$odd;
$node = node_load($n->nid);
if ($teasers) {
if ($odd) {
$cl = 'odd';
} else {
$cl = 'even';
}
}
$output .= node_view($node, $teasers, false, $links);
if ($cl) {
$output = '<div class="'.$cl.'">'.$output.'</div>';
}
}
return $output;
}Спасибо, работает.
В конце только строка
$output .= '<div class="object-'.$cl.'">'.node_view($node, $teasers, false, $links).'</div>';
ато лесенкой теги закрывает.
# | beerman
<?php function theme_views_view_news($view, $type, $nodes) ?>
во views в списке полей значится Node:Body, но при выводе
<?php print_r($nodes) ?>
его нет. подскажите, где его можно получить?
# | goran
А есть ли наработки по темизации Views2, по сути API там достаточно отличается от первой, а документаций почти нигде нет.
Можно ли темизировать саму страницу вывода вьюсы?
Т.е. тип вьюсы - Page, а как для этой page задать шаблон отличающийся от page.tpl.php?
# | mc
Вот хороший подкаст по Views 2. Прадва звук не важнецкий, но посмотреть можно :)
http://www.youtube.com/watch?v=D6qZ4usOV-E
Ссылки с других сайтов
Все молчат как партизаны.