From adbde112d8ccdafa42543c7014e66af43fe08dfe Mon Sep 17 00:00:00 2001
From: Tobias Gross-Vogt <tgros@tugraz.at>
Date: Sun, 17 Apr 2022 21:07:46 +0200
Subject: [PATCH] local data mechanism for course entity

---
 composer.json                                 |  8 +-
 composer.lock                                 | 89 ++++++++++++++-----
 .../CourseCollectionDataProvider.php          |  8 +-
 src/DataProvider/CourseItemDataProvider.php   | 11 +--
 src/Entity/Course.php                         | 11 ++-
 src/Entity/CourseInterface.php                |  4 -
 src/Entity/CourseTrait.php                    | 56 ------------
 src/Service/DummyCourseProvider.php           |  1 -
 8 files changed, 83 insertions(+), 105 deletions(-)

diff --git a/composer.json b/composer.json
index a7f6370..6224fc9 100644
--- a/composer.json
+++ b/composer.json
@@ -6,8 +6,8 @@
         "php": ">=7.3",
         "ext-json": "*",
         "api-platform/core": "^2.6",
-        "dbp/relay-base-person-bundle": "^0.2.0",
-        "dbp/relay-core-bundle": "^0.1.11",
+        "dbp/relay-base-person-bundle": "dev-main as 0.2.0",
+        "dbp/relay-core-bundle": "dev-main as 0.1.32",
         "symfony/config": "^5.4",
         "symfony/framework-bundle": "^5.4",
         "symfony/security-bundle": "^5.4",
@@ -31,6 +31,10 @@
         {
             "type": "vcs",
             "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-base-person-bundle.git"
+        },
+        {
+            "type": "vcs",
+            "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-core-bundle.git"
         }
     ],
     "autoload": {
diff --git a/composer.lock b/composer.lock
index 247a7cc..d70fa81 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "b2b79dd11f5249d0da83a212ed0860e1",
+    "content-hash": "61364976a44315d6eb550031d0646c4b",
     "packages": [
         {
             "name": "api-platform/core",
@@ -169,17 +169,11 @@
         },
         {
             "name": "dbp/relay-base-person-bundle",
-            "version": "v0.2.0",
+            "version": "dev-main",
             "source": {
                 "type": "git",
-                "url": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-base-person-bundle.git",
-                "reference": "9793a5e69a4a4b4ae76f0eacc1510ad33e5ec1a3"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://gitlab.tugraz.at/api/v4/projects/dbp%2Frelay%2Fdbp-relay-base-person-bundle/repository/archive.zip?sha=9793a5e69a4a4b4ae76f0eacc1510ad33e5ec1a3",
-                "reference": "9793a5e69a4a4b4ae76f0eacc1510ad33e5ec1a3",
-                "shasum": ""
+                "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-base-person-bundle.git",
+                "reference": "2f5f6dc3ca4adebdcb0838845e11cbe283f07204"
             },
             "require": {
                 "api-platform/core": "^2.6.3",
@@ -210,6 +204,7 @@
                 "symfony/phpunit-bridge": "^5.2",
                 "vimeo/psalm": "^4.4"
             },
+            "default-branch": true,
             "type": "symfony-bundle",
             "autoload": {
                 "psr-4": {
@@ -249,19 +244,15 @@
             "license": [
                 "AGPL-3.0-or-later"
             ],
-            "support": {
-                "source": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-base-person-bundle/-/tree/v0.2.0",
-                "issues": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-base-person-bundle/-/issues"
-            },
-            "time": "2022-03-23T10:31:04+01:00"
+            "time": "2022-04-16T00:28:26+00:00"
         },
         {
             "name": "dbp/relay-core-bundle",
-            "version": "v0.1.32",
+            "version": "dev-main",
             "source": {
                 "type": "git",
-                "url": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-core-bundle",
-                "reference": "b7b60c7505b42a042dac8869b3e837d73fb9da5e"
+                "url": "git@gitlab.tugraz.at:dbp/relay/dbp-relay-core-bundle.git",
+                "reference": "ad6f2efb52a6dc3c8ee730bc4652a6486e5dd539"
             },
             "require": {
                 "api-platform/core": "^2.6.6",
@@ -303,6 +294,7 @@
                 "symfony/phpunit-bridge": "^5.3",
                 "vimeo/psalm": "^4.4"
             },
+            "default-branch": true,
             "type": "symfony-bundle",
             "extra": {
                 "hooks": {
@@ -316,12 +308,47 @@
                     "Dbp\\Relay\\CoreBundle\\": "src/"
                 }
             },
-            "notification-url": "https://packagist.org/downloads/",
+            "autoload-dev": {
+                "psr-4": {
+                    "Dbp\\Relay\\CoreBundle\\Tests\\": "tests/"
+                }
+            },
+            "scripts": {
+                "post-install-cmd": [
+                    "cghooks add --ignore-lock"
+                ],
+                "post-update-cmd": [
+                    "cghooks update"
+                ],
+                "test": [
+                    "@php vendor/bin/phpunit"
+                ],
+                "phpstan": [
+                    "@php vendor/bin/phpstan analyze --ansi"
+                ],
+                "psalm": [
+                    "@php vendor/bin/psalm"
+                ],
+                "lint": [
+                    "@composer run cs",
+                    "@composer run phpstan",
+                    "@composer run psalm"
+                ],
+                "cs-fix": [
+                    "@php vendor/bin/php-cs-fixer --ansi fix"
+                ],
+                "cs": [
+                    "@php vendor/bin/php-cs-fixer --ansi fix --dry-run --diff"
+                ],
+                "coverage": [
+                    "@php -dxdebug.mode=coverage vendor/bin/phpunit --coverage-html _coverage"
+                ]
+            },
             "license": [
                 "AGPL-3.0-or-later"
             ],
             "description": "The core bundle of the Relay API gateway",
-            "time": "2022-02-15T09:59:16+00:00"
+            "time": "2022-04-17T00:15:35+00:00"
         },
         {
             "name": "doctrine/annotations",
@@ -10079,9 +10106,25 @@
             "time": "2015-12-17T08:42:14+00:00"
         }
     ],
-    "aliases": [],
+    "aliases": [
+        {
+            "package": "dbp/relay-base-person-bundle",
+            "version": "dev-main",
+            "alias": "0.2.0",
+            "alias_normalized": "0.2.0.0"
+        },
+        {
+            "package": "dbp/relay-core-bundle",
+            "version": "dev-main",
+            "alias": "0.1.32",
+            "alias_normalized": "0.1.32.0"
+        }
+    ],
     "minimum-stability": "stable",
-    "stability-flags": [],
+    "stability-flags": {
+        "dbp/relay-base-person-bundle": 20,
+        "dbp/relay-core-bundle": 20
+    },
     "prefer-stable": false,
     "prefer-lowest": false,
     "platform": {
@@ -10092,5 +10135,5 @@
     "platform-overrides": {
         "php": "7.3"
     },
-    "plugin-api-version": "2.3.0"
+    "plugin-api-version": "2.2.0"
 }
diff --git a/src/DataProvider/CourseCollectionDataProvider.php b/src/DataProvider/CourseCollectionDataProvider.php
index 62f0d34..1c631d8 100644
--- a/src/DataProvider/CourseCollectionDataProvider.php
+++ b/src/DataProvider/CourseCollectionDataProvider.php
@@ -8,10 +8,8 @@ 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\Exception\ApiError;
 use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-use Symfony\Component\HttpFoundation\Response;
 
 final class CourseCollectionDataProvider extends AbstractController implements CollectionDataProviderInterface, RestrictedDataProviderInterface
 {
@@ -41,11 +39,7 @@ final class CourseCollectionDataProvider extends AbstractController implements C
         }
 
         if ($include = ($filters['include'] ?? null)) {
-            if ($include === 'localData') {
-                $options['includeLocalData'] = true;
-            } else {
-                throw new ApiError(Response::HTTP_BAD_REQUEST, 'requested inclusion of unknown resource '.$include);
-            }
+            $options['include'] = $include;
         }
 
         $organizationId = $filters['organization'] ?? null;
diff --git a/src/DataProvider/CourseItemDataProvider.php b/src/DataProvider/CourseItemDataProvider.php
index 7d51ffa..a5a9fc2 100644
--- a/src/DataProvider/CourseItemDataProvider.php
+++ b/src/DataProvider/CourseItemDataProvider.php
@@ -8,9 +8,7 @@ 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\Exception\ApiError;
 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-use Symfony\Component\HttpFoundation\Response;
 
 final class CourseItemDataProvider extends AbstractController implements ItemDataProviderInterface, RestrictedDataProviderInterface
 {
@@ -30,16 +28,13 @@ final class CourseItemDataProvider extends AbstractController implements ItemDat
     {
         $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
 
-        $options = [];
         $filters = $context['filters'] ?? [];
+        $options = [];
+
         $options['lang'] = $filters['lang'] ?? 'de';
 
         if ($include = ($filters['include'] ?? null)) {
-            if ($include === 'localData') {
-                $options['includeLocalData'] = true;
-            } else {
-                throw new ApiError(Response::HTTP_BAD_REQUEST, 'requested inclusion of unknown resource '.$include);
-            }
+            $options['include'] = $include;
         }
 
         return $this->api->getCourseById($id, $options);
diff --git a/src/Entity/Course.php b/src/Entity/Course.php
index dd5f8ca..afeaba5 100644
--- a/src/Entity/Course.php
+++ b/src/Entity/Course.php
@@ -5,6 +5,8 @@ declare(strict_types=1);
 namespace Dbp\Relay\BaseCourseBundle\Entity;
 
 use ApiPlatform\Core\Annotation\ApiResource;
+use Dbp\Relay\CoreBundle\Entity\LocalDataAwareInterface;
+use Dbp\Relay\CoreBundle\Entity\LocalDataAwareTrait;
 use Symfony\Component\Serializer\Annotation\Groups;
 
 /**
@@ -19,7 +21,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
  *                     {"name" = "term", "in" = "query", "description" = "Teaching term", "type" = "string", "enum" = {"W", "S"}, "example" = "W"},
  *                     {"name" = "organization", "in" = "query", "description" = "Get courses of an organization (ID of BaseOrganization resource)", "required" = false, "type" = "string", "example" = "1190"},
  *                     {"name" = "lecturer", "in" = "query", "description" = "Get courses of a lecturer", "required" = false, "type" = "string", "example" = "woody007"},
- *                     {"name" = "include", "in" = "query", "description" = "Optional resources to include", "type" = "string", "example" = "localData"}
+ *                     {"name" = "include", "in" = "query", "description" = "Optional resources to include", "type" = "string", "example" = "BaseCourse.code,BaseCourse.numberOfCredits"}
  *                 }
  *             }
  *         }
@@ -32,17 +34,18 @@ use Symfony\Component\Serializer\Annotation\Groups;
  *                 "parameters" = {
  *                     {"name" = "identifier", "in" = "path", "description" = "Resource identifier", "required" = true, "type" = "string", "example" = "257571"},
  *                     {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"},
- *                     {"name" = "include", "in" = "query", "description" = "Optional resources to include", "type" = "string", "example" = "localData"}
+ *                     {"name" = "include", "in" = "query", "description" = "Optional resources to include", "type" = "string", "example" = "BaseCourse.code,BaseCourse.numberOfCredits"}
  *                 }
  *             }
  *         }
  *     },
  *     shortName="BaseCourse",
  *     iri="https://schema.org/Course",
- *     normalizationContext={"groups" = {"BaseCourse:output"}, "jsonld_embed_context" = true},
+ *     normalizationContext={"groups" = {"BaseCourse:output", "LocalData:output"}, "jsonld_embed_context" = true},
  * )
  */
-class Course implements CourseInterface
+class Course implements CourseInterface, LocalDataAwareInterface
 {
+    use LocalDataAwareTrait;
     use CourseTrait;
 }
diff --git a/src/Entity/CourseInterface.php b/src/Entity/CourseInterface.php
index a438edc..57b491f 100644
--- a/src/Entity/CourseInterface.php
+++ b/src/Entity/CourseInterface.php
@@ -17,8 +17,4 @@ interface CourseInterface
     public function getType(): string;
 
     public function setType(string $type): void;
-
-    public function getDescription(): string;
-
-    public function setDescription(string $description): void;
 }
diff --git a/src/Entity/CourseTrait.php b/src/Entity/CourseTrait.php
index 32193d5..76c6211 100644
--- a/src/Entity/CourseTrait.php
+++ b/src/Entity/CourseTrait.php
@@ -6,7 +6,6 @@ namespace Dbp\Relay\BaseCourseBundle\Entity;
 
 use ApiPlatform\Core\Annotation\ApiProperty;
 use Symfony\Component\Serializer\Annotation\Groups;
-use Symfony\Component\Serializer\Annotation\Ignore;
 
 trait CourseTrait
 {
@@ -31,22 +30,6 @@ trait CourseTrait
      */
     private $type;
 
-    /**
-     * @ApiProperty(iri="https://schema.org/description")
-     * @Groups({"BaseCourse:output"})
-     *
-     * @var string
-     */
-    private $description;
-
-    /**
-     * @ApiProperty(iri="https://schema.org/additionalProperty")
-     * @Groups({"BaseCourse:output"})
-     *
-     * @var array
-     */
-    private $localData;
-
     public function getIdentifier(): string
     {
         return $this->identifier;
@@ -76,43 +59,4 @@ trait CourseTrait
     {
         $this->type = $type;
     }
-
-    public function getDescription(): string
-    {
-        return $this->description;
-    }
-
-    public function setDescription(string $description): void
-    {
-        $this->description = $description;
-    }
-
-    public function getLocalData(): array
-    {
-        return $this->localData;
-    }
-
-    /**
-     * Allows attaching local data to a Course object.
-     *
-     * @param ?mixed $value
-     */
-    public function setLocalDataValue(string $key, $value): void
-    {
-        if (!$this->localData) {
-            $this->localData = [];
-        }
-        $this->localData[$key] = $value;
-    }
-
-    /**
-     * @Ignore
-     * Gets local data from a Course object.
-     *
-     * @return ?mixed
-     */
-    public function getLocalDataValue(string $key)
-    {
-        return $this->localData ? ($this->localData[$key] ?? null) : null;
-    }
 }
diff --git a/src/Service/DummyCourseProvider.php b/src/Service/DummyCourseProvider.php
index 80d4b0b..939f17c 100644
--- a/src/Service/DummyCourseProvider.php
+++ b/src/Service/DummyCourseProvider.php
@@ -15,7 +15,6 @@ class DummyCourseProvider implements CourseProviderInterface
         $course = new Course();
         $course->setIdentifier($identifier);
         $course->setName('Field Theory');
-        $course->setDescription('News from field theory');
 
         return $course;
     }
-- 
GitLab