mangaRepository->findOneBy(['slug' => $mangaSlug]); if (!$manga) { throw $this->createNotFoundException("Le manga demandé n'existe pas."); } $chapter = $manga->getChapterByNumber($chapterNumber); if (!$chapter) { throw $this->createNotFoundException("Le chapitre demandé n'existe pas."); } if (is_null($chapter->getCbzPath())) { $this->notificationService->sendUpdate([ 'status' => 'error', 'message' => 'Le chapitre demandé n\'est pas encore disponible.', ]); return $this->redirectToRoute('app_manga_show', ['mangaSlug' => $mangaSlug]); } $totalPages = $this->cbzService->getPageCount($chapter->getCbzPath()); return $this->render('reader/index.html.twig', [ 'manga' => $manga, 'chapter' => $chapter, 'totalPages' => $totalPages, ]); } #[Route('/api/read/{mangaSlug}/{chapterNumber}/{pageNumber}', name: 'app_reader_page')] public function getPage(string $mangaSlug, float $chapterNumber, int $pageNumber): Response { $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]); if (!$manga) { throw $this->createNotFoundException("Le manga demandé n'existe pas."); } $chapter = $manga->getChapterByNumber($chapterNumber); if (!$chapter) { throw $this->createNotFoundException("Le chapitre demandé n'existe pas."); } $pageContent = $this->cbzService->getPageContent($chapter->getCbzPath(), $pageNumber); if (!$pageContent) { throw $this->createNotFoundException("La page demandée n'existe pas."); } return new Response(base64_encode($pageContent), 200, ['Content-Type' => 'text/plain']); } #[Route('/api/chapters/{mangaSlug}', name: 'app_reader_chapters')] public function getChapters(string $mangaSlug): JsonResponse { $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]); if (!$manga) { throw $this->createNotFoundException("Le manga demandé n'existe pas."); } $chapters = $manga->getChapters() ->filter(fn ($chapter) => $chapter->isVisible() && !is_null($chapter->getCbzPath())) ->toArray(); usort($chapters, fn ($a, $b) => $b->getNumber() <=> $a->getNumber()); $chapters = array_values(array_map(fn ($chapter) => [ 'number' => $chapter->getNumber(), 'title' => $chapter->getTitle(), ], $chapters)); return $this->json($chapters); } #[Route('/api/previous-chapter/{mangaSlug}/{currentChapterNumber}', name: 'app_reader_previous_chapter')] public function getPreviousChapter(string $mangaSlug, float $currentChapterNumber): JsonResponse { $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]); if (!$manga) { throw $this->createNotFoundException("Le manga demandé n'existe pas."); } $chapters = $manga->getChapters() ->filter(fn ($chapter) => $chapter->isVisible() && $chapter->getNumber() < $currentChapterNumber) ->toArray(); usort($chapters, fn ($a, $b) => $b->getNumber() <=> $a->getNumber()); $previousChapter = reset($chapters) ?: null; return $this->json($previousChapter ? [ 'number' => $previousChapter->getNumber(), 'title' => $previousChapter->getTitle(), ] : null); } #[Route('/api/next-chapter/{mangaSlug}/{currentChapterNumber}', name: 'app_reader_next_chapter')] public function getNextChapter(string $mangaSlug, float $currentChapterNumber): JsonResponse { $manga = $this->mangaRepository->findOneBy(['slug' => $mangaSlug]); if (!$manga) { throw $this->createNotFoundException("Le manga demandé n'existe pas."); } $nextChapter = $manga->getChapters() ->filter(fn ($chapter) => $chapter->isVisible() && $chapter->getNumber() > $currentChapterNumber) ->toArray(); usort($nextChapter, fn ($a, $b) => $a->getNumber() <=> $b->getNumber()); $nextChapter = reset($nextChapter) ?: null; return $this->json($nextChapter ? [ 'number' => $nextChapter->getNumber(), 'title' => $nextChapter->getTitle(), ] : null); } }