From 4b805849419f05202023fbeb0969a7d0834b4941 Mon Sep 17 00:00:00 2001
From: Tobias Gross-Vogt <tgros@tugraz.at>
Date: Tue, 15 Nov 2022 10:09:13 +0100
Subject: [PATCH] AbstractDataProvider update; new pagination handling

---
 composer.lock                                 | 20 ++------
 src/API/CourseProviderInterface.php           | 16 ++++---
 src/Controller/GetAttendeesByCourse.php       | 18 +++++--
 .../CourseCollectionDataProvider.php          | 47 -------------------
 src/DataProvider/CourseDataProvider.php       | 12 +----
 src/DataProvider/CourseItemDataProvider.php   | 40 ----------------
 src/Service/DummyCourseProvider.php           | 23 ++-------
 7 files changed, 35 insertions(+), 141 deletions(-)
 delete mode 100644 src/DataProvider/CourseCollectionDataProvider.php
 delete mode 100644 src/DataProvider/CourseItemDataProvider.php

diff --git a/composer.lock b/composer.lock
index 63298e5..75c0edf 100644
--- a/composer.lock
+++ b/composer.lock
@@ -169,17 +169,11 @@
         },
         {
             "name": "dbp/relay-core-bundle",
-            "version": "v0.1.55",
+            "version": "v0.1.56",
             "source": {
                 "type": "git",
-                "url": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle.git",
-                "reference": "b1d1eaa5e9efc58a09e6176215c243041df168f3"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://gitlab.tugraz.at/api/v4/projects/dbp%2Frelay%2Fdbp-relay-core-bundle/repository/archive.zip?sha=b1d1eaa5e9efc58a09e6176215c243041df168f3",
-                "reference": "b1d1eaa5e9efc58a09e6176215c243041df168f3",
-                "shasum": ""
+                "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-core-bundle.git",
+                "reference": "0183be15e0c582d935420fb558ea293ab6af1b8b"
             },
             "require": {
                 "api-platform/core": "^2.6.8 <2.7.0",
@@ -278,11 +272,7 @@
                 "AGPL-3.0-or-later"
             ],
             "description": "The core bundle of the Relay API gateway",
-            "support": {
-                "source": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle/-/tree/v0.1.55",
-                "issues": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle/-/issues"
-            },
-            "time": "2022-11-10T11:15:38+01:00"
+            "time": "2022-11-15T08:43:56+00:00"
         },
         {
             "name": "doctrine/annotations",
@@ -10088,5 +10078,5 @@
     "platform-overrides": {
         "php": "7.3"
     },
-    "plugin-api-version": "2.3.0"
+    "plugin-api-version": "2.2.0"
 }
diff --git a/src/API/CourseProviderInterface.php b/src/API/CourseProviderInterface.php
index b0c50e4..978b980 100644
--- a/src/API/CourseProviderInterface.php
+++ b/src/API/CourseProviderInterface.php
@@ -5,14 +5,14 @@ declare(strict_types=1);
 namespace Dbp\Relay\BaseCourseBundle\API;
 
 use Dbp\Relay\BaseCourseBundle\Entity\Course;
+use Dbp\Relay\BaseCourseBundle\Entity\CourseAttendee;
 use Dbp\Relay\CoreBundle\Exception\ApiError;
-use Dbp\Relay\CoreBundle\Pagination\Paginator;
 
 interface CourseProviderInterface
 {
     /**
      * @param array $options Available options:
-     *                       * 'lang' ('de' or 'en')
+     *                       * Locale::LANGUAGE_OPTION (language in ISO 639‑1 format)
      *                       * LocalData::INCLUDE_PARAMETER_NAME
      *
      * @throws ApiError
@@ -21,20 +21,24 @@ interface CourseProviderInterface
 
     /**
      * @param array $options Available options:
-     *                       * 'lang' ('de' or 'en')
+     *                       * Locale::LANGUAGE_OPTION (language in ISO 639‑1 format)
      *                       * Course::SEARCH_PARAMETER_NAME (partial, case-insensitive text search on 'name' attribute)
      *                       * LocalData::INCLUDE_PARAMETER_NAME
      *                       * LocalData::QUERY_PARAMETER_NAME
      *
+     * @return Course[]
+     *
      * @throws ApiError
      */
-    public function getCourses(array $options = []): Paginator;
+    public function getCourses(int $currentPageNumber, int $maxNumItemsPerPage, array $options = []): array;
 
     /**
      * @param array $options Available options:
-     *                       * 'lang' ('de' or 'en')
+     *                       * Locale::LANGUAGE_OPTION (language in ISO 639‑1 format)
+     *
+     * @return CourseAttendee[]
      *
      * @throws ApiError
      */
-    public function getAttendeesByCourse(string $courseId, array $options = []): Paginator;
+    public function getAttendeesByCourse(string $courseId, int $currentPageNumber, int $maxNumItemsPerPage, array $options = []): array;
 }
diff --git a/src/Controller/GetAttendeesByCourse.php b/src/Controller/GetAttendeesByCourse.php
index 6e1f02b..dd51ce1 100644
--- a/src/Controller/GetAttendeesByCourse.php
+++ b/src/Controller/GetAttendeesByCourse.php
@@ -5,8 +5,10 @@ declare(strict_types=1);
 namespace Dbp\Relay\BaseCourseBundle\Controller;
 
 use Dbp\Relay\BaseCourseBundle\API\CourseProviderInterface;
+use Dbp\Relay\CoreBundle\Locale\Locale;
 use Dbp\Relay\CoreBundle\Pagination\Pagination;
 use Dbp\Relay\CoreBundle\Pagination\Paginator;
+use Dbp\Relay\CoreBundle\Pagination\PartialPaginator;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -15,9 +17,13 @@ class GetAttendeesByCourse extends AbstractController
     /** @var CourseProviderInterface */
     private $coursesProvider;
 
-    public function __construct(CourseProviderInterface $coursesProvider)
+    /** @var Locale */
+    private $locale;
+
+    public function __construct(CourseProviderInterface $coursesProvider, Locale $locale)
     {
         $this->coursesProvider = $coursesProvider;
+        $this->locale = $locale;
     }
 
     public function __invoke(string $identifier, Request $request): Paginator
@@ -25,10 +31,14 @@ class GetAttendeesByCourse extends AbstractController
         $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
 
         $options = [];
-        $options['lang'] = $request->query->get('lang', 'de');
+        $options[Locale::LANGUAGE_OPTION] = $this->locale->getCurrentPrimaryLanguage();
 
-        Pagination::addOptions($options, $request->query->all());
+        $query = $request->query->all();
+        $currentPageNumber = Pagination::getCurrentPageNumber($query);
+        $maxNumItemsPerPage = Pagination::getMaxNumItemsPerPage($query);
 
-        return $this->coursesProvider->getAttendeesByCourse($identifier, $options);
+        return new PartialPaginator($this->coursesProvider->getAttendeesByCourse($identifier,
+            Pagination::getCurrentPageNumber($query), Pagination::getMaxNumItemsPerPage($query), $options),
+            $currentPageNumber, $maxNumItemsPerPage);
     }
 }
diff --git a/src/DataProvider/CourseCollectionDataProvider.php b/src/DataProvider/CourseCollectionDataProvider.php
deleted file mode 100644
index ee26089..0000000
--- a/src/DataProvider/CourseCollectionDataProvider.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Dbp\Relay\BaseCourseBundle\DataProvider;
-
-use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
-use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
-use Dbp\Relay\BaseCourseBundle\API\CourseProviderInterface;
-use Dbp\Relay\BaseCourseBundle\Entity\Course;
-use Dbp\Relay\CoreBundle\LocalData\LocalData;
-use Dbp\Relay\CoreBundle\Pagination\Pagination;
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-
-final class CourseCollectionDataProvider extends AbstractController implements CollectionDataProviderInterface, RestrictedDataProviderInterface
-{
-    /** @var CourseProviderInterface */
-    private $courseProvider;
-
-    public function __construct(CourseProviderInterface $courseProvider)
-    {
-        $this->courseProvider = $courseProvider;
-    }
-
-    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
-    {
-        return Course::class === $resourceClass;
-    }
-
-    public function getCollection(string $resourceClass, string $operationName = null, array $context = []): iterable
-    {
-        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
-
-        $filters = $context['filters'] ?? [];
-        $options = [];
-        $options['lang'] = $filters['lang'] ?? 'de';
-
-        if ($search = ($filters['search'] ?? null)) {
-            $options['search'] = $search;
-        }
-
-        LocalData::addOptions($options, $filters);
-        Pagination::addOptions($options, $filters);
-
-        return $this->courseProvider->getCourses($options);
-    }
-}
diff --git a/src/DataProvider/CourseDataProvider.php b/src/DataProvider/CourseDataProvider.php
index b15d5d9..b428b89 100644
--- a/src/DataProvider/CourseDataProvider.php
+++ b/src/DataProvider/CourseDataProvider.php
@@ -7,17 +7,14 @@ namespace Dbp\Relay\BaseCourseBundle\DataProvider;
 use Dbp\Relay\BaseCourseBundle\API\CourseProviderInterface;
 use Dbp\Relay\BaseCourseBundle\Entity\Course;
 use Dbp\Relay\CoreBundle\DataProvider\AbstractDataProvider;
-use Symfony\Component\HttpFoundation\RequestStack;
 
 class CourseDataProvider extends AbstractDataProvider
 {
     /** @var CourseProviderInterface */
     private $courseProvider;
 
-    public function __construct(CourseProviderInterface $courseProvider, RequestStack $requestStack)
+    public function __construct(CourseProviderInterface $courseProvider)
     {
-        parent::__construct($requestStack);
-
         $this->courseProvider = $courseProvider;
     }
 
@@ -37,11 +34,6 @@ class CourseDataProvider extends AbstractDataProvider
             $options['search'] = $search;
         }
 
-        // TODO: change getCourses to accept $currentPageNumber and $maxNumItemsPerPage as arguments and return page items as array
-        $options['page'] = $currentPageNumber;
-        $options['perPage'] = $maxNumItemsPerPage;
-        $options['partialPagination'] = true;
-
-        return $this->courseProvider->getCourses($options)->getItems();
+        return $this->courseProvider->getCourses($currentPageNumber, $maxNumItemsPerPage, $options);
     }
 }
diff --git a/src/DataProvider/CourseItemDataProvider.php b/src/DataProvider/CourseItemDataProvider.php
deleted file mode 100644
index 18378aa..0000000
--- a/src/DataProvider/CourseItemDataProvider.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Dbp\Relay\BaseCourseBundle\DataProvider;
-
-use ApiPlatform\Core\DataProvider\ItemDataProviderInterface;
-use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
-use Dbp\Relay\BaseCourseBundle\API\CourseProviderInterface;
-use Dbp\Relay\BaseCourseBundle\Entity\Course;
-use Dbp\Relay\CoreBundle\LocalData\LocalData;
-use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-
-final class CourseItemDataProvider extends AbstractController implements ItemDataProviderInterface, RestrictedDataProviderInterface
-{
-    private $api;
-
-    public function __construct(CourseProviderInterface $api)
-    {
-        $this->api = $api;
-    }
-
-    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
-    {
-        return Course::class === $resourceClass;
-    }
-
-    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?Course
-    {
-        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
-
-        $filters = $context['filters'] ?? [];
-        $options = [];
-
-        $options['lang'] = $filters['lang'] ?? 'de';
-        $options[LocalData::INCLUDE_PARAMETER_NAME] = LocalData::getIncludeParameter($filters);
-
-        return $this->api->getCourseById($id, $options);
-    }
-}
diff --git a/src/Service/DummyCourseProvider.php b/src/Service/DummyCourseProvider.php
index ac7ec3a..772e262 100644
--- a/src/Service/DummyCourseProvider.php
+++ b/src/Service/DummyCourseProvider.php
@@ -7,8 +7,6 @@ namespace Dbp\Relay\BaseCourseBundle\Service;
 use Dbp\Relay\BaseCourseBundle\API\CourseProviderInterface;
 use Dbp\Relay\BaseCourseBundle\Entity\Course;
 use Dbp\Relay\BaseCourseBundle\Entity\CourseAttendee;
-use Dbp\Relay\CoreBundle\Pagination\FullPaginator;
-use Dbp\Relay\CoreBundle\Pagination\Paginator;
 
 class DummyCourseProvider implements CourseProviderInterface
 {
@@ -21,20 +19,12 @@ class DummyCourseProvider implements CourseProviderInterface
         return $course;
     }
 
-    public function getCourses(array $options = []): Paginator
+    public function getCourses(int $currentPageNumber, int $maxNumItemsPerPage, array $options = []): array
     {
-        $courses = [];
-        $courses[] = $this->getCourseById('123', $options);
-
-        return new FullPaginator($courses, 1, count($courses), count($courses));
-    }
-
-    public function getCoursesByOrganization(string $orgUnitId, array $options = []): Paginator
-    {
-        return $this->getCourses($options);
+        return [$this->getCourseById('123', $options)];
     }
 
-    public function getAttendeesByCourse(string $courseId, array $options = []): Paginator
+    public function getAttendeesByCourse(string $courseId, int $currentPageNumber, int $maxNumItemsPerPage, array $options = []): array
     {
         $attendee = new CourseAttendee();
         $attendee->setIdentifier('aeinstein');
@@ -42,11 +32,6 @@ class DummyCourseProvider implements CourseProviderInterface
         $attendee->setFamilyName('Einstein');
         $attendee->setEmail('info@einstein.com');
 
-        return new FullPaginator($attendees = [$attendee], 1, count($attendees), count($attendees));
-    }
-
-    public function getCoursesByLecturer(string $lecturerId, array $options = []): Paginator
-    {
-        return $this->getCourses($options);
+        return [$attendee];
     }
 }
-- 
GitLab