Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create listCourses using CQRS #377

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
/build

.php-cs-fixer.cache
.idea/workspace.xml
.idea
4 changes: 4 additions & 0 deletions apps/mooc/backend/config/routes/list_courses.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
courses_list:
path: /courses/
controller: CodelyTv\Apps\Mooc\Backend\Controller\ListCourses\ListCoursesGetController
methods: [GET]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace CodelyTv\Apps\Mooc\Backend\Controller\ListCourses;

use CodelyTv\Mooc\Courses\Application\List\ListCoursesQuery;
use CodelyTv\Mooc\Courses\Application\List\ListCoursesResponse;
use CodelyTv\Mooc\Courses\Domain\Course;
use CodelyTv\Mooc\Courses\Domain\CourseCollection;
use CodelyTv\Shared\Infrastructure\Symfony\ApiController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class ListCoursesGetController extends ApiController
{
public function __invoke(Request $request): Response
{
/** @var ListCoursesResponse $response */
$response = $this->ask(new ListCoursesQuery());

return new JsonResponse(self::transformer($response->courses()));
}

protected function exceptions(): array
{
return [];
}

public static function transformer(CourseCollection $courseCollection): array
{
$res = [];

/** @var Course $course */
foreach ($courseCollection->courses() as $course)
{
$res[] = [
'id' => $course->id()->value(),
'name' => $course->name()->value(),
'duration' => $course->duration()->value(),
];
}
return $res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Feature: List all courses
In order to list courses on the platform
I want to list all courses

Scenario: List all courses
Given I send a GET request to "/courses"
Then the response status code should be 200
And the response should not be empty
22 changes: 22 additions & 0 deletions src/Mooc/Courses/Application/List/ListCourses.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace CodelyTv\Mooc\Courses\Application\List;

use CodelyTv\Mooc\Courses\Domain\CourseCollection;
use CodelyTv\Mooc\Courses\Domain\ListCourses as DomainListCourses;
use CodelyTv\Mooc\Courses\Domain\CourseRepository;

class ListCourses
{
private readonly DomainListCourses $listCourses;

public function __construct(CourseRepository $repository)
{
$this->listCourses = new DomainListCourses($repository);
}

public function __invoke(): CourseCollection
{
return $this->listCourses->listCourses();
}
}
9 changes: 9 additions & 0 deletions src/Mooc/Courses/Application/List/ListCoursesQuery.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace CodelyTv\Mooc\Courses\Application\List;

use CodelyTv\Shared\Domain\Bus\Query\Query;

final class ListCoursesQuery implements Query
{
}
18 changes: 18 additions & 0 deletions src/Mooc/Courses/Application/List/ListCoursesQueryHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace CodelyTv\Mooc\Courses\Application\List;

use CodelyTv\Shared\Domain\Bus\Query\QueryHandler;

class ListCoursesQueryHandler implements QueryHandler
{
public function __construct(private readonly ListCourses $listCourses)
{
}

public function __invoke(ListCoursesQuery $query): ListCoursesResponse
{
$courses = $this->listCourses->__invoke();
return new ListCoursesResponse($courses);
}
}
17 changes: 17 additions & 0 deletions src/Mooc/Courses/Application/List/ListCoursesResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace CodelyTv\Mooc\Courses\Application\List;

use CodelyTv\Mooc\Courses\Domain\CourseCollection;

class ListCoursesResponse
{
public function __construct(private readonly CourseCollection $courses)
{
}

public function courses(): CourseCollection
{
return $this->courses;
}
}
19 changes: 19 additions & 0 deletions src/Mooc/Courses/Domain/CourseCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace CodelyTv\Mooc\Courses\Domain;


class CourseCollection
{
private array $courses;

public function __construct(Course ...$courses)
{
$this->courses = $courses;
}

public function courses(): array
{
return $this->courses;
}
}
3 changes: 3 additions & 0 deletions src/Mooc/Courses/Domain/CourseRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ interface CourseRepository
public function save(Course $course): void;

public function search(CourseId $id): ?Course;

public function list(): CourseCollection;

}
15 changes: 15 additions & 0 deletions src/Mooc/Courses/Domain/ListCourses.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace CodelyTv\Mooc\Courses\Domain;

class ListCourses
{
public function __construct(private readonly CourseRepository $repository)
{
}

public function listCourses(): CourseCollection
{
return $this->repository->list();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace CodelyTv\Mooc\Courses\Infrastructure\Persistence;

use CodelyTv\Mooc\Courses\Domain\Course;
use CodelyTv\Mooc\Courses\Domain\CourseCollection;
use CodelyTv\Mooc\Courses\Domain\CourseRepository;
use CodelyTv\Mooc\Shared\Domain\Courses\CourseId;
use CodelyTv\Shared\Infrastructure\Persistence\Doctrine\DoctrineRepository;
Expand All @@ -20,4 +21,10 @@ public function search(CourseId $id): ?Course
{
return $this->repository(Course::class)->find($id);
}

public function list(): CourseCollection
{
$courses = $this->repository(Course::class)->findAll();
return new CourseCollection(...$courses);
}
}
12 changes: 12 additions & 0 deletions tests/Shared/Infrastructure/Behat/ApiContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ public function theResponseShouldBeEmpty(): void
}
}

/**
* @Then the response should not be empty
*/
public function theResponseShouldNotBeEmpty(): void
{
$actual = trim($this->sessionHelper->getResponse());

if (empty($actual)) {
throw new RuntimeException(sprintf("The outputs is empty, Actual:\n%s", $actual));
}
}

/**
* @Then print last api response
*/
Expand Down