Problem/Motivation
We just recently moved to Drupal 11.2. We have a server that stores an event related content type and ~20 client sites that consume these events. In this content type we are using smart dates for the date values. The client started showing dates of 12/30/1969. After much debugging, I found that during the import process the smart date values were transformed.
For example, the field for each date in the content should be represented like
smart_date = [
'0' = [
'value' => 'start_value',
'end_value' => 'end_value',
'duration' = > 'duration_value',
'rrule' => 'rrule_value',
'rrule_index' => 'rrule_index_value',
'timezone' => 'timezone_value'
],
'1' = . . .
However, the value key in the above is processed with a nested array repeating the smart_date structure
. . . [
'value' = [
'value' => 'start_value_timestamp',
'end_value' => . . .
],
'end_value' = [
'value' => 'end_value_timestamp',
'end_value' => . . .
], . . . .
Because of this when the entity is saved, the values for the value and end_value were inputted as 1 and this is why I was seeing the date of 1969.
We were on 3.3, I bumped it to 3.6, and then bumped it to the 4.0.1alpha (I believe that was the version) and this did not resolve.
I added the field_mapping core patch that Joachim mentions and this did not help. I also looked at a few patches from smart_date but none of those worked either.
As this is currently affecting some critical mission value sites, I came up with this really clunky .module hook that addresses my issue
/**
* Implements hook_entity_presave().
*/
function uclahs_custom_entity_presave($entity) {
// Only process content entities (nodes, users, etc.) - not config entities.
if (!$entity instanceof ContentEntityInterface) {
return;
}
// Only process entities that actually have the field.
if (!$entity->hasField('field_sf_smart_dates')) {
return;
}
// Check if this is running in an Entity Share context.
$request = \Drupal::request();
$route_name = \Drupal::routeMatch()->getRouteName();
$is_entity_share = (
str_contains($route_name, 'entity_share') ||
($request->query->has('_format') && $request->query->get('_format') === 'json') ||
str_contains($request->getRequestUri(), '/entity_share')
);
if ($is_entity_share) {
$values = $entity->get('field_sf_smart_dates')->getValue();
$fixed_values = [];
$needs_fix = FALSE;
foreach ($values as $delta => $value) {
// Check for the problematic nested structure.
if (isset($value['value']) && is_array($value['value'])) {
$needs_fix = TRUE;
// Extract the actual date data from the nested structure.
$actual_data = $value;
$fixed_values[$delta] = [
'value' => $actual_data['value']['value'] ?? 0,
'end_value' => $actual_data['end_value']['value'] ?? 0,
'duration' => $actual_data['duration'] ?? NULL,
'rrule' => $actual_data['rrule'] ?? NULL,
'rrule_index' => $actual_data['rrule_index'] ?? 0,
'timezone' => $actual_data['timezone'] ?? NULL,
];
}
else {
// Structure is already correct.
$fixed_values[$delta] = $value;
}
}
// Only update if we actually made changes.
if ($needs_fix) {
$entity->set('field_sf_smart_dates', $fixed_values);
\Drupal::logger('uclahs_custom')->notice('Fixed nested Smart Dates structure for entity @id (@type)', [
'@id' => $entity->id(),
'@type' => $entity->getEntityTypeId(),
]);
}
}
}
I know this is only a temporary fix; however, I wanted to reach out to the community to find out how I can further isolate where this bug is occurring and get the appropriate information either to the maintainers at entity_share or at smart_date (maybe a normalization issue).