Modifying LinkIt search results with hook_query_TAG_alter()


The LinkIt module adds a big upgrade to the editor experience in Drupal with regards to adding links to content. Among other features, it allows for you to add a new button to WYSIWYG editors for adding links that is far superior to default link options and, really, better than any other replacement link insertion options out there. The main reason for this opinion is that it turns link insertion into a search interface that queries against the content in your site and returns results grouped by type. Additionally, it implements autocomplete with no limit on result numbers. And... it's extensible!

By default LinkIt just searches across titles. However, you can fairly easily add other search criteria via hook_query_TAG_alter(). The use case I extended LinkIt for concerned allowing the user's query to not only search across node titles but also a special custom field "field_policy_code." Here's the code to make it happen:

 * Implements hook_query_TAG_alter().
 * Let the LinkIt plugin also query the policy code. Some of the code here is
 * inspired by
function mymodule_query_linkit_entity_autocomplete_alter(QueryAlterableInterface $query) {
  if ($query->alterMetaData['entity_field_query']->entityConditions['entity_type']['value'] == 'node') {
    // What the user entered for a search
    $query_string = $query->alterMetaData['entity_field_query']->propertyConditions[0]['value'];

    // Get a reference to the existing query conditions (set by LinkIt).
    $conditions =& $query->conditions();
    $condition1 = $conditions[0];
    $condition2 = $conditions[1];

    // Reset the condition array. It needs a default #conjunction for which AND
    // is fine
    $conditions = array('#conjunction' => 'AND');

    // Add a left join for the policy code data
      ->leftJoin('field_data_field_policy_code', 'fpc', 'node.nid = fpc.entity_id');
    $or = db_or()
      // Use query string against the policy code
      ->condition('fpc.field_policy_code_value', $query_string, "LIKE")
      // Move the query string for the title ($condition1) into the OR operator
      // with policy code
      ->condition($condition1['field'], $condition1['value'], $condition1['operator']);
    // $condition2 remains an AND (this refers to the content types allowed)
    $and = db_and()
      ->condition($condition2['field'], $condition2['value'], $condition2['operator']);
    // Chain the reworked conditions together

And with that, you've created a way to query against titles and special fields! In this use case editors let me know that this one customization saved them tons of time, so little customizations like this can really make a big difference. The key for me in understanding how this works is that the EntityFieldQuery that the LinkIt plugin created can only have AND operators, and this solution needed to implement OR which can only be done through SelectQuery objects.

Let me also acknowledge the main inspiration for my understanding of this issue, @Clive's response to a bountied question on Drupal Answers. Thanks Clive!

Add new comment

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.