Compare commits

..

No commits in common. "f3d5d729bf966fabbf9f73e6c46e39d15d2707ac" and "eac85a904502e69110e90a9152dfa7b982d3611e" have entirely different histories.

11 changed files with 18 additions and 203 deletions

View file

@ -32,7 +32,7 @@ class RatingController extends AbstractController
], ],
$repo->findAll() $repo->findAll()
), ),
]), 200); ]));
} }
#[Route('/api/ratings', methods: ['POST'])] #[Route('/api/ratings', methods: ['POST'])]
@ -88,27 +88,6 @@ class RatingController extends AbstractController
$em->flush(); $em->flush();
return $this->json(null, 202); return $this->json(null, 201);
}
#[Route('/api/ratings/{id}', methods: ['DELETE'])]
public function delete(
int $id,
EntityManagerInterface $em,
OutputService $output,
RatingRepository $ratingRepository,
): JsonResponse {
$rating = $ratingRepository->findById($id);
if ($rating === null) {
return $this->json(
$output->error(["UNKNOWN_RATING"])
);
}
$em->remove($rating);
$em->flush();
return $this->json(null, 204);
} }
} }

View file

@ -3,7 +3,6 @@
namespace App\Controller\Api; namespace App\Controller\Api;
use App\Entity\Restaurant; use App\Entity\Restaurant;
use App\Entity\User;
use App\Repository\SubjectRepository; use App\Repository\SubjectRepository;
use App\Services\OutputService; use App\Services\OutputService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -11,7 +10,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
class SubjectController extends AbstractController class SubjectController extends AbstractController
{ {
@ -27,62 +25,14 @@ class SubjectController extends AbstractController
public function create( public function create(
Request $request, Request $request,
EntityManagerInterface $em, EntityManagerInterface $em,
#[CurrentUser]
User $user,
): JsonResponse { ): JsonResponse {
$subject = new Restaurant(); $subject = new Restaurant();
$subject->setName($request->getPayload()->get('name')); $subject->setName($request->getPayload()->get('name'));
$subject->setCreatedBy($user); $subject->setCreatedBy($this->getUser());
$em->persist($subject); $em->persist($subject);
$em->flush(); $em->flush();
return $this->json(null, 201); return $this->json(null, 201);
} }
#[Route('/api/subjects/{id}', methods: ['PATCH'])]
public function update(
int $id,
Request $request,
EntityManagerInterface $em,
OutputService $output,
SubjectRepository $repository,
): JsonResponse {
$subject = $repository->findById($id);
if ($subject === null) {
return $this->json(
$output->error(["UNKNOWN_RATING"])
);
}
$payload = $request->getPayload();
if ($payload->has('name')) {
$subject->setName($payload->getString('name'));
}
$em->flush();
return $this->json(null, 202);
}
#[Route('/api/subjects/{id}', methods: ['DELETE'])]
public function delete(
int $id,
EntityManagerInterface $em,
OutputService $output,
SubjectRepository $repository,
): JsonResponse {
$subject = $repository->findById($id);
if ($subject === null) {
return $this->json($output->error(["UNKNOWN_RATING"]));
}
$em->remove($subject);
$em->flush();
return $this->json(null, 204);
}
} }

View file

@ -16,7 +16,7 @@ class Rating
#[ORM\ManyToOne(inversedBy: 'ratings')] #[ORM\ManyToOne(inversedBy: 'ratings')]
#[ORM\JoinColumn(nullable: false)] #[ORM\JoinColumn(nullable: false)]
private Subject $subject; private ?Subject $subject = null;
#[ORM\Column(type: Types::SMALLINT, nullable: true)] #[ORM\Column(type: Types::SMALLINT, nullable: true)]
private ?int $score = null; private ?int $score = null;

View file

@ -20,7 +20,7 @@ abstract class Subject
private ?int $id = null; private ?int $id = null;
#[ORM\Column(length: 255)] #[ORM\Column(length: 255)]
private string $name; private ?string $name = null;
#[ORM\ManyToOne] #[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: true)] #[ORM\JoinColumn(nullable: true)]
@ -42,7 +42,7 @@ abstract class Subject
return $this->id; return $this->id;
} }
public function getName(): string public function getName(): ?string
{ {
return $this->name; return $this->name;
} }
@ -76,9 +76,9 @@ abstract class Subject
public function addRating(Rating $rating): static public function addRating(Rating $rating): static
{ {
if (! $this->ratings->contains($rating)) { if (!$this->ratings->contains($rating)) {
$this->ratings->add($rating); $this->ratings->add($rating);
$rating->setSubject($this); $rating->setSubjectId($this);
} }
return $this; return $this;
@ -88,8 +88,8 @@ abstract class Subject
{ {
if ($this->ratings->removeElement($rating)) { if ($this->ratings->removeElement($rating)) {
// set the owning side to null (unless already changed) // set the owning side to null (unless already changed)
if ($rating->getSubject() === $this) { if ($rating->getSubjectId() === $this) {
$rating->setSubject(null); $rating->setSubjectId(null);
} }
} }

View file

@ -18,7 +18,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
private ?int $id = null; private ?int $id = null;
#[ORM\Column(length: 180)] #[ORM\Column(length: 180)]
private string $email; private ?string $email = null;
/** /**
* @var list<string> The user roles * @var list<string> The user roles
@ -30,14 +30,14 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
* @var string The hashed password * @var string The hashed password
*/ */
#[ORM\Column] #[ORM\Column]
private string $password; private ?string $password = null;
public function getId(): int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
public function getEmail(): string public function getEmail(): ?string
{ {
return $this->email; return $this->email;
} }

View file

@ -26,9 +26,6 @@ class RatingRepository extends ServiceEntityRepository
->getOneOrNullResult(); ->getOneOrNullResult();
} }
/**
* @return Rating[]
*/
public function findAllBySubject(Subject $subject): array public function findAllBySubject(Subject $subject): array
{ {
return $this->createQueryBuilder('r') return $this->createQueryBuilder('r')

View file

@ -4,10 +4,6 @@ namespace App\Services;
class OutputService class OutputService
{ {
/**
* @param array<string, mixed> $output
* @return array{status: string, payload: array<string, mixed>, errors: null}
*/
public function success(array $output): array public function success(array $output): array
{ {
return [ return [
@ -17,10 +13,6 @@ class OutputService
]; ];
} }
/**
* @param array<int, string> $errors
* @return array{status: string, payload: null, errors: array<int, string>}
*/
public function error(array $errors): array public function error(array $errors): array
{ {
return [ return [

View file

@ -106,7 +106,7 @@ class RatingControllerTest extends WebTestCase
); );
$this->assertResponseIsSuccessful(); $this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(202); $this->assertResponseStatusCodeSame(201);
$em = static::getContainer()->get(EntityManagerInterface::class); $em = static::getContainer()->get(EntityManagerInterface::class);
$em->clear(); $em->clear();
@ -115,39 +115,4 @@ class RatingControllerTest extends WebTestCase
$this->assertSame(8, $updated->getScore()); $this->assertSame(8, $updated->getScore());
$this->assertSame('Other note', $updated->getNote()); $this->assertSame('Other note', $updated->getNote());
} }
public function testDelete(): void
{
$client = static::createClient();
$user = UserFactory::createOne();
$client->loginUser($user);
$subject = RestaurantFactory::createOne([
'createdBy' => $user,
]);
$rating = RatingFactory::createOne([
'subject' => $subject,
'score' => 0,
'note' => 'first note',
]);
$id = $rating->getId();
$client->request(
'DELETE',
'/api/ratings/' . $id,
server: ['CONTENT_TYPE' => 'application/json'],
);
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(204);
$em = static::getContainer()->get(EntityManagerInterface::class);
$em->clear();
$this->assertNull(
$em->getRepository(Rating::class)->find($id)
);
}
} }

View file

@ -2,15 +2,10 @@
namespace App\Tests\Unit\Controller\Api; namespace App\Tests\Unit\Controller\Api;
use App\Entity\Rating;
use App\Entity\Restaurant; use App\Entity\Restaurant;
use App\Entity\Subject;
use App\Factory\RatingFactory;
use App\Factory\RestaurantFactory;
use App\Factory\SubjectFactory; use App\Factory\SubjectFactory;
use App\Factory\UserFactory; use App\Factory\UserFactory;
use App\Repository\SubjectRepository; use App\Repository\SubjectRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class SubjectControllerTest extends WebTestCase class SubjectControllerTest extends WebTestCase
@ -42,7 +37,7 @@ class SubjectControllerTest extends WebTestCase
$this->assertCount(5, $data['payload']['subjects']); $this->assertCount(5, $data['payload']['subjects']);
} }
public function testCreate(): void public function testAddingNewSubjectViaApi(): void
{ {
$client = static::createClient(); $client = static::createClient();
@ -73,67 +68,4 @@ class SubjectControllerTest extends WebTestCase
$this->assertNotNull($subject->getCreatedBy()); $this->assertNotNull($subject->getCreatedBy());
$this->assertSame($user->getId(), $subject->getCreatedBy()->getId()); $this->assertSame($user->getId(), $subject->getCreatedBy()->getId());
} }
public function testUpdate(): void
{
$client = static::createClient();
$user = UserFactory::createOne();
$client->loginUser($user);
$subject = RestaurantFactory::createOne([
'name' => 'Old name',
'createdBy' => $user,
]);
$name = 'New name';
$client->request(
'PATCH',
'/api/subjects/' . $subject->getId(),
server: ['CONTENT_TYPE' => 'application/json'],
content: json_encode([
'name' => $name,
]),
);
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(202);
$em = static::getContainer()->get(EntityManagerInterface::class);
$em->clear();
$updated = $em->getRepository(Subject::class)->find($subject->getId());
$this->assertSame($name, $updated->getName());
}
public function testDelete(): void
{
$client = static::createClient();
$user = UserFactory::createOne();
$client->loginUser($user);
$subject = RestaurantFactory::createOne([
'name' => 'My Restaurant',
'createdBy' => $user,
]);
$id = $subject->getId();
$client->request(
'DELETE',
'/api/subjects/' . $id,
server: ['CONTENT_TYPE' => 'application/json'],
);
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(204);
$em = static::getContainer()->get(EntityManagerInterface::class);
$em->clear();
$this->assertNull(
$em->getRepository(Subject::class)->find($id)
);
}
} }

View file

@ -13,7 +13,7 @@ class LoginTest extends WebTestCase
$faker = \Zenstruck\Foundry\faker(); $faker = \Zenstruck\Foundry\faker();
$email = $faker->email(); $email = $faker->email();
$plainPwd = $faker->password(8, 12); $plainPwd = $faker->word(8);
$client->request('GET', '/account/register'); $client->request('GET', '/account/register');

View file

@ -13,7 +13,7 @@ class RegistrationControllerTest extends WebTestCase
$faker = \Zenstruck\Foundry\faker(); $faker = \Zenstruck\Foundry\faker();
$email = $faker->email(); $email = $faker->email();
$plainPwd = $faker->password(8, 12); $plainPwd = $faker->word(8);
$client->request('GET', '/account/register'); $client->request('GET', '/account/register');