From 25b6bf055629d66b06b064a8cf09080f164e2c6d Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Tue, 14 Nov 2023 14:11:05 +0000
Subject: [PATCH] add faculty and sub-institutes relationship to institutes
 route, fixes #3458

Closes #3458

Merge request studip/studip!2359
---
 .../Routes/Institutes/InstitutesIndex.php     |  34 +++++-
 .../Routes/Institutes/InstitutesShow.php      |   2 +
 lib/classes/JsonApi/Schemas/Institute.php     | 105 +++++++++++++++---
 3 files changed, 124 insertions(+), 17 deletions(-)

diff --git a/lib/classes/JsonApi/Routes/Institutes/InstitutesIndex.php b/lib/classes/JsonApi/Routes/Institutes/InstitutesIndex.php
index d7ef8de3c67..6eef1b63ccd 100644
--- a/lib/classes/JsonApi/Routes/Institutes/InstitutesIndex.php
+++ b/lib/classes/JsonApi/Routes/Institutes/InstitutesIndex.php
@@ -10,17 +10,45 @@ use JsonApi\Schemas\Institute as InstituteSchema;
 class InstitutesIndex extends JsonApiController
 {
     protected $allowedIncludePaths = [
+        InstituteSchema::REL_FACULTY,
         InstituteSchema::REL_STATUS_GROUPS,
+        InstituteSchema::REL_SUB_INSTITUTES,
     ];
 
+    protected $allowedFilteringParameters = ['is-faculty'];
+
     protected $allowedPagingParameters = ['offset', 'limit'];
 
     public function __invoke(Request $request, Response $response, $args)
     {
-        list($offset, $limit) = $this->getOffsetAndLimit();
-        $institutes = \Institute::findBySql('1 ORDER BY Name LIMIT ? OFFSET ?', [$limit, $offset]);
-        $total = \Institute::countBySql();
+        [$offset, $limit] = $this->getOffsetAndLimit();
+
+        $filters = $this->getFilters();
+
+        if (!isset($filters['is-faculty'])) {
+            $condition = '1';
+        } elseif ($filters['is-faculty']) {
+            $condition = 'fakultaets_id = Institut_id';
+        } else {
+            $condition = 'fakultaets_id != Institut_id';
+        }
+
+        $institutes = \Institute::findBySql("{$condition} ORDER BY Name LIMIT ? OFFSET ?", [$limit, $offset]);
+        $total = \Institute::countBySql($condition);
 
         return $this->getPaginatedContentResponse($institutes, $total);
     }
+
+    private function getFilters()
+    {
+        $filtering = $this->getQueryParameters()->getFilteringParameters() ?? [];
+
+        $filters = [];
+
+        if (isset($filtering['is-faculty'])) {
+            $filters['is-faculty'] = (bool) $filtering['is-faculty'];
+        }
+
+        return $filters;
+    }
 }
diff --git a/lib/classes/JsonApi/Routes/Institutes/InstitutesShow.php b/lib/classes/JsonApi/Routes/Institutes/InstitutesShow.php
index 4847982c2d3..5ef3b5a8d02 100644
--- a/lib/classes/JsonApi/Routes/Institutes/InstitutesShow.php
+++ b/lib/classes/JsonApi/Routes/Institutes/InstitutesShow.php
@@ -15,7 +15,9 @@ use JsonApi\Schemas\Institute as InstituteSchema;
 class InstitutesShow extends JsonApiController
 {
     protected $allowedIncludePaths = [
+        InstituteSchema::REL_FACULTY,
         InstituteSchema::REL_STATUS_GROUPS,
+        InstituteSchema::REL_SUB_INSTITUTES,
     ];
 
     /**
diff --git a/lib/classes/JsonApi/Schemas/Institute.php b/lib/classes/JsonApi/Schemas/Institute.php
index c1775b1646d..13e061a2d11 100644
--- a/lib/classes/JsonApi/Schemas/Institute.php
+++ b/lib/classes/JsonApi/Schemas/Institute.php
@@ -10,48 +10,56 @@ class Institute extends SchemaProvider
     const TYPE = 'institutes';
 
     const REL_BLUBBER = 'blubber-threads';
+    const REL_FACULTY = 'faculty';
     const REL_FILES = 'file-refs';
     const REL_FOLDERS = 'folders';
     const REL_MEMBERSHIPS = 'memberships';
     const REL_STATUS_GROUPS = 'status-groups';
+    const REL_SUB_INSTITUTES = 'sub-institutes';
 
+    /**
+     * @param \Institute $institute
+     */
     public function getId($institute): ?string
     {
         return $institute->id;
     }
 
+    /**
+     * @param \Institute $institute
+     */
     public function getAttributes($institute, ContextInterface $context): iterable
     {
         return [
-            'name' => (string) $institute['Name'],
-            'city' => $institute['Plz'],
-            'street' => $institute['Strasse'],
-            'phone' => $institute['telefon'],
-            'fax' => $institute['fax'],
-            'url' => $institute['url'],
-            'mkdate' => date('c', $institute['mkdate']),
-            'chdate' => date('c', $institute['chdate']),
+            'name'       => (string) $institute->name,
+            'city'       => $institute->plz,
+            'street'     => $institute->strasse,
+            'phone'      => $institute->telefon,
+            'fax'        => $institute->fax,
+            'url'        => $institute->url,
+            'is-faculty' => $institute->is_fak,
+            'mkdate'     => date('c', $institute->mkdate),
+            'chdate'     => date('c', $institute->chdate),
         ];
     }
 
     /**
+     * @param \Institute $resource
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getRelationships($resource, ContextInterface $context): iterable
     {
         $relationships = [];
 
-        $filesLink = $this->getRelationshipRelatedLink($resource, self::REL_FILES);
         $relationships[self::REL_FILES] = [
             self::RELATIONSHIP_LINKS => [
-                Link::RELATED => $filesLink,
+                Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_FILES),
             ],
         ];
 
-        $foldersLink = $this->getRelationshipRelatedLink($resource, self::REL_FOLDERS);
         $relationships[self::REL_FOLDERS] = [
             self::RELATIONSHIP_LINKS => [
-                Link::RELATED => $foldersLink,
+                Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_FOLDERS),
             ],
         ];
 
@@ -73,6 +81,60 @@ class Institute extends SchemaProvider
             $this->shouldInclude($context, self::REL_STATUS_GROUPS)
         );
 
+        if (!$resource->is_fak) {
+            $relationships = $this->addFacultyRelationship(
+                $relationships,
+                $resource,
+                $this->shouldInclude($context, self::REL_FACULTY)
+            );
+        }
+
+        $relationships = $this->addSubInstitutesRelationship(
+            $relationships,
+            $resource,
+            $this->shouldInclude($context, self::REL_SUB_INSTITUTES)
+        );
+
+        return $relationships;
+    }
+
+    private function addFacultyRelationship(array $relationships, \Institute $resource, bool $includeData): array
+    {
+        $relation = [
+            self::RELATIONSHIP_LINKS => [
+                Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_FACULTY),
+            ],
+        ];
+
+        if ($includeData) {
+            $relation[self::RELATIONSHIP_DATA] = $resource->faculty;
+        } else {
+            $relation[self::RELATIONSHIP_DATA] = \Institute::build(['id' => $resource->faculty->id]);
+        }
+
+        $relationships[self::REL_FACULTY] = $relation;
+
+        return $relationships;
+    }
+
+    private function addSubInstitutesRelationship(array $relationships, \Institute $resource, bool $includeData): array
+    {
+        $relation = [
+            self::RELATIONSHIP_LINKS => [
+                Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_SUB_INSTITUTES),
+            ],
+        ];
+
+        if ($includeData) {
+            $relation[self::RELATIONSHIP_DATA] = $resource->sub_institutes;
+        } else {
+            $relation[self::RELATIONSHIP_DATA] = $resource->sub_institutes->map(function (\Institute $institute): \Institute {
+                return \Institute::build(['id' => $institute->id]);
+            });
+        }
+
+        $relationships[self::REL_SUB_INSTITUTES] = $relation;
+
         return $relationships;
     }
 
@@ -86,11 +148,26 @@ class Institute extends SchemaProvider
                 Link::RELATED => $this->getRelationshipRelatedLink($resource, self::REL_STATUS_GROUPS),
             ]
         ];
+
         if ($includeData) {
-            $related = $resource->status_groups;
-            $relation[self::RELATIONSHIP_DATA] = $related;
+            $relation[self::RELATIONSHIP_DATA] = $resource->status_groups;
         }
 
         return array_merge($relationships, [self::REL_STATUS_GROUPS => $relation]);
     }
+
+    public function hasResourceMeta($resource): bool
+    {
+        return true;
+    }
+
+    /**
+     * @param \Institute $resource
+     */
+    public function getResourceMeta($resource)
+    {
+        return [
+            'sub-institutes-count' => count($resource->sub_institutes),
+        ];
+    }
 }
-- 
GitLab