List and add ratings

This commit is contained in:
myrmidex 2026-06-04 22:00:51 +00:00
parent 40eb1ca7a8
commit a3963d093e
8 changed files with 172 additions and 3 deletions

View file

@ -0,0 +1,62 @@
<?php
namespace App\Controller\Api;
use App\Entity\Rating;
use App\Entity\Restaurant;
use App\Repository\RatingRepository;
use App\Repository\SubjectRepository;
use App\Services\OutputService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
class RatingController extends AbstractController
{
#[Route('/api/ratings', methods: ['GET'])]
public function index(
RatingRepository $repo,
OutputService $output,
): JsonResponse {
return $this->json($output->success([
'ratings' => array_map(
fn(Rating $rating) => [
'id' => $rating->getId(),
'score' => $rating->getScore(),
'subject' => [
'id' => $rating->getSubject()->getId(),
'name' => $rating->getSubject()->getName(),
],
],
$repo->findAll()
),
]));
}
#[Route('/api/ratings', methods: ['POST'])]
public function create(
Request $request,
EntityManagerInterface $em,
OutputService $output,
SubjectRepository $subjectRepository,
): JsonResponse {
$subject = $subjectRepository->findById($request->getPayload()->get('subject_id'));
if ($subject === null) {
return $this->json(
$output->error(["UNKNOWN_SUBJECT"])
);
}
$rating = new Rating();
$rating->setSubject($subject);
$rating->setScore($request->getPayload()->get('score'));
$em->persist($rating);
$em->flush();
return $this->json(null, 201);
}
}

View file

@ -29,7 +29,7 @@ abstract class Subject
/**
* @var Collection<int, Rating>
*/
#[ORM\OneToMany(targetEntity: Rating::class, mappedBy: 'subject_id', orphanRemoval: true)]
#[ORM\OneToMany(targetEntity: Rating::class, mappedBy: 'subject', orphanRemoval: true)]
private Collection $ratings;
public function __construct()

View file

@ -36,7 +36,7 @@ final class RatingFactory extends PersistentObjectFactory
protected function defaults(): array|callable
{
return [
'subject_id' => SubjectFactory::new(),
'subject' => SubjectFactory::new(),
];
}

View file

@ -37,7 +37,7 @@ final class SubjectFactory extends PersistentObjectFactory
protected function defaults(): array|callable
{
return [
'name' => self::faker()->text(255),
'name' => self::faker()->text(10),
];
}

View file

@ -3,6 +3,7 @@
namespace App\Repository;
use App\Entity\Rating;
use App\Entity\Subject;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
@ -16,6 +17,24 @@ class RatingRepository extends ServiceEntityRepository
parent::__construct($registry, Rating::class);
}
public function findById(int $id): ?Rating
{
return $this->createQueryBuilder('r')
->where('r.id = :id')
->setParameter('id', $id)
->getQuery()
->getOneOrNullResult();
}
public function findAllBySubject(Subject $subject): array
{
return $this->createQueryBuilder('r')
->where('r.subject = :subject')
->setParameter('subject', $subject)
->getQuery()
->getResult();
}
// /**
// * @return Rating[] Returns an array of Rating objects
// */

View file

@ -16,6 +16,15 @@ class SubjectRepository extends ServiceEntityRepository
parent::__construct($registry, Subject::class);
}
public function findById(int $id): ?Subject
{
return $this->createQueryBuilder('s')
->where('s.id = :id')
->setParameter('id', $id)
->getQuery()
->getOneOrNullResult();
}
// /**
// * @return Subject[] Returns an array of Subject objects
// */

View file

@ -0,0 +1,79 @@
<?php
namespace App\Tests\Unit\Controller\Api;
use App\Entity\Rating;
use App\Entity\Restaurant;
use App\Factory\RatingFactory;
use App\Factory\RestaurantFactory;
use App\Factory\UserFactory;
use App\Repository\RatingRepository;
use App\Repository\SubjectRepository;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class RatingControllerTest extends WebTestCase
{
public function testList(): void
{
$client = static::createClient();
$user = UserFactory::createOne();
$client->loginUser($user);
$subject = RestaurantFactory::createOne([
'createdBy' => $user,
]);
$ratings = RatingFactory::createMany(5, [
'subject' => $subject,
]);
$client->request(
'GET',
'/api/ratings',
server: ['CONTENT_TYPE' => 'application/json'],
content: json_encode(['name' => 'Riviera']),
);
$data = json_decode($client->getResponse()->getContent(), true);
$this->assertResponseIsSuccessful();
$this->assertCount(5, $data['payload']['ratings']);
}
public function testCreate(): void
{
$client = static::createClient();
$repo = static::getContainer()->get(RatingRepository::class);
$user = UserFactory::createOne();
$client->loginUser($user);
$subject = RestaurantFactory::createOne([
'createdBy' => $user,
]);
$client->request(
'POST',
'/api/ratings',
server: ['CONTENT_TYPE' => 'application/json'],
content: json_encode([
'subject_id' => $subject->getId(),
'score' => 8,
]),
);
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(201);
$this->assertCount(1, $repo->findAll());
$ratings = static::getContainer()
->get(RatingRepository::class)
->findAllBySubject($subject);
$this->assertNotNull($ratings);
$this->assertCount(1, $ratings);
$this->assertInstanceOf(Rating::class, $ratings[0]);
}
}