You are here

function name_autocomplete in Name Field 7

Menu callback for the name autocomplete.

Retrieve a JSON object containing autocomplete suggestions for existing values as defined by the widget.

This is complicated by the fact that there can be multiple sources and that multiple components may want to be searched.

1 string reference to 'name_autocomplete'
name_menu in ./name.module
Implements hook_menu().

File

./name.admin.inc, line 17
General administration functions.

Code

function name_autocomplete($field_name, $target, $string = '') {
  $matches = array();
  $limit = 10;
  if ($string) {
    $all_components = array_keys(_name_translations());
    $autocomplete_sources = module_invoke_all('name_data_sources');
    $autocomplete_map = array();
    $autocomplete_fallback = array();
    foreach ($autocomplete_sources as $ac_source => $ac_settings) {
      foreach ($all_components as $key) {
        if (empty($ac_settings['components']) || in_array($key, $ac_settings['components'])) {
          if (!empty($ac_settings['autocomplete callback'])) {
            $autocomplete_map[$key][$ac_source] = $ac_settings['name'];
            if (!empty($ac_settings['autonomous'])) {
              $autocomplete_fallback[$ac_source] = $ac_settings['name'];
            }
          }
        }
      }
    }
    $field_name = str_replace('-', '_', $field_name);
    $field = field_info_field($field_name);
    if ($field) {
      $settings = $field['settings'];
      foreach ($all_components as $component) {
        if (!isset($settings['autocomplete_source'][$component])) {
          $settings['autocomplete_source'][$component] = array();
        }
        $settings['autocomplete_source'][$component] = array_filter($settings['autocomplete_source'][$component]);
      }
    }
    else {
      $settings = array(
        'autocomplete_source' => array_combine($all_components, array_fill(0, count($all_components), $autocomplete_fallback)),
        'autocomplete_separator' => array(
          'given' => ' -',
          'middle' => ' -',
          'family' => ' -',
        ) + array_combine($all_components, array_fill(0, count($all_components), ' ')),
      );
    }
    $action = array();
    switch ($target) {
      case 'name':
        $action['components'] = drupal_map_assoc(array(
          'given',
          'middle',
          'family',
        ));
        break;
      case 'name-all':
        $action['components'] = drupal_map_assoc($all_components);
        break;
      default:
        $action['components'] = array();
        foreach (explode('-', $target) as $component) {
          if (in_array($component, $all_components)) {
            $action['components'][$component] = $component;
          }
        }
        break;
    }
    $action['source'] = array();
    $action['separater'] = '';
    $separator_characters = '';
    foreach ($action['components'] as $component) {
      if (empty($settings['autocomplete_source'][$component]) || empty($autocomplete_map[$component])) {
        unset($action['components'][$component]);
      }
      else {
        $sep = (string) $settings['autocomplete_separator'][$component];
        $separator_characters .= strlen($sep) ? $sep : ' ';
        $settings['autocomplete_source'][$component] = array_intersect_key($settings['autocomplete_source'][$component], $autocomplete_map[$component]);
        if ($settings['autocomplete_source'][$component]) {
          foreach ($settings['autocomplete_source'][$component] as $src) {
            $action['source'][$src][] = $component;
          }
        }
        else {
          unset($action['components'][$component]);
        }
      }
    }
    $action['separater'] = count_chars($separator_characters, 3);
    $pieces = preg_split('/[' . preg_quote($action['separater']) . ']+/', $string);

    // We should have nice clean parameters to query.
    if (!empty($pieces) && !empty($action['components'])) {
      $test_string = drupal_strtolower(array_pop($pieces));
      $base_string = drupal_substr($string, 0, drupal_strlen($string) - drupal_strlen($test_string));
      foreach ($action['source'] as $ac_action => $components) {
        if ($field || !empty($autocomplete_sources[$ac_action]['autonomous'])) {
          $func = $autocomplete_sources[$ac_action]['autocomplete callback'];
          $arguments = empty($autocomplete_sources[$ac_action]['autocomplete arguments']) ? array() : $autocomplete_sources[$ac_action]['autocomplete arguments'];
          if (function_exists($func)) {
            $results = $func($action['source'][$ac_action], $base_string, $test_string, $field, $limit, $arguments);
            foreach ($results as $name => $safe_name) {
              $matches[$base_string . $name] = $safe_name;
              $limit--;
            }
          }
        }
      }
    }
  }
  drupal_json_output($matches);
}