From eb6fcd5c560f3938ea4f60fbe70ad09261c300cc Mon Sep 17 00:00:00 2001
From: Peter Thienel <thienel@data-quest.de>
Date: Wed, 8 May 2024 08:16:05 +0000
Subject: [PATCH] =?UTF-8?q?Resolve=20"iCal=20Export=20liefert=20abgew?=
 =?UTF-8?q?=C3=A4hlte=20Veranstaltungstermine=20mit=20aus"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #3938

Merge request studip/studip!2940
---
 .../calendar/ICalendarExport.class.php        | 49 +++++--------------
 .../calendar/CalendarCourseDate.class.php     | 48 +++++++++++++++++-
 2 files changed, 60 insertions(+), 37 deletions(-)

diff --git a/lib/classes/calendar/ICalendarExport.class.php b/lib/classes/calendar/ICalendarExport.class.php
index ce50f872eeb..14541797b1f 100644
--- a/lib/classes/calendar/ICalendarExport.class.php
+++ b/lib/classes/calendar/ICalendarExport.class.php
@@ -76,20 +76,7 @@ class ICalendarExport
         if ($this->time === 0) {
             $this->time = time();
         }
-        $dates = CourseDate::findBySql(
-            "LEFT JOIN `seminar_user`
-                ON `termine`.`range_id` = `seminar_user`.`Seminar_id`
-            WHERE
-                `seminar_user`.`user_id` = :user_id
-                AND `seminar_user`.`bind_calendar` = 1
-                AND (`termine`.`date` <= :end
-                    AND `termine`.`end_time` >= :begin)",
-            [
-                ':user_id'  => $user_id,
-                ':begin'    => $start->getTimestamp(),
-                ':end'      => $end->getTimestamp(),
-            ]
-        );
+        $dates = CalendarCourseDate::getEvents($start, $end, $user_id);
         $ical = '';
         foreach ($dates as $date) {
             $ical .= $this->writeICalEvent($this->prepareCourseDate($date));
@@ -102,20 +89,7 @@ class ICalendarExport
         if ($this->time === 0) {
             $this->time = time();
         }
-        $dates = CourseExDate::findBySql(
-            "LEFT JOIN `seminar_user`
-                ON `ex_termine`.`range_id` = `seminar_user`.`Seminar_id`
-            WHERE
-                `seminar_user`.`user_id` = :user_id
-                AND `seminar_user`.`bind_calendar` = 1
-                AND (`ex_termine`.`date` <= :end
-                    AND `ex_termine`.`end_time` >= :begin)",
-            [
-                ':user_id'  => $user_id,
-                ':begin'    => $start->getTimestamp(),
-                ':end'      => $end->getTimestamp(),
-            ]
-        );
+        $dates = CalendarCourseExDate::getEvents($start, $end, $user_id);
         $ical = '';
         foreach ($dates as $date) {
             $ical .= $this->writeICalEvent($this->prepareCourseDate($date));
@@ -124,10 +98,10 @@ class ICalendarExport
     }
 
     /**
-     * @param CalendarDate | CourseExDate $date
-     * @return array
+     * @param CalendarDate $date The calendar date to export.
+     * @return array Calendar date data prepared for export.
      */
-    public function prepareCalendarDate($date): array
+    public function prepareCalendarDate(CalendarDate $date): array
     {
         return [
             'SUMMARY'       => $date->title,
@@ -155,8 +129,8 @@ class ICalendarExport
     }
 
     /**
-     * @param CalendarDate | CourseExDate $date
-     * @return array
+     * @param CourseDate | CourseExDate $date The course date to export.
+     * @return array Course date data prepared for export.
      */
     public function prepareCourseDate($date): array
     {
@@ -165,10 +139,13 @@ class ICalendarExport
         if ($date instanceof CourseExDate) {
             $summary .= ' ' . _('(fällt aus)');
             $categories = '';
+            $description = $date->content;
+        } else {
+            $description = implode("\n", $date->topics->pluck('title'));
         }
         return [
             'SUMMARY'       => $summary,
-            'DESCRIPTION'   => '',
+            'DESCRIPTION'   => $description,
             'LOCATION'      => $date->getRoomName(),
             'CATEGORIES'    => $categories,
             'LAST-MODIFIED' => $date->chdate,
@@ -381,8 +358,8 @@ class ICalendarExport
     public function _exportDateTime($value, $utc = false)
     {
         $date_time = new DateTime();
-        $date_time->setTimestamp($value);
-        //transform local time in UTC
+        $date_time->setTimestamp(intval($value));
+        //transform local time to UTC
         if ($utc) {
             $tz_utc = new DateTimeZone('UTC');
             $date_time->setTimezone($tz_utc);
diff --git a/lib/models/calendar/CalendarCourseDate.class.php b/lib/models/calendar/CalendarCourseDate.class.php
index 49179bd579d..370dcd14449 100644
--- a/lib/models/calendar/CalendarCourseDate.class.php
+++ b/lib/models/calendar/CalendarCourseDate.class.php
@@ -8,7 +8,13 @@ class CalendarCourseDate extends CourseDate
 {
     public static function getEvents(DateTime $begin, DateTime $end, string $range_id): array
     {
-        return parent::findBySQL(
+        $events = [];
+        parent::findEachBySQL(
+            function ($e) use (&$events, $range_id) {
+                if (self::checkRelated($e, $range_id)) {
+                    $events[] = $e;
+                }
+            },
             "JOIN `seminar_user`
                ON `seminar_user`.`seminar_id` = `termine`.`range_id`
              WHERE `seminar_user`.`user_id` = :user_id
@@ -30,5 +36,45 @@ class CalendarCourseDate extends CourseDate
                 'user_id' => $range_id
             ]
         );
+        return $events;
+    }
+
+    /**
+     * Checks if given user is the responsible lecturer or is member of a
+     * related group.
+     *
+     * @global object $perm The global perm object.
+     * @param CalendarCourseDate $event The course event to check against.
+     * @param string $user_id The id of the user.
+     * @return boolean
+     */
+    protected static function checkRelated(CalendarCourseDate $event, string $user_id): bool
+    {
+        $check_related = false;
+        $permission = $GLOBALS['perm']->get_studip_perm($event->range_id, $user_id);
+        switch ($permission) {
+            case 'dozent' :
+                $related_persons = $event->dozenten->pluck('user_id');
+                if (count($related_persons) > 0) {
+                    $check_related = in_array($user_id, $related_persons);
+                } else {
+                    $check_related = true;
+                }
+                break;
+            case 'tutor' :
+                $check_related = true;
+                break;
+            default :
+                $group_ids = $event->statusgruppen->pluck('statusgruppe_id');
+                if (count($group_ids) > 0) {
+                    $member = StatusgruppeUser::findBySQL(
+                        'statusgruppe_id IN(?) AND user_id = ?',
+                        [$group_ids, $user_id]);
+                    $check_related = count($member) > 0;
+                } else {
+                    $check_related = true;
+                }
+        }
+        return $check_related;
     }
 }
-- 
GitLab