diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index d73a1527b28..1dfbd6cc06d 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -850,8 +850,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 6d42f2dc2ae..4666d787063 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -891,8 +891,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 59da1a15939..e0eb68cfa17 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'; @@ -172,6 +174,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $objId, $tagsAssigned )); + $this->dispatcher->dispatchTyped(new TagAssignedEvent($objectType, [$objId], $tagsAssigned)); } /** @@ -202,6 +205,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $objId, $tagIds )); + $this->dispatcher->dispatchTyped(new TagUnassignedEvent($objectType, [$objId], $tagIds)); } /** @@ -307,6 +311,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; @@ -338,6 +345,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 45de74d538f..ed51dd3ffd6 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([