[TikiWiki-commits] [Git][tikiwiki/tiki][27.x] [BP][FIX] CalendarController: Prevent one-day backward shift for date-only...
"Bruno Kambere \(@kambereBr\) via TikiWiki-cvs" <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <69f0f37f26075_3818ee6c1613@gitlab-sidekiq-low-urgency-cpu-bound-v2-6778cd888b-s2stg.mail> |
Bruno Kambere pushed to branch 27.x at Tiki Wiki CMS Groupware / Tiki
Commits:
289c7887 by Bruno Kambere at 2026-04-28T20:43:02+03:00
[BP][FIX] CalendarController: Prevent one-day backward shift for date-only tracker fields in non-UTC timezones
---
* [BP][FIX] CalendarController: Prevent one-day backward shift for date-only tracker fields in non-UTC timezones
---
* [BP][FIX] CalendarController: Prevent one-day backward shift for date-only tracker fields in non-UTC timezones
---
* [FIX] CalendarController: Prevent one-day backward shift for date-only tracker fields in non-UTC timezones
---
* [FIX] JsCalendar: Improve date normalization logic for form submissions
* [REF] Simplify date-only calendar field handling across picker and field handlers
* [ENH] CalendarController: Support TrackerList calendar with start-only/end-only date fields
* [REF] JsCalendar: Refactor normalizeDateOnlyTimestamp method
* [FIX] JsCalendar: Normalize date-only timestamps and improve date handling in date picker
* [ENH] CalendarController: Enhance date-only event handling for tracker fields
* [FIX] CalendarController: Prevent one-day backward shift for date-only tracker fields in non-UTC timezones
See merge request tikiwiki/tiki!9742
See merge request tikiwiki/tiki!10095
See merge request tikiwiki/tiki!10097
See merge request tikiwiki/tiki!10098
- - - - -
2 changed files:
- lib/core/Services/Tracker/CalendarController.php
- lib/core/Tracker/Field/DateTime.php
Changes:
=====================================
lib/core/Services/Tracker/CalendarController.php
=====================================
@@ -24,17 +24,29 @@ class Services_Tracker_CalendarController
$unifiedsearchlib = TikiLib::lib('unifiedsearch');
$index = $unifiedsearchlib->getIndex();
- $start = 'tracker_field_' . $input->beginField->word();
- $end = 'tracker_field_' . $input->endField->word();
- $title = 'tracker_field_' . $input->title->word();
- $description = 'tracker_field_' . $input->description->word();
+ $beginFieldName = $input->beginField->word();
+ $endFieldName = $input->endField->word();
+ $start = 'tracker_field_' . $beginFieldName;
+ $end = 'tracker_field_' . $endFieldName;
+ $hasStartField = ! empty($beginFieldName) && $beginFieldName !== 'null';
+ $hasEndField = ! empty($endFieldName) && $endFieldName !== 'null';
+ $titleFieldName = $input->title->word();
+ $title = ($titleFieldName && $titleFieldName !== 'null') ? 'tracker_field_' . $titleFieldName : null;
+ $descriptionFieldName = $input->description->word();
+ $description = ($descriptionFieldName && $descriptionFieldName !== 'null') ? 'tracker_field_' . $descriptionFieldName : null;
- if ($resource = $input->resourceField->word()) {
- $resource = 'tracker_field_' . $resource;
+ $resource = null;
+ if ($resourceFieldName = $input->resourceField->word()) {
+ if ($resourceFieldName !== 'null') {
+ $resource = 'tracker_field_' . $resourceFieldName;
+ }
}
- if ($coloring = $input->coloringField->word()) {
- $coloring = 'tracker_field_' . $coloring;
+ $coloring = null;
+ if ($coloringFieldName = $input->coloringField->word()) {
+ if ($coloringFieldName !== 'null') {
+ $coloring = 'tracker_field_' . $coloringFieldName;
+ }
}
$query = $unifiedsearchlib->buildQuery([]);
@@ -57,8 +69,12 @@ class Services_Tracker_CalendarController
}
}
- $query->filterRange(0, $to, $start);
- $query->filterRange($from, $to + 1000 * 365 * 86400, $end);
+ if ($hasStartField) {
+ $query->filterRange(0, $to, $start);
+ }
+ if ($hasEndField) {
+ $query->filterRange($from, $to + 1000 * 365 * 86400, $end);
+ }
$maxRecords = $input->maxRecords->int() ?: null;
$query->setRange(0, $maxRecords);
@@ -74,7 +90,25 @@ class Services_Tracker_CalendarController
$response = [];
$fields = [];
+ $beginDateFieldHandler = null;
+ $endDateFieldHandler = null;
if ($definition = Tracker_Definition::get($input->trackerId->int())) {
+ $factory = $definition->getFieldFactory();
+
+ if ($hasStartField) {
+ $beginFieldInfo = $definition->getField($beginFieldName);
+ if ($beginFieldInfo) {
+ $beginDateFieldHandler = $factory->getHandler($beginFieldInfo);
+ }
+ }
+
+ if ($hasEndField) {
+ $endFieldInfo = $definition->getField($endFieldName);
+ if ($endFieldInfo) {
+ $endDateFieldHandler = $factory->getHandler($endFieldInfo);
+ }
+ }
+
foreach ($definition->getPopupFields() as $fieldId) {
if ($field = $definition->getField($fieldId)) {
$fields[] = $field;
@@ -137,22 +171,53 @@ class Services_Tracker_CalendarController
$colormap = base64_decode($input->colormap->word());
- $dtStart = $this->getTimestamp($row[$start]);
- $dtEnd = $this->getTimestamp($row[$end]);
+ $startValue = ($hasStartField && isset($row[$start])) ? $row[$start] : null;
+ $endValue = ($hasEndField && isset($row[$end])) ? $row[$end] : null;
+
+ if ($startValue === null && $endValue === null) {
+ continue;
+ }
+
+ // If only one of start or end is provided, use that value for both to ensure the event appears on the calendar,
+ $dtStart = $this->getTimestamp($startValue ?? $endValue);
+ $dtEnd = $this->getTimestamp($endValue ?? $startValue);
+
+ // If end is before start, treat as a single instant event by using the start value for both
+ if ($dtEnd < $dtStart) {
+ $dtEnd = $dtStart;
+ }
+
+ $beginIsDateOnly = $beginDateFieldHandler instanceof Tracker_Field_DateTime
+ && $beginDateFieldHandler->isDateOnlyCalendarValue();
+ $endIsDateOnly = $endDateFieldHandler instanceof Tracker_Field_DateTime
+ && $endDateFieldHandler->isDateOnlyCalendarValue();
+
+ // Determine if event is date-only
+ // If only one field is specified, check that field; if both are specified, both must be date-only
+ if ($beginDateFieldHandler !== null && $endDateFieldHandler !== null) {
+ $isDateOnlyEvent = $beginIsDateOnly && $endIsDateOnly;
+ } elseif ($beginDateFieldHandler !== null) {
+ $isDateOnlyEvent = $beginIsDateOnly;
+ } elseif ($endDateFieldHandler !== null) {
+ $isDateOnlyEvent = $endIsDateOnly;
+ } else {
+ $isDateOnlyEvent = false;
+ }
$response[] = [
'id' => $row['object_id'],
'trackerId' => $row['tracker_id'] ?? null,
- 'title' => $row[$title] ?: $row['title'],
- 'extendedProps' => ['description' => $row[$description] ?: $row['description']],
+ 'title' => ($title && isset($row[$title])) ? $row[$title] : ($row['title'] ?? ''),
+ 'extendedProps' => ['description' => ($description && isset($row[$description])) ? $row[$description] : ($row['description'] ?? '')],
'url' => smarty_modifier_sefurl($row['object_id'], $row['object_type']),
- 'allDay' => false,
- 'start' => $useTimestamp ? $dtStart : TikiLib::date_format("c", $dtStart, $user, 5, false),
- 'end' => $useTimestamp ? $dtEnd : TikiLib::date_format("c", $dtEnd, $user, 5, false),
+ // For all-day events, return date-only strings so FullCalendar does not apply timezone conversions that can shift the visible day.
+ 'allDay' => $isDateOnlyEvent,
+ 'start' => $isDateOnlyEvent ? gmdate('Y-m-d', $dtStart) : ($useTimestamp ? $dtStart : TikiLib::date_format("c", $dtStart, $user, 5, false)),
+ 'end' => $isDateOnlyEvent ? gmdate('Y-m-d', $dtEnd) : ($useTimestamp ? $dtEnd : TikiLib::date_format("c", $dtEnd, $user, 5, false)),
'editable' => $item->canModify(),
- 'color' => $row[$coloring] ? ($row[$coloring] ?: $row['coloring']) : ($this->getColor($row[$coloring] ?? '', $colormap)),
+ 'color' => ($coloring && isset($row[$coloring])) ? ($row[$coloring] ?: $row['coloring'] ?? '') : ($this->getColor($row[$coloring] ?? '', $colormap)),
'textColor' => '#000',
- 'resourceId' => strtolower($row[$resource] ?? ''),
+ 'resourceId' => $resource && isset($row[$resource]) ? strtolower($row[$resource]) : '',
'resourceEditable' => true,
];
}
=====================================
lib/core/Tracker/Field/DateTime.php
=====================================
@@ -341,4 +341,9 @@ class Tracker_Field_DateTime extends \Tracker\Field\AbstractItemField implements
})
];
}
+
+ public function isDateOnlyCalendarValue(): bool
+ {
+ return $this->getOption('datetime') === 'd';
+ }
}
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/289c78879dc44161a860346d792aff7619082e63
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/289c78879dc44161a860346d792aff7619082e63
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs