diff --git a/src/app/Packages/Domains/WorldHeritage/Tests/QueryService/WorldHeritageQueryService_getHeritagesByIdsTest.php b/src/app/Packages/Domains/WorldHeritage/Tests/QueryService/WorldHeritageQueryService_getHeritagesByIdsTest.php new file mode 100644 index 0000000..112d5d3 --- /dev/null +++ b/src/app/Packages/Domains/WorldHeritage/Tests/QueryService/WorldHeritageQueryService_getHeritagesByIdsTest.php @@ -0,0 +1,98 @@ +refresh(); + + $seeder = new DatabaseSeeder(); + $seeder->run(); + + $this->app->bind(WorldHeritageSearchPort::class, static function () { + return new class implements WorldHeritageSearchPort { + public function search($query, int $currentPage, int $perPage): HeritageSearchResult { + return new HeritageSearchResult(ids: [], total: 0, currentPage: 1, perPage: $perPage, lastPage: 0); + } + }; + }); + + $this->queryService = app(WorldHeritageQueryService::class); + } + + protected function tearDown(): void + { + $this->refresh(); + parent::tearDown(); + } + + private function refresh(): void + { + if (env('APP_ENV') === 'testing') { + DB::connection('mysql')->statement('SET FOREIGN_KEY_CHECKS=0;'); + WorldHeritage::truncate(); + Country::truncate(); + DB::table('site_state_parties')->truncate(); + Image::truncate(); + WorldHeritageDescription::truncate(); + DB::connection('mysql')->statement('SET FOREIGN_KEY_CHECKS=1;'); + } + } + + public function test_returns_world_heritage_dto_collection(): void + { + $ids = DB::table('world_heritage_sites')->orderBy('id')->limit(2)->pluck('id')->all(); + + $result = $this->queryService->getHeritagesByIds($ids); + + $this->assertInstanceOf(WorldHeritageDtoCollection::class, $result); + } + + public function test_preserves_order_of_given_ids(): void + { + $ids = DB::table('world_heritage_sites')->orderBy('id')->limit(3)->pluck('id')->all(); + $this->assertCount(3, $ids, 'Seeder must insert at least 3 world heritages.'); + + $requested = [$ids[2], $ids[0], $ids[1]]; + + $result = $this->queryService->getHeritagesByIds($requested); + + $resultIds = array_map(fn ($dto) => $dto->getId(), $result->getHeritages()); + $this->assertSame($requested, $resultIds); + } + + public function test_returns_empty_collection_when_no_ids_given(): void + { + $result = $this->queryService->getHeritagesByIds([]); + + $this->assertSame([], $result->getHeritages()); + } + + public function test_skips_missing_ids_without_failing(): void + { + $existingId = (int) DB::table('world_heritage_sites')->orderBy('id')->value('id'); + $this->assertNotNull($existingId, 'Seeder must insert at least 1 world heritage.'); + + $result = $this->queryService->getHeritagesByIds([$existingId, 999_999_999]); + + $resultIds = array_map(fn ($dto) => $dto->getId(), $result->getHeritages()); + $this->assertSame([$existingId], $resultIds); + } +} diff --git a/src/app/Packages/Domains/WorldHeritage/WorldHeritageQueryService.php b/src/app/Packages/Domains/WorldHeritage/WorldHeritageQueryService.php index ca7a96c..f9dd068 100644 --- a/src/app/Packages/Domains/WorldHeritage/WorldHeritageQueryService.php +++ b/src/app/Packages/Domains/WorldHeritage/WorldHeritageQueryService.php @@ -246,6 +246,17 @@ public function searchHeritages(AlgoliaSearchListQuery $query): PaginationDto ); } + public function getHeritagesByIds(array $ids): WorldHeritageDtoCollection + { + $models = $this->readQueryService->findByIdsPreserveOrder($ids); + + $payloads = $models + ->map(fn ($m) => $this->buildWorldHeritagePayload($m)) + ->all(); + + return $this->buildDtoFromCollection($payloads); + } + public function getEachRegionsHeritagesCount(): array { $counts = $this->model diff --git a/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php b/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php index e7919e7..63539cb 100644 --- a/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php +++ b/src/app/Packages/Features/QueryUseCases/QueryServiceInterface/WorldHeritageQueryServiceInterface.php @@ -5,6 +5,7 @@ use App\Common\Pagination\PaginationDto; use App\Packages\Features\QueryUseCases\Dto\WorldHeritageDto; +use App\Packages\Features\QueryUseCases\Dto\WorldHeritageDtoCollection; use App\Packages\Features\QueryUseCases\ListQuery\AlgoliaSearchListQuery; @@ -25,5 +26,9 @@ public function searchHeritages( AlgoliaSearchListQuery $query ): PaginationDto; + public function getHeritagesByIds( + array $ids + ): WorldHeritageDtoCollection; + public function getEachRegionsHeritagesCount(): array; } \ No newline at end of file diff --git a/src/app/Packages/Features/QueryUseCases/Tests/UseCase/GetFavoriteHeritagesUseCaseTest.php b/src/app/Packages/Features/QueryUseCases/Tests/UseCase/GetFavoriteHeritagesUseCaseTest.php new file mode 100644 index 0000000..d777492 --- /dev/null +++ b/src/app/Packages/Features/QueryUseCases/Tests/UseCase/GetFavoriteHeritagesUseCaseTest.php @@ -0,0 +1,70 @@ +shouldReceive('getFavoriteWorldHeritageIds') + ->once() + ->with(1) + ->andReturn([3, 2]); + + $dtoCollection = new WorldHeritageDtoCollection(); + + /** @var WorldHeritageQueryServiceInterface|MockInterface $worldHeritageQueryService */ + $worldHeritageQueryService = Mockery::mock(WorldHeritageQueryServiceInterface::class); + $worldHeritageQueryService->shouldReceive('getHeritagesByIds') + ->once() + ->with([3, 2]) + ->andReturn($dtoCollection); + + $useCase = new GetFavoriteHeritagesUseCase($favoriteRepository, $worldHeritageQueryService); + + $result = $useCase->handle(1); + + $this->assertSame($dtoCollection, $result); + } + + public function test_handle_returns_empty_collection_when_user_has_no_favorites(): void + { + /** @var FavoriteRepositoryInterface|MockInterface $favoriteRepository */ + $favoriteRepository = Mockery::mock(FavoriteRepositoryInterface::class); + $favoriteRepository->shouldReceive('getFavoriteWorldHeritageIds') + ->once() + ->with(1) + ->andReturn([]); + + $dtoCollection = new WorldHeritageDtoCollection(); + + /** @var WorldHeritageQueryServiceInterface|MockInterface $worldHeritageQueryService */ + $worldHeritageQueryService = Mockery::mock(WorldHeritageQueryServiceInterface::class); + $worldHeritageQueryService->shouldReceive('getHeritagesByIds') + ->once() + ->with([]) + ->andReturn($dtoCollection); + + $useCase = new GetFavoriteHeritagesUseCase($favoriteRepository, $worldHeritageQueryService); + + $result = $useCase->handle(1); + + $this->assertSame([], $result->getHeritages()); + } +} diff --git a/src/app/Packages/Features/QueryUseCases/UseCase/Favorite/GetFavoriteHeritagesUseCase.php b/src/app/Packages/Features/QueryUseCases/UseCase/Favorite/GetFavoriteHeritagesUseCase.php new file mode 100644 index 0000000..857e68f --- /dev/null +++ b/src/app/Packages/Features/QueryUseCases/UseCase/Favorite/GetFavoriteHeritagesUseCase.php @@ -0,0 +1,22 @@ +favoriteRepository->getFavoriteWorldHeritageIds($userId); + + return $this->worldHeritageQueryService->getHeritagesByIds($ids); + } +}