Drupal 8 - Combine two facets
Authored on
Once upon a time I was asked to use `Facets` module to expose new facets based on content types. I made them and it worked properly but a requeriment was to combine two specific ones into a single facet, let's say `article` and `page` content types need to be together. In order to solve it I decided to create a new facet processor plugin.
Then I create a new custom module named `keboca_search` where I included a new plugin into `src` folder at the following path: `Plugin/facets/processor/MergeArticlePage.php`
namespace Drupal\keboca_search\Plugin\facets\processor;
use Drupal\facets\Annotation\FacetsProcessor;
use Drupal\facets\FacetInterface;
use Drupal\facets\Processor\BuildProcessorInterface;
use Drupal\facets\Processor\ProcessorPluginBase;
/**
* Class MergeArticlePage which's merging two hard-coded content types.
*
* @package Drupal\keboca_search\Plugin\facets\processor
*
* @FacetsProcessor(
* id = "keboca_search_merge_article_page",
* label = @Translation("Merge Articles and Pages together."),
* description = @Translation("An integration to force put together Articles
* and Pages into a single facet."),
* stages = {
* "build" = 60
* }
* )
*/
class MergeArticlePage extends ProcessorPluginBase implements BuildProcessorInterface {
/**
* {@inheritdoc}
*/
public function build(FacetInterface $facet, array $results) {
/** @var \Drupal\facets\Result\Result[] $facets */
$facets = array_reduce($results, function ($carry, $item) {
/** @var \Drupal\facets\Result\Result $item */
$carry[$item->getRawValue()] = $item;
return $carry;
}, []);
/** @var \Drupal\facets\Result\Result $article */
$article = $facets['article'] ?? NULL;
/** @var \Drupal\facets\Result\Result $page */
$page = $facets['page'] ?? NULL;
// Parse `page` facet instance.
if (!is_null($page)) {
/** @var \Drupal\Core\Url $url */
$url = $page->getUrl();
/** @var array $query */
$query = $url->getOption('query');
// Init flag variables.
$updated = FALSE;
$filter = 'content_type:article';
// Look-up for query string.
if (!in_array($filter, $query['sitewide'])) {
// Inject filter to current query.
$updated = TRUE;
$query['sitewide'][] = $filter;
}
// Verify when current facet is active.
elseif ($page->isActive()) {
// Remove duplication filter values.
$updated = TRUE;
$query['sitewide'] = array_filter($query['sitewide'], function ($param) use ($filter) {
return $param != $filter;
});
// Remove whole query string when there are not filters.
if (empty($query['sitewide'])) {
unset($query['sitewide']);
}
}
// Overwrite URL options then define it back to facet.
if ($updated) {
$url->setOption('query', $query);
$page->setUrl($url);
}
// Update facet count value when article facet was found.
if (!is_null($article)) {
$page->setCount($page->getCount() + $article->getCount());
// Remove `article` facet instance.
unset($facets['article']);
}
}
return array_values($facets);
}
}
Finally I jumped into my content type facet edit form (`/admin/config/search/facets/content_type/edit`) where I enabled the new processor into "Facet settings" section:

I've also review "Advanced Settings" section to be sure the build stage section was defining the new processor at the very end.
That said, I hope it helps you at some point somehow!
Happy coding!