Score:0

Apply or expose a filter based on the value of a field in a referenced entity

rs flag

I have a search_api SOLR view of downloads on path /downloads that filters on current language and has a contextual filter on category so /downloads/foo shows downloads that have the category "foo" and /downloads/bar shows downloads with the category "bar".

I want to make it so I can have certain categories not filter on current language and instead show downloads of all languages and expose the language filter to the user. So I want to add a checkbox to the category taxonomy terms and have the language filter (and its exposedness) be dependent on the value of this checkbox.

Is there an existing module that could help me achieve this or will I have to resort to writing a custom filter plugin? Something like views_dependent_filters, but one that wouldn't have the dependency be on the value of another filter, but rather on a field value (via a relationship).

Score:1
cn flag

There is no existing module that can directly help achieve this. However, it can be achieved by writing a custom filter plugin.

Here's a general outline of how this can be done:

  1. Create a custom filter plugin that extends the existing search_api filter plugin.

  2. In the plugin, add a new option to the filter configuration form that allows the user to select whether or not the filter should be dependent on the value of the checkbox in the category taxonomy terms.

  3. Use the Views API to add a relationship to the referenced entity (the category taxonomy term) in the view.

  4. Use the relationship to get the value of the checkbox for the current category taxonomy term.

  5. Based on the value of the checkbox, either apply or expose the language filter.

Here's an example of how the custom module code might look like:

use Drupal\views\Plugin\views\filter\SearchApiFilter;

/**
 * Provides a custom filter plugin for downloads view.
 *
 * @ViewsFilter("downloads_custom_filter")
 */
class DownloadsCustomFilter extends SearchApiFilter {

  /**
   * {@inheritdoc}
   */
  public function exposeOptions() {
    $options = parent::exposeOptions();
    $options['custom_dependent'] = array('default' => FALSE);
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function query() {
    $dependent = $this->options['custom_dependent'];
    $term_field = $this->definition['term_field'];

    if ($dependent) {
      // Add relationship to the referenced category entity.
      $this->query->addRelationship('field_category', [
        'plugin_id' => 'standard',
        'base' => $this->definition['entity_type'],
        'field' => $term_field,
        'label' => $this->t('Category'),
      ]);

      // Get the value of the checkbox for the current category term.
      $checkbox_value = $this->query->addExpression("field_category.field_checkbox_value", 'checkbox_value');

      if ($checkbox_value == TRUE) {
        // Apply the language filter.
        parent::query();
      }
      else {
        // Expose the language filter to the user.
        $this->query->addExposedFilter('language');
      }
    }
    else {
      // Apply the language filter.
      parent::query();
    }
  }
}

After creating the custom module, you can enable it and add the new filter plugin to your downloads view. You can then configure the filter to be dependent on the value of the checkbox in the category taxonomy terms.

I hope this could help!

Score:0
rs flag

So I managed so solve my issue by implementing hook_views_pre_view and hook_form_views_exposed_form_alter & I set my filter to be exposed by default in the views settings.

In the hook_views_pre_view, I check the view ID and display ID and make sure we're on a taxonomy page. I load the taxonomy term and check the field value, if it's not enabled, I load the filters, make sure it's set to exposed and then set it to not exposed and change the value. This didn't automatically remove the field from the exposed filters form, so I did that in the hook_form_views_exposed_form_alter.

function MODULE_views_pre_view(\Drupal\views\ViewExecutable $view, $display_id, array &$args) {
  if ($view->id() == 'downloads' && $display_id == 'full') {
    // If we are on a taxonomy term page and it is set to not expose language.
    // Or we are not on a taxonomy term page.
    if (\Drupal::routeMatch()->getRouteName() == 'entity.taxonomy_term.canonical') {
      $term = \Drupal::routeMatch()->getParameter('taxonomy_term');
      if (isset($term->field_expose_language)) {
        $expose = $term->get('field_expose_language');
      }
    }
    if (!isset($expose) || $expose->value === '0' || $expose->value === NULL) {
      $filters = $view->display_handler->getOption('filters');
      // Set the exposed filter to not exposed and set it to the current language.
      if (isset($filters['search_api_language']) && $filters['search_api_language']['expose'] == TRUE) {
        $filters['search_api_language']['exposed'] = FALSE;
        $filters['search_api_language']['value'] = [
          '***LANGUAGE_language_interface***' => '***LANGUAGE_language_interface***'
        ];
        $view->display_handler->setOption('filters', $filters);
      }
    }
  }
}

function MODULE_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if (\Drupal::routeMatch()->getRouteName() == 'entity.taxonomy_term.canonical') {
    $term = \Drupal::routeMatch()->getParameter('taxonomy_term');
    if (isset($term->field_expose_language)) {
      $expose = $term->get('field_expose_language');
    }
  }
  if ((!isset($expose) || $expose->value === '0' || $expose->value === NULL) && isset($form['language'])) {
    $form['language']['#value'] = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $form['language']['#access'] = FALSE;
  }
}
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.