-
Notifications
You must be signed in to change notification settings - Fork 10
Description
What?
For some strange reason (reason I'm opening this ISSUE) when a Facet Range Widget + a normal Search Query is done and there are no results the Facet Summary Links for both the date Facet entry and the Search item are incorrect and do not allow to "disable" just one of them.
What is strange is if we add an extra facet selection to this (even without results) the Links are OK.
This is happening somewhere here:
Lines 32 to 269 in 51a827b
| public function build(FacetsSummaryInterface $facets_summary, array $build, array $facets) { | |
| $config = $facets_summary->getProcessorConfigs()[$this->getPluginId()]; | |
| $results_count = array_sum(array_map(function ($it) { | |
| /** @var \Drupal\facets\FacetInterface $it */ | |
| return count($it->getResults()); | |
| }, $facets)); | |
| if (($results_count == 0 ) || ($config['settings']['enable_query'] ?? FALSE)) { | |
| /** @var \drupal\facets\FacetSource\FacetSourcePluginInterface $facet_source_plugin */ | |
| $facet_source_plugin = \Drupal::service( | |
| 'plugin.manager.facets.facet_source' | |
| )->createInstance($facets_summary->getFacetSourceId()); | |
| $search_id = $facet_source_plugin->getDisplay()->getPluginId(); | |
| $results_query = \Drupal::service('search_api.query_helper')->getResults( | |
| $search_id | |
| ); | |
| } | |
| if ($results_count == 0 && $results_query) { | |
| $results = []; | |
| foreach ($facets as $facet) { | |
| $build_stage_processors = $facet->getProcessorsByStage(ProcessorInterface::STAGE_BUILD); | |
| $active_values = $facet->getActiveItems(); | |
| // Need to reset this bc each facet might have a different Query processor. | |
| $facet_results = []; | |
| if (empty($active_values)) { | |
| continue; | |
| } | |
| foreach ($active_values as $active_value) { | |
| if ($facet->getQueryType() == 'search_api_date' && !is_array($active_value)) { | |
| if (in_array( | |
| 'date_item', array_keys($build_stage_processors) | |
| ) | |
| ) { | |
| try { | |
| $active_value = $this->getTimestamp($active_value, $build_stage_processors['date_item']->getConfiguration()['granularity'] ?? 1); | |
| } catch (\Exception $exception) { | |
| // Do nothing if the String to Timestamp Date failed. | |
| continue; | |
| } | |
| } | |
| } | |
| $facet_results[] = [ | |
| 'filter' => $active_value, | |
| 'count' => 1, | |
| ]; | |
| } | |
| $configuration = [ | |
| 'query' => $results_query->getQuery(), | |
| 'facet' => $facet, | |
| 'results' => $facet_results ?? [], | |
| ]; | |
| $query_type = \Drupal::service('plugin.manager.facets.query_type') | |
| ->createInstance( | |
| $facet->getQueryType(), $configuration | |
| ); | |
| $query_type->getConfiguration(); | |
| $query_type->build(); | |
| // This will just rebuild the widget bc the facets | |
| // were already built and statically cached so ...\Drupal::service('facets.manager')->build($facet); | |
| $facet_results = $facet->getResults(); | |
| foreach ($build_stage_processors as $processor) { | |
| if (!$processor instanceof | |
| \Drupal\facets\Processor\BuildProcessorInterface | |
| ) { | |
| throw new InvalidProcessorException("The processor {$processor->getPluginDefinition()['id']} has a build definition but doesn't implement the required BuildProcessorInterface interface"); | |
| } | |
| $facet_results = $processor->build($facet, $facet_results); | |
| } | |
| $facet->setResults($facet_results); | |
| // Accumulate URLs? | |
| foreach( $facet->getResults() as $result) { | |
| $urls[] = $result->getUrl(); | |
| } | |
| $results = array_merge( | |
| $results, $this->buildResultTree($facet->getResults()) | |
| ); | |
| } | |
| $build['#items'] = $results; | |
| if ($config['settings']['enable_empty_message'] ?? FALSE) { | |
| $item = [ | |
| '#theme' => 'facets_summary_empty', | |
| '#message' => [ | |
| '#type' => 'processed_text', | |
| '#text' => $config['settings']['text']['value'], | |
| '#format' => $config['settings']['text']['format'], | |
| ], | |
| ]; | |
| array_unshift($build['#items'], $item); | |
| } | |
| } | |
| if (($config['settings']['enable_query'] ?? FALSE) && $results_query) { | |
| // The original View | |
| /** @var \Drupal\views\ViewExecutable $view */ | |
| $view = $results_query->getQuery()->getOptions()['search_api_view']; | |
| if ($view->getDisplay()->displaysExposed()) { | |
| $exposed_input = $view->getExposedInput(); | |
| $view->getRequest()->getRequestUri(); | |
| $keys_to_filter = []; | |
| $key_with_search_value = [] ; | |
| // Oh gosh, blocks... | |
| if (!$view->getDisplay()->isDefaultDisplay() && empty($view->getDisplay()->options['filters'] ?? [] )) { | |
| $filters = $view->getDisplay()->handlers['filter']; | |
| foreach ($filters as $filter) { | |
| /* @var \Drupal\views\Plugin\views\ViewsHandlerInterface $filter */ | |
| if ($filter->getPluginId() == 'search_api_fulltext' && $filter->isExposed()) { | |
| $keys_to_filter[] = $filter->options['expose']['operator_id'] ?? NULL; | |
| $keys_to_filter[] = $filter->options['expose']['identifier'] ?? NULL; | |
| $key_with_search_value[] = $filter->options['expose']['identifier'] ?? NULL; | |
| } | |
| elseif ($filter->getPluginId() == 'sbf_advanced_search_api_fulltext' | |
| && $filter->isExposed() | |
| ) { | |
| $extra_keys_to_filter = []; | |
| $keys_to_filter[] =$filter->options['expose']['operator_id'] ?? NULL; | |
| $keys_to_filter[] = $filter->options['expose']['identifier'] ?? NULL; | |
| $key_with_search_value[] = $filter->options['expose']['identifier'] ?? NULL; | |
| $keys_to_filter[] = $filter->options['expose']['searched_fields_id'] ?? NULL; | |
| $keys_to_filter[] = $filter->options['expose']['advanced_search_operator_id'] | |
| ?? NULL; | |
| foreach ($keys_to_filter as $key_to_filter) { | |
| for ( | |
| $i = 1; | |
| $i < $filter->options['expose']['advanced_search_fields_count'] ?? 1; | |
| $i++ | |
| ) { | |
| $extra_keys_to_filter[] = $key_to_filter . '_' . $i; | |
| if (in_array($key_to_filter, $key_with_search_value)){ | |
| $key_with_search_value[] = $key_to_filter . '_' . $i; | |
| } | |
| } | |
| } | |
| $keys_to_filter = array_filter($keys_to_filter); | |
| $keys_to_filter = array_merge( | |
| $keys_to_filter, $extra_keys_to_filter | |
| ); | |
| } | |
| } | |
| } | |
| else { | |
| foreach ($view->getDisplay()->options['filters'] as $filter) { | |
| if ($filter['plugin_id'] == 'search_api_fulltext' | |
| && $filter['exposed'] | |
| ) { | |
| $keys_to_filter[] = $filter['expose']['operator_id'] ?? NULL; | |
| $keys_to_filter[] = $filter['expose']['identifier'] ?? NULL; | |
| $key_with_search_value[] = $filter['expose']['identifier'] ?? | |
| NULL; | |
| } | |
| elseif ($filter['plugin_id'] == 'sbf_advanced_search_api_fulltext' | |
| && $filter['exposed'] | |
| ) { | |
| $extra_keys_to_filter = []; | |
| $keys_to_filter[] = $filter['expose']['operator_id'] ?? NULL; | |
| $keys_to_filter[] = $filter['expose']['identifier'] ?? NULL; | |
| $key_with_search_value[] = $filter['expose']['identifier'] ?? | |
| NULL; | |
| $keys_to_filter[] = $filter['expose']['searched_fields_id'] ?? | |
| NULL; | |
| $keys_to_filter[] | |
| = $filter['expose']['advanced_search_operator_id'] | |
| ?? NULL; | |
| foreach ($keys_to_filter as $key_to_filter) { | |
| for ( | |
| $i = 1; | |
| $i < $filter['expose']['advanced_search_fields_count'] ?? 1; | |
| $i++ | |
| ) { | |
| $extra_keys_to_filter[] = $key_to_filter . '_' . $i; | |
| if (in_array($key_to_filter, $key_with_search_value)) { | |
| $key_with_search_value[] = $key_to_filter . '_' . $i; | |
| } | |
| } | |
| } | |
| $keys_to_filter = array_filter($keys_to_filter); | |
| $keys_to_filter = array_merge( | |
| $keys_to_filter, $extra_keys_to_filter | |
| ); | |
| } | |
| } | |
| } | |
| $request = $view->getRequest(); | |
| $facet_source = $facets_summary->getFacetSource(); | |
| $urlGenerator = \Drupal::service('facets.utility.url_generator'); | |
| $url_active = $urlGenerator->getUrlForRequest( | |
| $request, $facet_source ? $facet_source->getPath() : NULL | |
| ); | |
| $params = $request->query->all(); | |
| $search_terms = []; | |
| foreach ($params as $key => $param) { | |
| if (in_array($key, $keys_to_filter)) { | |
| $search_term = NULL; | |
| if (in_array($key, $key_with_search_value)) { | |
| $search_terms[] = $exposed_input[$key] ?? NULL; | |
| } | |
| unset($params[$key]); | |
| } | |
| } | |
| $search_terms = array_filter($search_terms, function ($element) { | |
| return ((is_string($element) && '' !== trim($element)) || is_numeric($element)); | |
| }); | |
| if (count($search_terms)) { | |
| $url_active->setOption('query', $params); | |
| $item = [ | |
| '#theme' => 'facets_result_item__summary', | |
| '#value' => implode(" ", array_map(function($string) { | |
| return '"' . $string . '"'; | |
| }, $search_terms)), | |
| '#show_count' => FALSE, | |
| '#count' => 0, | |
| '#is_active' => TRUE, | |
| ]; | |
| $item = (new Link($item, $url_active))->toRenderable(); | |
| $item['#wrapper_attributes'] = [ | |
| 'class' => [ | |
| 'facet-summary-item--facet', | |
| 'facet-summary-item--query', | |
| ], | |
| ]; | |
| $build['#items'][] = $item; | |
| } | |
| } | |
| } | |
| return $build; | |
| } |
How to test (make it fail)?
Enable this Facet summary processor with all its options and disable the existing "Show a message when no results" built in one. Make a Faceted Search using a Date Range Facet. Then search for something that you know does not exist. When no results are returned this processor will try to generate Facet Summaries using an alternative method but the links for each Facet Summary will be wrong.
How to see the odd part working?
Enable this Facet summary processor with all its options and disable the existing "Show a message when no results" built in one. Make a Faceted Search using a Date Range Facet. The select another Facet (e.g Digital Object Type). Then search for something that you know does not exist. When no results are returned this processor will try to generate Facet Summaries using an alternative method and the links will all be right allowing you to deselect one of the choices without affecting the others.