Drupal 8 - Combine two facets

By k, 3 November, 2019

Authored on

Sun, 11/03/2019 - 16:26
Image
munchen

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:

merge_article_page_procesor

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!

Comments 2

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

Marisol (not verified)

10 months ago

I've been browsing online greater than three hours lately,
yet I by no means discovered any interesting article like yours.
It is lovely worth enough for me. Personally,
if all webmasters and bloggers made excellent content material as you
did, the net will be a lot more useful than ever before.