From f2a7c979d16fdb0c0e1862577b8ca76016f92efd Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Fri, 12 May 2023 08:22:13 +0000
Subject: [PATCH] add semester filter to user courses route, fixes #2572

Closes #2572

Merge request studip/studip!1733
---
 .../Routes/Courses/CoursesByUserIndex.php     | 67 +++++++++++++++++--
 1 file changed, 62 insertions(+), 5 deletions(-)

diff --git a/lib/classes/JsonApi/Routes/Courses/CoursesByUserIndex.php b/lib/classes/JsonApi/Routes/Courses/CoursesByUserIndex.php
index 2adf6d7ccb2..ba2536909c0 100644
--- a/lib/classes/JsonApi/Routes/Courses/CoursesByUserIndex.php
+++ b/lib/classes/JsonApi/Routes/Courses/CoursesByUserIndex.php
@@ -2,11 +2,15 @@
 
 namespace JsonApi\Routes\Courses;
 
+use Course;
 use JsonApi\Errors\AuthorizationFailedException;
+use JsonApi\Errors\BadRequestException;
 use JsonApi\Errors\RecordNotFoundException;
 use JsonApi\JsonApiController;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
+use Semester;
+use User;
 
 class CoursesByUserIndex extends JsonApiController
 {
@@ -31,12 +35,14 @@ class CoursesByUserIndex extends JsonApiController
 
     protected $allowedPagingParameters = ['offset', 'limit'];
 
+    protected $allowedFilteringParameters = ['semester'];
+
     /**
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __invoke(Request $request, Response $response, array $args): Response
     {
-        if (!$user = \User::find($args['id'])) {
+        if (!$user = User::find($args['id'])) {
             throw new RecordNotFoundException();
         }
 
@@ -44,14 +50,65 @@ class CoursesByUserIndex extends JsonApiController
             throw new AuthorizationFailedException();
         }
 
-        $courses = $this->findCoursesByUser($user);
+        if ($error = $this->validateFilters()) {
+            throw new BadRequestException($error);
+        }
+
+        $courses = $this->findCoursesByUser(
+            $user,
+            $this->getSemesterFilter()
+        );
         list($offset, $limit) = $this->getOffsetAndLimit();
 
-        return $this->getPaginatedContentResponse(array_slice($courses, $offset, $limit), count($courses));
+        return $this->getPaginatedContentResponse(
+            array_slice($courses, $offset, $limit),
+            count($courses)
+        );
+    }
+
+    private function validateFilters()
+    {
+        $filtering = $this->getQueryParameters()->getFilteringParameters() ?: [];
+
+        // semester
+        if (isset($filtering['semester'])) {
+            if (!Semester::exists($filtering['semester'])) {
+                return 'Invalid "semester".';
+            }
+        }
+    }
+
+    private function getSemesterFilter(): ?Semester
+    {
+        $filtering = $this->getQueryParameters()->getFilteringParameters();
+
+        if (!isset($filtering['semester'])) {
+            return null;
+        }
+
+        return Semester::find($filtering['semester']);
     }
 
-    private function findCoursesByUser(\User $user)
+
+    /**
+     * @param User $user
+     * @param Semester|null $semester
+     *
+     * @return Course[]
+     */
+    private function findCoursesByUser(User $user, ?Semester $semester): array
     {
-        return \Course::findMany($user->course_memberships->pluck('seminar_id'), 'ORDER BY start_time, name');
+        $courses = Course::findMany(
+            $user->course_memberships->pluck('seminar_id'),
+            'ORDER BY start_time, name'
+        );
+
+        if ($semester) {
+            $courses = array_filter($courses, function (Course $course) use ($semester): bool {
+                return $course->isInSemester($semester);
+            });
+        }
+
+        return $courses;
     }
 }
-- 
GitLab