Exemplo n.º 1
0
 /**
  * Creates a database query condition for a given search filter.
  *
  * Used as a helper method in createDbQuery().
  *
  * @param \Drupal\search_api\Query\ConditionGroupInterface $conditions
  *   The conditions for which a condition should be created.
  * @param array $fields
  *   Internal information about the index's fields.
  * @param \Drupal\Core\Database\Query\SelectInterface $db_query
  *   The database query to which the condition will be added.
  * @param \Drupal\search_api\IndexInterface $index
  *   The index we're searching on.
  *
  * @return \Drupal\Core\Database\Query\ConditionInterface|null
  *   The condition to set on the query, or NULL if none is necessary.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if an unknown field was used in the filter.
  */
 protected function createDbCondition(ConditionGroupInterface $conditions, array $fields, SelectInterface $db_query, IndexInterface $index)
 {
     $db_condition = new Condition($conditions->getConjunction());
     $db_info = $this->getIndexDbInfo($index);
     // Store whether a JOIN already occurred for a field, so we don't JOIN
     // repeatedly for OR filters.
     $first_join = array();
     // Store the table aliases for the fields in this condition group.
     $tables = array();
     foreach ($conditions->getConditions() as $condition) {
         if ($condition instanceof ConditionGroupInterface) {
             $sub_condition = $this->createDbCondition($condition, $fields, $db_query, $index);
             if ($sub_condition) {
                 $db_condition->condition($sub_condition);
             }
         } else {
             $field = $condition->getField();
             $operator = $condition->getOperator();
             $value = $condition->getValue();
             $not_equals = $operator == '<>' || $operator == '!=';
             // We don't index the datasource explicitly, so this needs a bit of
             // magic.
             // @todo Index the datasource explicitly so this doesn't need magic.
             if ($field === 'search_api_datasource') {
                 if (empty($tables[NULL])) {
                     $table = array('table' => $db_info['index_table']);
                     $tables[NULL] = $this->getTableAlias($table, $db_query);
                 }
                 $operator = $not_equals ? 'NOT LIKE' : 'LIKE';
                 $prefix = Utility::createCombinedId($value, '');
                 $db_condition->condition($tables[NULL] . '.item_id', $this->database->escapeLike($prefix) . '%', $operator);
                 continue;
             }
             if (!isset($fields[$field])) {
                 throw new SearchApiException(new FormattableMarkup('Unknown field in filter clause: @field.', array('@field' => $field)));
             }
             $field_info = $fields[$field];
             // For NULL values, we can just use the single-values table, since we
             // only need to know if there's any value at all for that field.
             if ($value === NULL || empty($field_info['multi-valued'])) {
                 if (empty($tables[NULL])) {
                     $table = array('table' => $db_info['index_table']);
                     $tables[NULL] = $this->getTableAlias($table, $db_query);
                 }
                 $column = $tables[NULL] . '.' . $field_info['column'];
                 if ($value === NULL) {
                     $method = $not_equals ? 'isNotNull' : 'isNull';
                     $db_condition->{$method}($column);
                 } else {
                     $db_condition->condition($column, $value, $operator);
                 }
                 continue;
             }
             if (Utility::isTextType($field_info['type'])) {
                 $keys = $this->prepareKeys($value);
                 if (!isset($keys)) {
                     continue;
                 }
                 $query = $this->createKeysQuery($keys, array($field => $field_info), $fields, $index);
                 // We only want the item IDs, so we use the keys query as a nested
                 // query.
                 $query = $this->database->select($query, 't')->fields('t', array('item_id'));
                 $db_condition->condition('t.item_id', $query, $not_equals ? 'NOT IN' : 'IN');
             } else {
                 $new_join = $conditions->getConjunction() == 'AND' || empty($first_join[$field]);
                 if ($new_join || empty($tables[$field])) {
                     $tables[$field] = $this->getTableAlias($field_info, $db_query, $new_join);
                     $first_join[$field] = TRUE;
                 }
                 $column = $tables[$field] . '.' . 'value';
                 if ($not_equals) {
                     // The situation is more complicated for multi-valued fields, since
                     // we must make sure that results are excluded if ANY of the field's
                     // values equals the one given in this condition.
                     $query = $this->database->select($field_info['table'], 't')->fields('t', array('item_id'))->condition('value', $value);
                     $db_condition->condition('t.item_id', $query, 'NOT IN');
                 } else {
                     $db_condition->condition($column, $value, $operator);
                 }
             }
         }
     }
     return $db_condition->count() ? $db_condition : NULL;
 }
Exemplo n.º 2
0
 /**
  * {@inheritdoc}
  */
 public function addCondition($field, $value, $operator = '=')
 {
     $this->conditionGroup->addCondition($field, $value, $operator);
     return $this;
 }
Exemplo n.º 3
0
 /**
  * Transforms a query filter into a flat array of Solr filter queries, using
  * the field names in $field_names.
  */
 protected function createFilterQueries(ConditionGroupInterface $conditions, array $solr_fields, array $index_fields)
 {
     $or = $conditions->getConjunction() == 'OR';
     $fq = array();
     foreach ($conditions->getConditions() as $condition) {
         if ($condition instanceof ConditionInterface) {
             $field = $condition->getField();
             if (!isset($index_fields[$field])) {
                 throw new SearchApiException(t('Filter term on unknown or unindexed field @field.', array('@field' => $field)));
             }
             $value = $condition->getValue();
             if ($value !== '') {
                 $fq[] = $this->createFilterQuery($solr_fields[$field], $value, $condition->getOperator(), $index_fields[$field]);
             }
         } else {
             $q = $this->createFilterQueries($condition, $solr_fields, $index_fields);
             if ($conditions->getConjunction() != $condition->getConjunction()) {
                 // $or == TRUE means the nested filter has conjunction AND, and vice versa
                 $sep = $or ? ' ' : ' OR ';
                 $fq[] = count($q) == 1 ? reset($q) : '((' . implode(')' . $sep . '(', $q) . '))';
             } else {
                 $fq = array_merge($fq, $q);
             }
         }
     }
     return $or && count($fq) > 1 ? array('((' . implode(') OR (', $fq) . '))') : $fq;
 }