feat(blog): implement medical review gate for blog posts

- Added new fields to the Blog entity: sources, review_status, reviewer, reviewed_at, review_note, and topic_slug.
- Created API endpoints for reviewing blog posts: GET /api/v1/admin/blog/review-queue and POST /api/v1/admin/blog/{uuid}/review.
- Updated BlogController to handle review logic, including approval and rejection of posts.
- Introduced BlogReviewPage component for admin interface to manage blog reviews.
- Added migration to update the database schema for new fields.
- Implemented tests for review queue functionality and review decision handling.
This commit is contained in:
hamed
2026-07-23 21:01:58 +03:30
parent 2abf915f95
commit 14730e43ce
10 changed files with 746 additions and 0 deletions
+27
View File
@@ -12,6 +12,33 @@ class BlogRepository extends ServiceEntityRepository
public function findByUuid(string $uuid): ?Blog { return $this->findOneBy(['uuid' => $uuid]); }
public function findBySlug(string $slug): ?Blog { return $this->findOneBy(['slug' => $slug]); }
public function findByTopicSlug(string $topicSlug): ?Blog { return $this->findOneBy(['topicSlug' => $topicSlug]); }
/**
* The admin review queue: posts awaiting a doctor's decision, newest first.
* @return Blog[]
*/
public function findByReviewStatus(string $reviewStatus, int $page = 1, int $limit = 20): array
{
return $this->createQueryBuilder('b')
->leftJoin('b.city', 'c')->addSelect('c')
->leftJoin('b.reviewer', 'r')->addSelect('r')
->where('b.reviewStatus = :rs')
->setParameter('rs', $reviewStatus)
->orderBy('b.createdAt', 'DESC')
->setFirstResult(($page - 1) * $limit)
->setMaxResults($limit)
->getQuery()->getResult();
}
public function countByReviewStatus(string $reviewStatus): int
{
return (int) $this->createQueryBuilder('b')
->select('COUNT(b.id)')
->where('b.reviewStatus = :rs')
->setParameter('rs', $reviewStatus)
->getQuery()->getSingleScalarResult();
}
/** @return Blog[] published, newest first */
public function findPublished(int $page = 1, int $limit = 20, ?string $tag = null, ?int $cityId = null): array