You are here

function synonyms_autocomplete_entity in Synonyms 7

Page callback: Outputs JSON for entity autocomplete suggestions.

This callback outputs entity name suggestions in response to Ajax requests made by the synonyms autocomplete widget for entity reference fields. The output is a JSON object of plain-text entity suggestions, keyed by the user-entered value with the completed entity name appended. Entity names containing commas are wrapped in quotes. The search is made with consideration of synonyms.

Parameters

string $field_name: The name of the entity reference field.

string $entity_type: Entity type to which the supplied $field_name is attached to

string $bundle: Bundle name to which the supplied $field_name is attached to

string $tags_typed: (optional) A comma-separated list of entity names entered in the autocomplete form element. Only the last term is used for autocompletion. Defaults to '' (an empty string).

5 string references to 'synonyms_autocomplete_entity'
EntityReferenceAutocompleteSynonymsWebTestCase::setUp in ./synonyms.test
SetUp method.
synonyms_field_widget_form in ./synonyms.module
Implements hook_field_widget_form().
synonyms_field_widget_settings_form in ./synonyms.module
Implements hook_field_widget_settings_form().
synonyms_menu in ./synonyms.module
Implements hook_menu().
synonyms_views_handler_filter_entityreference_synonyms::value_form in views/synonyms_views_handler_filter_entityreference_synonyms.inc
Provide a simple textfield for equality

File

./synonyms.pages.inc, line 203
Menu page callbacks of Synonyms module.

Code

function synonyms_autocomplete_entity($field_name, $entity_type, $bundle, $tags_typed = '') {

  // If the request has a '/' in the search text, then the menu system will have
  // split it into multiple arguments, recover the intended $tags_typed.
  $args = func_get_args();

  // Shift off the $field_name argument.
  array_shift($args);

  // Shift off the $entity_type argument.
  array_shift($args);

  // Shift off the $bundle argument.
  array_shift($args);
  $tags_typed = implode('/', $args);
  if (!($field = field_info_field($field_name)) || $field['type'] != 'entityreference') {
    print t('Entity reference field @field_name not found.', array(
      '@field_name' => $field_name,
    ));
    exit;
  }
  if (!($instance = field_info_instance($entity_type, $field['field_name'], $bundle))) {

    // Error string. The JavaScript handler will realize this is not JSON and
    // will display it as debugging information.
    print t('There was not found an instance of @field_name in @entity_type.', array(
      '@field_name' => $field_name,
      '@entity_type' => $entity_type,
    ));
    exit;
  }
  $widget = $instance['widget']['type'] == 'synonyms_autocomplete_entity' ? $instance['widget']['settings'] : field_info_widget_settings('synonyms_autocomplete_entity');

  // How many suggestions maximum we are able to output.
  $max_suggestions = $widget['suggestion_size'];

  // Whether we are allowed to suggest more than one entry per term, shall that
  // entry be either term name itself or one of its synonyms.
  $suggest_only_unique = $widget['suggest_only_unique'];
  $tags_typed = drupal_explode_tags($tags_typed);
  $tag_last = drupal_strtolower(array_pop($tags_typed));
  $prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
  $handler = entityreference_get_selection_handler($field, $instance, $entity_type, NULL);
  $tags_typed_entity_ids = array();
  if (!empty($tags_typed)) {
    foreach ($tags_typed as $v) {
      foreach ($handler
        ->getReferencableEntities($v, '=') as $target_entity_ids) {
        $tags_typed_entity_ids = array_merge($tags_typed_entity_ids, array_keys($target_entity_ids));
      }
    }
  }
  $matches = array();
  if ($tag_last) {
    foreach ($handler
      ->getReferencableEntities($tag_last) as $target_entity_ids) {
      foreach (array_diff_key($target_entity_ids, drupal_map_assoc($tags_typed_entity_ids)) as $target_id => $label) {

        // We do not use the label such as given us by
        // $handler->getReferencableEntities() because some handlers may include
        // more than just plain entity label. However, our validate handler
        // expects the exact labels in the text field. So we assure we put a
        // label there.
        // These entities have already been loaded by $handler, so we shouldn't
        // care that much performance-wise about loading them in batch.
        $entity = entity_load($field['settings']['target_type'], array(
          $target_id,
        ));
        $entity = reset($entity);
        $matches[] = array(
          'target_id' => $target_id,
          'name' => entity_label($field['settings']['target_type'], $entity),
        );
        if (count($matches) == $max_suggestions) {
          break 2;
        }
      }
    }
    if (count($matches) < $max_suggestions) {
      $behavior_implementations = synonyms_behavior_get('autocomplete', $field['settings']['target_type'], synonyms_field_target_bundles($field), TRUE);
      foreach ($behavior_implementations as $implementation) {
        $condition = db_and();
        $condition
          ->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, '%' . db_like($tag_last) . '%', 'LIKE');
        if (!empty($tags_typed_entity_ids)) {
          $condition
            ->condition(AbstractSynonymsBehavior::COLUMN_ENTITY_ID_PLACEHOLDER, $tags_typed_entity_ids, 'NOT IN');
        }
        if ($suggest_only_unique && !empty($matches)) {
          $tmp = array();
          foreach ($matches as $match) {
            $tmp[] = $match['target_id'];
          }
          $condition
            ->condition(AbstractSynonymsBehavior::COLUMN_ENTITY_ID_PLACEHOLDER, $tmp, 'NOT IN');
        }
        $new_target_ids = array();
        foreach ($implementation['object']
          ->synonymsFind($condition) as $synonym) {
          if (!$suggest_only_unique || !in_array($synonym->entity_id, $new_target_ids)) {
            $matches[] = array(
              'target_id' => $synonym->entity_id,
              'synonym' => $synonym->synonym,
              'behavior_implementation' => $implementation,
            );
            $new_target_ids[] = $synonym->entity_id;
            if (count($matches) == $max_suggestions) {
              break 2;
            }
          }
        }
      }
    }
    $synonym_entities = array();
    foreach ($matches as $match) {
      if (!isset($match['wording']) && isset($match['synonym'])) {
        $synonym_entities[] = $match['target_id'];
      }
    }
    if (!empty($synonym_entities)) {
      $synonym_entities = entity_load($field['settings']['target_type'], $synonym_entities);
      foreach ($matches as $k => $match) {
        if (!isset($match['name']) && isset($match['synonym'])) {
          if (entity_access('view', $field['settings']['target_type'], $synonym_entities[$match['target_id']])) {
            $entity_ids = entity_extract_ids($field['settings']['target_type'], $synonym_entities[$match['target_id']]);
            $matches[$k]['name'] = entity_label($field['settings']['target_type'], $synonym_entities[$match['target_id']]);
            $matches[$k]['bundle'] = $entity_ids[2];
          }
          else {
            unset($matches[$k]);
          }
        }
      }
      $matches = array_values($matches);
    }
  }
  drupal_json_output(synonyms_autocomplete_format($matches, $prefix));
}