public function SearchApiAllTerms::query in Search API 8
Set up the query for this argument.
The argument sent may be found at $this->argument.
Overrides SearchApiStandard::query
File
- src/
Plugin/ views/ argument/ SearchApiAllTerms.php, line 68
Class
- SearchApiAllTerms
- Defines a contextual filter searching through all indexed taxonomy fields.
Namespace
Drupal\search_api\Plugin\views\argumentCode
public function query($group_by = FALSE) {
if (empty($this->value)) {
$this
->fillValue();
if (empty($this->value)) {
return;
}
}
$not_negated = empty($this->options['not']);
// If using an OR query, we can use IN for improved performance.
$conjunction = strtoupper($this->operator);
$use_in_conditions = $conjunction === 'OR';
if ($not_negated) {
$operator = $use_in_conditions ? 'IN' : '=';
}
else {
if ($use_in_conditions) {
$conjunction = 'AND';
$operator = 'NOT IN';
}
else {
$conjunction = 'OR';
$operator = '<>';
}
}
try {
$terms = $this
->getEntityTypeManager()
->getStorage('taxonomy_term')
->loadMultiple($this->value);
} catch (PluginException $e) {
$this->query
->abort($this
->t('Could not load taxonomy terms.'));
return;
}
// If values were given, but weren't valid taxonomy term IDs, we abort the
// query, as this wouldn't have yielded any results. (Unless the filter is
// negated, in which case this is of course fine.)
if (empty($terms)) {
if ($not_negated) {
$this->query
->abort($this
->t('No valid taxonomy term IDs given for "All taxonomy term fields" contextual filter.'));
}
return;
}
// Same if at least one term couldn't be loaded and we use the "AND"
// conjunction.
if ($not_negated && $conjunction == 'AND' && count($terms) < count($this->value)) {
$this->query
->abort($this
->t('Invalid taxonomy term ID given for "All taxonomy term fields" contextual filter.'));
return;
}
$vocabulary_fields = $this->definition['vocabulary_fields'];
// Add an empty array for the "all vocabularies" fields, so this is always
// present (to simplify the code below a bit).
$vocabulary_fields += [
'' => [],
];
$values = $multi_field_values = [];
$term_conditions = $this->query
->createConditionGroup($conjunction);
$this->query
->addConditionGroup($term_conditions);
foreach ($terms as $term) {
// Set filters for all term reference fields which don't specify a
// vocabulary, as well as for all fields specifying the term's vocabulary.
$vocabulary_id = $term
->bundle();
$term_id = $term
->id();
$fields_count = count($vocabulary_fields[$vocabulary_id] ?? []) + count($vocabulary_fields['']);
// If we are using an AND conjunction for our conditions, we need to make
// sure all terms actually lead to (at least) one query condition (as a
// term not matching any indexed field has to be treated as a FALSE
// condition).
if ($conjunction === 'AND' && $fields_count === 0) {
$variables = [
'@id' => $term_id,
'%label' => $term
->label(),
'%vocabulary' => $vocabulary_id,
];
$this->query
->abort($this
->t('"All taxonomy term fields" contextual filter could not be applied as taxonomy term %label (ID: @id) belongs to vocabulary %vocabulary, not contained in any indexed fields.', $variables));
return;
}
// If the operator is "AND" (commas in the argument) and there are more
// than one fields for a term, things get complicated: we need to create a
// condition group for each individual value, containing the conditions
// for all its associated fields.
if ($this->operator === 'and' && $fields_count > 1) {
foreach ($vocabulary_fields[$vocabulary_id] ?? [] as $field) {
$multi_field_values[$term_id][] = $field;
}
foreach ($vocabulary_fields[''] as $field) {
$multi_field_values[$term_id][] = $field;
}
}
else {
foreach ($vocabulary_fields[$vocabulary_id] ?? [] as $field) {
$values[$field][] = $term_id;
}
foreach ($vocabulary_fields[''] as $field) {
$values[$field][] = $term_id;
}
}
}
// Add the collected field/value conditions to the condition group.
foreach ($values as $field => $items) {
if ($use_in_conditions) {
$term_conditions
->addCondition($field, $items, $operator);
}
else {
foreach ($items as $value) {
$term_conditions
->addCondition($field, $value, $operator);
}
}
}
foreach ($multi_field_values as $value => $fields) {
$flipped_conjunction = $conjunction === 'AND' ? 'OR' : 'AND';
$group = $this->query
->createConditionGroup($flipped_conjunction);
$term_conditions
->addConditionGroup($group);
foreach ($fields as $field) {
$group
->addCondition($field, $value, $not_negated ? '=' : '<>');
}
}
if (!$term_conditions
->getConditions()) {
$labels = [];
foreach ($terms as $term) {
$labels[] = $term
->label();
}
$variables = [
'@terms' => implode(', ', $labels),
];
$this->query
->abort($this
->t('"All taxonomy term fields" contextual filter could not be applied as no indexed fields were found matching the given vocabularies of the given terms (@terms).', $variables));
}
}