protected function AbstractSearchApiSolrMultilingualBackend::preQuery in Search API Solr 8.2
Modify the query before it is sent to solr.
Replaces all language unspecific fulltext query fields by language specific ones.
Parameters
\Solarium\Core\Query\QueryInterface $solarium_query: The Solarium select query object.
\Drupal\search_api\Query\QueryInterface $query: The \Drupal\search_api\Query\Query object representing the executed search query.
Overrides SearchApiSolrBackend::preQuery
File
- src/
Plugin/ search_api/ backend/ AbstractSearchApiSolrMultilingualBackend.php, line 174
Class
- AbstractSearchApiSolrMultilingualBackend
- A abstract base class for all multilingual Solr Search API backends.
Namespace
Drupal\search_api_solr\Plugin\search_api\backendCode
protected function preQuery(SolariumQueryInterface $solarium_query, QueryInterface $query) {
// Do not modify 'Server index status' queries.
// @see https://www.drupal.org/node/2668852
if ($query
->hasTag('server_index_status')) {
return;
}
parent::preQuery($solarium_query, $query);
$language_ids = $query
->getLanguages();
if (!empty($language_ids)) {
$index = $query
->getIndex();
$fulltext_fields = $this
->getQueryFulltextFields($query);
$field_names = $this
->getSolrFieldNames($index);
$language_specific_fields = [];
foreach ($language_ids as $language_id) {
foreach ($fulltext_fields as $fulltext_field) {
$field_name = $field_names[$fulltext_field];
$language_specific_fields[$language_id][$field_name] = Utility::encodeSolrName(Utility::getLanguageSpecificSolrDynamicFieldNameForSolrDynamicFieldName($field_name, $language_id));
}
}
$components = $solarium_query
->getComponents();
if (isset($components[ComponentAwareQueryInterface::COMPONENT_HIGHLIGHTING])) {
$hl = $solarium_query
->getHighlighting();
$highlighted_fields = $hl
->getFields();
foreach ($field_names as $field_name) {
if (isset($highlighted_fields[$field_name])) {
$exchanged = FALSE;
foreach ($language_ids as $language_id) {
if (isset($language_specific_fields[$language_id][$field_name])) {
$language_specific_field = $language_specific_fields[$language_id][$field_name];
// Copy the already set highlighting options over to the language
// specific fields. getField() creates a new one first.
$highlighted_field = $hl
->getField($language_specific_field);
$highlighted_field
->setOptions($highlighted_fields[$field_name]
->getOptions());
$highlighted_field
->setName($language_specific_field);
$exchanged = TRUE;
}
}
if ($exchanged) {
$hl
->removeField($field_name);
}
}
}
}
if (!empty($this->configuration['retrieve_data'])) {
if ($fields_to_be_retrieved = $query
->getOption('search_api_retrieved_field_values', [])) {
$language_specific_fields_to_retrieve = [];
$fields_to_retrieve = $solarium_query
->getFields();
foreach ($fields_to_retrieve as $key => $field_name) {
$language_specific_name = FALSE;
foreach ($language_ids as $language_id) {
if (isset($language_specific_fields[$language_id][$field_name])) {
$language_specific_fields_to_retrieve[] = $language_specific_fields[$language_id][$field_name];
$language_specific_name = TRUE;
}
}
if ($language_specific_name) {
unset($fields_to_retrieve[$key]);
}
}
if ($language_specific_fields_to_retrieve) {
$solarium_query
->setFields(array_merge($language_specific_fields_to_retrieve, $fields_to_retrieve));
}
}
}
if ($query
->hasTag('mlt')) {
$mlt_fields = [];
foreach ($language_ids as $language_id) {
/** @var \Solarium\QueryType\MoreLikeThis\Query $solarium_query */
foreach ($solarium_query
->getMltFields() as $mlt_field) {
if (isset($language_specific_fields[$language_id][$mlt_field])) {
$mlt_fields[] = $language_specific_fields[$language_id][$mlt_field];
}
else {
// Make sure untranslated fields are still kept.
$mlt_fields[$mlt_field] = $mlt_field;
}
}
}
$solarium_query
->setMltFields($mlt_fields);
}
elseif ($keys = $query
->getKeys()) {
/** @var \Solarium\QueryType\Select\Query\Query $solarium_query */
$edismax = $solarium_query
->getEDisMax();
if ($solr_fields = $edismax
->getQueryFields()) {
$parse_mode_id = $query
->getParseMode()
->getPluginId();
if ('terms' == $parse_mode_id) {
// Using the 'phrase' parse mode, Search API provides one big phrase
// as keys. Using the 'terms' parse mode, Search API provides chunks
// of single terms as keys. But these chunks might contain not just
// real terms but again a phrase if you enter something like this in
// the search box: term1 "term2 as phrase" term3. This will be
// converted in this keys array: ['term1', 'term2 as phrase',
// 'term3']. To have Solr behave like the database backend, these
// three "terms" should be handled like three phrases.
$parse_mode_id = 'phrase';
}
$new_keys = [];
foreach ($language_ids as $language_id) {
$new_solr_fields = $solr_fields;
foreach ($fulltext_fields as $fulltext_field) {
$field_name = $field_names[$fulltext_field];
$new_solr_fields = str_replace($field_name, $language_specific_fields[$language_id][$field_name], $new_solr_fields);
}
if ($new_solr_fields == $solr_fields) {
// If there's no change for the first language, there won't be
// any change for the other languages, too.
return;
}
$flat_keys = $this
->flattenKeys($keys, explode(' ', $new_solr_fields), $parse_mode_id);
if (strpos($flat_keys, '(') !== 0 && strpos($flat_keys, '+(') !== 0 && strpos($flat_keys, '-(') !== 0) {
$flat_keys = '(' . $flat_keys . ')';
}
$new_keys[] = $flat_keys;
}
if (count($new_keys) > 1) {
$new_keys['#conjunction'] = 'OR';
}
$new_keys['#escaped'] = TRUE;
// Preserve the original keys to be set again in postQuery().
$this->origKeys = $query
->getOriginalKeys();
// The orginal keys array is now already flatten once per language.
// that means that we already build Solr query strings containing
// fields and keys. Now we set these query strings again as keys
// using an OR conjunction but remove all query fields. That will
// cause the parent class to just concatenate the language specific
// query strings using OR as they are.
$query
->keys($new_keys);
$edismax
->setQueryFields([]);
}
}
}
}