2

I'm using the entity reference module to associate users with a particular content type. I'm using the auto-complete widget (tag-style). By default, it uses the user name when auto-completing users. However, I want to change the field it's searching on. I have a field, field_complete_name that I want to use instead of the name field.

My question is, is the Entity Reference module capable of doing this? If so, how do I do it?

  • It's more than capable :) The logic would be the same as in this question, but you would just use field_complete_name as the output field in the View – Clive Aug 8 '12 at 16:51
  • Hi Clive, see this issue I just created over at the Entity Reference issue queue drupal.org/node/1719738. Sorry to fragment the conversation into two places but that seemed like the more appropriate place to document the problem. – Lester Peabody Aug 8 '12 at 21:37
1

You can either use the solution mentioned by Clive in the comment above, or build your own CTools plugin for entityreference_selection. That may take some trial and error but could give you even better control over the queries and logic behind the autocomplete feature.

7

I took Mikey's suggestion and made a ctools plugin. Here's what I came up with:

I'm using a custom module to house the plugin, but technically you could put the plugin into the entity-reference module itself. This would be ok because this method doesn't replace any module code (which would break updates).

Assuming you make a custom module you will need to put this hook into your .module file:

/* 
 * Implements hook_ctools_plugin_directory
 */
function custom_module_ctools_plugin_directory($module, $plugin) {
  if ($module == 'entityreference') {
    return 'plugins/' . $plugin;
  }
}

Then you will make a file thats located within your module's ctools plugin directory: .../modules/custom_module/plugins/selection/realname.inc

The file can be called whatever you want but the file path matters. You could also make the file in .../modules/entityreference/plugins/selection/ as well (as mentioned above).

Contents of realname.inc:

<?php

$plugin = array(
  'title' => t('Use realname'),
  'class' => 'EntityReferenceSelectRealname',
  'weight' => 10,
);

You will then make another file in the same directory as this one. The file uses the name of the class provided above then .class.php so it will be EntityReferenceSelectRealname.class.php for this one.

Contents of EntityReferenceSelectRealname.class.php:

<?php

class EntityReferenceSelectRealname extends EntityReference_SelectionHandler_Generic {

  /**
   * Implements EntityReferenceHandler::getInstance().
   */
  public static function getInstance($field, $instance = NULL, $entity_type = NULL, $entity = NULL) {
    $target_entity_type = $field['settings']['target_type'];

    // Check if the entity type does exist and has a base table.
    $entity_info = entity_get_info($target_entity_type);
    if (empty($entity_info['base table'])) {
      return EntityReference_SelectionHandler_Broken::getInstance($field, $instance);
    }

    if (class_exists($class_name = 'EntityReferenceSelectRealname_' . $target_entity_type)) {
      return new $class_name($field, $instance, $entity_type, $entity);
    }
    else {
      return new EntityReferenceSelectRealname($field, $instance, $entity_type, $entity);
    }
  }
}

/**
 * Override for the User type.
 *
 * This only exists to workaround core bugs.
 */
class EntityReferenceSelectRealname_user extends EntityReferenceSelectRealname {
  public function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
    $query = parent::buildEntityFieldQuery($match, $match_operator);

    // The user entity doesn't have a label column.
    if (isset($match)) {
      //This line uses the regular username:
      //$query->propertyCondition('name', $match, $match_operator);

      //This was added to use the "realname" field instead of the regular username:
      //CHANGE THIS:
      $query->fieldCondition('field_er_realname', 'value', $match, $match_operator);
    }

    // Adding the 'user_access' tag is sadly insufficient for users: core
    // requires us to also know about the concept of 'blocked' and
    // 'active'.
    if (!user_access('administer users')) {
      $query->propertyCondition('status', 1);
    }
    return $query;
  }

  //Not sure if this is necessary, but I'll add it in to be safe.
  public function entityFieldQueryAlter(SelectQueryInterface $query) {
    if (user_access('administer users')) {
      // In addition, if the user is administrator, we need to make sure to
      // match the anonymous user, that doesn't actually have a name in the
      // database.
      $conditions = &$query->conditions();
      foreach ($conditions as $key => $condition) {
        if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users.name') {
          // Remove the condition.
          unset($conditions[$key]);

          // Re-add the condition and a condition on uid = 0 so that we end up
          // with a query in the form:
          //    WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
          $or = db_or();
          $or->condition($condition['field'], $condition['value'], $condition['operator']);
          // Sadly, the Database layer doesn't allow us to build a condition
          // in the form ':placeholder = :placeholder2', because the 'field'
          // part of a condition is always escaped.
          // As a (cheap) workaround, we separately build a condition with no
          // field, and concatenate the field and the condition separately.
          $value_part = db_and();
          $value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
          $value_part->compile(Database::getConnection(), $query);
          $or->condition(db_and()
            ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => format_username(user_load(0))))
            ->condition('users.uid', 0)
          );
          $query->condition($or);
        }
      }
    }
  }
}

You will want to go in and change field_er_realname to your field's name. Which is field_complete_name in your case. Btw, I used the Computed Field module to generate my "realname" field based on the first and last name provided.

  • Thanks, Andrew. I found that entityFieldQueryAlter() doesn't need an override for my use case (select by email address), and that while you're developing, it never hurts to drush cc all. – paul-m May 8 '13 at 0:23
  • This is interesting, but how can one add the email address to the autocomplete widget and have it accepted? I tried just using a hook_form_alter and was able to get the user reference field to display the "realname (mail)" format, but it won't save. Also, can it be done without the Computed Field module? – Jav Aug 18 '14 at 17:02
0

The simplest way of doing that is providing a view for entity selection mode. You can follow the simple instructions on this comment:

https://drupal.stackexchange.com/a/39076/10176

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.