search_api_meilisearch-1.0.x-dev/modules/search_api_meilisearch_facets/src/EventSubscriber/ProcessingResultsSubscriber.php
modules/search_api_meilisearch_facets/src/EventSubscriber/ProcessingResultsSubscriber.php
<?php
namespace Drupal\search_api_meilisearch_facets\EventSubscriber;
use Drupal\search_api\Event\ProcessingResultsEvent;
use Drupal\search_api\Event\SearchApiEvents;
use Drupal\search_api_meilisearch\Api\MeilisearchApiServiceInterface;
use Drupal\search_api_meilisearch\Parser\FilterParserInterface;
use Drupal\search_api_meilisearch\Plugin\search_api\backend\SearchApiMeilisearchBackend;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Subscribes to processing results events.
*/
class ProcessingResultsSubscriber implements EventSubscriberInterface {
/**
* The MeiliSearch facets API service.
*
* @var \Drupal\search_api_meilisearch\Api\MeilisearchApiServiceInterface
*/
protected MeilisearchApiServiceInterface $meiliService;
/**
* The filter parser.
*
* @var \Drupal\search_api_meilisearch\Parser\FilterParserInterface
*/
protected FilterParserInterface $filterParser;
/**
* Constructs a new ProcessingResultsSubscriber object.
*/
public function __construct(MeilisearchApiServiceInterface $meiliService, FilterParserInterface $filterParser) {
$this->meiliService = $meiliService;
$this->filterParser = $filterParser;
}
/**
* For each facet, get results count.
*
* @param string $indexId
* The name of the index.
* @param array $facets
* The facets to get results count for.
* @param array $filters
* The filters to apply.
* @param string $query
* The query to apply.
*
* @return array
* The facet results.
*
* @throws \Drupal\search_api_meilisearch\Api\MeiliSearchApiException
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function getFacetData(string $indexId, array $facets, array $filters, string $query): array {
$processFacets = [];
foreach ($facets as $facet) {
/*
* @todo this is a hack to get all facets,
* if meilisearch ever adds support for getting all facets remove this.
*/
$allFacets = $this->meiliService->searchFacets($indexId, $facet);
$allFacets = $allFacets->getFacetHits();
$facetResult = $this->meiliService->searchFacets($indexId, $facet, NULL, $filters, $query);
$facetResult = $facetResult->getFacetHits();
$processFacets[$facet] = array_map(function ($facet) use ($facetResult) {
// Check if the facet is in the facet result.
$contains = array_filter($facetResult, function ($facetResult) use ($facet) {
return $facetResult['value'] === $facet['value'];
});
return [
'count' => empty($contains) ? 0 : reset($contains)['count'],
'filter' => $facet['value'],
];
}, $allFacets);
}
return $processFacets;
}
/**
* Adds facets to the search results.
*
* @param \Drupal\search_api\Event\ProcessingResultsEvent $event
* The event.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\search_api\SearchApiException
* @throws \Drupal\search_api_meilisearch\Api\MeiliSearchApiException
*/
public function onProcessingResults(ProcessingResultsEvent $event): void {
$results = $event->getResults();
$query = $results->getQuery();
$backend = $query->getIndex()->getServerInstance()->getBackend();
if ($backend instanceof SearchApiMeilisearchBackend) {
$this->setConfiguration($backend);
$keys = $query->getOriginalKeys() ?? '';
$filters = $this->filterParser->parseExpression($query->getConditionGroup(), $query->getIndex());
$facets = $query->getOption('search_api_facets', []);
$facetResults = $this->getFacetData($query->getIndex()->id(), array_keys($facets), [$filters], $keys);
$results->setExtraData('search_api_facets', $facetResults);
}
}
/**
* Set Meilisearch api connection configuration.
*
* @param \Drupal\search_api_meilisearch\Plugin\search_api\backend\SearchApiMeilisearchBackend $backend
* The backend.
*/
protected function setConfiguration(SearchApiMeilisearchBackend $backend): void {
$this->meiliService->setUrl($backend->getConfiguration()['meilisearch_host_address'] . ':' . $backend->getConfiguration()['meilisearch_host_port']);
$this->meiliService->setMasterKey($backend->getConfiguration()['meilisearch_master_key']);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
return [
SearchApiEvents::PROCESSING_RESULTS => 'onProcessingResults',
];
}
}
