Вы здесь

Views BEF. Вывод кол-ва материалов (count) помеченных термином таксономии

0

Приветствую!

Необходимо у фильтра BEF (который имеет настройки: BEF Settings > Exposed Filter Settings > Display "tid" exposed filter as Links) выводить, также, количество материалов (нод), которые отмечены терминами из словаря.

В гугле нашёл вот такое решение:

/**
 * Implements hook_form_alter().
 * 
 * This adds counts to our taxonomy terms in a particular view.
 */
function MYTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form_state['view']->name == 'MY_VIEW_NAME') {
    // Set an index if there are multiple terms used.   
    $index = 1;
    // Used for the array's string index.
    $string_index = '';

    // Continue for each vocabulary that is used.
    while (isset($form['tid' . $string_index])) {

      // Cycle through each of the terms.   
      foreach ($form['tid' . $string_index]['#options'] as $tid => $option) {

        // Build a query to get the nodes for this term that have been
        // specified as filters.    
        $query = db_select('node', 'n')
          ->fields('n', array('title'))
          ->condition('n.type', $form_state['view']->display_handler->handlers['filter']['type']->value, 'IN')
          ->condition('ti.tid', $tid, '=');

        // A quirk in db_select(). You need to add the join separately.
        $query->innerJoin('taxonomy_index', 'ti', 'ti.nid = n.nid');

        $results = $query->execute();

        $count = $results->rowCount();
        $form['tid' . $string_index]['#options'][$tid] .= ' (' . $count . ')';
      }

      // Increment for the next tid index in the array.
      $index += 1;
      $string_index = '_' . $index;
    }
  }
}

Всё работает, но есть проблема. При выводе происходит следующее:

// Стандартная ссылка для показа всех материалов фильтра.
// Настраивается тут: BEF Settings > MORE OPTIONS FOR "TID" > Override "Any" option label
Все материалы (0) 
// Далее - пошли термины таксономии из словаря:
Записи в апреле (12)
Записи в мае (24)
Записи в июне (149)
...

Собственно вопрос! Как сделать так, что бы в пункте "Все материалы" было либо:

  1. Сумма всех материалов (аля "Все материалы (350)");
  2. Вообще не показывалось кол-во материалов (аля "Все материалы").

Заранее спасибо за любую помощь.

Версия Drupal: 
7.x
Связанные проекты: 
Better Exposed Filters
Вопрос задан 13.08.2015 - 21:55

Ответы

1

Эту строку:

$form['tid' . $string_index]['#options'][$tid] .= ' (' . $count . ')';

Поменяйте на:

if($count > 0) {
    $form['tid' . $string_index]['#options'][$tid] .= ' (' . $count . ')';
}

Тогда если материалов в разделе нету или это ссылка Все материалы, то количество не будет показываться.

Ответ дан 13.08.2015 - 21:58

Спасибо, решение, как обычно, простое :)

Ещё вопрос. Когда ставлю не скобки, а, например, вот так:

if($count > 0) {
    $form['tid' . $string_index]['#options'][$tid] .= ' <sup>' . $count . '</sup>';
}

Выводится вот так:

...
Записи в апреле <sup>12</sup>
...

В файрбаге - всё нормально, но почему-то тег не преобразуется.

Комментарий оставлен 13.08.2015 - 22:11

Скорее всего в опциях хранить html нельзя. Сейчас проверю.
Как выводите фильтры? В виде ссылок?

Комментарий оставлен 13.08.2015 - 22:15

Если ссылками, то темизируйте вывод theme_select_as_links
Оригинал - в модуле BEF в файле better_expodes_filters.theme
Скопируйте код функции в свою версию theme_select_as_links, найдите строку

$elem['#children'] = l($value, $url, $link_options);

Она как раз отвечает за генерацию ссылки.
До этой строки вставьте:

$link_options['html'] = TRUE; // разрешить HTML в тексте ссылки
$value = filter_xss($value, array('sup')); // Разрешить только тег sup
Комментарий оставлен 13.08.2015 - 22:42

Кстати, да. Было бы совсем хорошо :)

Ещё заметил одну странность: при клике на термин теперь иногда (после чистки кэша особенно) не отрабатывается фильтрация, пишет ошибку "Сделан недопустимый выбор. Пожалуйста, обратитесь к администратору сайта".

В журнале (admin/reports/dblog) пишет вот такое:

ТИП : форма
ДАТА: 14.08.2015
ПОЛЬЗОВАТЕЛЬ: Гость (не проверено)
МЕСТО: http://mysite.ru/views/ajax
ИСТОЧНИК ОТСЫЛКИ: http://mysite.ru/blog
СООБЩЕНИЕ: Недопустимый выбор в элементе tid.
ВАЖНОСТЬ: ошибка
...

Попробовал удалить ту функцию, которую копировал с theme_select_as_links(), всё работает отлично, без ошибок. Такое ощущение, что он теперь считает, что термин таксономии не тот, который создан в словаре, а тот, который мы переопределили — то есть со счётчиком (и тегом).

И, логично, начинает сравнивать (при клике) его со словарём, не находит совпадений и выводит ошибку. Хм..

ADD

Проблема ещё актуальна.
Пробую по всякому крутить theme_select_as_links(), но пока что без результата..

Комментарий оставлен 14.08.2015 - 16:01

Странно, ведь вы не меняете URL ссылки. А там должен передаваться параметр tid. Только он определяет что должно быть выбрано. Проблема с ajax может быть?
Речь о сайте фастколор же? Там когда кликаю на ссылку - выходит какая-то ошибка, связанная, кажется, с онлайн консультантом. А если открываю в новом окне - то работает норм. Помоему связка ajax и консультанта каратит. Попробуйте на время отключить его. Или других скриптов - может счетчиков каких-нибудь.

Комментарий оставлен 14.08.2015 - 16:11

Я нашел когда возникает баг.
1. Если у view включить ajax
2. Если разрешить у ссылки html: $link_options['html'] = TRUE;
3. Если добавить в текст ссылки теги html (<sup>).
Только при наличии этих 3-х факторов конкретная ссылка перестает работать.
Т.е. если отключить ajax то теги будут нормально работать.
Или если оставить ajax и разрешить html, но не передавать теги, то тоже работает.

Комментарий оставлен 14.08.2015 - 16:39

Да, он самый.

Попробовал отключить консультанты (коих там много и непонятно зачем) — не помогло. Ошибка, которую даёт LiveTex из файрбага чисто его собственная, на остальной AJAX на сайте, вроде как, не влияет:

Font from origin 'http://widgets.livetex.ru' has been blocked from loading by 
Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is 
present on the requested resource. Origin 'http://www.mysite.ru' is therefore not allowed access.

Тема для сайта сделана как субтема Bootstrap. Вот список всех JS, которые подключены:

// Только нужные скрипты из бутстрапа
scripts[] = 'bootstrap/js/affix.js'
scripts[] = 'bootstrap/js/alert.js'
scripts[] = 'bootstrap/js/dropdown.js'
scripts[] = 'bootstrap/js/button.js'
scripts[] = 'bootstrap/js/collapse.js'
scripts[] = 'bootstrap/js/modal.js'
scripts[] = 'bootstrap/js/tooltip.js'
scripts[] = 'bootstrap/js/popover.js'
scripts[] = 'bootstrap/js/scrollspy.js'
scripts[] = 'bootstrap/js/tab.js'

scripts[] = assets/js/selectize.min.js // Для темизации select @ http://brianreavis.github.io/selectize.js/
scripts[] = assets/js/mmenu.min.all.js // Меню для мобил @ http://mmenu.frebsite.nl
scripts[] = assets/js/fontsmoothie.min.js // Хак для отображения шрифтов в разных браузерах @ https://gist.github.com/letorbi/5177771
scripts[] = assets/js/maskedinput.min.js // Ввод телефона по маске @ http://digitalbush.com/projects/masked-input-plugin/

scripts[] = assets/js/script.js // Мой скрипт, где вызываются скрипты выше

Отключал по-одному и все целиком — не в этом дело.

Комментарий оставлен 14.08.2015 - 16:40

Над вашим комментом я написал какие три фактора должны быть, чтобы возник баг. Поэтому если отключить ajax у view, то все будет работать.
Еще могу предложить другой вариант.
Запрос к базе делайте не в форм_альтер, а в theme_select_as_links. И дописывайте цифру с тегом *после* ссылки.
Т.е. вместо строчки

$elem['#children'] = l($value, $url, $link_options);

вы сделаете

$elem['#children'] = l($value, $url, $link_options)  . '<sup>' . $count . '</sup>';

В $count должно быть число - результат запроса, которое означает кол-во материалов.

Комментарий оставлен 14.08.2015 - 16:53

Тут комменты сортируются по дате обновления, так что лишний раз не изменяйте :-)

Выше я предложил вынести запрос из form alter в theme.
Уберите код из form alter, верните функцию THEME_select_as_link к исходному состоянию, и в ней сразу после строчки

$elem['#children'] = l($value, $url, $link_options)

вставьте:

$query = db_select('node', 'n')
      ->fields('n', array('title'))
      ->condition('n.type', array('тип_ноды_1', 'тип_ноды_2', 'тип_ноды_3'), 'IN')
      ->condition('ti.tid', $key, '=');

    // A quirk in db_select(). You need to add the join separately.
    $query->innerJoin('taxonomy_index', 'ti', 'ti.nid = n.nid');

    $results = $query->execute();

    $count = $results->rowCount();
    if($count > 0) {
        $elem['#children'] .= '<sup>' . $count . '</sup>';
    }
Комментарий оставлен 14.08.2015 - 17:14

Страницы