You are here

protected function SearchApiDbService::convert in Search API Database Search 7

Converts a value between two search types.

Parameters

$value: The value to convert.

$type: The type to convert to. One of the keys from search_api_default_field_types().

$original_type: The value's original type.

SearchApiIndex $index: The index for which this conversion takes place.

Return value

mixed The converted value.

Throws

SearchApiException If $type is unknown.

1 call to SearchApiDbService::convert()
SearchApiDbService::indexItem in ./service.inc
Indexes a single item on the specified index.

File

./service.inc, line 1015
Contains SearchApiDbService.

Class

SearchApiDbService
Indexes and searches items using the database.

Code

protected function convert($value, $type, $original_type, SearchApiIndex $index) {
  if (search_api_is_list_type($type)) {
    $type = substr($type, 5, -1);
    $original_type = search_api_extract_inner_type($original_type);
    $ret = array();
    if (is_array($value)) {
      foreach ($value as $v) {
        $v = $this
          ->convert($v, $type, $original_type, $index);

        // Don't add NULL values to the return array. Also, adding an empty
        // array is, of course, a waste of time.
        if (isset($v) && $v !== array()) {
          $ret = array_merge($ret, is_array($v) ? $v : array(
            $v,
          ));
        }
      }
    }
    return $ret;
  }
  if (!isset($value)) {

    // For text fields, we have to return an array even if the value is NULL.
    return search_api_is_text_type($type, array(
      'text',
      'tokens',
    )) ? array() : NULL;
  }
  switch ($type) {
    case 'text':

      // For dates, splitting the timestamp makes no sense.
      if ($original_type == 'date') {
        $value = format_date($value, 'custom', 'Y y F M n m j d l D');
      }
      $ret = array();
      foreach (preg_split('/[^\\p{L}\\p{N}]+/u', $value, -1, PREG_SPLIT_NO_EMPTY) as $v) {
        if ($v) {
          $ret[] = array(
            'value' => $v,
            'score' => 1,
          );
        }
      }
      $value = $ret;

    // FALL-THROUGH!
    case 'tokens':
      while (TRUE) {
        foreach ($value as $i => $v) {

          // Check for over-long tokens.
          $score = $v['score'];
          $v = $v['value'];
          if (drupal_strlen($v) > 50) {
            $words = preg_split('/[^\\p{L}\\p{N}]+/u', $v, -1, PREG_SPLIT_NO_EMPTY);
            if (count($words) > 1 && max(array_map('drupal_strlen', $words)) <= 50) {

              // Overlong token is due to bad tokenizing.
              // Check for "Tokenizer" preprocessor on index.
              if (empty($index->options['processors']['search_api_tokenizer']['status'])) {
                watchdog('search_api_db', 'An overlong word (more than 50 characters) was encountered while indexing, due to bad tokenizing. ' . 'It is recommended to enable the "Tokenizer" preprocessor for indexes using database servers. ' . 'Otherwise, the service class has to use its own, fixed tokenizing.', array(), WATCHDOG_WARNING);
              }
              else {
                watchdog('search_api_db', 'An overlong word (more than 50 characters) was encountered while indexing, due to bad tokenizing. ' . 'Please check your settings for the "Tokenizer" preprocessor to ensure that data is tokenized correctly.', array(), WATCHDOG_WARNING);
              }
            }
            $tokens = array();
            foreach ($words as $word) {
              if (drupal_strlen($word) > 50) {
                watchdog('search_api_db', 'An overlong word (more than 50 characters) was encountered while indexing: %word.<br />' . 'Database search servers currently cannot index such words correctly – the word was therefore trimmed to the allowed length.', array(
                  '%word' => $word,
                ), WATCHDOG_WARNING);
                $word = drupal_substr($word, 0, 50);
              }
              $tokens[] = array(
                'value' => $word,
                'score' => $score,
              );
            }
            array_splice($value, $i, 1, $tokens);
            continue 2;
          }
        }
        break;
      }
      return $value;
    case 'string':
    case 'uri':

      // For non-dates, PHP can handle this well enough.
      if ($original_type == 'date') {
        return date('c', $value);
      }
      if (drupal_strlen($value) > 255) {
        $value = drupal_substr($value, 0, 255);
        watchdog('search_api_db', 'An overlong value (more than 255 characters) was encountered while indexing: %value.<br />' . 'Database search servers currently cannot index such values correctly – the value was therefore trimmed to the allowed length.', array(
          '%value' => $value,
        ), WATCHDOG_WARNING);
      }
      return $value;
    case 'integer':
    case 'duration':
    case 'decimal':
      return 0 + $value;
    case 'boolean':

      // Numeric strings need to be converted to a numeric type before
      // converting to a boolean, as strings like '0.00' evaluate to TRUE.
      if (is_string($value) && is_numeric($value)) {
        $value = 0 + $value;
      }
      return $value ? 1 : 0;
    case 'date':
      if (is_numeric($value) || !$value) {
        return 0 + $value;
      }
      return strtotime($value);
    default:
      throw new SearchApiException(t('Unknown field type @type. Database search module might be out of sync with Search API.', array(
        '@type' => $type,
      )));
  }
}