*/ private array $mangas = []; /** @var array> */ private array $chapters = []; /** @var array */ private array $savedChapters = []; public function findAll(int $page = 1, int $limit = 20, string $sortBy = 'title', string $sortOrder = 'asc'): array { $sortedMangas = array_values($this->mangas); usort($sortedMangas, function (Manga $a, Manga $b) use ($sortBy, $sortOrder) { $valueA = $this->getPropertyValue($a, $sortBy); $valueB = $this->getPropertyValue($b, $sortBy); return $sortOrder === 'asc' ? $valueA <=> $valueB : $valueB <=> $valueA; }); $offset = ($page - 1) * $limit; return array_slice($sortedMangas, $offset, $limit); } public function count(): int { return count($this->mangas); } public function findById(string $id): ?Manga { return $this->mangas[$id] ?? null; } public function findBySlug(MangaSlug $slug): ?Manga { foreach ($this->mangas as $manga) { if ($manga->getSlug()->getValue() === $slug->getValue()) { return $manga; } } return null; } public function save(Manga $manga): void { $this->mangas[$manga->getId()->getValue()] = $manga; } public function delete(Manga $manga): void { unset($this->mangas[$manga->getId()->getValue()]); } private function getPropertyValue(Manga $manga, string $property): mixed { return match($property) { 'title' => $manga->getTitle()->getValue(), 'publicationYear' => $manga->getPublicationYear(), default => throw new \InvalidArgumentException("Unknown sort property: $property") }; } public function findChapters(string $mangaId, int $page = 1, int $limit = 20, string $sortOrder = 'desc'): array { if (!isset($this->chapters[$mangaId])) { return []; } $chapters = $this->chapters[$mangaId]; usort($chapters, function (Chapter $a, Chapter $b) use ($sortOrder) { return $sortOrder === 'desc' ? $b->getNumber() <=> $a->getNumber() : $a->getNumber() <=> $b->getNumber(); }); $offset = ($page - 1) * $limit; return array_slice($chapters, $offset, $limit); } public function countChapters(string $mangaId): int { return count($this->chapters[$mangaId] ?? []); } public function addChaptersToManga(string $mangaId, int $count): void { $this->chapters[$mangaId] = []; for ($i = 1; $i <= $count; $i++) { $this->chapters[$mangaId][] = new Chapter( id: new ChapterId((string)$i), mangaId: $mangaId, number: (float)$i, title: "Chapter $i", volume: (int)ceil($i / 10), isVisible: true, createdAt: new \DateTimeImmutable() ); } } public function findByExternalId(ExternalId $externalId): ?Manga { foreach ($this->mangas as $manga) { if ($manga->getExternalId() && $manga->getExternalId()->getValue() === $externalId->getValue()) { return $manga; } } return null; } public function saveChapter(Chapter $chapter): void { $this->savedChapters[] = $chapter; if (!isset($this->chapters[$chapter->getMangaId()])) { $this->chapters[$chapter->getMangaId()] = []; } $this->chapters[$chapter->getMangaId()][] = $chapter; } /** @return array */ public function getSavedChapters(): array { return $this->savedChapters; } public function clear(): void { $this->mangas = []; $this->chapters = []; $this->savedChapters = []; } public function search(string $query, int $page = 1, int $limit = 20): array { $filteredMangas = array_filter($this->mangas, function (Manga $manga) use ($query) { $searchableFields = [ $manga->getTitle()->getValue(), $manga->getSlug()->getValue(), $manga->getAuthor(), $manga->getDescription() ]; foreach ($searchableFields as $field) { if (str_contains(strtolower($field), strtolower($query))) { return true; } } return false; }); $sortedMangas = array_values($filteredMangas); usort($sortedMangas, fn (Manga $a, Manga $b) => $a->getTitle()->getValue() <=> $b->getTitle()->getValue()); $offset = ($page - 1) * $limit; return array_slice($sortedMangas, $offset, $limit); } public function countSearch(string $query): int { return count($this->search($query, 1, PHP_INT_MAX)); } }