/**
  * Retrieves the fulltext fields that will be searched for the search keys.
  *
  * @return array
  *   An array containing the fields that should be searched for the search
  *   keys.
  *
  * @see fields()
  *
  * @see \Drupal\search_api\Query\QueryInterface::getFields()
  */
 public function &getFields()
 {
     if (!$this->shouldAbort()) {
         return $this->query->getFields();
     }
     $ret = NULL;
     return $ret;
 }
 /**
  * Creates a database query for a search.
  *
  * Used as a helper method in search() and getAutocompleteSuggestions().
  *
  * @param \Drupal\search_api\Query\QueryInterface $query
  *   The search query for which to create the database query.
  * @param array $fields
  *   The internal field information to use.
  *
  * @return \Drupal\Core\Database\Query\SelectInterface
  *   A database query object which will return the appropriate results (except
  *   for the range and sorting) for the given search query.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if some illegal query setting (unknown field, etc.) was
  *   encountered.
  */
 protected function createDbQuery(QueryInterface $query, array $fields)
 {
     $keys =& $query->getKeys();
     $keys_set = (bool) $keys;
     $keys = $this->prepareKeys($keys);
     // Only filter by fulltext keys if there are any real keys present.
     if ($keys && (!is_array($keys) || count($keys) > 2 || !isset($keys['#negation']) && count($keys) > 1)) {
         // Special case: if the outermost $keys array has "#negation" set, we can't
         // handle it like other negated subkeys. To avoid additional complexity
         // later, we just wrap $keys so it becomes a subkey.
         if (!empty($keys['#negation'])) {
             $keys = array('#conjunction' => 'AND', $keys);
         }
         $fulltext_fields = $query->getFields();
         if ($fulltext_fields) {
             $_fulltext_fields = $fulltext_fields;
             $fulltext_fields = array();
             foreach ($_fulltext_fields as $name) {
                 if (!isset($fields[$name])) {
                     throw new SearchApiException(SafeMarkup::format('Unknown field @field specified as search target.', array('@field' => $name)));
                 }
                 if (!Utility::isTextType($fields[$name]['type'])) {
                     $types = $this->getDataTypePluginManager()->getDataTypeDefinitions();
                     $type = $types[$fields[$name]['type']]['label'];
                     throw new SearchApiException(SafeMarkup::format('Cannot perform fulltext search on field @field of type @type.', array('@field' => $name, '@type' => $type)));
                 }
                 $fulltext_fields[$name] = $fields[$name];
             }
             $db_query = $this->createKeysQuery($keys, $fulltext_fields, $fields, $query->getIndex());
         } else {
             $this->getLogger()->warning('Search keys are given but no fulltext fields are defined.');
             $msg = $this->t('Search keys are given but no fulltext fields are defined.');
             $this->warnings[$msg] = 1;
         }
     } elseif ($keys_set) {
         $msg = $this->t('No valid search keys were present in the query.');
         $this->warnings[$msg] = 1;
     }
     if (!isset($db_query)) {
         $db_query = $this->database->select($this->configuration['index_tables'][$query->getIndex()->id()], 't');
         $db_query->addField('t', 'item_id', 'item_id');
         $db_query->addExpression(':score', 'score', array(':score' => self::SCORE_MULTIPLIER));
         $db_query->distinct();
     }
     $filter = $query->getFilter();
     if ($filter->getFilters()) {
         $condition = $this->createFilterCondition($filter, $fields, $db_query, $query->getIndex());
         if ($condition) {
             $db_query->condition($condition);
         }
     }
     $db_query->addTag('search_api_db_search');
     $db_query->addMetaData('search_api_query', $query);
     $db_query->addMetaData('search_api_db_fields', $fields);
     return $db_query;
 }