Skip to content
Snippets Groups Projects
Commit 67d13690 authored by Matt Glaman's avatar Matt Glaman Committed by Matt Glaman
Browse files

Issue #3094192 by mglaman: Support filtering on index fields

parent ee0b3f6d
Branches
Tags
No related merge requests found
......@@ -12,6 +12,7 @@ use Drupal\jsonapi\Query\OffsetPage;
use Drupal\jsonapi\ResourceResponse;
use Drupal\jsonapi_resources\Resource\EntityResourceBase;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Item\Field;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\ParseMode\ParseModeInterface;
use Drupal\search_api\ParseMode\ParseModePluginManager;
......@@ -82,7 +83,7 @@ final class IndexResource extends EntityResourceBase implements ContainerInjecti
$query->range($pagination->getOffset(), $pagination->getSize());
if ($request->query->has('filter')) {
$this->applyFiltersToQuery($request, $query);
$this->applyFiltersToQuery($request, $query, $cacheability);
}
// Get the results and convert to JSON:API resource object data.
......@@ -106,10 +107,12 @@ final class IndexResource extends EntityResourceBase implements ContainerInjecti
* The request.
* @param \Drupal\search_api\Query\QueryInterface $query
* The query.
* @param \Drupal\Core\Cache\CacheableMetadata $cacheability
* The cache metadata.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
*/
protected function applyFiltersToQuery(Request $request, QueryInterface $query): void {
protected function applyFiltersToQuery(Request $request, QueryInterface $query, CacheableMetadata $cacheability): void {
$parse_mode = $this->parseModeManager->createInstance('terms');
assert($parse_mode instanceof ParseModeInterface);
$query->setParseMode($parse_mode);
......@@ -119,6 +122,17 @@ final class IndexResource extends EntityResourceBase implements ContainerInjecti
$query->keys($filter['fulltext']);
unset($filter['fulltext']);
}
$index = $query->getIndex();
$filterable_fields = array_filter($index->getFields(), static function (Field $field) {
return $field->getType() !== 'text';
});
foreach ($filter as $filterable_field_name => $filterable_field_value) {
if (!isset($filterable_fields[$filterable_field_name])) {
throw new CacheableBadRequestHttpException($cacheability, sprintf('The %s field is not filterable.', $filterable_field_name));
}
$query->addCondition($filterable_field_name, $filterable_field_value);
}
}
/**
......
......@@ -78,6 +78,7 @@ final class IndexResourceTest extends BrowserTestBase {
* @dataProvider noQueryDataProvider
* @dataProvider paginationDataProvider
* @dataProvider fulltextDataProvider
* @dataProvider filterDataProvider
*/
public function testCollection(array $query, int $expected_count, array $expected_ids, array $expected_links_keys): void {
$request_options = [];
......@@ -173,4 +174,43 @@ final class IndexResourceTest extends BrowserTestBase {
];
}
/**
* Filter data provider.
*
* @return \Generator
* The data.
*/
public function filterDataProvider(): \Generator {
yield [
[
'filter' => [
'keywords' => 'strawberry',
],
],
2,
[4, 5],
[],
];
yield [
[
'filter' => [
'keywords' => 'banana',
],
],
1,
[5],
[],
];
yield [
[
'filter' => [
'keywords' => 'orange',
],
],
3,
[1, 2, 5],
[],
];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment