Note this is a developer-experience (DX) issue; and was observed while working on Elasticsearch Connector's #3551591: Filter does not work with date range fields issue.
Problem/Motivation
Drupal core 8.2.0 introduced a Datetime Range module.
The Datetime Range module stores the start of the range in a property named value (like most other fields - this is also its main property name). Notably, though, it stores the end of the range in a property named end_value.
In Search API, the \Drupal\search_api\Utility\FieldsHelper class is responsible for extracting field values from entities so that they can be indexed.
When the FieldsHelper::extractFieldValues() function runs on a \Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem (i.e.: where $data instanceof DateRangeItem), it follows the "Process complex data types" branch in the code, which only extracts the main property name (value), and ignores the other property (i.e.: end_value).
The extracted data (which is now just a single date, the start date) is then passed to the Search API Data type plugin, in \Drupal\search_api\Item\Field::addValue().
If a module wants to add its own Search API Data Type plugin to handle date ranges (for example, Elasticsearch Connector's DateRangeDataType plugin, which is supposed to add support for Elasticsearch's date_range variant of its range field type), then the end_value data is no longer available by the time the Data Type plugin runs, and there's no reference back to the original entity (i.e.: to extract the end_value manually).
I can imagine this being an issue for other complex field types where there are multiple property values of equal importance. For example, Address, Double Field, etc.
***
I can see why it makes sense to return the mainPropertyValue for a complex data type; but if there is also no way for a Search API Data Type plugin to get the original field value, then site builders and/or module developers have to resort to more-complex work-arounds (e.g.: I think the developers of search_api_opensearch had to write a preprocessor plugin to support date range fields).
Steps to reproduce
- Download the latest version of Drupal core (I got 11.3.6) and search_api (I cloned 8.x-1.x branch and got commit e96a1c88)
- Install Drupal with the
minimalinstall profile. - Log in as an administrator
- Go to
/admin/modules, enablefield_ui,datetime_range,search_api, and search_api_db (other search backends will work too; I first noticed this issue with elasticsearch_connector). - Go to
/admin/structure/types/addand create a content type. I happened to give mine the machine nameevent. - Go to
/admin/structure/types/manage/event/fields/add-field, click Date and time. In the popup, enter Label =Event date(machine namefield_event_date), Choose a field type =Date range, click theContinuebutton, then click theSavebutton to accept the defaults on the second page. - Go to
/node/add/event, set Title =Sprints, Start date =2026-04-10 09:45:00, End date =2026-04-11 16:15:00, then click theSavebutton. - Go to
/admin/config/search/search-api/add-serverand add a Search API Server. I happened to give mine the machine nameexample_db_backend. - Go to
/admin/config/search/search-api/add-index, set Index name =Events, Datasources =Content, Server =example_db_backend, then click theSavebutton. - Go to
/admin/config/search/search-api/index/events/fields/add/nojs; and click theAddbutton next to the Event date (field_event_date) field. Then click theDonebutton. On theManage fields for search index Events, in thefield_event_daterow, set Type =Date(doesn't really matter what you pick here since FieldsHelper discards theend_valuebefore the field type is used). Click theSave changesbutton. -
If possible, set breakpoints in the following functions...
\Drupal\search_api\Utility\FieldsHelper::extractFieldValues()\Drupal\search_api\Item\Field::addValue()\Drupal\search_api\Plugin\search_api\data_type\DateDataType::getValue()
...Then, go to/admin/config/search/search-api/index/eventsand click theIndex nowbutton. - Observe...
- First, you hit the breakpoint in
\Drupal\search_api\Utility\FieldsHelper::extractFieldValues(), stepping through note the end_value is discarded - Next, you hit
\Drupal\search_api\Item\Field::addValue(), and the value passed in is just the value of the start_date - Finally, you hit the breakpoint in
\Drupal\search_api\Plugin\search_api\data_type\DateDataType::getValue(), and at this level of the code, there is no longer any way to find the end_value or even the original DateRangeItem to extract the end_value from that
- First, you hit the breakpoint in
Proposed resolution
Not exactly sure, but if there was a way to pass a reference to the original DateRangeItem, that would be helpful!
Remaining tasks
- Decide on a solution
- Write a merge request with tests
- Community review
- Maintainer review
- Commit
- Release
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 3583991-2--xdebug-fieldshelper-extractfieldvalues.png | 635.21 KB | mparker17 |
Comments
Comment #2
mparker17Not sure if this will be helpful, but I took a screenshot of the call stack and defined variables in
\Drupal\search_api\Utility\FieldsHelper::extractFieldValues(), and annotated it a bit. I've attached it here.Comment #3
mparker17(fixed a few typos in the issue summary)
Comment #4
joachim commentedThe end_value works ok for me in a search index if I add it to the index as a separate property.
Comment #5
joachim commentedIt's the *start value* that's broken for me -- see #3591122: date_range field is not treated as a date in Search index .