dispatcher = $dispatcher; } /** * @param SearchResultSet $resultSet * @param string $facetName * @param array $facetConfiguration * @return OptionsFacet|null */ public function parse(SearchResultSet $resultSet, $facetName, array $facetConfiguration) { $response = $resultSet->getResponse(); $fieldName = $facetConfiguration['field']; $label = $this->getPlainLabelOrApplyCObject($facetConfiguration); $optionsFromMeilisearchResponse = $this->getOptionsFromMeilisearchResponse($facetName, $response); $metricsFromMeilisearchResponse = $this->getMetricsFromMeilisearchResponse($facetName, $response); $optionsFromRequest = $this->getActiveFacetValuesFromRequest($resultSet, $facetName); $hasOptionsInResponse = !empty($optionsFromMeilisearchResponse); $hasSelectedOptionsInRequest = count($optionsFromRequest) > 0; $hasNoOptionsToShow = !$hasOptionsInResponse && !$hasSelectedOptionsInRequest; $hideEmpty = !$resultSet->getUsedSearchRequest()->getContextTypoScriptConfiguration()->getSearchFacetingShowEmptyFacetsByName($facetName); if ($hasNoOptionsToShow && $hideEmpty) { return null; } /** @var $facet OptionsFacet */ $facet = $this->objectManager->get( OptionsFacet::class, $resultSet, $facetName, $fieldName, $label, $facetConfiguration ); $hasActiveOptions = count($optionsFromRequest) > 0; $facet->setIsUsed($hasActiveOptions); $facet->setIsAvailable($hasOptionsInResponse); $optionsToCreate = $this->getMergedFacetValueFromSearchRequestAndMeilisearchResponse($optionsFromMeilisearchResponse, $optionsFromRequest); foreach ($optionsToCreate as $optionsValue => $count) { if ($this->getIsExcludedFacetValue($optionsValue, $facetConfiguration)) { continue; } $isOptionsActive = in_array($optionsValue, $optionsFromRequest); $label = $this->getLabelFromRenderingInstructions($optionsValue, $count, $facetName, $facetConfiguration); $facet->addOption($this->objectManager->get(Option::class, $facet, $label, $optionsValue, $count, $isOptionsActive, $metricsFromMeilisearchResponse[$optionsValue])); } // after all options have been created we apply a manualSortOrder if configured // the sortBy (lex,..) is done by the meilisearch server and triggered by the query, therefore it does not // need to be handled in the frontend. $this->applyManualSortOrder($facet, $facetConfiguration); $this->applyReverseOrder($facet, $facetConfiguration); if(!is_null($this->dispatcher)) { $this->dispatcher->dispatch(__CLASS__, 'optionsParsed', [&$facet, $facetConfiguration]); } return $facet; } /** * @param string $facetName * @param ResponseAdapter $response * @return array */ protected function getOptionsFromMeilisearchResponse($facetName, ResponseAdapter $response) { $optionsFromMeilisearchResponse = []; if (!isset($response->facets->{$facetName})) { return $optionsFromMeilisearchResponse; } foreach ($response->facets->{$facetName}->buckets as $bucket) { $optionValue = $bucket->val; $optionCount = $bucket->count; $optionsFromMeilisearchResponse[$optionValue] = $optionCount; } return $optionsFromMeilisearchResponse; } /** * @param string $facetName * @param ResponseAdapter $response * @return array */ protected function getMetricsFromMeilisearchResponse($facetName, ResponseAdapter $response) { $metricsFromMeilisearchResponse = []; if (!isset($response->facets->{$facetName}->buckets)) { return []; } foreach ($response->facets->{$facetName}->buckets as $bucket) { $bucketVariables = get_object_vars($bucket); foreach ($bucketVariables as $key => $value) { if (strpos($key, 'metrics_') === 0) { $metricsKey = str_replace('metrics_', '', $key); $metricsFromMeilisearchResponse[$bucket->val][$metricsKey] = $value; } } } return $metricsFromMeilisearchResponse; } }