diff --git a/src/Bundle/ChillDocStoreBundle/Audit/Displayer/StoredObjectSubjectDisplayer.php b/src/Bundle/ChillDocStoreBundle/Audit/Displayer/StoredObjectSubjectDisplayer.php new file mode 100644 index 000000000..9b33b3efe --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Audit/Displayer/StoredObjectSubjectDisplayer.php @@ -0,0 +1,51 @@ +type; + } + + public function display(Subject $subject, string $format = 'html', array $options = []): string + { + $id = $subject->identifiers['id']; + $storedObject = $this->storedObjectRepository->find($id); + + if ('html' === $format) { + return $this->twig->render('@ChillDocStore/Audit/stored_object.html.twig', [ + 'id' => $id, + 'storedObject' => $storedObject, + ]); + } + + if (null !== $storedObject) { + return $this->translator->trans('audit.stored_object.display_with_title', ['{id}' => $id, '{title}' => $storedObject->getTitle()]); + } + + return $this->translator->trans('audit.stored_object.display', ['{id}' => $id]); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Audit/SubjectConverter/StoredObjectSubjectConverter.php b/src/Bundle/ChillDocStoreBundle/Audit/SubjectConverter/StoredObjectSubjectConverter.php new file mode 100644 index 000000000..72b83be89 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Audit/SubjectConverter/StoredObjectSubjectConverter.php @@ -0,0 +1,54 @@ + + */ +final class StoredObjectSubjectConverter implements SubjectConverterInterface, SubjectConverterManagerAwareInterface +{ + use SubjectConverterManagerAwareTrait; + + public function __construct(private readonly AssociatedEntityToStoredObjectRepository $associatedEntityToStoredObjectRepository) {} + + public function convert(mixed $subject, bool $includeAssociated = false): SubjectBag + { + $main = new SubjectBag(new Subject('stored_object', ['id' => $subject->getId()])); + $associated = $this->associatedEntityToStoredObjectRepository->findAssociatedEntityToStoredObject($subject); + + if (null !== $associated) { + $main->append( + $this->subjectConverterManager->getSubjectsForEntity($associated, $includeAssociated) + ); + } + + return $main; + } + + public function supportsConvert(mixed $subject): bool + { + return $subject instanceof StoredObject; + } + + public static function getDefaultPriority(): int + { + return 0; + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/Audit/stored_object.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/Audit/stored_object.html.twig new file mode 100644 index 000000000..21af85069 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Resources/views/Audit/stored_object.html.twig @@ -0,0 +1 @@ +{{ 'audit.stored_object.display'|trans({'{{id}': id }) }}{% if storedObject is not null %} - {{ storedObject.title}}{% endif %} diff --git a/src/Bundle/ChillDocStoreBundle/tests/Audit/Displayer/StoredObjectSubjectDisplayerTest.php b/src/Bundle/ChillDocStoreBundle/tests/Audit/Displayer/StoredObjectSubjectDisplayerTest.php new file mode 100644 index 000000000..e4865d25b --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/tests/Audit/Displayer/StoredObjectSubjectDisplayerTest.php @@ -0,0 +1,104 @@ +repository = $this->createMock(StoredObjectRepositoryInterface::class); + $this->twig = $this->createMock(Environment::class); + $this->translator = $this->createMock(TranslatorInterface::class); + + $this->displayer = new StoredObjectSubjectDisplayer($this->repository, $this->twig, $this->translator); + } + + public function testSupportsDisplay(): void + { + $this->assertTrue($this->displayer->supportsDisplay(new Subject('stored_object', ['id' => 1]))); + $this->assertFalse($this->displayer->supportsDisplay(new Subject('person', ['id' => 1]))); + } + + public function testDisplayHtml(): void + { + $subject = new Subject('stored_object', ['id' => 123]); + $storedObject = $this->createMock(StoredObject::class); + + $this->repository->expects($this->once()) + ->method('find') + ->with(123) + ->willReturn($storedObject); + + $this->twig->expects($this->once()) + ->method('render') + ->with('@ChillDocStore/Audit/stored_object.html.twig', [ + 'id' => 123, + 'storedObject' => $storedObject, + ]) + ->willReturn('Rendered HTML'); + + $result = $this->displayer->display($subject, 'html'); + $this->assertSame('Rendered HTML', $result); + } + + public function testDisplayString(): void + { + $subject = new Subject('stored_object', ['id' => 123]); + $storedObject = $this->createMock(StoredObject::class); + $storedObject->method('getTitle')->willReturn('Document Title'); + $this->translator->method('trans')->with('audit.stored_object.display_with_title', ['{id}' => 123, '{title}' => 'Document Title']) + ->willReturn('translated'); + + $this->repository->expects($this->once()) + ->method('find') + ->with(123) + ->willReturn($storedObject); + + $result = $this->displayer->display($subject, 'string'); + $this->assertSame('translated', $result); + } + + public function testDisplayStringWithNotFoundObject(): void + { + $this->translator->method('trans')->with('audit.stored_object.display', ['{id}' => 123]) + ->willReturn('translated'); + + $subject = new Subject('stored_object', ['id' => 123]); + + $this->repository->expects($this->once()) + ->method('find') + ->with(123) + ->willReturn(null); + + $result = $this->displayer->display($subject, 'string'); + $this->assertSame('translated', $result); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/tests/Audit/SubjectConverter/StoredObjectSubjectConverterTest.php b/src/Bundle/ChillDocStoreBundle/tests/Audit/SubjectConverter/StoredObjectSubjectConverterTest.php new file mode 100644 index 000000000..0c3055911 --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/tests/Audit/SubjectConverter/StoredObjectSubjectConverterTest.php @@ -0,0 +1,85 @@ +prophesize(AssociatedEntityToStoredObjectRepository::class); + $subjectConverterManager = $this->prophesize(SubjectConverterManagerInterface::class); + $converter = new StoredObjectSubjectConverter($associatedEntity->reveal()); + $converter->setSubjectConverterManager($subjectConverterManager->reveal()); + + $this->assertTrue($converter->supportsConvert($this->createMock(StoredObject::class))); + $this->assertFalse($converter->supportsConvert(new \stdClass())); + } + + public function testConvertWithoutAssociated(): void + { + $storedObject = new StoredObject(); + $reflection = new \ReflectionClass($storedObject); + $id = $reflection->getProperty('id'); + $id->setValue($storedObject, 123); + + $associatedEntity = $this->prophesize(AssociatedEntityToStoredObjectRepository::class); + $subjectConverterManager = $this->prophesize(SubjectConverterManagerInterface::class); + $associatedEntity->findAssociatedEntityToStoredObject($storedObject)->willReturn(null)->shouldBeCalled(); + + $converter = new StoredObjectSubjectConverter($associatedEntity->reveal()); + $converter->setSubjectConverterManager($subjectConverterManager->reveal()); + + $subjectBag = $converter->convert($storedObject); + + $this->assertSame('stored_object', $subjectBag->subject->type); + $this->assertSame(['id' => 123], $subjectBag->subject->identifiers); + } + + public function testConvertWithAssociated(): void + { + $storedObject = new StoredObject(); + $reflection = new \ReflectionClass($storedObject); + $id = $reflection->getProperty('id'); + $id->setValue($storedObject, 123); + + $associatedEntity = $this->prophesize(AssociatedEntityToStoredObjectRepository::class); + $subjectConverterManager = $this->prophesize(SubjectConverterManagerInterface::class); + $associatedEntity->findAssociatedEntityToStoredObject($storedObject)->willReturn($associated = new \stdClass()); + $subjectConverterManager->getSubjectsForEntity($associated, true)->willReturn(new SubjectBag($s = new Subject('associated', ['id' => 456]))); + + $converter = new StoredObjectSubjectConverter($associatedEntity->reveal()); + $converter->setSubjectConverterManager($subjectConverterManager->reveal()); + + $subjectBag = $converter->convert($storedObject, true); + + $this->assertSame('stored_object', $subjectBag->subject->type); + $this->assertSame(['id' => 123], $subjectBag->subject->identifiers); + $this->assertCount(1, $subjectBag->associatedSubjects); + $this->assertSame($s, $subjectBag->associatedSubjects[0]); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/translations/messages.fr.yml b/src/Bundle/ChillDocStoreBundle/translations/messages.fr.yml index 94db395df..7979fdad3 100644 --- a/src/Bundle/ChillDocStoreBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillDocStoreBundle/translations/messages.fr.yml @@ -128,3 +128,8 @@ signatures: see_all_pages: Voir toutes les pages all_pages: Toutes les pages go_to_signature_unique: Aller à la zone de signature + +audit: + stored_object: + display: Document n°{id} + display_with_title: Document n°{id} - {title}