Skip to content

Commit

Permalink
Issue #3439023 by mkalkbrenner, drunken monkey: Invalid types "text" …
Browse files Browse the repository at this point in the history
…and "date" specified in SolrFieldDefinition data defintions
  • Loading branch information
mkalkbrenner committed Apr 10, 2024
1 parent b9cb010 commit 4976410
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 32 deletions.
40 changes: 23 additions & 17 deletions src/EventSubscriber/SearchApiSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Drupal\search_api_solr\EventSubscriber;

use Drupal\search_api\Event\MappingViewsFieldHandlersEvent;
use Drupal\search_api\Event\MappingViewsHandlersEvent;
use Drupal\search_api\Event\SearchApiEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

Expand All @@ -12,32 +13,38 @@
class SearchApiSubscriber implements EventSubscriberInterface {

/**
* Adds the mapping to treat some Solr special fields as fulltext in views.
* Adds the mapping how to treat some Solr special fields in views.
*
* @param \Drupal\search_api\Event\MappingViewsFieldHandlersEvent $event
* The Search API event.
*/
public function onMappingViewsFieldHandlers(MappingViewsFieldHandlersEvent $event) {
$mapping = & $event->getFieldHandlerMapping();

$mapping['solr_date'] = $mapping['datetime_iso8601'];
}

/**
* Adds the mapping how to treat some Solr special fields in views.
*
* @param \Drupal\search_api\Event\MappingViewsFieldHandlersEvent $event
* The Search API event.
*/
public function onMappingViewsHandlers(MappingViewsHandlersEvent $event) {
$mapping = & $event->getHandlerMapping();

$mapping['solr_text_omit_norms'] =
$mapping['solr_text_suggester'] =
$mapping['solr_text_spellcheck'] =
$mapping['solr_text_unstemmed'] =
$mapping['solr_text_wstoken'] = [
'argument' => [
'id' => 'search_api',
],
'filter' => [
'id' => 'search_api_fulltext',
],
'sort' => [
'id' => 'search_api',
],
];
$mapping['solr_text_wstoken'] =
$mapping['solr_text_custom'] =
$mapping['solr_text_custom_omit_norms'] = $mapping['text'];

/* @see \Drupal\search_api_solr\SolrFieldManager::buildFieldDefinitionsFromSolr() */
/* @see \_search_api_views_get_field_handler_mapping() */
$mapping['date'] = $mapping['timestamp'];
$mapping['solr_string_storage'] = $mapping['string'];

// Views can't handle a 'solr_date_range' natively.
$mapping['solr_date_range'] = $mapping['string'];
}

/**
Expand All @@ -52,8 +59,7 @@ public static function getSubscribedEvents() {

return [
SearchApiEvents::MAPPING_VIEWS_FIELD_HANDLERS => 'onMappingViewsFieldHandlers',
SearchApiEvents::MAPPING_VIEWS_HANDLERS => 'onMappingViewsHandlers',
];

}

}
33 changes: 33 additions & 0 deletions src/Plugin/DataType/SolrDate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Drupal\search_api_solr\Plugin\DataType;

use Drupal\Core\TypedData\Plugin\DataType\DateTimeIso8601;

/**
* A data type for Solr date strings.
*
* The plain value of this data type is a date string in ISO 8601 format.
*
* @DataType(
* id = "solr_date",
* label = @Translation("Solr date")
* )
*/
class SolrDate extends DateTimeIso8601 {

/**
* {@inheritdoc}
*/
public function getValue() {
return \Drupal::service('solarium.query_helper')->formatDate((string) $this->value);
}

/**
* {@inheritdoc}
*/
public function setValue($value, $notify = TRUE) {
parent::setValue(trim($value, 'Z'), $notify);
}

}
4 changes: 3 additions & 1 deletion src/Plugin/search_api/backend/SearchApiSolrBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ public function getSupportedFeatures() {
public function supportsDataType($type) {
static $custom_codes = [];

if (strpos($type, 'solr_text_custom') === 0) {
if (str_starts_with($type, 'solr_text_custom')) {
[, $custom_code] = explode(':', $type);
if (empty($custom_codes)) {
$custom_codes = SolrFieldType::getAvailableCustomCodes();
Expand All @@ -776,6 +776,8 @@ public function supportsDataType($type) {
'solr_text_spellcheck',
'solr_text_unstemmed',
'solr_text_wstoken',
'solr_text_custom',
'solr_text_custom_omit_norms',
'solr_date_range',
];
if (in_array($type, $built_in_support)) {
Expand Down
27 changes: 13 additions & 14 deletions src/SolrFieldManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function getFieldDefinitions(IndexInterface $index) {
/**
* Builds the field definitions for a Solr server.
*
* Initially the defintions will be built from a the response of a luke query
* Initially the definitions will be built from the response of a luke query
* handler directly from Solr. But once added to the Drupal config, the
* definitions will be a mix of the Drupal config and not yet used fields from
* Solr. This strategy also covers scenarios when the Solr server is
Expand All @@ -109,13 +109,8 @@ public function getFieldDefinitions(IndexInterface $index) {
protected function buildFieldDefinitions(IndexInterface $index) {
$solr_fields = $this->buildFieldDefinitionsFromSolr($index);
$config_fields = $this->buildFieldDefinitionsFromConfig($index);
$fields = $solr_fields + $config_fields;
/*** @var \Drupal\Core\TypedData\DataDefinitionInterface $field */
foreach ($config_fields as $key => $field) {
// Always use the type as already configured in Drupal previously.
$fields[$key]->setDataType($field->getDataType());
}
return $fields;
// Always prefer the type as already (re-)configured in Drupal.
return $config_fields + $solr_fields;
}

/**
Expand All @@ -130,10 +125,17 @@ protected function buildFieldDefinitions(IndexInterface $index) {
protected function buildFieldDefinitionsFromConfig(IndexInterface $index) {
$fields = [];
foreach ($index->getFields() as $index_field) {
$type = $index_field->getType();
if ($type === 'text' || str_starts_with($type, 'solr_text_')) {
$type = 'search_api_text';
}
elseif ($type === 'date') {
$type = 'solr_date';
}
$solr_field = $index_field->getPropertyPath();
$field = new SolrFieldDefinition(['schema' => '']);
$field->setLabel($index_field->getLabel());
$field->setDataType($index_field->getType());
$field->setDataType($type);
$fields[$solr_field] = $field;
}
return $fields;
Expand Down Expand Up @@ -194,13 +196,10 @@ protected function buildFieldDefinitionsFromSolr(IndexInterface $index) {
$field->setDataType('search_api_text');
}
elseif (strpos($type, 'date_range') !== FALSE) {
$field->setDataType('solr_date_range');
$field->setDataType('string');
}
elseif (strpos($type, 'date') !== FALSE) {
// The field config UI uses "date" but converts that to "timestamp"
// internally. We handle this in the mapping.
/* @see \Drupal\search_api_solr\EventSubscriber\SearchApiSubscriber::onMappingViewsFieldHandlers() */
$field->setDataType('date');
$field->setDataType('solr_date');
}
elseif (strpos($type, 'int') !== FALSE) {
$field->setDataType('integer');
Expand Down

0 comments on commit 4976410

Please sign in to comment.