From 22ace0c66e7c62bc99810a4eec150e457204547e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Fri, 13 Feb 2026 19:22:08 +0100 Subject: [PATCH] WIP: render entities --- .../Exception/DisplaySubjectException.php | 20 ++++++++++ src/Bundle/ChillMainBundle/Audit/Subject.php | 9 +++++ .../Audit/SubjectConverterManager.php | 17 ++++++++ .../SubjectConverterManagerInterface.php | 2 + .../Audit/SubjectDisplayerInterface.php | 27 +++++++++++++ .../Audit/Twig/SubjectRenderRuntimeTwig.php | 29 ++++++++++++++ .../Audit/Twig/SubjectRenderTwig.php | 25 ++++++++++++ .../ChillMainBundle/ChillMainBundle.php | 3 ++ .../Controller/AuditTrailSearchController.php | 40 +++++++++++++++++++ .../views/AuditTrail/_list_item.html.twig | 21 ++++++++++ .../Resources/views/AuditTrail/list.html.twig | 13 ++++++ .../config/services/audit.yaml | 3 ++ .../translations/messages.fr.yml | 10 +++++ .../AccompanyingPeriodSubjectDisplayer.php | 34 ++++++++++++++++ ...AccompanyingPeriodWorkSubjectDisplayer.php | 35 ++++++++++++++++ .../Displayer/PersonSubjectDisplayer.php | 37 +++++++++++++++++ .../views/Audit/accompanying_period.html.twig | 1 + .../Audit/accompanying_period_work.html.twig | 2 + .../Resources/views/Audit/person.html.twig | 1 + .../translations/messages.fr.yml | 8 ++++ 20 files changed, 337 insertions(+) create mode 100644 src/Bundle/ChillMainBundle/Audit/Exception/DisplaySubjectException.php create mode 100644 src/Bundle/ChillMainBundle/Audit/SubjectDisplayerInterface.php create mode 100644 src/Bundle/ChillMainBundle/Audit/Twig/SubjectRenderRuntimeTwig.php create mode 100644 src/Bundle/ChillMainBundle/Audit/Twig/SubjectRenderTwig.php create mode 100644 src/Bundle/ChillMainBundle/Controller/AuditTrailSearchController.php create mode 100644 src/Bundle/ChillMainBundle/Resources/views/AuditTrail/_list_item.html.twig create mode 100644 src/Bundle/ChillMainBundle/Resources/views/AuditTrail/list.html.twig create mode 100644 src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodSubjectDisplayer.php create mode 100644 src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodWorkSubjectDisplayer.php create mode 100644 src/Bundle/ChillPersonBundle/Audit/Displayer/PersonSubjectDisplayer.php create mode 100644 src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period.html.twig create mode 100644 src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period_work.html.twig create mode 100644 src/Bundle/ChillPersonBundle/Resources/views/Audit/person.html.twig diff --git a/src/Bundle/ChillMainBundle/Audit/Exception/DisplaySubjectException.php b/src/Bundle/ChillMainBundle/Audit/Exception/DisplaySubjectException.php new file mode 100644 index 000000000..e22899b71 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Audit/Exception/DisplaySubjectException.php @@ -0,0 +1,20 @@ +identifiers, 't' => $this->type]; } + public static function fromArray(array $subject): self + { + return new self($subject['t'], array_filter( + $subject, + static fn (string $key) => 't' !== $key, + ARRAY_FILTER_USE_KEY + )); + } + public function isEqual(Subject $subject): bool { if ($subject->type !== $this->type) { diff --git a/src/Bundle/ChillMainBundle/Audit/SubjectConverterManager.php b/src/Bundle/ChillMainBundle/Audit/SubjectConverterManager.php index 28116f727..6253692a2 100644 --- a/src/Bundle/ChillMainBundle/Audit/SubjectConverterManager.php +++ b/src/Bundle/ChillMainBundle/Audit/SubjectConverterManager.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle\Audit; use Chill\MainBundle\Audit\Exception\ConvertSubjectException; +use Chill\MainBundle\Audit\Exception\DisplaySubjectException; final readonly class SubjectConverterManager implements SubjectConverterManagerInterface { @@ -20,6 +21,11 @@ final readonly class SubjectConverterManager implements SubjectConverterManagerI * @var iterable */ private iterable $converters, + + /** + * @var iterable + */ + private iterable $displayers, ) {} public function getSubjectsForEntity(mixed $subject, bool $includeAssociated = false): SubjectBag @@ -36,4 +42,15 @@ final readonly class SubjectConverterManager implements SubjectConverterManagerI throw new ConvertSubjectException($subject); } + + public function display(Subject $subject, array $options = []): string + { + foreach ($this->displayers as $displayer) { + if ($displayer->supportsDisplay($subject, $options = [])) { + return $displayer->display($subject, $options = []); + } + } + + throw new DisplaySubjectException($subject->asArray()); + } } diff --git a/src/Bundle/ChillMainBundle/Audit/SubjectConverterManagerInterface.php b/src/Bundle/ChillMainBundle/Audit/SubjectConverterManagerInterface.php index aebff51e8..5925cf680 100644 --- a/src/Bundle/ChillMainBundle/Audit/SubjectConverterManagerInterface.php +++ b/src/Bundle/ChillMainBundle/Audit/SubjectConverterManagerInterface.php @@ -14,4 +14,6 @@ namespace Chill\MainBundle\Audit; interface SubjectConverterManagerInterface { public function getSubjectsForEntity(object $subject, bool $includeAssociated = false): SubjectBag; + + public function display(Subject $subject): string; } diff --git a/src/Bundle/ChillMainBundle/Audit/SubjectDisplayerInterface.php b/src/Bundle/ChillMainBundle/Audit/SubjectDisplayerInterface.php new file mode 100644 index 000000000..63e24ff5c --- /dev/null +++ b/src/Bundle/ChillMainBundle/Audit/SubjectDisplayerInterface.php @@ -0,0 +1,27 @@ +subjectConverterManager->display( + $subject instanceof Subject ? $subject : Subject::fromArray($subject), + $options + ); + } +} diff --git a/src/Bundle/ChillMainBundle/Audit/Twig/SubjectRenderTwig.php b/src/Bundle/ChillMainBundle/Audit/Twig/SubjectRenderTwig.php new file mode 100644 index 000000000..1ffd694ff --- /dev/null +++ b/src/Bundle/ChillMainBundle/Audit/Twig/SubjectRenderTwig.php @@ -0,0 +1,25 @@ + ['html']]), + ]; + } +} diff --git a/src/Bundle/ChillMainBundle/ChillMainBundle.php b/src/Bundle/ChillMainBundle/ChillMainBundle.php index a3222a685..0ed06cb4e 100644 --- a/src/Bundle/ChillMainBundle/ChillMainBundle.php +++ b/src/Bundle/ChillMainBundle/ChillMainBundle.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace Chill\MainBundle; use Chill\MainBundle\Audit\SubjectConverterInterface; +use Chill\MainBundle\Audit\SubjectDisplayerInterface; use Chill\MainBundle\Cron\CronJobInterface; use Chill\MainBundle\CRUD\CompilerPass\CRUDControllerCompilerPass; use Chill\MainBundle\DependencyInjection\CompilerPass\ACLFlagsCompilerPass; @@ -67,6 +68,8 @@ class ChillMainBundle extends Bundle ->addTag('chill_main.notification_flag_provider'); $container->registerForAutoconfiguration(SubjectConverterInterface::class) ->addTag('chill_main.audit_subject_converter'); + $container->registerForAutoconfiguration(SubjectDisplayerInterface::class) + ->addTag('chill_main.audit_subject_displayer'); $container->addCompilerPass(new SearchableServicesCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); $container->addCompilerPass(new ConfigConsistencyCompilerPass(), \Symfony\Component\DependencyInjection\Compiler\PassConfig::TYPE_BEFORE_OPTIMIZATION, 0); diff --git a/src/Bundle/ChillMainBundle/Controller/AuditTrailSearchController.php b/src/Bundle/ChillMainBundle/Controller/AuditTrailSearchController.php new file mode 100644 index 000000000..9f11b13af --- /dev/null +++ b/src/Bundle/ChillMainBundle/Controller/AuditTrailSearchController.php @@ -0,0 +1,40 @@ +auditTrailRepository->findByCriteria([]); + + return new Response($this->twig->render('@ChillMain/AuditTrail/list.html.twig', [ + 'auditTrails' => $auditTrails, + ])); + } +} diff --git a/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/_list_item.html.twig b/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/_list_item.html.twig new file mode 100644 index 000000000..bfa0fdd68 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/_list_item.html.twig @@ -0,0 +1,21 @@ +
+
+
+
+
{{ audit.mainSubject|chill_render_audit_subject }} | {{ ('audit_trail.action.'~audit.action)|trans }}{% if audit.description is not empty %} | {{ audit.description }}{% endif %}
+ {% if audit.user %}
{{ audit.user|chill_entity_render_box({'at_date': audit.occurredAt}) }}
{% endif %} +
+
+ {{ audit.occurredAt|format_datetime('medium', 'medium') }} +
+
+
+ {% if audit.subjects|length > 0 %} +
+ {{ 'audit_trail.list.associated_subject'|trans }}:  + {% for s in audit.subjects %} + {{ s|chill_render_audit_subject }}{% if not loop.last %}, {% endif %} + {% endfor %} +
+ {% endif %} +
diff --git a/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/list.html.twig b/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/list.html.twig new file mode 100644 index 000000000..c1a5f54bc --- /dev/null +++ b/src/Bundle/ChillMainBundle/Resources/views/AuditTrail/list.html.twig @@ -0,0 +1,13 @@ +{% extends '@ChillMain/layout.html.twig' %} + +{% block title 'audit_trail.list.title'|trans %} + +{% block content %} +

{{ block('title') }}

+ +
+ {% for audit in auditTrails %} + {{ include('@ChillMain/AuditTrail/_list_item.html.twig') }} + {% endfor %} +
+{% endblock %} diff --git a/src/Bundle/ChillMainBundle/config/services/audit.yaml b/src/Bundle/ChillMainBundle/config/services/audit.yaml index 173bfe7e4..2acd83b02 100644 --- a/src/Bundle/ChillMainBundle/config/services/audit.yaml +++ b/src/Bundle/ChillMainBundle/config/services/audit.yaml @@ -10,9 +10,12 @@ services: - '../../Audit/AuditEvent.php' - '../../Audit/SubjectConverterManagerAwareInterface.php' - '../../Audit/SubjectConverterManagerAwareTrait.php' + - '../../Audit/SubjectConverterInterface.php' + - '../../Audit/SubjectDisplayerInterface.php' - '../../Audit/Exception/' - '../../Audit/Exception/*' Chill\MainBundle\Audit\SubjectConverterManager: arguments: $converters: !tagged_iterator chill_main.audit_subject_converter + $displayers: !tagged_iterator chill_main.audit_subject_displayer diff --git a/src/Bundle/ChillMainBundle/translations/messages.fr.yml b/src/Bundle/ChillMainBundle/translations/messages.fr.yml index 387c16662..d15422dff 100644 --- a/src/Bundle/ChillMainBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillMainBundle/translations/messages.fr.yml @@ -1011,3 +1011,13 @@ editor: login_page: logo_alt: "Logo de Chill" + +audit_trail: + action: + view: Visualisation + update: Mise à jour + create: Création + delete: Suppression + list: + title: Liste des événements + associated_subject: Entités associées diff --git a/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodSubjectDisplayer.php b/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodSubjectDisplayer.php new file mode 100644 index 000000000..7057d24dc --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodSubjectDisplayer.php @@ -0,0 +1,34 @@ +type; + } + + public function display(Subject $subject, array $options = []): string + { + return $this->twig->render( + '@ChillPerson/Audit/accompanying_period.html.twig', + ['id' => $subject->identifiers['id']] + ); + } +} diff --git a/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodWorkSubjectDisplayer.php b/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodWorkSubjectDisplayer.php new file mode 100644 index 000000000..7c934735f --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Audit/Displayer/AccompanyingPeriodWorkSubjectDisplayer.php @@ -0,0 +1,35 @@ +type; + } + + public function display(Subject $subject, array $options = []): string + { + $work = $this->accompanyingPeriodWorkRepository->find($subject->identifiers['id']); + + return $this->twig->render('@ChillPerson/Audit/accompanying_period_work.html.twig', [ + 'work' => $work, 'id' => $subject->identifiers['id']]); + } +} diff --git a/src/Bundle/ChillPersonBundle/Audit/Displayer/PersonSubjectDisplayer.php b/src/Bundle/ChillPersonBundle/Audit/Displayer/PersonSubjectDisplayer.php new file mode 100644 index 000000000..5699cb56d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Audit/Displayer/PersonSubjectDisplayer.php @@ -0,0 +1,37 @@ +type; + } + + public function display(Subject $subject, array $options = []): string + { + $person = $this->personRepository->find($subject->identifiers['id']); + + return $this->twig->render('@ChillPerson/Audit/person.html.twig', ['id' => $subject->identifiers['id'], 'person' => $person]); + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period.html.twig new file mode 100644 index 000000000..8362cd7f7 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period.html.twig @@ -0,0 +1 @@ +{{ 'audit.accompanying_period.accompanying_period_number'|trans({'{id}': id}) }} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period_work.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period_work.html.twig new file mode 100644 index 000000000..6402dc5d4 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Audit/accompanying_period_work.html.twig @@ -0,0 +1,2 @@ +{{ 'audit.accompanying_period_work.accompanying_period_work_number'|trans({'id': id}) }} + {%- if work is not null %}: {{ work.socialAction.title|localize_translatable_string }}{% endif %} diff --git a/src/Bundle/ChillPersonBundle/Resources/views/Audit/person.html.twig b/src/Bundle/ChillPersonBundle/Resources/views/Audit/person.html.twig new file mode 100644 index 000000000..1462dcf8d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/views/Audit/person.html.twig @@ -0,0 +1 @@ +{% if person is not null %}{{ person|chill_entity_render_box }} {% else %}{{ 'audit.person.person_not_found_with_id'|trans({'id': id}) }}{% endif %} diff --git a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml index d35096199..101573752 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillPersonBundle/translations/messages.fr.yml @@ -1574,3 +1574,11 @@ my_parcours_filters: document_duplicate: to_evaluation_success: "Le document a été dupliquer" + +audit: + person: + person_not_found_with_id: "Personne inconnue avec l'identifiant {id}" + accompanying_period: + accompanying_period_number: "Parcours n°{id}" + accompanying_period_work: + accompanying_period_work_number: "Action d'accompagnement n°{id}"