D7 & Search API (SOLR)/Facet api taxonomy - фильтрация с иерархией в фильтре [РЕШЕНО]

Главные вкладки

Аватар пользователя t1mm1 t1mm1 22 июня 2015 в 11:03

Доброго дня, комрады.
Столкнулся с задачей построения фильтра по терминам таксономии с сохранением иерархии.

Имеем такой фильтр.
Термин 1
Термин 2
Термин 3
-- Термин 3_1
-- Термин 3_2
-- Термин 3_3
Термин_4
-- Термин 4_1
---- Термин 4_1_1
---- Термин 4_1_2
-- Термин 4_2

Нам нужно фильтровать сущности так, что выбирая "Термин 3" и "Термин 3_1" получить верный результат. Ведь если поставить условие AND, то при выборе будут пропадать термины, которые не относятся к остальным терминам. А есть ставить OR, то выборка в этом случае будет по обоим терминам, и обозначение дочерних терминов не будет влиять на выборку, так как будет происходить выбор по родителю, тем самым вклюя ВСЕ сущности (а не ТОЛЬКО дочерние в этой ветке.
Решение было найдело. Хоть и просит патчить "родной" facetapi.

Может, кому-либо пригодиться. Открываем файл sites/all/modules/contrib/facetapi/plugins/facetapi/inc url_processor_standard.inc .
Находим строку

$field_alias = rawurlencode($facet['field alias']);

И делаем как в примере.

  $field_alias = rawurlencode($facet['field alias']);

  // добавляем вот этот обработчик
  $global_settings = $this->adapter->getFacet($facet)->getSettings();

  if($global_settings->settings['operator'] == FACETAPI_OPERATOR_OR) {
    if (!empty($facet['hierarchy callback'])) {

      // Look up the parent of the current value.
      $hierarchy = $facet['hierarchy callback'](array($value));
      if (!empty($hierarchy[$value])) {
        // Search the query string for the parent value so we can remove it.
        $key = array_search($field_alias . ':' . $hierarchy[$value][0], $qstring[$this->filterKey]);
        if ($key !== FALSE) {
          unset($qstring[$this->filterKey][$key]);
        }
      }
    }
  }
  // конец хотфикса

  // Adds the filter to the query string.
  $qstring[$this->filterKey][] = $field_alias . ':' . $value;

Тем самым мы исключаем участие в фильтрации родителя, если выбран дочерний элемент.
Работает с активными чекбоксами.

Источник - https://www.drupal.org/node/2211945#comment-8638929 .
Ссылка на патч - https://www.drupal.org/files/issues/2211945-1-remove-parent-from-or-face... .
P.s. Если есть контриб решение этого вопроса, без патчей - поделитесь.

Комментарии

Аватар пользователя duozersk duozersk 23 июня 2015 в 23:59

FacetAPI довольно гибок, я когда-то писал подобное, но в другую сторону - то есть задача была наоборот добавлять к выбранному фасету термина фасет его родителя. Точно таким же образом можно убирать фасет родителя, если выбран ребенок. Отдать код не могу, писался на заказ за деньги хорошему человеку.

Нужно реализовать FacetAPI Dependency plugin через хуки hook_facetapi_facet_info_alter() и hook_facetapi_dependencies()
В классе, унаследованном от FacetapiDependency переопределить метод execute() и в нем убрать фасет родителя.

Аватар пользователя t1mm1 t1mm1 30 июня 2015 в 10:20

Признаться, не проверял.
Но по идее должно работать и это. Ведь я не "ломаю" логику построения самих урлов на выходе, только исключение в самой выборке (точнее простое добавление unset-а).
Попробуйте, должно работать. (я к этому моменту вернусь еще, предстоит что-то подобное).