You are here

public function SearchApiIndex::getFields in Search API 7

Returns a list of all known fields for this index.

Parameters

$only_indexed (optional): Return only indexed fields, not all known fields. Defaults to TRUE.

$get_additional (optional): Return not only known/indexed fields, but also related entities whose fields could additionally be added to the index.

Return value

array An array of all known fields for this index. Keys are the field identifiers, the values are arrays for specifying the field settings. The structure of those arrays looks like this:

  • name: The human-readable name for the field.
  • description: A description of the field, if available.
  • indexed: Boolean indicating whether the field is indexed or not.
  • type: The type set for this field. One of the types returned by search_api_default_field_types().
  • real_type: (optional) If a custom data type was selected for this field, this type will be stored here, and "type" contain the fallback default data type.
  • boost: A boost value for terms found in this field during searches. Usually only relevant for fulltext fields.
  • entity_type (optional): If set, the type of this field is really an entity. The "type" key will then contain "integer", meaning that servers will ignore this and merely index the entity's ID. Components displaying this field, though, are advised to use the entity label instead of the ID.

If $get_additional is TRUE, this array is encapsulated in another associative array, which contains the above array under the "fields" key, and a list of related entities (field keys mapped to names) under the "additional fields" key.

1 call to SearchApiIndex::getFields()
SearchApiIndex::getFulltextFields in includes/index_entity.inc
Convenience method for getting all of this index's fulltext fields.

File

includes/index_entity.inc, line 766
Contains SearchApiIndex.

Class

SearchApiIndex
Class representing a search index.

Code

public function getFields($only_indexed = TRUE, $get_additional = FALSE) {
  global $language;
  $only_indexed = $only_indexed ? 1 : 0;
  $get_additional = $get_additional ? 1 : 0;

  // First, try the static cache and the persistent cache bin.
  if (empty($this->fields[$only_indexed][$get_additional])) {
    $cid = $this
      ->getCacheId() . "-{$only_indexed}-{$get_additional}-{$language->language}";
    $cache = cache_get($cid);
    if ($cache) {
      $this->fields[$only_indexed][$get_additional] = $cache->data;
    }
  }

  // Otherwise, we have to compute the result.
  if (empty($this->fields[$only_indexed][$get_additional])) {
    $fields = empty($this->options['fields']) ? array() : $this->options['fields'];
    $wrapper = $this
      ->entityWrapper();
    $additional = array();
    $entity_types = entity_get_info();

    // First we need all already added prefixes.
    $added = $only_indexed || empty($this->options['additional fields']) ? array() : $this->options['additional fields'];
    foreach (array_keys($fields) as $key) {
      $len = strlen($key) + 1;
      $pos = $len;

      // The third parameter ($offset) to strrpos has rather weird behaviour,
      // necessitating this rather awkward code. It will iterate over all
      // prefixes of each field, beginning with the longest, adding all of them
      // to $added until one is encountered that was already added (which means
      // all shorter ones will have already been added, too).
      while ($pos = strrpos($key, ':', $pos - $len)) {
        $prefix = substr($key, 0, $pos);
        if (isset($added[$prefix])) {
          break;
        }
        $added[$prefix] = $prefix;
      }
    }

    // Then we walk through all properties and look if they are already
    // contained in one of the arrays.
    // Since this uses an iterative instead of a recursive approach, it is a bit
    // complicated, with three arrays tracking the current depth.
    // A wrapper for a specific field name prefix, e.g. 'user:' mapped to the user wrapper
    $wrappers = array(
      '' => $wrapper,
    );

    // Display names for the prefixes
    $prefix_names = array(
      '' => '',
    );

    // The list nesting level for entities with a certain prefix
    $nesting_levels = array(
      '' => 0,
    );
    $types = search_api_default_field_types();
    $flat = array();
    while ($wrappers) {
      foreach ($wrappers as $prefix => $wrapper) {
        $prefix_name = $prefix_names[$prefix];

        // Deal with lists of entities.
        $nesting_level = $nesting_levels[$prefix];
        $type_prefix = str_repeat('list<', $nesting_level);
        $type_suffix = str_repeat('>', $nesting_level);
        if ($nesting_level) {
          $info = $wrapper
            ->info();

          // The real nesting level of the wrapper, not the accumulated one.
          $level = search_api_list_nesting_level($info['type']);
          for ($i = 0; $i < $level; ++$i) {
            $wrapper = $wrapper[0];
          }
        }

        // Now look at all properties.
        foreach ($wrapper as $property => $value) {
          $info = $value
            ->info();

          // We hide the complexity of multi-valued types from the user here.
          $type = search_api_extract_inner_type($info['type']);

          // Treat Entity API type "token" as our "string" type.
          // Also let text fields with limited options be of type "string" by default.
          if ($type == 'token' || $type == 'text' && !empty($info['options list'])) {

            // Inner type is changed to "string".
            $type = 'string';

            // Set the field type accordingly.
            $info['type'] = search_api_nest_type('string', $info['type']);
          }
          $info['type'] = $type_prefix . $info['type'] . $type_suffix;
          $key = $prefix . $property;
          if ((isset($types[$type]) || isset($entity_types[$type])) && (!$only_indexed || !empty($fields[$key]))) {
            if (!empty($fields[$key])) {

              // This field is already known in the index configuration.
              $flat[$key] = $fields[$key] + array(
                'name' => $prefix_name . $info['label'],
                'description' => empty($info['description']) ? NULL : $info['description'],
                'boost' => '1.0',
                'indexed' => TRUE,
              );

              // Update the type and its nesting level for non-entity properties.
              if (!isset($entity_types[$type])) {
                $flat[$key]['type'] = search_api_nest_type(search_api_extract_inner_type($flat[$key]['type']), $info['type']);
                if (isset($flat[$key]['real_type'])) {
                  $real_type = search_api_extract_inner_type($flat[$key]['real_type']);
                  $flat[$key]['real_type'] = search_api_nest_type($real_type, $info['type']);
                }
              }
            }
            else {
              $flat[$key] = array(
                'name' => $prefix_name . $info['label'],
                'description' => empty($info['description']) ? NULL : $info['description'],
                'type' => $info['type'],
                'boost' => '1.0',
                'indexed' => FALSE,
              );
            }
            if (isset($entity_types[$type])) {
              $base_type = isset($entity_types[$type]['entity keys']['name']) ? 'string' : 'integer';
              $flat[$key]['type'] = search_api_nest_type($base_type, $info['type']);
              $flat[$key]['entity_type'] = $type;
            }
          }
          if (empty($types[$type])) {
            if (isset($added[$key])) {

              // Visit this entity/struct in a later iteration.
              $wrappers[$key . ':'] = $value;
              $prefix_names[$key . ':'] = $prefix_name . $info['label'] . ' » ';
              $nesting_levels[$key . ':'] = search_api_list_nesting_level($info['type']);
            }
            else {
              $name = $prefix_name . $info['label'];

              // Add machine names to discern fields with identical labels.
              if (isset($used_names[$name])) {
                if ($used_names[$name] !== FALSE) {
                  $additional[$used_names[$name]] .= ' [' . $used_names[$name] . ']';
                  $used_names[$name] = FALSE;
                }
                $name .= ' [' . $key . ']';
              }
              $additional[$key] = $name;
              $used_names[$name] = $key;
            }
          }
        }
        unset($wrappers[$prefix]);
      }
    }
    if (!$get_additional) {
      $this->fields[$only_indexed][$get_additional] = $flat;
    }
    else {
      $options = array();
      $options['fields'] = $flat;
      $options['additional fields'] = $additional;
      $this->fields[$only_indexed][$get_additional] = $options;
    }
    cache_set($cid, $this->fields[$only_indexed][$get_additional]);
  }
  return $this->fields[$only_indexed][$get_additional];
}