diff --git a/composer.json b/composer.json index 94f6ceb46f4d10459a533175c84eb8e9b87182bd..1a88b5456621d482dbfa67ddb2ad5ddd4343f37e 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "php": ">=7.3", "ext-json": "*", "api-platform/core": "^2.6", + "dbp/relay-base-person-bundle": "dev-main", "dbp/relay-core-bundle": "^0.1.11", "symfony/framework-bundle": "^5.4" }, @@ -34,6 +35,9 @@ "sort-packages": true, "platform": { "php": "7.3" + }, + "allow-plugins": { + "composer/package-versions-deprecated": true } }, "scripts": { diff --git a/composer.lock b/composer.lock index aa8268bcf82504d8e1b50811a5f48fa68aeeaeb2..158c78adf0959ea6c5c7a2431f3ef8d131e83cd5 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": "db61c2249bc8c4ee921893e623472e9a", + "content-hash": "c6de62624b6c871ceea7cd39f50c97b9", "packages": [ { "name": "api-platform/core", @@ -167,6 +167,56 @@ ], "time": "2022-01-11T10:29:54+00:00" }, + { + "name": "dbp/relay-base-person-bundle", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://gitlab.tugraz.at/dbp/relay/dbp-relay-base-person-bundle", + "reference": "a7e3c201348fe70841d7e7c031e7a5ca8a007a54" + }, + "require": { + "api-platform/core": "^2.6.3", + "dbp/relay-core-bundle": "^0.1.25", + "ext-json": "*", + "guzzlehttp/guzzle": "^7.0", + "nelmio/cors-bundle": "^2.1.0", + "php": ">=7.3", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", + "symfony/config": "^5.2", + "symfony/expression-language": "^5.2", + "symfony/framework-bundle": "^5.2", + "symfony/security-bundle": "^5.2", + "symfony/security-core": "^5.2", + "symfony/security-guard": "^5.2", + "symfony/twig-bundle": "^5.2", + "symfony/validator": "^5.2", + "symfony/yaml": "^5.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.0", + "phpstan/phpstan": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpunit/phpunit": "^9", + "symfony/browser-kit": "^5.2", + "symfony/http-client": "^5.2", + "symfony/monolog-bundle": "^3.7", + "symfony/phpunit-bridge": "^5.2", + "vimeo/psalm": "^4.4" + }, + "default-branch": true, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Dbp\\Relay\\BasePersonBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "time": "2022-01-31T11:47:53+00:00" + }, { "name": "dbp/relay-core-bundle", "version": "v0.1.30", @@ -9917,7 +9967,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "dbp/relay-base-person-bundle": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/phpstan.neon b/phpstan.neon index cf03a393954915c79150e1faf19b259a24902341..201f2e7236db14245641ea951ed2f2e3574cd06a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -6,6 +6,4 @@ parameters: level: 3 paths: - src - ignoreErrors: - - message: '#.*NodeDefinition::children.*#' - path: ./src/DependencyInjection + diff --git a/src/API/CourseProviderInterface.php b/src/API/CourseProviderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..a5fc072bf64c5ba8e81377e1bdac1ec347321ad3 --- /dev/null +++ b/src/API/CourseProviderInterface.php @@ -0,0 +1,39 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\API; + +use Dbp\Relay\BasePersonBundle\Entity\Person; +use Dbp\Relay\CourseBundle\Entity\Course; +use Dbp\Relay\CourseBundle\Entity\Exam; + +interface CourseProviderInterface +{ + public function getCourseById(string $identifier, array $options = []): ?Course; + + /** + * @return Course[] + */ + public function getCourses(array $options = []): array; + + /** + * @return Course[] + */ + public function getCoursesByOrganization(string $orgUnitId, array $options = []): array; + + /** + * @return Course[] + */ + public function getCoursesByPerson(string $personId, array $options = []): array; + + /** + * @return Person[] + */ + public function getStudentsByCourse(string $courseId, array $options = []): array; + + /** + * @return Exam[] + */ + public function getExamsByCourse(string $courseId, array $options = []): array; +} diff --git a/src/Command/TestCommand.php b/src/Command/TestCommand.php deleted file mode 100644 index ae5c64ba9b06953254aaea4b5b04bb909dea6ea2..0000000000000000000000000000000000000000 --- a/src/Command/TestCommand.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class TestCommand extends Command -{ - protected static $defaultName = 'dbp:my-custom-command'; - - public function __construct() - { - parent::__construct(); - } - - protected function configure() - { - $this->addArgument('argument', InputArgument::REQUIRED, 'Example.'); - $this->setDescription('Hey there!'); - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $argument = $input->getArgument('argument'); - $output->writeln($argument); - - return 0; - } -} diff --git a/src/Controller/GetCoursesByOrganization.php b/src/Controller/GetCoursesByOrganization.php new file mode 100644 index 0000000000000000000000000000000000000000..4b33c0ee2daae3d53ae885f683cb496df6033279 --- /dev/null +++ b/src/Controller/GetCoursesByOrganization.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Controller; + +use ApiPlatform\Core\DataProvider\PaginatorInterface; +use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; + +class GetCoursesByOrganization extends AbstractController +{ + public const ITEMS_PER_PAGE = 250; + + protected $coursesProvider; + + public function __construct(CourseProviderInterface $coursesProvider) + { + $this->coursesProvider = $coursesProvider; + } + + public function __invoke(string $id, Request $request): PaginatorInterface + { + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); + + $page = (int) $request->query->get('page', 1); + $perPage = (int) $request->query->get('perPage', self::ITEMS_PER_PAGE); + + $options = []; + if ($request->query->has('lang')) { + $options['lang'] = (string) $request->query->get('lang'); + } + + $courses = $this->coursesProvider->getCoursesByOrganization($id, $options); + + return new ArrayFullPaginator($courses, $page, $perPage); + } +} diff --git a/src/Controller/GetCoursesByPerson.php b/src/Controller/GetCoursesByPerson.php new file mode 100644 index 0000000000000000000000000000000000000000..b5c13ab6438b034e2feb61b51f2d64d2e40446e9 --- /dev/null +++ b/src/Controller/GetCoursesByPerson.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Controller; + +use ApiPlatform\Core\DataProvider\PaginatorInterface; +use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; + +class GetCoursesByPerson extends AbstractController +{ + public const ITEMS_PER_PAGE = 250; + + protected $coursesProvider; + + public function __construct(CourseProviderInterface $coursesProvider) + { + $this->coursesProvider = $coursesProvider; + } + + public function __invoke(string $id, Request $request): PaginatorInterface + { + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); + + $page = (int) $request->query->get('page', 1); + $perPage = (int) $request->query->get('perPage', self::ITEMS_PER_PAGE); + + $options = []; + if ($request->query->has('lang')) { + $options['lang'] = (string) $request->query->get('lang'); + } + + $courses = $this->coursesProvider->getCoursesByPerson($id, $options); + + return new ArrayFullPaginator($courses, $page, $perPage); + } +} diff --git a/src/Controller/GetExamsByCourse.php b/src/Controller/GetExamsByCourse.php new file mode 100644 index 0000000000000000000000000000000000000000..ee2413e802002cad21b7c2ff1e60e3600b24541e --- /dev/null +++ b/src/Controller/GetExamsByCourse.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Controller; + +use ApiPlatform\Core\DataProvider\PaginatorInterface; +use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; + +class GetExamsByCourse extends AbstractController +{ + public const ITEMS_PER_PAGE = 250; + + protected $coursesProvider; + + public function __construct(CourseProviderInterface $coursesProvider) + { + $this->coursesProvider = $coursesProvider; + } + + public function __invoke(string $id, Request $request): PaginatorInterface + { + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); + + $page = (int) $request->query->get('page', 1); + $perPage = (int) $request->query->get('perPage', self::ITEMS_PER_PAGE); + + $options = []; + if ($request->query->has('lang')) { + $options['lang'] = (string) $request->query->get('lang'); + } + + $courses = $this->coursesProvider->getExamsByCourse($id, $options); + + return new ArrayFullPaginator($courses, $page, $perPage); + } +} diff --git a/src/Controller/GetStudentsByCourse.php b/src/Controller/GetStudentsByCourse.php new file mode 100644 index 0000000000000000000000000000000000000000..827e1cfa61d8345423140170f6966f0350e59120 --- /dev/null +++ b/src/Controller/GetStudentsByCourse.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Controller; + +use ApiPlatform\Core\DataProvider\PaginatorInterface; +use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; + +class GetStudentsByCourse extends AbstractController +{ + public const ITEMS_PER_PAGE = 250; + + protected $coursesProvider; + + public function __construct(CourseProviderInterface $coursesProvider) + { + $this->coursesProvider = $coursesProvider; + } + + public function __invoke(string $id, Request $request): PaginatorInterface + { + $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); + + $page = (int) $request->query->get('page', 1); + $perPage = (int) $request->query->get('perPage', self::ITEMS_PER_PAGE); + + $options = []; + if ($request->query->has('lang')) { + $options['lang'] = (string) $request->query->get('lang'); + } + + $courses = $this->coursesProvider->getStudentsByCourse($id, $options); + + return new ArrayFullPaginator($courses, $page, $perPage); + } +} diff --git a/src/Controller/LoggedInOnly.php b/src/Controller/LoggedInOnly.php deleted file mode 100644 index 8acbb043717dfd749898aa9af7a6044a19d091b1..0000000000000000000000000000000000000000 --- a/src/Controller/LoggedInOnly.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\Controller; - -use Dbp\Relay\CourseBundle\Entity\Course; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\Request; - -class LoggedInOnly extends AbstractController -{ - public function __invoke(Course $data, Request $request): Course - { - $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY'); - - return $data; - } -} diff --git a/src/DataPersister/CourseDataPersister.php b/src/DataPersister/CourseDataPersister.php deleted file mode 100644 index d44682f8aec520f9c16238ff72a0115cd09756de..0000000000000000000000000000000000000000 --- a/src/DataPersister/CourseDataPersister.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\DataPersister; - -use ApiPlatform\Core\DataPersister\DataPersisterInterface; -use Dbp\Relay\CourseBundle\Entity\Course; -use Dbp\Relay\CourseBundle\Service\CourseProviderInterface; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; - -class CourseDataPersister extends AbstractController implements DataPersisterInterface -{ - private $api; - - public function __construct(CourseProviderInterface $api) - { - $this->api = $api; - } - - public function supports($data): bool - { - return $data instanceof Course; - } - - public function persist($data): void - { - // TODO - } - - public function remove($data) - { - // TODO - } -} diff --git a/src/DataProvider/CourseCollectionDataProvider.php b/src/DataProvider/CourseCollectionDataProvider.php index 7bb9ec49eea4efd781de2e55d119049ade566b07..5e55ecad7447de4e4e6b3e399f03ce0c3ff8ceb4 100644 --- a/src/DataProvider/CourseCollectionDataProvider.php +++ b/src/DataProvider/CourseCollectionDataProvider.php @@ -7,8 +7,8 @@ namespace Dbp\Relay\CourseBundle\DataProvider; use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; use Dbp\Relay\CoreBundle\Helpers\ArrayFullPaginator; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; use Dbp\Relay\CourseBundle\Entity\Course; -use Dbp\Relay\CourseBundle\Service\CourseProviderInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; final class CourseCollectionDataProvider extends AbstractController implements CollectionDataProviderInterface, RestrictedDataProviderInterface diff --git a/src/DataProvider/CourseItemDataProvider.php b/src/DataProvider/CourseItemDataProvider.php index 1d70f414777cb1556a7b9654a97aaca152660e6d..066fae77c81da0c6c9f5e1de2fef3591c126de90 100644 --- a/src/DataProvider/CourseItemDataProvider.php +++ b/src/DataProvider/CourseItemDataProvider.php @@ -6,8 +6,8 @@ namespace Dbp\Relay\CourseBundle\DataProvider; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; use Dbp\Relay\CourseBundle\Entity\Course; -use Dbp\Relay\CourseBundle\Service\CourseProviderInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; final class CourseItemDataProvider extends AbstractController implements ItemDataProviderInterface, RestrictedDataProviderInterface diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 2c56a090b499a7197d7c9e2552046a2d980aa233..ea3012b0edcacadaf75a66224d7f6198b2052c58 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -11,15 +11,6 @@ class Configuration implements ConfigurationInterface { public function getConfigTreeBuilder(): TreeBuilder { - $treeBuilder = new TreeBuilder('dbp_relay_course'); - - $treeBuilder->getRootNode() - ->children() - ->scalarNode('example_config') - ->defaultValue('42') - ->end() - ->end(); - - return $treeBuilder; + return new TreeBuilder('dbp_relay_course'); } } diff --git a/src/DependencyInjection/DbpRelayCourseExtension.php b/src/DependencyInjection/DbpRelayCourseExtension.php index d0e4d6aca31bb0dfb4d7ad15809f6a410af30800..36b695836f042acbed9bebfcbcac80191e4e3921 100644 --- a/src/DependencyInjection/DbpRelayCourseExtension.php +++ b/src/DependencyInjection/DbpRelayCourseExtension.php @@ -21,10 +21,6 @@ class DbpRelayCourseExtension extends ConfigurableExtension new FileLocator(__DIR__.'/../Resources/config') ); $loader->load('services.yaml'); - - // Inject the config value into the MyCustomService service - $definition = $container->getDefinition('Dbp\Relay\CourseBundle\Service\MyCustomService'); - $definition->addArgument($mergedConfig['example_config']); } private function extendArrayParameter(ContainerBuilder $container, string $parameter, array $values) diff --git a/src/Entity/Course.php b/src/Entity/Course.php index 468686dac78689daba529f211c562d3a5da3d0bf..4d018ad732cba84d1a84f2e7ffe17708a2ecc076 100644 --- a/src/Entity/Course.php +++ b/src/Entity/Course.php @@ -6,59 +6,61 @@ namespace Dbp\Relay\CourseBundle\Entity; use ApiPlatform\Core\Annotation\ApiProperty; use ApiPlatform\Core\Annotation\ApiResource; -use Dbp\Relay\CourseBundle\Controller\LoggedInOnly; use Symfony\Component\Serializer\Annotation\Groups; /** * @ApiResource( * collectionOperations={ * "get" = { - * "path" = "/course/courses", * "openapi_context" = { - * "tags" = {"Course API"}, - * }, - * } - * }, - * itemOperations={ - * "get" = { - * "path" = "/course/courses/{identifier}", - * "openapi_context" = { - * "tags" = {"Course API"}, - * }, + * "tags" = {"Courses"}, + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"} + * } + * } * }, - * "put" = { - * "path" = "/course/courses/{identifier}", + * "get_byorganization" = { + * "method" = "GET", + * "path" = "/base/organizations/{id}/courses", + * "controller" = GetCoursesByOrganization::class, + * "read" = false, * "openapi_context" = { - * "tags" = {"Course API"}, + * "tags" = {"Courses"}, + * "summary" = "Get the Courses related to an organization.", + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"}, + * {"name" = "id", "in" = "path", "description" = "Id of Organization", "required" = true, "type" = "string", "example" = "123456"} + * } * }, * }, - * "delete" = { - * "path" = "/course/courses/{identifier}", + * "get_byperson" = { + * "method" = "GET", + * "path" = "/base/people/{id}/courses", + * "controller" = GetCoursesByPerson::class, + * "read" = false, * "openapi_context" = { - * "tags" = {"Course API"}, + * "tags" = {"Courses"}, + * "summary" = "Get the Courses related to a person.", + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"}, + * {"name" = "id", "in" = "path", "description" = "Id of Organization", "required" = true, "type" = "string", "example" = "123456"} + * } * }, * }, - * "loggedin_only" = { - * "security" = "is_granted('IS_AUTHENTICATED_FULLY')", - * "method" = "GET", - * "path" = "/course/courses/{identifier}/loggedin-only", - * "controller" = LoggedInOnly::class, + * }, + * itemOperations={ + * "get" = { * "openapi_context" = { - * "summary" = "Only works when logged in.", - * "tags" = {"Course API"}, - * }, + * "tags" = {"Courses"}, + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"} + * } + * } * } * }, * iri="https://schema.org/Course", - * shortName="CourseCourse", - * normalizationContext={ - * "groups" = {"CourseCourse:output"}, - * "jsonld_embed_context" = true - * }, - * denormalizationContext={ - * "groups" = {"CourseCourse:input"}, - * "jsonld_embed_context" = true - * } + * normalizationContext={"groups" = {"Course:output"}, "jsonld_embed_context" = true}, + * denormalizationContext={"groups" = {"Course:input"}, "jsonld_embed_context" = true} * ) */ class Course @@ -70,12 +72,38 @@ class Course /** * @ApiProperty(iri="https://schema.org/name") - * @Groups({"CourseCourse:output", "CourseCourse:input"}) + * @Groups({"Course:output"}) * * @var string */ private $name; + /** + * @ApiProperty + * @Groups({"Course:output"}) + * + * @var string + */ + private $type; + + /** + * @ApiProperty(iri="https://schema.org/description") + * @Groups({"Course:output"}) + * + * @var string + */ + private $description; + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function setIdentifier(string $identifier): void + { + $this->identifier = $identifier; + } + public function getName(): string { return $this->name; @@ -86,13 +114,23 @@ class Course $this->name = $name; } - public function getIdentifier(): string + public function getType(): string { - return $this->identifier; + return $this->type; } - public function setIdentifier(string $identifier): void + public function setType(string $type): void { - $this->identifier = $identifier; + $this->type = $type; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): void + { + $this->description = $description; } } diff --git a/src/Entity/CourseAttendee.php b/src/Entity/CourseAttendee.php new file mode 100644 index 0000000000000000000000000000000000000000..6b375661fc25c25ad176e45d7baf41b9b0a0d6fd --- /dev/null +++ b/src/Entity/CourseAttendee.php @@ -0,0 +1,37 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Entity; + +use ApiPlatform\Core\Annotation\ApiResource; +use Dbp\Relay\BasePersonBundle\Entity\PersonTrait; + +/** + * @ApiResource( + * collectionOperations={ + * "get_bycourse" = { + * "method" = "GET", + * "path" = "/courses/{id}/attendees", + * "controller" = GetStudentsByCourse::class, + * "read" = false, + * "openapi_context" = { + * "tags" = {"Courses"}, + * "summary" = "Get the attendees attending to a course.", + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"}, + * {"name" = "id", "in" = "path", "description" = "Id of Organization", "required" = true, "type" = "string", "example" = "123456"} + * } + * }, + * } + * }, + * itemOperations={}, + * iri="https://schema.org/EducationEvent", + * normalizationContext={"groups" = {"BasePerson:output"}, "jsonld_embed_context" = true}, + * denormalizationContext={"groups" = {"BasePerson:input"}, "jsonld_embed_context" = true} + * ) + */ +class CourseAttendee +{ + use PersonTrait; +} diff --git a/src/Entity/Exam.php b/src/Entity/Exam.php new file mode 100644 index 0000000000000000000000000000000000000000..d97cc3782b78e788182971b90c573f12392e3fc0 --- /dev/null +++ b/src/Entity/Exam.php @@ -0,0 +1,127 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Entity; + +use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Core\Annotation\ApiResource; +use DateTime; +use DBP\API\CourseBundle\Controller\GetExamsByCourse; +use Symfony\Component\Serializer\Annotation\Groups; + +/** + * @ApiResource( + * collectionOperations={ + * "get_bycourse" = { + * "method" = "GET", + * "path" = "/courses/{id}/exams", + * "controller" = GetExamsByCourse::class, + * "read" = false, + * "openapi_context" = { + * "tags" = {"Courses"}, + * "summary" = "Get the Exams for a course.", + * "parameters" = { + * {"name" = "lang", "in" = "query", "description" = "Language of result", "type" = "string", "enum" = {"de", "en"}, "example" = "de"}, + * {"name" = "id", "in" = "path", "description" = "Id of Organization", "required" = true, "type" = "string", "example" = "123456"} + * } + * }, + * } + * }, + * itemOperations={}, + * iri="https://schema.org/EducationEvent", + * normalizationContext={"groups" = {"Exam:output"}, "jsonld_embed_context" = true}, + * denormalizationContext={"groups" = {"Exam:input"}, "jsonld_embed_context" = true} + * ) + */ +class Exam +{ + /** + * @ApiProperty(identifier=true) + * + * @var string + */ + private $identifier; + + /** + * @ApiProperty(iri="https://schema.org/description") + * @Groups({"Exam:output"}) + * + * @var string + */ + private $description; + + /** + * @ApiProperty(iri="https://schema.org/startDate") + * @Groups({"Exam:output"}) + * + * @var DateTime + */ + private $startDate; + + /** + * @ApiProperty(iri="https://schema.org/endDate") + * @Groups({"Exam:output"}) + * + * @var DateTime + */ + private $endDate; + + /** + * @ApiProperty(iri="https://schema.org/location") + * @Groups({"Exam:output"}) + * + * @var string + */ + private $location; + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function setIdentifier(string $identifier): void + { + $this->identifier = $identifier; + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): void + { + $this->description = $description; + } + + public function getStartDate(): DateTime + { + return $this->startDate; + } + + public function setStartDate(DateTime $startDate): void + { + $this->startDate = $startDate; + } + + public function getEndDate(): DateTime + { + return $this->endDate; + } + + public function setEndDate(DateTime $endDate): void + { + $this->endDate = $endDate; + } + + public function getLocation(): string + { + return $this->location; + } + + public function setLocation(string $location): void + { + $this->location = $location; + } +} diff --git a/src/Service/CourseProviderInterface.php b/src/Service/CourseProviderInterface.php deleted file mode 100644 index c2e9dfde6db4ef076b3d60325be43f332130d6b3..0000000000000000000000000000000000000000 --- a/src/Service/CourseProviderInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\Service; - -use Dbp\Relay\CourseBundle\Entity\Course; - -interface CourseProviderInterface -{ - public function getCourseById(string $identifier): ?Course; - - public function getCourses(): array; -} diff --git a/src/Service/DummyCourseProvider.php b/src/Service/DummyCourseProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..876ed28612adb73e18e3432d33b53380bcd6c9a2 --- /dev/null +++ b/src/Service/DummyCourseProvider.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +namespace Dbp\Relay\CourseBundle\Service; + +use DateTime; +use Dbp\Relay\BasePersonBundle\Entity\Person; +use Dbp\Relay\CourseBundle\API\CourseProviderInterface; +use Dbp\Relay\CourseBundle\Entity\Course; +use Dbp\Relay\CourseBundle\Entity\Exam; + +class DummyCourseProvider implements CourseProviderInterface +{ + public function getCourseById(string $identifier, array $options = []): ?Course + { + $course = new Course(); + $course->setIdentifier($identifier); + $course->setName('Field Theory'); + $course->setDescription('News from field theory'); + + return $course; + } + + public function getCourses(array $options = []): array + { + $course = $this->getCourseById('123', $options); + assert($course !== null); + + return [$course]; + } + + public function getCoursesByOrganization(string $orgUnitId, array $options = []): array + { + return $this->getCourses($options); + } + + public function getCoursesByPerson(string $personId, array $options = []): array + { + return $this->getCourses($options); + } + + public function getStudentsByCourse(string $courseId, array $options = []): array + { + $person = new Person(); + $person->setIdentifier('123'); + $person->setFamilyName('Spencer'); + $person->setGivenName('Bud'); + $person->setEmail('bud@spencer.net'); + $person->setBirthDate('1.1.1950'); + + return [$person]; + } + + public function getExamsByCourse(string $courseId, array $options = []): array + { + $exam = new Exam(); + $exam->setIdentifier('123'); + $exam->setDescription('Oral exam'); + $exam->setStartDate(new DateTime('25.08.2021 8:00AM')); + $exam->setEndDate(new DateTime('25.08.2021 10:00AM')); + $exam->setLocation('In a room'); + + return [$exam]; + } +} diff --git a/src/Service/ExternalApi.php b/src/Service/ExternalApi.php deleted file mode 100644 index e72ba4d83982eb6173dab833f8a3414f9da7c3e8..0000000000000000000000000000000000000000 --- a/src/Service/ExternalApi.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\Service; - -use Dbp\Relay\CourseBundle\Entity\Course; - -class ExternalApi implements CourseProviderInterface -{ - private $courses; - - public function __construct(MyCustomService $service) - { - // Make phpstan happy - $service = $service; - - $this->courses = []; - $course1 = new Course(); - $course1->setIdentifier('graz'); - $course1->setName('Graz'); - - $course2 = new Course(); - $course2->setIdentifier('vienna'); - $course2->setName('Vienna'); - - $this->courses[] = $course1; - $this->courses[] = $course2; - } - - public function getCourseById(string $identifier): ?Course - { - foreach ($this->courses as $course) { - if ($course->getIdentifier() === $identifier) { - return $course; - } - } - - return null; - } - - public function getCourses(): array - { - return $this->courses; - } -} diff --git a/src/Service/MyCustomService.php b/src/Service/MyCustomService.php deleted file mode 100644 index d08550e34c8529646aaac1c88b0b9eda70a108fc..0000000000000000000000000000000000000000 --- a/src/Service/MyCustomService.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Dbp\Relay\CourseBundle\Service; - -class MyCustomService -{ - private $someConfig; - - public function __construct(string $someConfig) - { - $this->$someConfig = $someConfig; - } -} diff --git a/tests/Service/ExternalApiTest.php b/tests/Service/ExternalApiTest.php index d3e4ab62b84d47c5e8bb48795912ead583937346..13f1f9b10ff8ff3f0bacd67aa38f236d782ccb2d 100644 --- a/tests/Service/ExternalApiTest.php +++ b/tests/Service/ExternalApiTest.php @@ -4,23 +4,15 @@ declare(strict_types=1); namespace Dbp\Relay\CourseBundle\Tests\Service; -use Dbp\Relay\CourseBundle\Service\ExternalApi; -use Dbp\Relay\CourseBundle\Service\MyCustomService; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class ExternalApiTest extends WebTestCase { - private $api; - protected function setUp(): void { - $service = new MyCustomService('test-42'); - $this->api = new ExternalApi($service); } public function test() { - $this->assertTrue(true); - $this->assertNotNull($this->api); } }