Изменяем страницу термина таксономии

В этой статье рассмотрим возможности изменения средствами API Drupal`а стандартного вывода списка материалов отдельно взятого термина таксономии. Говоря другими словами, той страницы, что отображается у нас по адресу: taxonomy/term/id-термина.

Стандартная функция вывода страницы термина

Изменять страницу вывода будем с помощью функции системы темизации Drupal`а theme_taxonomy_term_page, которая и отвечает за «собранный», конечный вид страницы термина.

Так выглядит код функции theme_taxonomy_term_page() в своем изначальном виде:
function theme_taxonomy_term_page($tids, $result) {
  drupal_add_css(drupal_get_path('module', 'taxonomy') .'/taxonomy.css');

  $output = '';

  // Only display the description if we have a single term, to avoid clutter and confusion.
  if (count($tids) == 1) {
    $term = taxonomy_get_term($tids[0]);
    $description = $term->description;

    // Check that a description is set.
    if (!empty($description)) {
      $output .= '<div class="taxonomy-term-description">';
      $output .= filter_xss_admin($description);
      $output .= '</div>';
    }
  }

  $output .= taxonomy_render_nodes($result);

  return $output;
}

Прежде, чем начать изменять, разберем ее по «кусочкам».

Подключение файла стилей:

function theme_taxonomy_term_page($tids, $result) {
  drupal_add_css(drupal_get_path('module', 'taxonomy') .'/taxonomy.css');

В самом начале кода функции дается команда присоединить к общей массе уже загружающихся CSS-файлов еще один - taxonomy.css. Того, что входит в комплект самого модуля Taxonomy. Если мы планируем самостоятельно управлять видом страницы термина(посредством файла style.css стилей темы, например), то можно данную строчку из кода функции изъять.

Смотрим далее:

  $output = '';

  // Only display the description if we have a single term, to avoid clutter and confusion.
  if (count($tids) == 1) {
    $term = taxonomy_get_term($tids[0]);
    $description = $term->description;

    // Check that a description is set.
    if (!empty($description)) {
      $output .= '<div class="taxonomy-term-description">';
      $output .= filter_xss_admin($description);
      $output .= '</div>';
    }
  }
 

Как гласит текст первого комментария в коде функции: отображаем описание термина, если это страница одного-единственного термина (условие if (count($tids) == 1), а не нескольких (речь идет о страницах типа taxonomy/term/термин1,термин2,термин3). Во второй части кода делается проверка, существует ли вообще описание для этого термина (if (!empty($description))). И если существует, то его следует выводить в DIV-контейнере с CSS-классом taxonomy-term-description.

И заключительный «кусок»:

  $output .= taxonomy_render_nodes($result);

  return $output;
}

Тут, собственно и происходит формирование вывода списка материалов, связанных с термином. Точнее происходит вежливый «отсыл» к другой функции API - taxonomy_render_nodes(). Эта функция, в свою очередь, и формирует то, что по-умолчанию Drupal нам показывает под описанием термина на его странице.

Код функции taxonomy_render_nodes():
function taxonomy_render_nodes($result) {
  $output = '';
  $has_rows = FALSE;
  while ($node = db_fetch_object($result)) {
    $output .= node_view(node_load($node->nid), 1);
    $has_rows = TRUE;
  }
  if ($has_rows) {
    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
  }
  else {
    $output .= '<p>'. t('There are currently no posts in this category.') .'</p>';
  }
  return $output;
}

Переопределением этого последнего «куска» функции мы далее и займемся.

Изменяем вывод материалов термина в функции theme_taxonomy_term_page()

Для начала поставим себе тестовое техзадание, каким мы желаем видеть вывод материалов, ассоциированных с отображаемым термином.

В примере рассмотрим вариант, когда при наличии у термина «дочерних» терминов, будет сначала отображаться список этих самых «подтерминов»(ссылками, естественно), и с указанием рядом с «дочерним» термином количества материалов, ассоциированных уже с ним. Ну и уже под этим списком пусть будут выведены заголовки материалов ссылками «основного» нашего термина, т.е. того, на чьей странице мы находимся в данный момент.

Переопределим так же количество заголовков материалов на страницу. И, конечно же, добавим пейджер, дабы можно было увидеть заголовки остальных материалов, если их у термина больше, чем задано нами в настройках лимита их вывода.

Приступаем к выполнению нашего ТЗ. Код верхней части функции theme_taxonomy_term_page() оставим как есть. Там все и так достаточно прозрачно. В нижеописанном же примере будем изменять лишь вывод материалов термина.

Формируем список «дочерних» терминов, если таковые имеют место быть.

$children_terms = taxonomy_get_children($term->tid); // Запрашиваем список дочерних дерминов нашего основного термина.
if ($children_terms) { // И если они есть, то выводим их.
$children_terms = taxonomy_get_children($term->tid);
foreach ($children_terms as $children_term )
{
$t_children_count = taxonomy_term_count_nodes($children_term->tid);
$children_items[] = l($children_term->name .' ('. $t_children_count .')','taxonomy/term/'. $children_term->tid, array('attributes' => array('title' => $children_term->name)));
}
$output .= theme('item_list', $children_items, t('Subsections')); // К списку «дочерних» терминов добавим так же заголовок.
}

Теперь формируем список заголовков нод термина ссылками на страницу ноды. Лимит для количества заголовков на страницу зададим переопределением переменной $default_nodes_main, значение которой до нашего вмешательства было тем, которое задано в Настройках публикации на странице admin/content/node-settings.

while ($node = db_fetch_object($result)) // «Расчленяем» ноду на свойства обьекта.
{
  $items[]  = l($node->title, 'node/'. $node->nid,array('attributes'=>array('title'=> $node->title))); // Добавим атрибут 'title' в тег 'a' заголовка-ссылки на страницу ноды.
  }
  $output .= theme('item_list', $items, t('Publications'), 'ul',array('class'=>'pub-list')); // Как и для списка «дочерних» терминов, добавим отображение заголовка списка нод термина.
  $output .= theme('pager', NULL, variable_set('default_nodes_main', 20), 0); // Формируем конечный вывод списка с пейджером и установкой лимита заголовков на страницу.
  $output .= '</div>';
  return $output;

Готово! Техзадание, в части подготовки рабочего кода, нами успешно выполнено.

Добавляем новую функцию в файл template.php темы

Переопределенная функция theme_taxonomy_term_page() (НАЗВАНИЕ_НАШЕЙ_ТЕМЫ_taxonomy_term_page()):
function НАЗВАНИЕ_ТЕМЫ_taxonomy_term_page($tids, $result)
{
drupal_add_css(drupal_get_path('module', 'taxonomy') .'/taxonomy.css');
$output = '<div id="category-item-list">';
// Only display the description if we have a single term, to avoid clutter and confusion.
if (count($tids) == 1) {
    $term = taxonomy_get_term($tids[0]);
    $description = $term->description;
// Check that a description is set.
if (!empty($description))
{
      $output .= '<div class="taxonomy-term-description">';
      $output .= filter_xss_admin($description);
      $output .= '</div>';
}
}

$children_terms = taxonomy_get_children($term->tid);
if ($children_terms) {
$children_terms = taxonomy_get_children($term->tid);
foreach ($children_terms as $children_term )
{
$t_children_count = taxonomy_term_count_nodes($children_term->tid);
$children_items[] = l($children_term->name .' ('. $t_children_count .')','taxonomy/term/'. $children_term->tid, array('attributes' => array('title' => $children_term->name)));
}
$output .= theme('item_list', $children_items, t('Subsections'));
}
while ($node = db_fetch_object($result))
{
  $items[]  = l($node->title, 'node/'. $node->nid,array('attributes'=>array('title'=> $node->title)));
  }
  $output .= theme('item_list', $items, t('Publications'), 'ul',array('class'=>'pub-list'));
  $output .= theme('pager', NULL, variable_set('default_nodes_main', 20), 0);
  $output .= '</div>';
  return $output;
}

Следующим и последним этапом будет практическое применение наших изменений к странице термина таксономии. Для этого открываем файл template.php текущей темы сайта, и вписываем в него переопределенную функцию theme_taxonomy_term_page().

Не забываем (!!!), что название переопределенной функции в template.php будет другим, а именно: НАЗВАНИЕ_НАШЕЙ_ТЕМЫ_taxonomy_term_page().

Сохраняем template.php, и перезагружаем реестр тем сайта, что бы новые настройки отображения страницы термина таксономии были приняты к исполнению Drupal`ом.

Dalay

Комментарии

Благодарю!
Всё чётко и понятно - а главное применимо!
Только возник один вопрос - а как в li вставлять odd и even?

Можно переопределить theme_item_list() через template.php. Примерно так:

function НАЗВАНИЕ_ТЕМЫ_item_list($items = array(), $title = NULL, $type = 'ul', $attributes = NULL) {
  static $count = 0;
  $output = '<div class="item-list">';
  if (isset($title)) {
    $output .= '<h3>'. $title .'</h3>';
  }
  if (!empty($items)) {
    $output .= "<$type" . drupal_attributes($attributes) . '>';
    foreach ($items as $item) {
      $zebra = ($count % 2) ? 'odd' : 'even';
      $count++;
      $attributes = array();
      $children = array();
      if (is_array($item)) {
        foreach ($item as $key => $value) {
          if ($key == 'data') {
            $data = $value;
          }
          elseif ($key == 'children') {
            $children = $value;
          }
          else {
            $attributes[$key] = $value;
          }
        }
      }
      else {
        $data = $item;
      }
      if (count($children) > 0) {
        $data .= theme_item_list($children, NULL, $type, $attributes);
      }
      $output .= '<li class="' . $zebra . '"' . drupal_attributes($attributes) . '>'. $data .'</li>';
    }
    $output .= "</$type>";
  }
  $output .= '</div>';
  return $output;
  }

Большое спасибо за такой интересный сайт. Он мне очень вовремя попался.
А по теме вопрос: а как можно сделать отображение анонсов нод в самом глубоком термине словаря?
Ну например есть такой словарь:
Словарь1
-Подсловарь1
--Подподсловарь1

Как сделать, чтобы при выборе --Подподсловарь1 отображались не просто заголовки нод, а их анонсы?

Думаю, что путем баловства с функцией taxonomy_get_children().

Привет.
есть страница термина /user/interests/1007724, я создал вьюшку "дисплей - страница" с урлом /user/interests/% , вписал аргумент по PHP коду if (arg(2)) {
return arg(2);
} все сохранил, почистил кеш и ничего, показывается все равно стандартная страница термина
в предварительном просмотре вьюшки если я вставляю туда айди термина, то показывается то что нужно

что не так или этот вариант не работает...

мне просто проще делать вьюшкой, это возможно?

При чем здесь Views?

а как перезагрузить "реестр тем сайта"?

Пересохраните настройки на странице выбора тем сайта.

Отличный материал, спасибо.
Не могу найти, какую функцию надо переопределить, чтобы сформировать вывод
всех терминов словаря таксономии?

тут искали?

Да, искал, понятно почему не нашел. Нету там вывода листинга всех терминов словаря. Написал сам.
Возник еще один вопрос.
Пытаюсь для примера, приведенного выше, сделать след. логику:
при отображении термина показываются дочерние термины и тизеры нодов, с которыми связан этот термин.
Если нет дочених терминов и привязан только один нод, то вместо вывода его тизера выводить нод целиком.
Соотв для этого последнего случая вместо
$output .= node_view(node_load($node->nid), 1);
для вывода тизера
пытаюсь использовать
$output .= node_view(node_load($node->nid), 0);
и нод не отображается.
Я что-то делаю не так?

Плохо искал.

Здравствуйте, этот рецепт с выводом дочерних терминов БЕЗ Views бесценен! :)
Не могли бы вы показать, как после дочерних терминов вывести не просто заголовки нод, а полноценные тизеры? То есть, отличие от стандартной страницы таксономии будет только в дополнительном списке дочерних терминов:
***
Имя текущего термина
Описание текущего термина
Subsections
* дочерние термины (х)
Тизеры нод текущего термина <- вместо простого списка заголовков
***
Если не затруднит.

Перечитайте, пожалуйста, статью еще раз. Все ответы в ней есть.

Я кажется понимаю, что вы о "заключительном куске" что в начале статьи, но пока знаний не хватает соединить это все в $output и вывести (

Присоединяюсь к вопросу, здравствуйте.

Похоже на то, что нам с Галиной нужно drupal . ru / node / 43742
Этот же код, что и в статье используется.

от души респектую ;-)
очень помог сайт, спасибо.

да, получилось. vko .lik.kz/category/materialy-saita/sotsialnye-proekty/alp-klub-raduga
вопрос по органик групп vko.lik.kz/ content/alp-klub-raduga-0
после выключения модуля видов (представлений) перестала работать любая статистика по закачкам и в "подробнее по группе" стали неактивными цифры пользователей группы и тех кто хочет присоединиться к группе. Обошла эту ситуацию тем, что при регистрации теперь есть выбор групп сразу. Может есть более простые способы решения?

Отличная статья, спасибо

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

А можно ли сделать такой вывод только для одного словари таксономии????

блин пол дня убил на друпал.ру на это. Надо было сразу в поисковике ответ искать, спасибо за статью.