Problem/Motivation
When I'm testing the season feature, it mostly works, but when I set the season start date to past and ending date to be yesterday, the rendering of the hours widget (field display on a node page) will show this warning:
Warning: Undefined array key "day" in Drupal\office_hours\OfficeHoursItemListFormatter->formatComments() (line 596 of modules/contrib/office_hours/src/OfficeHoursItemListFormatter.php).
Drupal\office_hours\OfficeHoursItemListFormatter->formatComments() (Line: 546)
Drupal\office_hours\OfficeHoursItemListFormatter->formatTimeSlots() (Line: 214)
Drupal\office_hours\OfficeHoursItemListFormatter->getRows() (Line: 118)
Drupal\office_hours\Plugin\Field\FieldType\OfficeHoursItemList->getRows() (Line: 54)
Drupal\office_hours\Plugin\Field\FieldFormatter\OfficeHoursFormatterDefault->viewElements() (Line: 91)
Steps to reproduce
- have a node type with hours field.
- enable seasons.
- field settings don't really matter, I think, I have "Show all days" and didn't enable any of the group / compress settings.
- add / edit the node with regular hours and a seaon / seasonal hours (e.g. Summer). make the season from sometime ago to yesterday.
- save node, view the node page and warning will appear. Note that if the ending date is a few days before, or today, or after today, there's no warnings. Only when the season ends yesterday, i.e. today is the first day of regular hours then the warning appears.
Proposed resolution
I did some diggings and the issue is in the following code:
// office_hours/src/OfficeHoursItemListFormatter.php
public function getRows(array $settings, array $field_settings, array $third_party_settings = [], int $time = 0, ?PluginSettingsBase $plugin = NULL) {
$office_hours = [];
...
(bulid list of office hours items)
...
// Mark the current time slot.
$current_item = $this->getCurrentSlot($time);
if ($current_item) {
$office_hours[$current_item->day]['is_current_slot'] = TRUE;
}
...
}
...
public function getCurrentSlot(int $time = 0) {
$next_day = $this->sortedList->getNextDay($time);
...
and the problem somehow happens when the season ended yesterday, the
getCurrentSlot
/
$this->sortedList->getNextDay($time);
gets the seaonal item (e.g. day = 102 instead day = 2) while item is already removed from the original list, eventually adding an item with day = NULL to the list.
Before / after the
$current_item = $this->getCurrentSlot($time);
lines I did dpm() with these results:
array:7 [▼
1 => array:8 [▶]
2 => array:8 [▶]
3 => array:8 [▶]
4 => array:8 [▶]
5 => array:8 [▶]
6 => array:8 [▶]
0 => array:8 [▶]
]
Drupal\office_hours\OfficeHoursItemListSorter {#3940 ▼
#itemList:
Drupal\office_hours\Plugin\Field\FieldType
\
OfficeHoursItemList
{#3886 ▶}
#sortedItemList: array:1 [▶]
}
array:1 [▼
1746507600 => array:1 [▶]
]
array:8 [▼
1 => array:8 [▶]
2 => array:8 [▶]
3 => array:8 [▶]
4 => array:8 [▶]
5 => array:8 [▶]
6 => array:8 [▶]
0 => array:8 [▶]
102 => array:2 [▶]
]
Remaining tasks
I'm not sure how to fix this yet, but I think it has something to do with the logic when try to find the next item / next day, it needs to consider seasons and if the next day is in an active season or not (i.e. yesterday the items is day 101, but next item should be day 2 instead of 102, if the season ends).