From 0248f7ed21f6ce4d4d631626b3cc6778c0b5e6c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20L=C3=B3pez?= <david.lopez@un.org>
Date: Thu, 27 Mar 2025 21:40:14 +0100
Subject: [PATCH 1/2] Issue #3444352: Views exposed form is not reflecting the
 active facets when they have been set using a process plugin

---
 .../src/Plugin/views/filter/FacetsFilter.php  | 49 ++++++++++++++++---
 1 file changed, 42 insertions(+), 7 deletions(-)

diff --git a/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php b/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
index 80f5e9ed..f58d1127 100644
--- a/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
+++ b/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
@@ -7,8 +7,10 @@ use Drupal\Core\Block\BlockPluginInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Form\SubformState;
 use Drupal\facets\Entity\Facet;
+use Drupal\facets\Exception\InvalidProcessorException;
 use Drupal\facets\FacetInterface;
 use Drupal\facets\Hierarchy\HierarchyPluginBase;
+use Drupal\facets\Processor\PreQueryProcessorInterface;
 use Drupal\facets\Processor\ProcessorInterface;
 use Drupal\facets\Processor\SortProcessorInterface;
 use Drupal\facets\Result\Result;
@@ -33,6 +35,13 @@ class FacetsFilter extends FilterPluginBase {
    */
   public $facet_results = [];
 
+  /**
+   * The facet object related to this filter.
+   *
+   * @var \Drupal\facets\FacetInterface|null
+   */
+  private ?FacetInterface $facet = NULL;
+
   /**
    * {@inheritdoc}
    */
@@ -159,7 +168,6 @@ class FacetsFilter extends FilterPluginBase {
       if (!empty($active_sort_processors)) {
         $facet->setResults($this->sortFacetResults($active_sort_processors, $facet->getResults()));
       }
-      $facet->setActiveItems(array_values($active_facet_values));
 
       // Store the processed facet so we can access it later (e.g. in an exposed form rendered as a block).
       facets_exposed_filters_get_processed_facet($this->view->id(), $this->view->current_display, $this->options["id"], $facet);
@@ -169,6 +177,11 @@ class FacetsFilter extends FilterPluginBase {
     $select_element = \Drupal::service('element_info')->getInfo('select');
 
     $this->value = $facet->getActiveItems();
+    if (!empty($this->value)) {
+      $identifier = $this->options['expose']['identifier'];
+      $form_state->getUserInput()[$identifier] = $this->value;
+    }
+
     // Store processed results so other modules can use these.
     $this->facet_results = $facet->getResults();
     $form['value'] = [
@@ -237,12 +250,28 @@ class FacetsFilter extends FilterPluginBase {
     return FALSE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function preQuery() {
+    $facet = $this->getFacet();
+    foreach ($facet->getProcessorsByStage(ProcessorInterface::STAGE_PRE_QUERY) as $processor) {
+      /** @var \Drupal\facets\Processor\PreQueryProcessorInterface $pre_query_processor */
+      $pre_query_processor = $facet->getProcessors()[$processor->getPluginDefinition()['id']];
+      if (!$pre_query_processor instanceof PreQueryProcessorInterface) {
+        throw new InvalidProcessorException("The processor {$processor->getPluginDefinition()['id']} has a pre_query definition but doesn't implement the required PreQueryProcessorInterface interface");
+      }
+      $pre_query_processor->preQuery($facet);
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
   public function query() {
     $facet = $this->getFacet();
     $active_values = $this->getActiveFacetValues();
+
     $facet->setActiveItems($active_values);
     $qtpm = \Drupal::service('plugin.manager.facets.query_type');
 
@@ -514,7 +543,10 @@ class FacetsFilter extends FilterPluginBase {
   /**
    * Helper function to retrieve the representing facet.
    */
-  private function getFacet() {
+  private function getFacet(): FacetInterface {
+    if ($this->facet instanceof FacetInterface) {
+      return $this->facet;
+    }
     $facet = Facet::create([
       'id' => $this->options["field"],
       'field_identifier' => $this->configuration["search_api_field_identifier"],
@@ -538,7 +570,8 @@ class FacetsFilter extends FilterPluginBase {
         ]);
       }
     }
-    return $facet;
+    $this->facet = $facet;
+    return $this->facet;
   }
 
   /**
@@ -548,22 +581,24 @@ class FacetsFilter extends FilterPluginBase {
    * to retrieve the active filters from the request ourself.
    */
   private function getActiveFacetValues() {
+    $active_values = $this->facet->getActiveItems();
+
     // Reset button in ajax request. We probably want a better way to detect if this was clicked.
     if(isset($_GET["reset"])) {
-      return [];
+      return $active_values;
     }
     $exposed = $this->view->getExposedInput();
     if (!isset($exposed[$this->options["expose"]["identifier"]])) {
-      return [];
+      return $active_values;
     }
     $enabled = $exposed[$this->options["expose"]["identifier"]];
     if ($enabled == 'All') {
-      return [];
+      return $active_values;
     }
     elseif (!is_array($enabled)) {
       $enabled = [$enabled];
     }
-    return $enabled;
+    return array_values(array_unique([...$active_values, ...$enabled]));
   }
 
   /**
-- 
GitLab


From 56294d588c2b00f573f4e6233acb5a31946e0d05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20L=C3=B3pez?= <david.lopez@un.org>
Date: Fri, 28 Mar 2025 08:58:59 +0100
Subject: [PATCH 2/2] Issue #3444352: Use key-value pairs to override the user
 input becuase is mandatory for checkboxes

---
 .../src/Plugin/views/filter/FacetsFilter.php                 | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php b/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
index f58d1127..495c076a 100644
--- a/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
+++ b/modules/facets_exposed_filters/src/Plugin/views/filter/FacetsFilter.php
@@ -178,8 +178,11 @@ class FacetsFilter extends FilterPluginBase {
 
     $this->value = $facet->getActiveItems();
     if (!empty($this->value)) {
+      $selected_value = array_combine($this->value, $this->value);
       $identifier = $this->options['expose']['identifier'];
-      $form_state->getUserInput()[$identifier] = $this->value;
+      if (empty($form_state->getUserInput()[$identifier])) {
+        $form_state->getUserInput()[$identifier] = $selected_value;
+      }
     }
 
     // Store processed results so other modules can use these.
-- 
GitLab