[TikiWiki-commits] [Git][tikiwiki/tiki][27.x] [BP][ENH] Calendar: Extend recurring events to several days in the calendar

"Adrien Mbuya Maloba \(@adrienmaloba\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <6a2ef65db3db5_371962c0725ed@gitlab-sidekiq-low-urgency-cpu-bound-v2-c9f44b7d4-crvhs.mail>

Adrien Mbuya Maloba pushed to branch 27.x at Tiki Wiki CMS Groupware / Tiki


Commits:
bd469055 by Adrien Mbuya Maloba at 2026-06-14T21:37:38+03:00
[BP][ENH] Calendar: Extend recurring events to several days in the calendar
---
* [BP][ENH] Calendar: Extend recurring events to several days in the calendar
---
* [BP][ENH] Calendar: Extend recurring events to several days in the calendar
---
* [ENH] Calendar: Extend recurring events to several days in the calendar
---
* [ENH] Calendar: Extend recurring events to several days in the calendar

See merge request tikiwiki/tiki!9238

See merge request tikiwiki/tiki!10261

See merge request tikiwiki/tiki!10521

See merge request tikiwiki/tiki!10522

- - - - -


5 changed files:

- db/tiki.sql
- + installer/schema/20251217_add_duration_calendar_recurrence_tiki.sql
- lib/calendar/calrecurrence.php
- lib/core/Services/Calendar/Controller.php
- lib/core/Tiki/SabreDav/Utilities.php


Changes:

=====================================
db/tiki.sql
=====================================
@@ -405,6 +405,7 @@ CREATE TABLE `tiki_calendar_recurrence` (
   `calendarId` int(14) NOT NULL default '0',
   `start` int(4) NOT NULL default '0',
   `end` int(4) NOT NULL default '2359',
+  `duration` int(14) default NULL,
   `allday` tinyint(1) NOT NULL default '0',
   `locationId` int(14) default NULL,
   `categoryId` int(14) default NULL,


=====================================
installer/schema/20251217_add_duration_calendar_recurrence_tiki.sql
=====================================
@@ -0,0 +1 @@
+ALTER TABLE `tiki_calendar_recurrence` ADD `duration` int(14) default NULL AFTER `end`;


=====================================
lib/calendar/calrecurrence.php
=====================================
@@ -13,6 +13,7 @@ class CalRecurrence extends TikiLib
     private $calendarId;
     private $start;
     private $end;
+    private $duration;
     private $allday;
     private $locationId;
     private $categoryId;
@@ -72,7 +73,7 @@ class CalRecurrence extends TikiLib
     {
         $dataExists = false;
         if ($this->getId() > 0) {
-            $query = "SELECT calendarId, start, end, allday, locationId, categoryId, nlId, priority, status, url, lang, name, description, daily, days,"
+            $query = "SELECT calendarId, start, end, duration, allday, locationId, categoryId, nlId, priority, status, url, lang, name, description, daily, days,"
                      . "weekly, weeks, weekdays, monthly, months, dayOfMonth, monthlyType, monthlyWeekdayValue, monthlyFirstlastWeekdayValue, yearly, years, yearlyType, dateOfYear,"
                      . "yearlyWeekdayValue, yearlyFirstlastWeekdayValue, yearlyWeekMonth, nbRecurrences, startPeriod, endPeriod, user, created, lastModif, uri, uid, recurrenceDstTimezone "
                      . "FROM tiki_calendar_recurrence WHERE recurrenceId = ?";
@@ -82,6 +83,7 @@ class CalRecurrence extends TikiLib
                 $this->setCalendarId($row['calendarId']);
                 $this->setStart($row['start']);
                 $this->setEnd($row['end']);
+                $this->setDuration(is_null($row['duration']) ? 0 : $row['duration']);
                 $this->setAllday($row['allday']);
                 $this->setLocationId($row['locationId']);
                 $this->setCategoryId($row['categoryId']);
@@ -125,6 +127,7 @@ class CalRecurrence extends TikiLib
             $this->setCalendarId(0);
             $this->setStart(0);
             $this->setEnd(0);
+            $this->setDuration(0);
             $this->setAllday(0);
             $this->setLocationId(0);
             $this->setCategoryId(0);
@@ -170,6 +173,9 @@ class CalRecurrence extends TikiLib
         $this->setCalendarId($data['calendarId']);
         $this->setStart(\DateTime::createFromFormat('U', $data['start'])->setTimezone(new \DateTimeZone('UTC'))->format('Hi'));
         $this->setEnd(\DateTime::createFromFormat('U', $data['end'])->setTimezone(new \DateTimeZone('UTC'))->format('Hi'));
+        if (isset($data['duration'])) {
+            $this->setDuration($data['duration']);
+        }
         if (isset($data['newloc'])) {
             $this->setLocationId($data['newloc']);
         }
@@ -362,15 +368,16 @@ class CalRecurrence extends TikiLib
      */
     private function create()
     {
-        $query = "INSERT INTO tiki_calendar_recurrence (calendarId, start, end, allday, locationId, categoryId, nlId, priority, status, url, lang, name, description, "
+        $query = "INSERT INTO tiki_calendar_recurrence (calendarId, start, end, duration, allday, locationId, categoryId, nlId, priority, status, url, lang, name, description, "
                  . "daily, days, weekly, weeks, weekdays, monthly, months, dayOfMonth, monthlyType, monthlyWeekdayValue, monthlyFirstlastWeekdayValue, yearly, years, yearlyType, dateOfYear, "
                  . "yearlyWeekdayValue, yearlyFirstlastWeekdayValue, yearlyWeekMonth, nbRecurrences, startPeriod, endPeriod, user, created, lastModif, uri, uid, recurrenceDstTimezone) "
-                 . "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+                 . "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
         $now = $this->now;
         $bindvars = [
                         $this->getCalendarId(),
                         $this->getStart(),
                         $this->getEnd(),
+                        $this->getDuration(),
                         $this->isAllday() ? 1 : 0,
                         $this->getLocationId() ?: 0,
                         $this->getCategoryId() ?: null,
@@ -427,7 +434,7 @@ class CalRecurrence extends TikiLib
      */
     private function update($updateManuallyChangedEvents = false)
     {
-        $query = "UPDATE tiki_calendar_recurrence SET calendarId = ?, start = ?, end = ?, allday = ?, locationId = ?, categoryId = ?, nlId = ?, priority = ?, status = ?, "
+        $query = "UPDATE tiki_calendar_recurrence SET calendarId = ?, start = ?, end = ?, duration = ?, allday = ?, locationId = ?, categoryId = ?, nlId = ?, priority = ?, status = ?, "
                  . "url = ?, lang = ?, name = ?, description = ?, daily = ?, days = ?, weekly = ?, weeks = ?, weekdays = ?, monthly = ?, months = ?, dayOfMonth = ?, monthlyType = ?, monthlyWeekdayValue = ?, monthlyFirstlastWeekdayValue = ?, yearly = ?, years = ?, yearlyType = ?, dateOfYear = ?, yearlyWeekdayValue = ?, yearlyFirstlastWeekdayValue = ?, yearlyWeekMonth = ?, nbRecurrences = ?, "
                  . "startPeriod = ?, endPeriod = ?, user = ?, lastModif = ?, uri = ?, uid = ?, recurrenceDstTimezone = ? WHERE recurrenceId = ?";
         $now = time();
@@ -435,6 +442,7 @@ class CalRecurrence extends TikiLib
                         $this->getCalendarId(),
                         $this->getStart(),
                         $this->getEnd(),
+                        $this->getDuration(),
                         $this->isAllday() ? 1 : 0,
                         $this->getLocationId(),
                         $this->getCategoryId(),
@@ -806,10 +814,6 @@ class CalRecurrence extends TikiLib
         if (TikiLib::date_format2('Hi', $evt['start']) != $oldRec->getStart()) {
             $result[] = "start";
         }
-        // checking the end is double check : is it the right hour ? is it the same day ?
-        if ((TikiLib::date_format2('Hi', $evt['end']) != $oldRec->getEnd()) || (TikiLib::date_format2('Ymd', $evt['start']) != TikiLib::date_format2('Ymd', $evt['end']))) {
-            $result[] = "end";
-        }
         if ($evt['allday'] != $oldRec->isAllday()) {
             $result[] = "allday";
         }
@@ -843,9 +847,6 @@ class CalRecurrence extends TikiLib
         if (TikiLib::date_format2('Hi', $evt['start']) != str_pad($oldRec->getStart(), 4, "0", STR_PAD_LEFT)) {
             $result[] = "_start";
         }
-        if (TikiLib::date_format2('Hi', $evt['end']) != str_pad($oldRec->getEnd(), 4, "0", STR_PAD_LEFT)) {
-            $result[] = "_end";
-        }
         if ($oldRec->isWeekly()) {
             $weekdays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
             if (! in_array($weekdays[TikiLib::date_format2('w', $evt['start'])], $oldRec->getWeekdays())) {
@@ -934,23 +935,36 @@ class CalRecurrence extends TikiLib
                 $calendar_timezones[$this->getCalendarId()] = $timezone;
             }
         }
+        // Calculate the offset of the event start in seconds
         if ($this->isAllday()) {
             $startOffset = 0;
-            $endOffset = 86399;
         } else {
             $startOffset = str_pad($this->getStart(), 4, '0', STR_PAD_LEFT);
             $startOffset = substr($startOffset, 0, 2) * 60 * 60 + substr($startOffset, -2) * 60;
-            $endOffset = str_pad($this->getEnd(), 4, '0', STR_PAD_LEFT);
-            $endOffset = substr($endOffset, 0, 2) * 60 * 60 + substr($endOffset, -2) * 60;
         }
-        // start/end period and start/end offsets are in UTC hours
+
         $dtzone = new DateTimeZone($timezone);
         $dtstart = DateTime::createFromFormat('U', TikiDate::getStartDay($this->getStartPeriod(), 'UTC') + $startOffset);
         $dtstart->setTimezone($dtzone);
-        $dtstart->setTimestamp($dtstart->getTimestamp());
-        $dtend = DateTime::createFromFormat('U', TikiDate::getStartDay($this->getStartPeriod(), 'UTC') + $endOffset);
-        $dtend->setTimezone($dtzone);
-        $dtend->setTimestamp($dtend->getTimestamp());
+
+        $duration = $this->getDuration(); // Get the event duration
+        // If event covers a single day
+        if (! $duration) {
+            // Event must finish the same day
+            if ($this->isAllday() && $dtstart->format('H:i:s') === '00:00:00') {
+                $duration = 86399;
+            } else {
+                $endOffset = str_pad($this->getEnd(), 4, '0', STR_PAD_LEFT);
+                $endOffset = substr($endOffset, 0, 2) * 60 * 60 + substr($endOffset, -2) * 60;
+                $duration = $endOffset - $startOffset;
+                if ($duration <= 0) {
+                    $duration += 86399;
+                }
+            }
+        }
+        $dtend = clone $dtstart;
+        // Add the event duration to the event start date for multi-day event
+        $dtend->modify("+{$duration} seconds");
 
         $data = [
             'CREATED' => DateTime::createFromFormat('U', $this->getCreated() ?? 0)->format('Ymd\THis\Z'),
@@ -1176,6 +1190,19 @@ class CalRecurrence extends TikiLib
         $this->end = $value;
     }
 
+    /**
+     * @param $value
+     */
+    public function setDuration($value)
+    {
+        $this->duration = $value;
+    }
+
+    public function getDuration()
+    {
+        return $this->duration;
+    }
+
     public function isAllday()
     {
         return $this->allday ?? 0;


=====================================
lib/core/Services/Calendar/Controller.php
=====================================
@@ -857,8 +857,10 @@ class Services_Calendar_Controller extends Services_Calendar_BaseController
         $tikidateStart->setDate($calitem['start']);
         $tikidateEnd = new TikiDate();
         $tikidateEnd->setDate($calitem['end']);
+        $duration = ($calitem['end'] - $calitem['start']);
         $recurrence->setStart($tikidateStart->format("%H%M", true));
         $recurrence->setEnd($tikidateEnd->format("%H%M", true));
+        $recurrence->setDuration($duration);
         date_default_timezone_set($tz);
         $recurrence->setAllday($calitem['allday']);
         $recurrence->setLocationId($calitem['locationId']);


=====================================
lib/core/Tiki/SabreDav/Utilities.php
=====================================
@@ -332,12 +332,14 @@ class Utilities
                 $lastOccurence = 0;
             }
         }
-
+        // Calculate the duration of the event
+        $duration = $lastOccurence - $firstOccurence;
         $result = [
             'start'          => $firstOccurence,
             'end'            => $lastOccurence,
             'rec'            => $rec,
             'uid'            => strval($component->UID),
+            'duration'       => $duration,
         ];
 
         $convertToString = function ($component_prop) {



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/bd469055ba16529c154ec54b191c8d9abfbc3369

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/bd469055ba16529c154ec54b191c8d9abfbc3369
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.