Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions search_api_solr_datasource.module
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,10 @@
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Query\QueryInterface;
use Drupal\search_api\Query\ResultSetInterface;
use Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend;
use Solarium\QueryType\Select\Query\Query as SolariumQuery;
use Solarium\QueryType\Select\Result\Result as SolariumResult;

/**
* Implements hook_search_api_field_type_mapping_alter().
*
* Add mappings for Solr data types to Search API data types.
*/
function search_api_solr_datasource_search_api_field_type_mapping_alter(array &$mapping) {
$mapping['long'] = 'integer';
$mapping['tdate'] = 'date';
$mapping['text'] = 'text';
}

/**
* Implements hook_search_api_solr_field_mapping_alter().
*
Expand Down Expand Up @@ -55,7 +45,9 @@ function search_api_solr_datasource_search_api_solr_field_mapping_alter(IndexInt
// Re-map the indexed fields.
foreach ($fields as $raw => $name) {
// Ignore the Search API fields.
if (strpos($raw, 'search_api_') === 0) {
if (strpos($raw, 'search_api_') === 0
|| empty($index_fields[$raw])
|| $index_fields[$raw]->getDatasourceId() !== 'solr_document') {
continue;
}
$fields[$raw] = $index_fields[$raw]->getPropertyPath();
Expand All @@ -68,8 +60,8 @@ function search_api_solr_datasource_search_api_solr_field_mapping_alter(IndexInt
function search_api_solr_datasource_search_api_solr_query_alter(SolariumQuery $solarium_query, QueryInterface $query) {
// Do not alter the query if the index does not use the solr_document
// datasource.
$datasources = $query->getIndex()->getDatasources();
if (!isset($datasources['solr_document'])) {
$index = $query->getIndex();
if (!$index->isValidDatasource('solr_document')) {
return;
}

Expand All @@ -78,9 +70,38 @@ function search_api_solr_datasource_search_api_solr_query_alter(SolariumQuery $s
$solarium_query->removeFilterQuery('index_id');

// Set requestHandler for the query type.
$config = $query->getIndex()->getDatasource('solr_document')->getConfiguration();
if (!empty($config['advanced']['request_handler'])) {
$solarium_query->addParam('qt', $config['advanced']['request_handler']);
$config = $index->getDatasource('solr_document')->getConfiguration();
if (!empty($config['request_handler'])) {
$solarium_query->addParam('qt', $config['request_handler']);
}

// Set the default query, if necessary and configured.
if (!$solarium_query->getQuery() && !empty($config['default_query'])) {
$solarium_query->setQuery($config['default_query']);
}

$backend = $index->getServerInstance()->getBackend();
if ($backend instanceof SearchApiSolrBackend) {
$solr_config = $backend->getConfiguration();
// @todo Should we maybe not even check that setting and use this to
// auto-enable fields retrieval from Solr?
if (!empty($solr_config['retrieve_data'])) {
$fields_list = [];
foreach ($backend->getSolrFieldNames($index) as $solr_field_name) {
$fields_list[] = $solr_field_name;
}
$extra_fields = [
'language_field',
'label_field',
'url_field',
];
foreach ($extra_fields as $config_key) {
if (!empty($config[$config_key])) {
$fields_list[] = $config[$config_key];
}
}
$solarium_query->setFields(array_unique($fields_list));
}
}
}

Expand Down
42 changes: 36 additions & 6 deletions src/Plugin/DataType/SolrDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
namespace Drupal\search_api_solr_datasource\Plugin\DataType;

use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\Exception\MissingDataException;
use Drupal\Core\TypedData\TypedData;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api_solr_datasource\TypedData\SolrDocumentDefinition;
use Solarium\QueryType\Select\Result\AbstractDocument;

/**
* Defines the "Solr document" data type.
Expand Down Expand Up @@ -66,14 +68,42 @@ public function get($property_name) {
if (!isset($this->item)) {
throw new MissingDataException("Unable to get Solr field $property_name as no item has been provided.");
}
$field = $this->item->getField($property_name);
if ($field === NULL) {
throw new \InvalidArgumentException("The Solr field $property_name has not been configured in the index.");
}
// Create a new typed data object from the item's field data.

// First, verify that this field actually exists in the Solr server. If we
// can't get a definition for it, it doesn't exist.
/** @var \Drupal\search_api_solr_datasource\Plugin\DataType\SolrField $plugin */
$plugin = \Drupal::typedDataManager()->getDefinition('solr_field')['class'];
return $plugin::createFromField($field, $property_name, $this);
$field_manager = \Drupal::getContainer()->get('solr_field.manager');
$server_id = $this->item->getIndex()->getServerInstance()->id();
$fields = $field_manager->getFieldDefinitions($server_id);
if (empty($fields[$property_name])) {
throw new \InvalidArgumentException("The Solr field $property_name could not be found on the $server_id server.");
}
// Create a new typed data object from the item's field data.
$property = $plugin::createInstance($fields[$property_name], $property_name, $this);

// Now that we have the property, try to find its values. We first look at
// the field values contained in the result item.
$found = FALSE;
foreach ($this->item->getFields(FALSE) as $field) {
if ($field->getDatasourceId() === 'solr_document'
&& $field->getPropertyPath() === $property_name) {
$property->setValue($field->getValues());
$found = TRUE;
break;
}
}

if (!$found) {
// If that didn't work, maybe we can get the field from the Solr document?
$document = $this->item->getExtraData('search_api_solr_document');
if ($document instanceof AbstractDocument
&& isset($document[$property_name])) {
$property->setValue($document[$property_name]);
}
}

return $property;
}

/**
Expand Down
30 changes: 6 additions & 24 deletions src/Plugin/DataType/SolrField.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
class SolrField extends TypedData implements \IteratorAggregate, TypedDataInterface {

/**
* The wrapped Search API Field.
* The field value(s).
*
* @var \Drupal\search_api\Item\FieldInterface|null
* @var mixed
*/
protected $field;
protected $value;

/**
* Creates an instance wrapping the given Field.
Expand All @@ -45,36 +45,18 @@ public static function createFromField(FieldInterface $field, $name, TypedDataIn
/** @var \Drupal\search_api_solr_datasource\SolrFieldManagerInterface $field_manager */
$field_manager = \Drupal::getContainer()->get('solr_field.manager');
$server_id = $field->getIndex()->getServerInstance()->id();
$field_id = $field->getFieldIdentifier();
$field_id = $field->getPropertyPath();
$definition = $field_manager->getFieldDefinitions($server_id)[$field_id];
$instance = new static($definition, $name, $parent);
$instance->setValue($field);
$instance->setValue($field->getValues());
return $instance;
}

/**
* {@inheritdoc}
*/
public function getValue() {
return $this->field;
}

/**
* {@inheritdoc}
*/
public function setValue($field, $notify = TRUE) {
$this->field = $field;
// Notify the parent of any changes.
if ($notify && isset($this->parent)) {
$this->parent->onChange($this->name);
}
}

/**
* {@inheritdoc}
*/
public function getIterator() {
return isset($this->field) ? $this->field->getIterator() : new \ArrayIterator([]);
return new \ArrayIterator((array) $this->value);
}

}
Loading