[TikiWiki-commits] [Git][tikiwiki/tiki][29.x] [BP][ENH] tracker calendar item: auto-sync event date, ability to support more...

"Baraka Kinywa \(@bkinywa24\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <68b8228a13e9c_2c12db864383f3@gitlab-sidekiq-low-urgency-cpu-bound-v2-dc78c9688-qvbvl.mail>

Baraka Kinywa pushed to branch 29.x at Tiki Wiki CMS Groupware / Tiki


Commits:
b38fb550 by MAGENE Sem Joel at 2025-09-03T14:04:21+03:00
[BP][ENH] tracker calendar item: auto-sync event date, ability to support more than one calendar item field per item
---
* [ENH] tracker calendar item: auto-sync event date, multi-field support
---
* [ENH] tracker calendar item: auto-sync event date, ability to support more than one calendar item field per item (e.g. different expiry dates), respect datetime vs date allday events

See merge request tikiwiki/tiki!8432

(cherry picked from commit 3f2e80b495f0db090b3b38a6dab27c9688092c71)

See merge request tikiwiki/tiki!8490

- - - - -


5 changed files:

- db/tiki.sql
- + installer/schema/20250828_add_fieldId_to_attributes_tiki.sql
- lib/attributes/attributelib.php
- lib/core/Services/Attribute/Controller.php
- lib/core/Tracker/Field/CalendarItem.php


Changes:

=====================================
db/tiki.sql
=====================================
@@ -3684,6 +3684,7 @@ CREATE TABLE `tiki_object_attributes` (
     `itemId` varchar(160) NOT NULL,
     `attribute` varchar(70) NOT NULL,
     `value` varchar(255),
+    `fieldId` INT DEFAULT NULL,
     `comment` varchar(255),
     UNIQUE `item_attribute_uq` ( `type`, `itemId`(91), `attribute`(50) ),
     KEY `attribute_lookup_ix` (`attribute`, `value`(121))


=====================================
installer/schema/20250828_add_fieldId_to_attributes_tiki.sql
=====================================
@@ -0,0 +1,9 @@
+ALTER TABLE `tiki_object_attributes` ADD COLUMN `fieldId` INT DEFAULT NULL AFTER `value`;
+UPDATE `tiki_object_attributes` toa
+    SET toa.`fieldId` = (
+        SELECT ttf.`fieldId`
+        FROM `tiki_tracker_fields` ttf, `tiki_tracker_items` tti
+        WHERE tti.itemId = toa.`itemId` AND ttf.trackerId = tti.trackerId AND ttf.type = 'CAL'
+        LIMIT 1
+    )
+    WHERE toa.`attribute` = 'tiki.calendar.item' and toa.`type` = 'trackeritem';
\ No newline at end of file


=====================================
lib/attributes/attributelib.php
=====================================
@@ -77,13 +77,18 @@ class AttributeLib extends TikiDb_Bridge
      * @param $type string          One of \ObjectLib::get_supported_types()
      * @param $objectId mixed       Object id (or name for wiki pages)
      * @param $attribute string     At least two dots and only lowercase letters
+     * @param $fieldId int          Field id (optional)
      * @return string|boolean       Contents of the attribute on the object or false if not present
      */
-    public function get_attribute($type, $objectId, $attribute)
+    public function get_attribute($type, $objectId, $attribute, $fieldId = null)
     {
+        $search = ['type' => $type, 'itemId' => $objectId, 'attribute' => $attribute];
+        if ($fieldId) {
+            $search['fieldId'] = $fieldId;
+        }
         return $this->attributes->fetchOne(
             'value',
-            ['type' => $type, 'itemId' => $objectId, 'attribute' => $attribute]
+            $search
         );
     }
 
@@ -97,19 +102,20 @@ class AttributeLib extends TikiDb_Bridge
      * attribute naming, and document new tiki.*.* names that you add
      * (also grep "set_attribute" just in case there are undocumented names already used)
      */
-    public function set_attribute($type, $objectId, $attribute, $value, $comment = null)
+    public function set_attribute($type, $objectId, $attribute, $value, $comment = null, $fieldId = null)
     {
         if (false === $name = $this->get_valid($attribute)) {
             return false;
         }
 
+        $search = ['type' => $type, 'itemId' => $objectId, 'attribute' => $name];
+        if ($fieldId) {
+            $search['fieldId'] = $fieldId;
+        }
+
         if ($value === '') {
             $this->attributes->delete(
-                [
-                    'type' => $type,
-                    'itemId' => $objectId,
-                    'attribute' => $name,
-                ]
+                $search
             );
         } else {
             $this->attributes->insertOrUpdate(
@@ -117,11 +123,7 @@ class AttributeLib extends TikiDb_Bridge
                     'value' => $value,
                     'comment' => $comment,
                 ],
-                [
-                    'type' => $type,
-                    'itemId' => $objectId,
-                    'attribute' => $name,
-                ]
+                $search
             );
         }
 
@@ -150,13 +152,16 @@ class AttributeLib extends TikiDb_Bridge
          * @param $value
          * @return mixed
          */
-    public function find_objects_with($attribute, $value)
+    public function find_objects_with($attribute, $value, $fieldId = null)
     {
         $attribute = $this->get_valid($attribute);
-
+        $search = ['attribute' => $attribute, 'value' => $value];
+        if ($fieldId) {
+            $search['fieldId'] = $fieldId;
+        }
         return $this->attributes->fetchAll(
-            ['type', 'itemId', 'comment'],
-            ['attribute' => $attribute, 'value' => $value,]
+            ['type', 'itemId', 'comment', 'fieldId'],
+            $search
         );
     }
 
@@ -165,11 +170,16 @@ class AttributeLib extends TikiDb_Bridge
      * @param $value
      * @return mixed
      */
-    public function delete_objects_with($attribute, $value)
+    public function delete_objects_with($attribute, $value, $fieldId = null)
     {
         $attribute = $this->get_valid($attribute);
+
+        $search = ['attribute' => $attribute, 'value' => $value];
+        if ($fieldId) {
+            $search['fieldId'] = $fieldId;
+        }
         return $this->attributes->delete(
-            ['attribute' => $attribute, 'value' => $value]
+            $search
         );
     }
 }


=====================================
lib/core/Services/Attribute/Controller.php
=====================================
@@ -17,6 +17,7 @@ class Services_Attribute_Controller
      *  ->attribute string      lowercase letters and two dots
      *  ->type string           object type
      *  ->object mixed          id or name of object
+     *  ->fieldId int           optionalfieldId
      *
      * @return array value=>string containing the value
      * @throws Exception
@@ -27,6 +28,8 @@ class Services_Attribute_Controller
         $attribute = $input->attribute->text();
         $type = $input->type->text();
         $object = $input->object->text();
+        $fieldId = $input->fieldId->int();
+        $fieldId = $fieldId == 0 ? null : $fieldId;
         $value = '';
 
         // ensure the target, source, and relation info are passed to the service
@@ -35,7 +38,7 @@ class Services_Attribute_Controller
         }
 
         if ($object) {      // for objects yet to be created we don't get an object id, so don't set any attributes
-            $value = TikiLib::lib('attribute')->get_attribute($type, $object, $attribute);
+            $value = TikiLib::lib('attribute')->get_attribute($type, $object, $attribute, $fieldId);
         }
 
         //return the attribute value if there were no errors
@@ -51,6 +54,8 @@ class Services_Attribute_Controller
         $value = $input->value->text();
         $comment = $input->comment->text();
         $attribute = $input->attribute->text();
+        $fieldId = $input->fieldId->int();
+        $fieldId = $fieldId == 0 ? null : $fieldId;
 
         // Check if required infos are passed to the service
         if (! $type || ! $itemId || ! $attribute) {
@@ -69,7 +74,8 @@ class Services_Attribute_Controller
             $itemId,
             $attribute,
             $value,
-            $comment
+            $comment,
+            $fieldId
         );
     }
 
@@ -77,6 +83,8 @@ class Services_Attribute_Controller
     {
         $attribute = $input->attribute->text();
         $value = $input->value->text();
+        $fieldId = $input->fieldId->int();
+        $fieldId = $fieldId == 0 ? null : $fieldId;
 
         // Check if info are passed to the service
         if (! $attribute || ! $value) {
@@ -91,7 +99,8 @@ class Services_Attribute_Controller
         $attributeLib = TikiLib::lib('attribute');
         $ojects = $attributeLib->find_objects_with(
             $attribute,
-            $value
+            $value,
+            $fieldId
         );
 
         return [
@@ -104,6 +113,8 @@ class Services_Attribute_Controller
         $type = $input->type->text();
         $itemId = $input->itemId->text();
         $attribute = $input->attribute->text();
+        $fieldId = $input->fieldId->int();
+        $fieldId = $fieldId == 0 ? null : $fieldId;
 
         // Check if info are passed to the service
         if (! $type || ! $itemId || ! $attribute) {
@@ -120,7 +131,8 @@ class Services_Attribute_Controller
         $result = $attributeLib->get_attribute(
             $type,
             $itemId,
-            $attribute
+            $attribute,
+            $fieldId
         );
 
         return $result;


=====================================
lib/core/Tracker/Field/CalendarItem.php
=====================================
@@ -40,6 +40,16 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
                             1 => tr('Yes'),
                         ],
                     ],
+                    'overrideCalendarItemTime' => [
+                        'name' => tr('Override Calendar Item Time'),
+                        'description' => tr('When saving the tracker item, should it override the calendar item date and time with this field\'s value or should it prefer the calendar item date and time?'),
+                        'filter' => 'int',
+                        'options' => [
+                            0 => tr('Prefer Calendar Item Time'),
+                            1 => tr('Override Calendar Item Time'),
+                        ],
+                        'default' => 0,
+                    ],
                 ],
             ],
         ];
@@ -118,11 +128,25 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
             if ($itemId) {
                 $trackerId = $this->getConfiguration('trackerId');
 
+                if ($this->getOption('datetime') == 'd') {
+                    // convert to UTC @12:00am, so we don't depend on user's timezone when displaying later
+                    $start = new TikiDate();
+                    $start->setDate($value);
+                    $start->setTZbyID(TikiLib::lib('tiki')->get_display_timezone());
+                    $start->convertTimeToUTC(0, 0, 0);
+                    $start = $start->getTime();
+                    $end = $start;
+                } else {
+                    $start = $value;
+                    $end = $value + 3600;
+                }
+
                 if (! $event) { // new calendar item please
                     $data = [
                         'calendarId' => $calendarId,
-                        'start'      => $value,
-                        'end'        => $value + 3600,
+                        'start'      => $start,
+                        'end'        => $end,
+                        'allday'     => $this->getOption('datetime') == 'd' ? 1 : 0,
                         //      'locationId',
                         //      'categoryId',
                         //      'nlId',
@@ -146,8 +170,15 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
                     $calitemId = $this->calendarLib->getMaxItemId();
 
                     $this->setCalendarItemId($calitemId);
-                } elseif ($event['start'] != $value) {
-                    $value = (int) $event['start'];
+                } elseif ($event['start'] != $start) {
+                    if ($this->getOption('overrideCalendarItemTime')) {
+                        $event['start'] = $start;
+                        $event['end'] = $end;
+                        $client = new \Tiki\SabreDav\CaldavClient();
+                        $client->saveCalendarObject($event);
+                    } else {
+                        $value = (int) $event['start'];
+                    }
                 }
             }
         }
@@ -270,7 +301,7 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
      */
     private function getCalendarItemId()
     {
-        $calitemId = $this->attributeLib->get_attribute('trackeritem', $this->getItemId(), 'tiki.calendar.item');
+        $calitemId = $this->attributeLib->get_attribute('trackeritem', $this->getItemId(), 'tiki.calendar.item', $this->getFieldId());
         return $calitemId;
     }
 
@@ -279,7 +310,7 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
      */
     private function removeCalendarItemId()
     {
-        $this->attributeLib->set_attribute('trackeritem', $this->getItemId(), 'tiki.calendar.item', '');
+        $this->attributeLib->set_attribute('trackeritem', $this->getItemId(), 'tiki.calendar.item', '', null, $this->getFieldId());
     }
 
     /**
@@ -291,7 +322,9 @@ class Tracker_Field_CalendarItem extends Tracker_Field_JsCalendar
             'trackeritem',
             $this->getItemId(),
             'tiki.calendar.item',
-            $calitemId
+            $calitemId,
+            null,
+            $this->getFieldId()
         );
     }
 }



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

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/b38fb550c08cc6b1877f4eb6bb1fabdffdb166d2
You're receiving this email because of your account on gitlab.com.

_______________________________________________
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.