getNextId(); $post = new Post( id: $id, userId: $dto->userId, title: $dto->title, body: $dto->body, createdAt: $dto->createdAt, featureSlot: null, ); $this->existingPosts[$id] = $post; return $this->copy($post); } public function find(int $id): ?Post { $post = $this->existingPosts[$id] ?? null; if ($post === null) { return null; } return $this->copy($post); } /** * @return Post[] */ public function findByUserId(int $userId): array { $matching = []; foreach ($this->existingPosts as $post) { if ($post->getUserId() === $userId) { $matching[] = $this->copy($post); } } usort( $matching, function (Post $left, Post $right) { return $right->getCreatedAt() <=> $left->getCreatedAt(); }, ); return $matching; } /** * @return Post[] */ public function findRecent(int $limit): array { $all = array_map( function (Post $post) { return $this->copy($post); }, array_values($this->existingPosts), ); usort( $all, function (Post $left, Post $right) { return $right->getCreatedAt() <=> $left->getCreatedAt(); }, ); return array_slice($all, 0, $limit); } public function delete(int $id): void { unset($this->existingPosts[$id]); } /** * @throws RuntimeException */ public function update(Post $post): Post { $id = $post->getId(); if (! isset($this->existingPosts[$id])) { throw new RuntimeException( "Post with id: $id does not exist" ); } $this->existingPosts[$id] = $post; return $this->copy($post); } public function findByFeatureSlot(int $slot): ?Post { foreach ($this->existingPosts as $post) { if ($post->getFeatureSlot() === $slot) { return $this->copy($post); } } return null; } /** * @return Post[] */ public function findFeatured(): array { $featured = []; foreach ($this->existingPosts as $post) { if ($post->isFeatured()) { $featured[] = $this->copy($post); } } usort( $featured, function (Post $left, Post $right) { return $left->getFeatureSlot() <=> $right->getFeatureSlot(); }, ); return $featured; } private function copy(Post $post): Post { return new Post( id: $post->getId(), userId: $post->getUserId(), title: $post->getTitle(), body: $post->getBody(), createdAt: $post->getCreatedAt(), featureSlot: $post->getFeatureSlot(), ); } private function getNextId(): int { return count($this->existingPosts) + 1; } }