Представления 3 удаляют выставленный фильтр программно


9

У меня есть несколько типов узлов, каждый из которых относится к разным словарным терминам таксономии. Для показа категорий я использую модуль taxonomy_display.

Например, у нас есть две категории: киев и бильярдных шаров.

Cues имеет цену от, цена и фильтры типа древесины. Но у шаров нет деревянного фильтра.

Так что мне нужно удалить фильтр типа дерева, если tid taxonomy_term ссылается на словарь бильярдных шаров.

Таким образом, мне нужно удалить один из множества выставленных фильтров программно.

function modulename_views_pre_view(&$view, &$display_id, &$args) {
  // Some custom logic wich field_info_instances checking ...
  $filter_field = 'filter_id';
  // Removes from everywhere where i can find filter or filters properties
  unset($view->display[$view->current_display]->display_options['filters'][$filter_field]);
  unset($view->display[$view->current_display]->handler->options['filters'][$filter_field]);
  unset($view->display_handler->display->display_options['filters'][$filter_field]);
  unset($view->display_handler->options['filters'][$filter_field]);
}

Поле фильтра удаляется успешно, но я получил уведомление php:

  Notice: Undefined index: field_wood_reference_tid in function views_handler_filter_term_node_tid->exposed_validate()

Также я пытаюсь удалить поле в hook_pre_execute (), но с тем же результатом:

function modulename_views_pre_execute(&$view) {
  $filter_field = 'filter_id';
  unset($view->display_handler->handlers['filter'][$filter_field]);
  unset($view->filter[$filter_field]);
}

Также попробуйте использовать метод override_option (), как здесь - http://groups.drupal.org/node/82219 , но без результата.

Какие-либо предложения? Пожалуйста помогите =)


Спасибо всем за ответ, но у меня до сих пор нет ответа. Может, что-то не понятно? знак равно


Вы пробовали hook_views_pre_render () ? Вы также можете показать / скрыть соответствующие фильтры в зависимости от выбора с помощью jQuery.
Enzipher

Привет, я понимаю, что ваше решение работает хорошо, но нет правильного пути . Так что я могу скрыть это, используя даже CSS-условия ... Попытка объяснить. Каждый вид кода должен размещаться там, где он должен быть. Для этой проблемы, если я скрываю открытый фильтр до или после рендера, представления все еще обрабатывают его. И если я попытаюсь добавить строку запроса, вроде smt ?filter_id=val, представления возвращают пустое отображение или ошибку неправильного выбора ...
Олег Щербаков

Вы пробовали мой ответ?
Матханкумар

Мне не нужно изменять форму (я знаю, что ваш вариант работает), я хочу изменить объект представления так, чтобы он соответствовал вашему результату, но раньше, чем сборка формы.
Олег Щербаков

Ответы:



1

Вот протестированный фрагмент, который позволит вам удалить фильтры из открытой формы представлений, используя изменение формы, как упомянуто Скоттом Томасом,

/**
 *Implements hook_form_FORM_ID_alter().
 */
function hook_form_views_exposed_form_alter(&$form, &$form_state) {
  $filter_field = 'filter_id';
  // Get the filters list for the current view. Here page_1 is the display ID.
  $filters = $form_state['view']->get_items('filter', 'page_1');
  if (isset($filters[$filter_field])) {
    $info_key = 'filter-' . $filter_field;
    unset($form[$filter_field], $form['#info'][$info_key]);
  }     
}

Помимо удаления поля формы, вам также необходимо удалить информацию для конкретного фильтра, которая доступна в $ form ['# info'], чтобы она также удаляла метку. Если вы удалите только элемент формы, тогда метка фильтра будет отображаться даже при удалении поля, поэтому всегда проверяйте, удаляете ли вы также эту информацию.

Измените это в соответствии с вашими потребностями. Если вы хотите выполнить это для определенного вида, то добавьте условие для этого, например,

if ($form_state['view']->name == 'view_name') {
  // DO your operation.
}

Здесь $ form_state ['view'] даст вам текущий объект представления, который обрабатывается.

Надеюсь это поможет.


Это было единственное решение, которое скрывало метки и виджеты полей для меня, и оно работало в открытой форме фильтра в блоке.
ксенофил

1

Следуйте инструкциям ниже

  1. Сначала напишите hook_form_alter в пользовательском модуле
  2. Затем попробуйте следующий кусок кода

    снята с охраны ($ форма [ '# информация'] [ 'your_field_name']); $ form ['your_field_name'] ['# access'] = 'FALSE';

Надеюсь, это поможет.


1

Вы также можете удалить открытый фильтр, используя файл шаблона.

Используйте эту команду:

cp sites/all/modules/contrib/views/theme/views-view.tpl.php sites/all/themes/costa/templates/views/views-view--<machine_name>.tpl.php

В файле шаблона найдите этот код:

  <?php if ($exposed): ?>
    <div class="view-filters">
      <?php print $exposed; ?>
    </div>
  <?php endif; ?>

И удали это. Ваш выставленный фильтр будет удален с дисплея, но будет продолжать работать, передавая правильные аргументы в URL.


Спасибо за ответ, но я жду D8, который использует основные формы API для создания открытых фильтров :)
Олег Щербаков

0

Поправьте меня, если я ошибаюсь, потому что я не уверен, что полностью понимаю вашу проблему. Итак, вы хотели бы скрыть открытый фильтр в представлении в зависимости от значения другого открытого фильтра? Если это так, вы можете попробовать модуль Views Dependent Filters . Я использовал его несколько раз, и он делает свою работу.

Вы можете проверить обзор нашего модуля из Lullabot об этом модуле.

Если вам действительно нужно сделать это в коде, открытая опция должна работать: filter [$ filter_id] -> options ['cted '] = FALSE;


Я хотел бы скрыть открытый фильтр, если текущий тип содержимого не имеет этого (отфильтрованного) поля. Пробуя ваш фрагмент, у $view->display_handler->handlers['filter'][$filter_field]->options['exposed'] = FALSE;меня есть фатальная ошибка PHP Fatal error: Call to undefined method stdClass::access() in .../view.inc on line 766. Я думаю, что его правильное поведение, потому что, если фильтр не выставлен, он также требует значения по умолчанию. Любые идеи?
Олег Щербаков

pastebin.com/f1FKgUde вот мой код, возможно, он будет более понятным, чем мой английский
Олег Щербаков

0

Следующее сделало это для меня внутри hook_form_alter:

$info_key = 'filter-' . $fieldName;
unset($form[$fieldName], $form['#info'][$info_key], $form_state['view']->display_handler->options['filters'][$fieldName], $form_state['view']->display_handler->handlers['filter'][$fieldName], $form_state['view']->filter[$fieldName]);

0

Способ 1

Используя hook_views_query_alter (). Смотрите следующий пример:

<?php
/**
 * Implements hook_views_query_alter().
 */
function foo_views_query_alter(&$view, &$query) {

  if ($view->name == 'foo_view') {

    // Allow any distance when the postcode it is not specified.
    if (empty($_GET['postcode']['postal_code']) || $_GET['postcode']['postal_code'] === 'All') { 
      // Scan through the query.
      foreach ($query->where as $condition_group_key => &$condition_group) {
        foreach ($condition_group['conditions'] as $condition_key => &$condition) {
          $search_name = '(COALESCE(ACOS(';
          if (is_string($condition['field']) && strstr($condition['field'], $search_name) !== FALSE) {
            // Remove filter from the query.
            unset($query->where[$condition_group_key]['conditions'][$condition_key]);
          }
        } // end: foreach
      } // end: foreach
    } // end: if


    /*
     * Change the field conditions.
     * Possible field values: 1, 2, 3
     * Logic: When 3 is selected, then display 1, 2 and 3.
     */
    switch (@$view->display_handler->handlers['filter']['field_123_value']->value[0]) {

      case 3:
        foreach ($query->where as $condition_group_key => &$condition_group) {
          foreach ($condition_group['conditions'] as $condition_key => &$condition) {
            if($condition['field'] == 'field_data_field_123.field_123_value') {
              unset($query->where[$condition_group_key]['conditions'][$condition_key]);
              $query->where[] = array(
                  'conditions' => array(
                      array(
                          'field' => 'field_data_field_123.field_123_value',
                          'value' => 1,
                          'operator' => "=",
                      ),
                      array(
                          'field' => 'field_data_field_123.field_123_value',
                          'value' => 2,
                          'operator' => "=",
                      ),
                      array(
                          'field' => 'field_data_field_123.field_123_value',
                          'value' => 3,
                          'operator' => "=",
                      ),
                  ),
                  'args' => array(),
                  'type' => 'OR',
              );
            }
          }
        } // end: foreach
        break;

    } // end: switch

  } // end: if
}

Способ 2

Посмотрите пример, используя hook_views_pre_execute и пользовательскую функцию, которая пытается найти правильное условие поля и вернуть ссылку на него:

/**
 * Implements hook_views_pre_execute().
 */
function foo_views_pre_execute(&$view) {

  if ($view->name == 'foo_view') {


    foo_get_view_filter_recursively(
      $view,
      $view->build_info['query']->conditions(),
      'field_data_field_123.field_123_value',
      $filter
    );

    // We want our filter to work as a bit mask.
    $filter[0]['operator'] = '&';

    unset ($filter);

    // Example of finding Proximity filter condition
    $search_name = '(COALESCE(ACOS(';

    foo_get_view_filter_recursively(
      $view,
      $view->build_info['query']->conditions(),
      $search_name,
      $filter
    );

    if (empty($_GET['postcode']['postal_code']) || $_GET['postcode']['postal_code'] === 'All') {
      // Allowing any distance.
      $filter[0]['value'][':distance'] = 10000000;
    }
    else {
      $filter[0]['value'][':distance'] = 80000;
    }

    unset ($filter);


    // Fetching single record?

    foo_get_view_filter_recursively(
      $view,
      $view->build_info['query']->conditions(),
      'node.nid',
      $filter
    );

    if (!empty($_GET['nid'])) {
      $filter[0]['value'] = (int) $_GET['nid'];
    }
    else {
      $filter[0]['operator'] = '<>';
    }

    unset ($filter);                                                        

    // echo '<pre style="font-size:11px;font-family: Monaco">'; print_r($view->build_info['query']); exit;
  }
}

/**
 * Custom function to find the field condition within the view
 */
function foo_get_view_filter_recursively($view, &$conditions, $field_name, &$filter) {

  if (!empty($conditions)) {

    foreach ($conditions as &$condition) {
      if ($condition instanceof DatabaseCondition) {
        if (foo_get_view_filter_recursively($view, $condition->conditions(), $field_name, $filter)) {
          return TRUE;
        }
      } else if ($condition['field'] instanceof DatabaseCondition) {
        if (foo_get_view_filter_recursively($view, $condition['field']->conditions(), $field_name, $filter)) {
          return TRUE;
        }
      } elseif (is_string($condition['field']) && strstr($condition['field'], $field_name) !== FALSE) {
        @$filter = array(&$condition);
        return TRUE;
      }
    } // end: foreach

  } // end: if

  return FALSE;
}

0

Я удаляю это из файлов шаблона. Переопределите views-view.tpl.php и удалите из него следующий код:

  <?php if ($exposed): ?>
    <div class="view-filters">
      <?php print $exposed; ?>
    </div>
  <?php endif; ?>

0

Я думаю, что операция была на правильном пути. У меня была похожая ситуация без открытых фильтров, поэтому я не мог использовать метод hook_form_alter. Вот пример кода для всех, кто сталкивался с этим:

$view->set_item($view->current_display, 'filter', $filter_id, null);

Объект представления не имеет remove_itemфункции, он просто заявляет в коде, что вы можете установить его в null, чтобы удалить элемент, включая фильтры: views/includes/view.incon line 2526.

Вот полный пример для любого, который предназначается для определенного представления и отображения:

/**
 * Implements HOOK_views_pre_view().
 */
function HOOK_views_pre_view(&$view) {
  if($view->name == 'VIEW_MACHINE_NAME') {
    switch($view->current_display) {
      case 'VIEW_DISPLAY_MACHINE_NAME':
        $view_filters = $view->display_handler->get_option('filters');
        foreach ($view_filters as $filter_id => $filter) {
          if ($filter_id == 'my_filter') {
            $view->set_item($view->current_display, 'filter', $filter_id, null);
          }
        }
      break;
    }
  }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.