Changing Link Texts in Solr Facets

In a recent post, I wrote about how we can group items in Solr search facets. This latest addition to the Solr post series will discuss how one can change the link text in Facet API’s Drupal blocks.

Let’s assume I have a content type facet, as illustrated in the image below, and I wish to change the link text of the Discussion filter to Thread

 

Original link titles

Now, this sounds easy, right? One would think you could just implement hook_block_view_alter, and change the block’s content. However, this will turn out not to be the best approach. Even though this will allow you to manipulate the facet block’s render array, the individual facet links in the render array are already rendered to HTML. The snipped below is an example from the content type facet.

<a href="https://cryptic.zone/search/site/virtus?f%5B0%5D=bundle%3Aarticle" rel="nofollow" class="facetapi-inactive" id="facetapi-link--35">Article (129)<span class="element-invisible"> Apply Article filter </span></a>

These rendered links are passed to theme_item_list as is. Technically, one could do a search and replace on this string to change the link text, but that’s just plain wrong. It will break as soon as the content type name is changed in Drupal.

To allow you to manipulate such aspects of facets, the Facet API module offers hook_facetapi_facet_info_alter. Among other things, this hook will let you set a callback that will be called when Facet API maps content type machine names to human readable names, which will end up in the facet block. What we need to do is inject our custom callback into the “map callback” array element in the hook as illustrated below.

/**
 * Implements hook_facetapi_facet_info_alter();
 */
function myfacet_facetapi_facet_info_alter(array &$facet_info, array $searcher_info) {
  if ($searcher_info['adapter'] == 'apachesolr') {
    // Add our own callback to override content type names.
    $facet_info['bundle']['map callback']= 'myfacet_bundle_facet_map_callback';
  }
}

I added an if condition to check if the facet is being generated for Solr, but this technique should work for Drupal’s core search as well. The map callback may be implemented as follows:

/**
 * Facet callback to customize bundle names.
 */
function myfacet_bundle_facet_map_callback(array $values, array $options) {
  // Invoke the original implementation.
  $map = facetapi_map_bundle($values, $options);

  // Assign new label to the content type we want changed.
  if (isset($map['discussion'])) {
    $map['discussion'] = 'Thread';
  }

  return $map;
}

The default implementation of this callback is facetapi_map_bundle, which looks up human readable content type names. We should call this first so as to not break the original behavior. The original map function returns an array of content type names keyed by the machine name. These will be used in the facet links. The array might look like something like this:

Array
(
    [article] => Article
    [blog_post] => Blog post
    [discussion] => Discussion
)

Since we have changed the title of the Discussion content type in this array, the link in the facet block should now display the new title.

Updated link titles