From 2bb2fa50ee91fc81d7b67992b098f49cfd5b5c55 Mon Sep 17 00:00:00 2001 From: Marcel Klehr Date: Tue, 2 Sep 2025 15:37:23 +0200 Subject: [PATCH] feat(SystemTag): Add typed events for tag mapper events Signed-off-by: Marcel Klehr --- lib/composer/composer/autoload_classmap.php | 2 + lib/composer/composer/autoload_static.php | 2 + .../SystemTag/SystemTagObjectMapper.php | 10 +++ lib/public/SystemTag/TagAssignedEvent.php | 73 +++++++++++++++++++ lib/public/SystemTag/TagUnassignedEvent.php | 73 +++++++++++++++++++ .../SystemTag/SystemTagObjectMapperTest.php | 33 +++++++++ 6 files changed, 193 insertions(+) create mode 100644 lib/public/SystemTag/TagAssignedEvent.php create mode 100644 lib/public/SystemTag/TagUnassignedEvent.php diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index f591a982a39..3af23258c72 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -848,8 +848,10 @@ return array( 'OCP\\SystemTag\\MapperEvent' => $baseDir . '/lib/public/SystemTag/MapperEvent.php', 'OCP\\SystemTag\\SystemTagsEntityEvent' => $baseDir . '/lib/public/SystemTag/SystemTagsEntityEvent.php', 'OCP\\SystemTag\\TagAlreadyExistsException' => $baseDir . '/lib/public/SystemTag/TagAlreadyExistsException.php', + 'OCP\\SystemTag\\TagAssignedEvent' => $baseDir . '/lib/public/SystemTag/TagAssignedEvent.php', 'OCP\\SystemTag\\TagCreationForbiddenException' => $baseDir . '/lib/public/SystemTag/TagCreationForbiddenException.php', 'OCP\\SystemTag\\TagNotFoundException' => $baseDir . '/lib/public/SystemTag/TagNotFoundException.php', + 'OCP\\SystemTag\\TagUnassignedEvent' => $baseDir . '/lib/public/SystemTag/TagUnassignedEvent.php', 'OCP\\SystemTag\\TagUpdateForbiddenException' => $baseDir . '/lib/public/SystemTag/TagUpdateForbiddenException.php', 'OCP\\Talk\\Exceptions\\NoBackendException' => $baseDir . '/lib/public/Talk/Exceptions/NoBackendException.php', 'OCP\\Talk\\IBroker' => $baseDir . '/lib/public/Talk/IBroker.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 649886b76ca..4fe519f6be3 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -889,8 +889,10 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\SystemTag\\MapperEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/MapperEvent.php', 'OCP\\SystemTag\\SystemTagsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/SystemTagsEntityEvent.php', 'OCP\\SystemTag\\TagAlreadyExistsException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagAlreadyExistsException.php', + 'OCP\\SystemTag\\TagAssignedEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagAssignedEvent.php', 'OCP\\SystemTag\\TagCreationForbiddenException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagCreationForbiddenException.php', 'OCP\\SystemTag\\TagNotFoundException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagNotFoundException.php', + 'OCP\\SystemTag\\TagUnassignedEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagUnassignedEvent.php', 'OCP\\SystemTag\\TagUpdateForbiddenException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagUpdateForbiddenException.php', 'OCP\\Talk\\Exceptions\\NoBackendException' => __DIR__ . '/../../..' . '/lib/public/Talk/Exceptions/NoBackendException.php', 'OCP\\Talk\\IBroker' => __DIR__ . '/../../..' . '/lib/public/Talk/IBroker.php', diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php index 1fa5975dafb..afd45103a98 100644 --- a/lib/private/SystemTag/SystemTagObjectMapper.php +++ b/lib/private/SystemTag/SystemTagObjectMapper.php @@ -17,7 +17,9 @@ use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; use OCP\SystemTag\ISystemTagObjectMapper; use OCP\SystemTag\MapperEvent; +use OCP\SystemTag\TagAssignedEvent; use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagUnassignedEvent; class SystemTagObjectMapper implements ISystemTagObjectMapper { public const RELATION_TABLE = 'systemtag_object_mapping'; @@ -169,6 +171,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $objId, $tagsAssigned )); + $this->dispatcher->dispatchTyped(new TagAssignedEvent($objectType, [$objId], $tagsAssigned)); } /** @@ -199,6 +202,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $objId, $tagIds )); + $this->dispatcher->dispatchTyped(new TagUnassignedEvent($objectType, [$objId], $tagIds)); } /** @@ -304,6 +308,9 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { [(int)$tagId] )); } + if (!empty($removedObjectIds)) { + $this->dispatcher->dispatchTyped(new TagUnassignedEvent($objectType, array_map(fn ($objectId) => (string)$objectId, $removedObjectIds), [(int)$tagId])); + } if (empty($objectIds)) { return; @@ -335,6 +342,9 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { [(int)$tagId] )); } + if (!empty($addedObjectIds)) { + $this->dispatcher->dispatchTyped(new TagAssignedEvent($objectType, array_map(fn ($objectId) => (string)$objectId, $addedObjectIds), [(int)$tagId])); + } // Dispatch unassign events for removed object ids foreach ($removedObjectIds as $objectId) { diff --git a/lib/public/SystemTag/TagAssignedEvent.php b/lib/public/SystemTag/TagAssignedEvent.php new file mode 100644 index 00000000000..596e30fe0be --- /dev/null +++ b/lib/public/SystemTag/TagAssignedEvent.php @@ -0,0 +1,73 @@ + */ + protected array $objectIds; + /** @var list */ + protected array $tags; + + /** + * constructor + * + * @param list $objectIds + * @param list $tags + * @since 32.0.0 + */ + public function __construct(string $objectType, array $objectIds, array $tags) { + parent::__construct(); + $this->objectType = $objectType; + $this->objectIds = $objectIds; + $this->tags = $tags; + } + + /** + * @since 32.0.0 + */ + public function getObjectType(): string { + return $this->objectType; + } + + /** + * @return list + * @since 32.0.0 + */ + public function getObjectIds(): array { + return $this->objectIds; + } + + /** + * @return list + * @since 32.0.0 + */ + public function getTags(): array { + return $this->tags; + } + + /** + * @return array{objectType: string, objectIds: list, tagIds: list} + * @since 32.0.0 + */ + public function getWebhookSerializable(): array { + return [ + 'objectType' => $this->getObjectType(), + 'objectIds' => $this->getObjectIds(), + 'tagIds' => $this->getTags(), + ]; + } +} diff --git a/lib/public/SystemTag/TagUnassignedEvent.php b/lib/public/SystemTag/TagUnassignedEvent.php new file mode 100644 index 00000000000..8d7fbd4a93b --- /dev/null +++ b/lib/public/SystemTag/TagUnassignedEvent.php @@ -0,0 +1,73 @@ + */ + protected array $objectIds; + /** @var list */ + protected array $tags; + + /** + * constructor + * + * @param list $objectIds + * @param list $tags + * @since 32.0.0 + */ + public function __construct(string $objectType, array $objectIds, array $tags) { + parent::__construct(); + $this->objectType = $objectType; + $this->objectIds = $objectIds; + $this->tags = $tags; + } + + /** + * @since 32.0.0 + */ + public function getObjectType(): string { + return $this->objectType; + } + + /** + * @return list + * @since 32.0.0 + */ + public function getObjectIds(): array { + return $this->objectIds; + } + + /** + * @return list + * @since 32.0.0 + */ + public function getTags(): array { + return $this->tags; + } + + /** + * @return array{objectType: string, objectIds: list, tagIds: list} + * @since 32.0.0 + */ + public function getWebhookSerializable(): array { + return [ + 'objectType' => $this->getObjectType(), + 'objectIds' => $this->getObjectIds(), + 'tagIds' => $this->getTags(), + ]; + } +} diff --git a/tests/lib/SystemTag/SystemTagObjectMapperTest.php b/tests/lib/SystemTag/SystemTagObjectMapperTest.php index a43bda3b659..8e216dc45bc 100644 --- a/tests/lib/SystemTag/SystemTagObjectMapperTest.php +++ b/tests/lib/SystemTag/SystemTagObjectMapperTest.php @@ -11,13 +11,16 @@ namespace Test\SystemTag; use OC\SystemTag\SystemTag; use OC\SystemTag\SystemTagManager; use OC\SystemTag\SystemTagObjectMapper; +use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; use OCP\Server; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; use OCP\SystemTag\ISystemTagObjectMapper; +use OCP\SystemTag\TagAssignedEvent; use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagUnassignedEvent; use Test\TestCase; /** @@ -208,16 +211,46 @@ class SystemTagObjectMapperTest extends TestCase { } public function testAssignUnassignTags(): void { + $event = null; + $this->dispatcher->expects($this->any())->method('dispatchTyped')->willReturnCallback(function (Event $e) use (&$event) { + $event = $e; + }); + $this->tagMapper->unassignTags('1', 'testtype', [$this->tag1->getId()]); + $this->assertNotNull($event); + $this->assertEquals(TagUnassignedEvent::class, $event::class); + $this->assertEquals('testtype', $event->getObjectType()); + $this->assertCount(1, $event->getObjectIds()); + $this->assertEquals('1', current($event->getObjectIds())); + $this->assertCount(1, $event->getTags()); + $this->assertEquals($this->tag1->getId(), current($event->getTags())); + $tagIdMapping = $this->tagMapper->getTagIdsForObjects('1', 'testtype'); $this->assertEquals([ 1 => [$this->tag2->getId()], ], $tagIdMapping); $this->tagMapper->assignTags('1', 'testtype', [$this->tag1->getId()]); + + $this->assertNotNull($event); + $this->assertEquals(TagAssignedEvent::class, $event::class); + $this->assertEquals('testtype', $event->getObjectType()); + $this->assertCount(1, $event->getObjectIds()); + $this->assertEquals('1', current($event->getObjectIds())); + $this->assertCount(1, $event->getTags()); + $this->assertEquals($this->tag1->getId(), current($event->getTags())); + $this->tagMapper->assignTags('1', 'testtype', $this->tag3->getId()); + $this->assertNotNull($event); + $this->assertEquals(TagAssignedEvent::class, $event::class); + $this->assertEquals('testtype', $event->getObjectType()); + $this->assertCount(1, $event->getObjectIds()); + $this->assertEquals('1', current($event->getObjectIds())); + $this->assertCount(1, $event->getTags()); + $this->assertEquals($this->tag3->getId(), current($event->getTags())); + $tagIdMapping = $this->tagMapper->getTagIdsForObjects('1', 'testtype'); $this->assertEquals([