From 59d2e4f33d291672093f49b78f3b155d49321c0d Mon Sep 17 00:00:00 2001
From: Moritz Strohm <strohm@data-quest.de>
Date: Wed, 13 Nov 2024 13:17:23 +0000
Subject: [PATCH] fixed functionality issues in TIC 4387, re #4387

Merge request studip/studip!3629
---
 app/controllers/course/timesrooms.php         | 39 ++++++++++++++++---
 lib/exceptions/Exception.php                  |  8 ++++
 .../resources/ResourceBookingException.php    |  2 +-
 .../ResourceBookingOverlapException.php       |  2 +-
 lib/models/resources/Resource.php             |  8 +++-
 lib/models/resources/ResourceBooking.php      |  8 +++-
 6 files changed, 55 insertions(+), 12 deletions(-)

diff --git a/app/controllers/course/timesrooms.php b/app/controllers/course/timesrooms.php
index 6249d4790f9..9e189ca175a 100644
--- a/app/controllers/course/timesrooms.php
+++ b/app/controllers/course/timesrooms.php
@@ -584,7 +584,7 @@ class Course_TimesroomsController extends AuthenticatedController
                                 } else {
                                     PageLayout::postError(
                                         studip_interpolate(
-                                            _('Der Raum %{room_name} wird an dem Termin %{date} bereits durch eine andere Veranstaltung belegt.'),
+                                            _('Der Raum %{room_name} wird an dem Termin %{date} bereits anderweitig belegt.'),
                                             [
                                                 'room_name'   => $room->name,
                                                 'date'        => $termin->getFullName()
@@ -1123,6 +1123,7 @@ class Course_TimesroomsController extends AuthenticatedController
         }
 
         if (in_array(Request::get('action'), ['room', 'freetext', 'noroom']) || Request::get('course_type')) {
+            $success_cases = 0;
             $errors = [];
             foreach ($singledates as $singledate) {
                 if ($singledate instanceof CourseExDate) {
@@ -1147,12 +1148,32 @@ class Course_TimesroomsController extends AuthenticatedController
                             $failure = false;
                             try {
                                 $failure = !$singledate->bookRoom($room, intval($preparation_time));
-                            } catch (ResourceBookingException|ResourceBookingOverlapException $e) {
+                            } catch (ResourceBookingException $e) {
                                 $errors[] = sprintf(
                                     _('Der angegebene Raum konnte für den Termin %1$s nicht gebucht werden: %2$s'),
                                     '<strong>' . htmlReady($singledate->getFullName()) . '</strong>',
                                     $e->getMessage()
                                 );
+                            } catch (ResourceBookingOverlapException $e) {
+                                $course = $e->getRange();
+                                if ($course instanceof Course) {
+                                    $errors[] = studip_interpolate(
+                                        _('Der Raum %{room_name} wird an dem Termin %{date} bereits durch die Veranstaltung %{course_name} belegt.'),
+                                        [
+                                            'room_name'   => $room->name,
+                                            'date'        => $singledate->getFullName(),
+                                            'course_name' => $course->name
+                                        ]
+                                    );
+                                } else {
+                                    $errors[] = studip_interpolate(
+                                        _('Der Raum %{room_name} wird an dem Termin %{date} bereits anderweitig belegt.'),
+                                        [
+                                            'room_name'   => $room->name,
+                                            'date'        => $singledate->getFullName()
+                                        ]
+                                    );
+                                }
                             }
                             if ($failure) {
                                 $errors[] = sprintf(
@@ -1160,10 +1181,7 @@ class Course_TimesroomsController extends AuthenticatedController
                                     '<strong>' . htmlReady($singledate->getFullName()) . '</strong>'
                                 );
                             } else {
-                                PageLayout::postSuccess(sprintf(
-                                    _('Die Änderungen am Termin %s wurden gespeichert.'),
-                                    $singledate->getFullName()
-                                ));
+                                $success_cases++;
                             }
                         }
                     } else if (Request::get('room_id_parameter')) {
@@ -1202,6 +1220,15 @@ class Course_TimesroomsController extends AuthenticatedController
                     ));
                 }
             }
+            if ($success_cases > 0) {
+                if (!$errors) {
+                    //Everything went well.
+                    PageLayout::postSuccess(_('Die Änderungen wurden gespeichert.'));
+                } else {
+                    //Not everything went well.
+                    PageLayout::postWarning(_('Es konnten nicht alle Termine geändert werden.'));
+                }
+            }
             if ($errors) {
                 PageLayout::postError(
                     _('Die folgenden Fehler traten auf:'),
diff --git a/lib/exceptions/Exception.php b/lib/exceptions/Exception.php
index 606c03c30f7..714998ec8b4 100644
--- a/lib/exceptions/Exception.php
+++ b/lib/exceptions/Exception.php
@@ -55,4 +55,12 @@ class Exception extends \Exception
             $this->range
         );
     }
+
+    /**
+     * @return \Range|null The range of the exception.
+     */
+    public function getRange() : ?\Range
+    {
+        return $this->range;
+    }
 }
diff --git a/lib/exceptions/resources/ResourceBookingException.php b/lib/exceptions/resources/ResourceBookingException.php
index 3dcf4834b8a..a39da502c14 100644
--- a/lib/exceptions/resources/ResourceBookingException.php
+++ b/lib/exceptions/resources/ResourceBookingException.php
@@ -18,7 +18,7 @@
  * This exception is thrown when a general error occurs when dealing with
  * ResourceBooking objects.
  */
-class ResourceBookingException extends InvalidArgumentException
+class ResourceBookingException extends \Studip\Exception
 {
 
 }
diff --git a/lib/exceptions/resources/ResourceBookingOverlapException.php b/lib/exceptions/resources/ResourceBookingOverlapException.php
index 697cfc5746c..39497e7a731 100644
--- a/lib/exceptions/resources/ResourceBookingOverlapException.php
+++ b/lib/exceptions/resources/ResourceBookingOverlapException.php
@@ -18,7 +18,7 @@
  * This exception is thrown when a resource booking overlaps with
  * other resource bookings or with a resource lock.
  */
-class ResourceBookingOverlapException extends InvalidArgumentException
+class ResourceBookingOverlapException extends \Studip\Exception
 {
 
 }
diff --git a/lib/models/resources/Resource.php b/lib/models/resources/Resource.php
index 4dae189b3f9..661e8f42b63 100644
--- a/lib/models/resources/Resource.php
+++ b/lib/models/resources/Resource.php
@@ -872,7 +872,9 @@ class Resource extends SimpleORMap implements StudipItem
                         $begin->format('d.m.Y H:i'),
                         $end->format('H:i'),
                         $e->getMessage()
-                    )
+                    ),
+                    $e->getCode(),
+                    $e->getRange()
                 );
             } else {
                 throw new ResourceBookingOverlapException(
@@ -882,7 +884,9 @@ class Resource extends SimpleORMap implements StudipItem
                         $begin->format('d.m.Y H:i'),
                         $end->format('d.m.Y H:i'),
                         $e->getMessage()
-                    )
+                    ),
+                    $e->getCode(),
+                    $e->getRange()
                 );
             }
         } catch (Exception $e) {
diff --git a/lib/models/resources/ResourceBooking.php b/lib/models/resources/ResourceBooking.php
index 3c84cb84651..49de3815bbf 100644
--- a/lib/models/resources/ResourceBooking.php
+++ b/lib/models/resources/ResourceBooking.php
@@ -521,6 +521,9 @@ class ResourceBooking extends SimpleORMap implements PrivacyObject, Studip\Calen
                 }
             );
         }
+
+        $course = null;
+
         foreach ($time_intervals as $time_interval) {
             foreach ($existing_deleted_intervals as $deleted_interval) {
                 if (
@@ -563,7 +566,6 @@ class ResourceBooking extends SimpleORMap implements PrivacyObject, Studip\Calen
                         [self::TYPE_NORMAL, self::TYPE_LOCK],
                         [$this->id]
                     );
-                    $course = null;
                     if (
                         count($other_booking) >= 1
                         && !empty($other_booking[0]->assigned_course_date->course)
@@ -606,7 +608,9 @@ class ResourceBooking extends SimpleORMap implements PrivacyObject, Studip\Calen
         }
         if ($time_interval_overlaps) {
             throw new ResourceBookingOverlapException(
-                implode(', ', $time_interval_overlaps)
+                implode(', ', $time_interval_overlaps),
+                0,
+                $course
             );
         }
 
-- 
GitLab