Hello,
I would like to know if this code could be valid for limiting the facet terms based on the depth level.
I've done a quick code to see if it is the proper way, could someone check it and tell me if it is the way to go?
It is working fine in the first try that I've made (not fully tested with bunch of cases).
Code is not complete and vocabulary is needed (probably we can get vocabulary from the facet source).

<?php

namespace Drupal\my_module\Plugin\facets\processor;

use Drupal\Core\Form\FormStateInterface;
use Drupal\facets\FacetInterface;
use Drupal\facets\Processor\BuildProcessorInterface;
use Drupal\facets\Processor\ProcessorPluginBase;
use Drupal\taxonomy\Entity\Vocabulary;

/**
 * Processor that filters out results if they don't belong to a level of depth. 
 *
 * @FacetsProcessor(
 *   id = "term_depth",
 *   label = @Translation("Show only terms for a given level of depth"),
 *   description = @Translation("Show only terms for a given level of depth"),
 *   stages = {
 *     "build" = 40
 *   }
 * )
 */
class TermDepth extends ProcessorPluginBase implements BuildProcessorInterface {

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state, FacetInterface $facet) {
    $processors = $facet->getProcessors();
    $config = isset($processors[$this->getPluginId()]) ?
      $processors[$this->getPluginId()] : NULL;

    $min_level = 1;
    $build['level'] = [
      '#title' => $this->t('Level'),
      '#type' => 'number',
      '#min' => $min_level,
      '#default_value' => !is_null($config) ? $config->getConfiguration()['level'] : $min_level,
      '#description' => $this->t("Only show results for this level being 1 the root level."),
    ];

    $options = [];
    $vocabularies = Vocabulary::loadMultiple();
    foreach ($vocabularies as $vid => $vocab) {
      $options[$vid] = $vocab->label();
    }
    $build['bundle'] = [
      '#type' => 'select',
      '#title' => $this->t('Vocabulary'),
      '#default_value' => !is_null($config) ? $config->getConfiguration()['bundle'] : NULL,
      '#description' => $this->t("Choose vocabulary."),
      '#options' => $options,
    ];

    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function build(FacetInterface $facet, array $results) {
    $processors = $facet->getProcessors();
    $config = $processors[$this->getPluginId()];
    $level = $config->getConfiguration()['level'];
    $depth = $level - 1;
    $vocabulary = $config->getConfiguration()['bundle'];

    try {
      /** @var \Drupal\taxonomy\TermInterface[] $market_tree_root_terms */
      $terms = \Drupal::entityTypeManager()
        ->getStorage('taxonomy_term')
        ->loadTree($vocabulary, 0, $level, FALSE);

      $valid_terms = [];
      foreach ($terms as $term) {
        if ($term->depth === $depth) {
          $valid_terms[] = $term->tid;
        }
      }

      /** @var \Drupal\facets\Result\ResultInterface $result */
      $filtered_results = array_filter($results, function ($result) use ($valid_terms) {
        return in_array($result->getRawValue(), $valid_terms);
      });

      $results = $filtered_results;
    }
    catch (\Exception $e) {
      $results = [];
    }

    return $results;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array $form, FormStateInterface $form_state, FacetInterface $facet) {
    parent::validateConfigurationForm($form, $form_state, $facet);
  }
}

Thanks in advance.

Comments

TuWebO created an issue. See original summary.

rituraj.gupta’s picture

Hi,

Above code is well written but if you have multiple vocab with depth then this will not work.

tuwebo’s picture

Status: Active » Fixed

Hi @rituraj.,gupta, thanks very much for the review, I appreciate it. We can close this support request, anyone feel free to open it if it is needed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

vlad.dancer’s picture

@TuWebO, thank you for the shared solution!

sivamallareddy’s picture

@TuWebO Thanks for the solution!! For me also it is working fine.