mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-14 14:24:24 +00:00
Add functionality to add comments to tickets
A new controller, 'AddCommentController', has been added. This controller implements the 'AddCommentCommandHandler', allowing users to add comments to tickets. Additionally, corresponding test cases were implemented. The Ticket entity was also updated to accept and manage comments. API endpoint specs were updated to reflect these changes.
This commit is contained in:
parent
56a1a488de
commit
613ee8b186
@ -64,3 +64,32 @@ paths:
|
||||
description: "ACCEPTED"
|
||||
422:
|
||||
description: "UNPROCESSABLE ENTITY"
|
||||
|
||||
/1.0/ticket/{id}/comment/add:
|
||||
post:
|
||||
tags:
|
||||
- ticket
|
||||
summary: Add a comment to an existing ticket
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
description: The ticket id
|
||||
schema:
|
||||
type: integer
|
||||
format: integer
|
||||
minimum: 1
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
responses:
|
||||
201:
|
||||
description: "ACCEPTED"
|
||||
422:
|
||||
description: "UNPROCESSABLE ENTITY"
|
||||
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Action\Ticket;
|
||||
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
final readonly class AddCommentCommand
|
||||
{
|
||||
public function __construct(
|
||||
#[Assert\NotBlank()]
|
||||
#[Assert\NotNull]
|
||||
#[Serializer\Groups(['write'])]
|
||||
public ?string $content = null,
|
||||
) {}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Action\Ticket\Handler;
|
||||
|
||||
use Chill\TicketBundle\Action\Ticket\AddCommentCommand;
|
||||
use Chill\TicketBundle\Entity\Comment;
|
||||
use Chill\TicketBundle\Entity\Ticket;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
final readonly class AddCommentCommandHandler
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager,
|
||||
) {}
|
||||
|
||||
public function handle(Ticket $ticket, AddCommentCommand $command): void
|
||||
{
|
||||
$comment = new Comment($command->content, $ticket);
|
||||
|
||||
$this->entityManager->persist($comment);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Controller;
|
||||
|
||||
use Chill\TicketBundle\Action\Ticket\AddCommentCommand;
|
||||
use Chill\TicketBundle\Action\Ticket\Handler\AddCommentCommandHandler;
|
||||
use Chill\TicketBundle\Entity\Ticket;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
final readonly class AddCommentController
|
||||
{
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
private SerializerInterface $serializer,
|
||||
private ValidatorInterface $validator,
|
||||
private AddCommentCommandHandler $addCommentCommandHandler,
|
||||
private EntityManagerInterface $entityManager,
|
||||
) {}
|
||||
|
||||
#[Route('/api/1.0/ticket/{id}/comment/add', name: 'chill_ticket_comment_add', methods: ['POST'])]
|
||||
public function __invoke(Ticket $ticket, Request $request): Response
|
||||
{
|
||||
if (!$this->security->isGranted('ROLE_USER')) {
|
||||
throw new AccessDeniedHttpException('Only user can add ticket comments.');
|
||||
}
|
||||
|
||||
$command = $this->serializer->deserialize($request->getContent(), AddCommentCommand::class, 'json', ['groups' => 'write']);
|
||||
|
||||
$errors = $this->validator->validate($command);
|
||||
|
||||
if (count($errors) > 0) {
|
||||
return new JsonResponse(
|
||||
$this->serializer->serialize($errors, 'json'),
|
||||
Response::HTTP_UNPROCESSABLE_ENTITY,
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$this->addCommentCommandHandler->handle($ticket, $command);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(
|
||||
$this->serializer->serialize($ticket, 'json', ['groups' => 'read']),
|
||||
Response::HTTP_CREATED,
|
||||
[],
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
@ -31,12 +31,14 @@ class Comment implements TrackCreationInterface, TrackUpdateInterface
|
||||
private ?int $id = null;
|
||||
|
||||
public function __construct(
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])]
|
||||
private string $content,
|
||||
#[ORM\ManyToOne(targetEntity: Ticket::class, inversedBy: 'comments')]
|
||||
#[JoinColumn(nullable: false)]
|
||||
private Ticket $ticket,
|
||||
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])]
|
||||
private string $content = ''
|
||||
) {}
|
||||
) {
|
||||
$ticket->addComment($this);
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
|
@ -104,16 +104,27 @@ class Ticket implements TrackCreationInterface, TrackUpdateInterface
|
||||
->getValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal use @see{Comment::__construct} instead
|
||||
*/
|
||||
public function addComment(Comment $comment): void
|
||||
{
|
||||
$this->comments->add($comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a PersonHistory.
|
||||
*
|
||||
* This method should not be used, use @see{PersonHistory::__construct()} insted.
|
||||
* @internal use @see{PersonHistory::__construct} instead
|
||||
*/
|
||||
public function addPersonHistory(PersonHistory $personHistory): void
|
||||
{
|
||||
$this->personHistories->add($personHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal use @see{MotiveHistory::__construct} instead
|
||||
*/
|
||||
public function addMotiveHistory(MotiveHistory $motiveHistory): void
|
||||
{
|
||||
$this->motiveHistories->add($motiveHistory);
|
||||
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Tests\Action\Ticket\Handler;
|
||||
|
||||
use Chill\TicketBundle\Action\Ticket\AddCommentCommand;
|
||||
use Chill\TicketBundle\Action\Ticket\Handler\AddCommentCommandHandler;
|
||||
use Chill\TicketBundle\Entity\Comment;
|
||||
use Chill\TicketBundle\Entity\Ticket;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class AddCommentCommandHandlerTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
public function testAddComment(): void
|
||||
{
|
||||
$handler = $this->buildCommand();
|
||||
|
||||
$ticket = new Ticket();
|
||||
$command = new AddCommentCommand(content: 'test');
|
||||
|
||||
$handler->handle($ticket, $command);
|
||||
|
||||
self::assertCount(1, $ticket->getComments());
|
||||
self::assertEquals('test', $ticket->getComments()[0]->getContent());
|
||||
}
|
||||
|
||||
private function buildCommand(): AddCommentCommandHandler
|
||||
{
|
||||
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||
$entityManager->persist(Argument::type(Comment::class))->shouldBeCalled();
|
||||
|
||||
return new AddCommentCommandHandler($entityManager->reveal());
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Tests\Controller;
|
||||
|
||||
use Chill\TicketBundle\Action\Ticket\Handler\AddCommentCommandHandler;
|
||||
use Chill\TicketBundle\Controller\AddCommentController;
|
||||
use Chill\TicketBundle\Entity\Comment;
|
||||
use Chill\TicketBundle\Entity\Ticket;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Prophecy\Argument;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
class AddCommentControllerTest extends KernelTestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private SerializerInterface $serializer;
|
||||
private ValidatorInterface $validator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$this->validator = self::getContainer()->get(ValidatorInterface::class);
|
||||
$this->serializer = self::getContainer()->get(SerializerInterface::class);
|
||||
}
|
||||
|
||||
public function testAddComment(): void
|
||||
{
|
||||
$controller = $this->buildController(willFlush: true);
|
||||
|
||||
$ticket = new Ticket();
|
||||
$request = new Request(content: <<<'JSON'
|
||||
{"content": "test"}
|
||||
JSON);
|
||||
|
||||
$response = $controller->__invoke($ticket, $request);
|
||||
|
||||
self::assertEquals(201, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testAddCommentWithBlankContent(): void
|
||||
{
|
||||
$controller = $this->buildController(willFlush: false);
|
||||
|
||||
$ticket = new Ticket();
|
||||
$request = new Request(content: <<<'JSON'
|
||||
{"content": ""}
|
||||
JSON);
|
||||
|
||||
$response = $controller->__invoke($ticket, $request);
|
||||
|
||||
self::assertEquals(422, $response->getStatusCode());
|
||||
|
||||
$request = new Request(content: <<<'JSON'
|
||||
{"content": null}
|
||||
JSON);
|
||||
|
||||
$response = $controller->__invoke($ticket, $request);
|
||||
|
||||
self::assertEquals(422, $response->getStatusCode());
|
||||
}
|
||||
|
||||
private function buildController(bool $willFlush): AddCommentController
|
||||
{
|
||||
$security = $this->prophesize(Security::class);
|
||||
$security->isGranted('ROLE_USER')->willReturn(true);
|
||||
|
||||
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||
|
||||
if ($willFlush) {
|
||||
$entityManager->persist(Argument::type(Comment::class))->shouldBeCalled();
|
||||
$entityManager->flush()->shouldBeCalled();
|
||||
}
|
||||
|
||||
$commandHandler = new AddCommentCommandHandler($entityManager->reveal());
|
||||
|
||||
return new AddCommentController(
|
||||
$security->reveal(),
|
||||
$this->serializer,
|
||||
$this->validator,
|
||||
$commandHandler,
|
||||
$entityManager->reveal(),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user