Хитрости таксономии Друпала

Умолчально предлагаемый друпалом способ выдачи нод принадлежащих термину таксономии прост, но все-таки достаточно убог. Формируем адрес taxonomy/term/N (N - номер термина) и получаем список нод принадлежащих ему.

Но подобная плоская иерархия редко бывает востребована. Поэтому сразу начинаешь искать некоторые дополнительные возможности, вроде Vocablary Index, Taxonomy Menu и прочие.
Правда, многие возможности уже заложены в сам модуль таксономии, хотя и редко упоминаются.

Используются эти возможности специально сформированным адресом страницы после term

Все ноды из нескольких категорий

По адресу taxonomy/term/N1+N2 мы получим все ноды принадлежащие сразу двум терминам таксономии за номерами N1 и N2. Число терминов таксономии в адресе может быть любым. Знак "плюс" выступает в качестве оператора "ИЛИ". В качестве разделителя также срабатывает и "пробел", но я думаю, что это не лучший символ для использования в адресах веб-страниц.

Только ноды находящиеся сразу в нескольких категориях

Адрес taxonomy/term/N1,N2 отображает только те ноды, которые одновременно принадлежат и термину за номером N1, и термину за номером N2. Как и выше, число терминов таксономии может быть любым. Знак "запятая" выполняет роль оператора "И".

Все ноды из подчиненных категорий

Пусть наш словарь таксономии содержит иерархический список с категориями и подкатегориями. Ноды прикрепляются к подкатегориям. Но здесь сразу встает задача показать в категориях все ноды из принадлежащих им подкатегорий. Такая возможность также предусмотрена в Drupal.

Адрес taxonomy/term/N/1 говорит модулю таксономии, что надо показать все ноды находящиеся в иерархии термина N на глубине 1. Адресtaxonomy/term/N/2 покажет все ноды принадлежащие терминам, подчиненным термину за номером N до глубины 2 включительно. И наконец, taxonomy/term/N/all выдаст ноды принадлежащие всем подчиненным терминам таксономии предком которых является N. Также во всех случаях будут показаны ноды принадлежащие самому термину N.

Комбинации нескольких терминов и глубины иерархии.

Оба вышеуказанных способа можно комбинировать. Примерно так:

taxonomy/term/N1+N2/2
taxonomy/term/N1+N2+N3/all
taxonomy/term/N1,N2,N3/2
taxonomy/term/N1,N2/all

Надеюсь уже понятно, что вы увидите по таким адресам.

Примечание.

Есть ограничение - применять в списке терминов таксономии можно только один из операторов, либо "плюс", либо "запятая". Сложное логическое выражение составить не получится. Скобки тоже не работают.

И не забудьте, что N, N1, N2 и N3 - это номера (идентификаторы) терминов таксономии, а не буквы с индексами.

Изменяем оператор И

Выше я уже говорил, что использование пробела в качестве разделителя терминов таксономии в адресе - это не самая лучшая идея. Данный символ в URL-адресах преобразуется в кодовую последовательность со знаком процента %20.
Вряд ли адрес вида taxonomy/term/25%2011%203/all можно назвать "чистым". Но поскольку есть альтернатива в виде знака "плюс", то эту проблему можно считать снятой.

С запятой происходит та же история. В адресах она преобразуется в %2C, что тоже плохо выглядит: taxonomy/term/25%2C11%2C3/all. И тут как назло, альтернативы не имеется.

Желающим исправить данную неприятность предлагаю небольшой хак модуля Taxonomy.

Разбор аргумента с номерами терминов таксономии производится в функцией taxonomy_terms_parse_string () которая находится в файле modules/taxonomy/taxonomy.module
Выглядит она следующим образом (Drupal 6):

 

function taxonomy_terms_parse_string($str_tids) {
  $terms = array('operator' => '''tids' => array());
  if (preg_match('/^([0-9]+[+ ])+[0-9]+$/'$str_tids)) {
    $terms['operator'] = 'or';
    // The '+' character in a query string may be parsed as ' '.
    $terms['tids'] = preg_split('/[+ ]/'$str_tids);
  }
  else if (preg_match('/^([0-9]+,)*[0-9]+$/'$str_tids)) {
    $terms['operator'] = 'and';
    $terms['tids'] = explode(','$str_tids);
  }
  return $terms;
}

 

Нас интересуют седьмая и девятая строчки. Добавим туда еще один знак "минус" и заменим функцию разбивающую строку на элементы.

function taxonomy_terms_parse_string($str_tids) {
  $terms = array('operator' => '''tids' => array());
  if (preg_match('/^([0-9]+[+ ])+[0-9]+$/'$str_tids)) {
    $terms['operator'] = 'or';
    // The '+' character in a query string may be parsed as ' '.
    $terms['tids'] = preg_split('/[+ ]/'$str_tids);
  }
  else if (preg_match('/^([0-9]+[-,])*[0-9]+$/'$str_tids)) {
    $terms['operator'] = 'and';
    $terms['tids'] = preg_split('/[-,]/'$str_tids);
  }
  return $terms;
}

 

Теперь для формирования страницы на которой узлы принадлежат нескольким терминам таксономии мы можем использовать адреса вида:
taxonomy/term/N1-N2-N3/all
<!--

Изменяем глубину просмотра иерархии по умолчанию

Если вы хотите при ссылке на термин таксономии всегда видеть все ноды как из него, так и из всех подчиненных ему нод, то сделать это достаточно просто.
-->

Убираем выделенный термин таксономии из ноды

Подача материалов (нод) на страницах таксономии раздражает одним моментом. Термин таксономии из заголовка повторяется в каждой ноде да еще и с гиперссылкой на эту же страницу.

Просмотрим код нашей веб-странице и попробуем выяснить цепочку классов, которые однозначно укажут в отображении ноды, на данный термин таксономии. В моем блоге это .terms .links .active и теперь можно убрать выделенный термин простое правило в файле CSS активной темы сайта.

 

.terms .links .active {
  display: none;
}

 

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

 

.terms .links {
  margin-top: 0;
}

 

Автора автора