ShvetsGroup

 

Темизация Views

  • neochief's picture
0 comments

Темизация Views

Статья эвакуирована с DrupalDance.com

Данная статья повествует о темизации вьюсов пятой версии Друпала. Темизация для шестой ветки будет расписана позже. Оставайтесь с нами ;)

С выходом релиз-кандидатов модулей Views 2 и CCK 2 для шестой версии друпала, стоит уже серьезно задуматься о переходе на Drupal 6.

Чтобы дать толчок этому процессу, я решил окончательно раскрыть тему темизации этих модулей, сначала, для пятой ветки, а затем и для шестой.

Итак, начнем с темизации вьюсов.

Наверное, первым камнем преткновения разработчика, познавшего начальные прелести Друпала, является темизация модуля Views. Этот процесс содержит минимум документации, так что, порой, некоторые начинающие разработчики вообще не догадываются, что с вьюсами можно что-то делать.

# Простейший путь

В поставку модуля Views входит модуль Views Theme Wizard. Включив этот модуль, вы получите инструмент быстрого создания простых шаблонов темизации вьюсов:

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 .= "
name) ."'>". views_theme($plugins[$view_type]['summary_theme'], $view, $type, $level, $nodes, $args) . '
'; } else { $output .= "
name) ."'>". views_theme($plugins[$view_type]['theme'], $view, $nodes, $type) . '
'; } $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 = "
name) ."'>$output
\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 .= "
" . $field['label'] . "
"; } // темизация отдельного поля $item .= "
" . views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $node, $view) . "
"; } } $items[] = "
name) ."'>$item
\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);
}

# Темизация вьюсы c полными нодами


// вариация с именем вьюсы:
// 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 нужно вставить такой код:


name == 'viewname') { ?> // измените для вашего случая
  // здесь вставлять свой код

Думаю, здесь пояснения излишни.

# Темизация summary-представления

Довольно редко используемое, 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 "";
}

Есть еще одна функция темизации, о которой я не упоминал. Но она используется только в случае программной вставки вьюшки в страницу (например так 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);
  }
}

Got anything to add?