mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2026-03-03 12:39:42 +00:00
Add audit functionality for Comment actions and integrate CommentSubjectConverter and CommentSubjectDisplayer
- Introduced `CommentSubjectConverter` and `CommentSubjectDisplayer` for audit conversion and display logic. - Integrated `TriggerAuditInterface` into `AccompanyingCourseCommentController` and added audit triggers for create, view, update, delete, pin, unpin, and list actions with translatable descriptions. - Added unit test `CommentSubjectConverterTest` to ensure proper behavior of the subject converter. - Enhanced French translations (`messages.fr.yml`) with audit-related labels for comment actions.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?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\PersonBundle\Audit\Displayer;
|
||||
|
||||
use Chill\MainBundle\Audit\Subject;
|
||||
use Chill\MainBundle\Audit\SubjectDisplayerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
final readonly class CommentSubjectDisplayer implements SubjectDisplayerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private TranslatorInterface $translator,
|
||||
) {}
|
||||
|
||||
public function supportsDisplay(Subject $subject, array $options = []): bool
|
||||
{
|
||||
return 'accompanying_period_comment' === $subject->type;
|
||||
}
|
||||
|
||||
public function display(Subject $subject, string $format = 'html', array $options = []): string
|
||||
{
|
||||
return $this->translator->trans('audit.accompanying_period_comment.comment_number', ['{id}' => $subject->identifiers['id']]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?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\PersonBundle\Audit\SubjectConverter;
|
||||
|
||||
use Chill\MainBundle\Audit\Subject;
|
||||
use Chill\MainBundle\Audit\SubjectBag;
|
||||
use Chill\MainBundle\Audit\SubjectConverterInterface;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerAwareInterface;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerAwareTrait;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
|
||||
/**
|
||||
* @implements SubjectConverterInterface<Comment>
|
||||
*/
|
||||
class CommentSubjectConverter implements SubjectConverterInterface, SubjectConverterManagerAwareInterface
|
||||
{
|
||||
use SubjectConverterManagerAwareTrait;
|
||||
|
||||
public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag
|
||||
{
|
||||
\assert($subject instanceof Comment);
|
||||
|
||||
$main = new SubjectBag(new Subject('accompanying_period_comment', ['id' => $subject->getId()]));
|
||||
|
||||
if (null !== $subject->getAccompanyingPeriod()) {
|
||||
$main->append($this->subjectConverterManager->getSubjectsForEntity($subject->getAccompanyingPeriod(), false));
|
||||
}
|
||||
|
||||
return $main;
|
||||
}
|
||||
|
||||
public function supportsConvert(mixed $subject): bool
|
||||
{
|
||||
return $subject instanceof Comment;
|
||||
}
|
||||
|
||||
public static function getDefaultPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\Audit\TriggerAuditInterface;
|
||||
use Chill\MainBundle\Entity\AuditTrail;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Form\AccompanyingCourseCommentType;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodCommentVoter;
|
||||
@@ -27,6 +29,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Translation\TranslatableMessage;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class AccompanyingCourseCommentController extends AbstractController
|
||||
@@ -36,6 +39,7 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
private readonly FormFactoryInterface $formFactory,
|
||||
private readonly TranslatorInterface $translator,
|
||||
private readonly ManagerRegistry $managerRegistry,
|
||||
private readonly TriggerAuditInterface $triggerAudit,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -48,6 +52,12 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
{
|
||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE_DETAILS, $accompanyingCourse);
|
||||
|
||||
$this->triggerAudit->triggerAudit(
|
||||
AuditTrail::AUDIT_LIST,
|
||||
$accompanyingCourse,
|
||||
description: new TranslatableMessage('audit.accompanying_period_comment.list')
|
||||
);
|
||||
|
||||
$em = $this->managerRegistry->getManager();
|
||||
$afterSuccessfulRedirectResponse = $this->redirectToRoute('chill_person_accompanying_period_comment_list', [
|
||||
'accompanying_period_id' => $accompanyingCourse->getId(),
|
||||
@@ -84,6 +94,8 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
if ($editForm->isSubmitted() && $editForm->isValid()) {
|
||||
$em->flush();
|
||||
|
||||
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_UPDATE, $commentEdited);
|
||||
|
||||
return $afterSuccessfulRedirectResponse;
|
||||
}
|
||||
|
||||
@@ -103,6 +115,8 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
$em->persist($newComment);
|
||||
$em->flush();
|
||||
|
||||
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_CREATE, $newComment);
|
||||
|
||||
return $afterSuccessfulRedirectResponse;
|
||||
}
|
||||
}
|
||||
@@ -129,6 +143,8 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->triggerAudit->triggerAudit(AuditTrail::AUDIT_DELETE, $comment);
|
||||
|
||||
$this->entityManager->remove($comment);
|
||||
|
||||
if ($comment->getAccompanyingPeriod()->getPinnedComment() === $comment) {
|
||||
@@ -163,6 +179,12 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
|
||||
$this->managerRegistry->getManager()->flush();
|
||||
|
||||
$this->triggerAudit->triggerAudit(
|
||||
AuditTrail::AUDIT_UPDATE,
|
||||
$comment,
|
||||
description: new TranslatableMessage('audit.accompanying_period_comment.pin')
|
||||
);
|
||||
|
||||
$this->addFlash('success', $this->translator->trans('accompanying_course.comment is pinned'));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_period_comment_list', [
|
||||
@@ -179,6 +201,12 @@ class AccompanyingCourseCommentController extends AbstractController
|
||||
|
||||
$this->managerRegistry->getManager()->flush();
|
||||
|
||||
$this->triggerAudit->triggerAudit(
|
||||
AuditTrail::AUDIT_UPDATE,
|
||||
$comment,
|
||||
description: new TranslatableMessage('audit.accompanying_period_comment.unpin')
|
||||
);
|
||||
|
||||
$this->addFlash('success', $this->translator->trans('accompanying_course.comment is unpinned'));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_period_comment_list', [
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?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\PersonBundle\Tests\Audit\SubjectConverter;
|
||||
|
||||
use Chill\MainBundle\Audit\Subject;
|
||||
use Chill\MainBundle\Audit\SubjectBag;
|
||||
use Chill\MainBundle\Audit\SubjectConverterManagerInterface;
|
||||
use Chill\PersonBundle\Audit\SubjectConverter\CommentSubjectConverter;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @covers \Chill\PersonBundle\Audit\SubjectConverter\CommentSubjectConverter
|
||||
*/
|
||||
class CommentSubjectConverterTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
private CommentSubjectConverter $converter;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->converter = new CommentSubjectConverter();
|
||||
}
|
||||
|
||||
public function testSupportsConvert(): void
|
||||
{
|
||||
$this->assertTrue($this->converter->supportsConvert($this->prophesize(Comment::class)->reveal()));
|
||||
$this->assertFalse($this->converter->supportsConvert(new \stdClass()));
|
||||
}
|
||||
|
||||
public function testConvert(): void
|
||||
{
|
||||
$comment = $this->prophesize(Comment::class);
|
||||
$comment->getId()->willReturn(456);
|
||||
|
||||
$accompanyingPeriod = $this->prophesize(AccompanyingPeriod::class);
|
||||
$comment->getAccompanyingPeriod()->willReturn($accompanyingPeriod->reveal());
|
||||
|
||||
$subjectConverterManager = $this->prophesize(SubjectConverterManagerInterface::class);
|
||||
$accompanyingPeriodSubject = new Subject('accompanying_period', ['id' => 123]);
|
||||
$accompanyingPeriodSubjectBag = new SubjectBag($accompanyingPeriodSubject);
|
||||
|
||||
$subjectConverterManager->getSubjectsForEntity($accompanyingPeriod->reveal(), false)
|
||||
->willReturn($accompanyingPeriodSubjectBag);
|
||||
|
||||
$this->converter->setSubjectConverterManager($subjectConverterManager->reveal());
|
||||
|
||||
$result = $this->converter->convert($comment->reveal());
|
||||
|
||||
$this->assertSame('accompanying_period_comment', $result->subject->type);
|
||||
$this->assertSame(['id' => 456], $result->subject->identifiers);
|
||||
|
||||
$this->assertCount(1, $result->associatedSubjects);
|
||||
$this->assertSame($accompanyingPeriodSubject, $result->associatedSubjects[0]);
|
||||
}
|
||||
}
|
||||
@@ -1608,3 +1608,8 @@ audit:
|
||||
household_member:
|
||||
not_found_with_id: 'Membre du ménage non trouvé avec identifiant {id}'
|
||||
member_in_household: 'membre du ménage'
|
||||
accompanying_period_comment:
|
||||
comment_number: "Commentaire n°{id}"
|
||||
list: "Liste des commentaires d'un parcours"
|
||||
pin: "Commentaire épinglé"
|
||||
unpin: "Commentaire désépinglé"
|
||||
|
||||
Reference in New Issue
Block a user