Skip to content

Commit 33ad9a6

Browse files
[CHA-609] Add support for draft messages (#139)
* feat: Add support for draft messages * fix: try to fix tests * fixing test Signed-off-by: Lennart Kuijs <[email protected]> --------- Signed-off-by: Lennart Kuijs <[email protected]> Co-authored-by: Lennart Kuijs <[email protected]>
1 parent d396bc3 commit 33ad9a6

File tree

3 files changed

+238
-19
lines changed

3 files changed

+238
-19
lines changed

lib/GetStream/StreamChat/Channel.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,4 +640,43 @@ public function updateMemberPartial(string $userId, ?array $set = null, ?array $
640640
];
641641
return $this->client->patch($this->getUrl() . "/member/" . urlencode($userId), $update);
642642
}
643+
644+
/**
645+
* Creates a draft message in the channel.
646+
* @link https://getstream.io/chat/docs/php/drafts/?language=php#creating-a-draft-message
647+
* @throws StreamException
648+
*/
649+
public function createDraft(array $message, string $userId): StreamResponse
650+
{
651+
$payload = ["message" => self::addUser($message, $userId)];
652+
return $this->client->post($this->getUrl() . "/draft", $payload);
653+
}
654+
655+
/**
656+
* Deletes a draft message in the channel.
657+
* @link https://getstream.io/chat/docs/php/drafts/?language=php#deleting-a-draft-message
658+
* @throws StreamException
659+
*/
660+
public function deleteDraft(string $userId, ?string $parentId = null): StreamResponse
661+
{
662+
$params = ["user_id" => $userId];
663+
if ($parentId !== null) {
664+
$params["parent_id"] = $parentId;
665+
}
666+
return $this->client->delete($this->getUrl() . "/draft", $params);
667+
}
668+
669+
/**
670+
* Retrieves a draft message in the channel.
671+
* @link https://getstream.io/chat/docs/php/drafts/?language=php#loading-a-draft-message
672+
* @throws StreamException
673+
*/
674+
public function getDraft(string $userId, ?string $parentId = null): StreamResponse
675+
{
676+
$params = ["user_id" => $userId];
677+
if ($parentId !== null) {
678+
$params["parent_id"] = $parentId;
679+
}
680+
return $this->client->get($this->getUrl() . "/draft", $params);
681+
}
643682
}

lib/GetStream/StreamChat/Client.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,4 +1598,28 @@ public function unreadCountsBatch(array $userIds): StreamResponse
15981598
{
15991599
return $this->post("unread_batch", ["user_ids" => $userIds]);
16001600
}
1601+
1602+
/**
1603+
* Queries drafts for a user.
1604+
* @link https://getstream.io/chat/docs/php/drafts/?language=php#querying-draft-messages
1605+
* @throws StreamException
1606+
*/
1607+
public function queryDrafts(string $userId, ?array $filter = null, ?array $sort = null, ?array $options = null): StreamResponse
1608+
{
1609+
$data = ["user_id" => $userId];
1610+
1611+
if ($filter !== null) {
1612+
$data["filter"] = $filter;
1613+
}
1614+
1615+
if ($sort !== null) {
1616+
$data["sort"] = $sort;
1617+
}
1618+
1619+
if ($options !== null) {
1620+
$data = array_merge($data, $options);
1621+
}
1622+
1623+
return $this->post("drafts/query", $data);
1624+
}
16011625
}

tests/integration/IntegrationTest.php

Lines changed: 175 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,27 @@ public function testDeleteChannels()
274274
$this->assertTrue(array_key_exists("task_id", (array)$response));
275275

276276
$taskId = $response["task_id"];
277-
for ($i = 0; $i < 30; $i++) {
277+
$completed = false;
278+
while (!$completed) {
278279
$response = $this->client->getTask($taskId);
279280
if ($response["status"] == "completed") {
280-
$this->assertSame($response["result"][$c1->getCID()]["status"], "ok");
281-
$this->assertSame($response["result"][$c2->getCID()]["status"], "ok");
282-
return;
281+
$completed = true;
283282
}
284-
usleep(300000);
283+
usleep(500000);
285284
}
286-
$this->assertSame($response["status"], "completed");
285+
$this->assertSame("ok", $response["result"][$c1->getCID()]["status"]);
286+
$this->assertSame("ok", $response["result"][$c2->getCID()]["status"]);
287+
288+
// for ($i = 0; $i < 30; $i++) {
289+
// $response = $this->client->getTask($taskId);
290+
// if ($response["status"] == "completed") {
291+
// $this->assertSame($response["result"][$c1->getCID()]["status"], "ok");
292+
// $this->assertSame($response["result"][$c2->getCID()]["status"], "ok");
293+
// return;
294+
// }
295+
// usleep(500000);
296+
// }
297+
$this->assertSame("completed", $response["status"]);
287298
}
288299

289300
public function testDeactivateUser()
@@ -305,7 +316,7 @@ public function testDeactivateReactivateUsers()
305316
if ($response["status"] == "completed") {
306317
break;
307318
}
308-
usleep(300000);
319+
usleep(500000);
309320
}
310321

311322
// Since we don't want to test the backend functionality, just
@@ -560,7 +571,7 @@ public function testPendingMessage()
560571
$msg = ["id" => $msgId, "text" => "hello world"];
561572
$response1 = $this->channel->sendMessage($msg, $this->user1["id"], null, ["pending" => true]);
562573
$this->assertSame($msgId, $response1["message"]["id"]);
563-
574+
564575
$response = $this->client->queryChannels(["id" => $this->channel->id], null, ['user_id' => $this->user1["id"]]);
565576
// check if length of $response["channels"][0]['pending_messages']) is 1
566577
$this->assertSame(1, sizeof($response["channels"][0]['pending_messages']));
@@ -1205,7 +1216,7 @@ public function testPartialUpdateUsers()
12051216

12061217
public function testPartialUpdateUserWithTeam()
12071218
{
1208-
$user = ["id" => $this->generateGuid(), "name" => "Test User"];
1219+
$user = ["id" => $this->generateGuid(), "name" => "Test User", "teams" => ["blue"]];
12091220
$response = $this->client->upsertUser($user);
12101221
$this->assertTrue(array_key_exists("users", (array)$response));
12111222
$this->assertTrue(array_key_exists($user["id"], $response["users"]));
@@ -1312,7 +1323,7 @@ public function testImportEnd2End()
13121323
public function testUnreadCounts()
13131324
{
13141325
$this->channel->addMembers([$this->user1["id"]]);
1315-
$msgResp= $this->channel->sendMessage(["text" => "hi"], "random_user_4321");
1326+
$msgResp = $this->channel->sendMessage(["text" => "hi"], "random_user_4321");
13161327

13171328
$resp = $this->client->unreadCounts($this->user1["id"]);
13181329
$this->assertNotEmpty($resp["total_unread_count"]);
@@ -1440,34 +1451,32 @@ public function testSendMessageWithRestrictedVisibility()
14401451
"text" => "secret message",
14411452
"restricted_visibility" => [$this->user1["id"]]
14421453
];
1443-
1444-
1454+
14451455
$response = $this->channel->sendMessage($msg, $this->user1["id"]);
14461456
$this->assertNotNull($response["message"]["restricted_visibility"]);
14471457
$this->assertEquals([$this->user1["id"]], $response["message"]["restricted_visibility"]);
1448-
14491458
}
14501459

14511460
public function testUpdateMessageWithRestrictedVisibility()
14521461
{
14531462
$this->channel->addMembers([$this->user1["id"], $this->user2["id"]]);
1454-
1463+
14551464
// First send a regular message
14561465
$msgId = $this->generateGuid();
14571466
$msg = [
14581467
"id" => $msgId,
14591468
"text" => "original message"
14601469
];
14611470
$response = $this->channel->sendMessage($msg, $this->user1["id"]);
1462-
1471+
14631472
// Then update it with restricted visibility
14641473
$updatedMsg = [
14651474
"id" => $msgId,
14661475
"text" => "updated secret message",
14671476
"restricted_visibility" => [$this->user1["id"]],
14681477
"user" => ["id" => $this->user1["id"]]
14691478
];
1470-
1479+
14711480
$response = $this->client->updateMessage($updatedMsg);
14721481
$this->assertNotNull($response["message"]["restricted_visibility"]);
14731482
$this->assertEquals([$this->user1["id"]], $response["message"]["restricted_visibility"]);
@@ -1476,15 +1485,15 @@ public function testUpdateMessageWithRestrictedVisibility()
14761485
public function testUpdateMessagePartialWithRestrictedVisibility()
14771486
{
14781487
$this->channel->addMembers([$this->user1["id"], $this->user2["id"]]);
1479-
1488+
14801489
// First send a regular message
14811490
$msgId = $this->generateGuid();
14821491
$msg = [
14831492
"id" => $msgId,
14841493
"text" => "original message"
14851494
];
14861495
$response = $this->channel->sendMessage($msg, $this->user1["id"]);
1487-
1496+
14881497
// Then do a partial update with restricted visibility
14891498
$response = $this->client->partialUpdateMessage(
14901499
$msgId,
@@ -1496,7 +1505,7 @@ public function testUpdateMessagePartialWithRestrictedVisibility()
14961505
],
14971506
$this->user1["id"]
14981507
);
1499-
1508+
15001509
$this->assertNotNull($response["message"]["restricted_visibility"]);
15011510
$this->assertEquals([$this->user1["id"]], $response["message"]["restricted_visibility"]);
15021511
}
@@ -1520,4 +1529,151 @@ public function testExportUsers()
15201529
}
15211530
$this->assertSame($response["status"], "completed");
15221531
}
1532+
1533+
public function testCreateDraft()
1534+
{
1535+
$message = ["text" => "This is a draft message"];
1536+
$response = $this->channel->createDraft($message, $this->user1["id"]);
1537+
1538+
$this->assertTrue(array_key_exists("draft", (array)$response));
1539+
$this->assertSame($response["draft"]["message"]["text"], "This is a draft message");
1540+
}
1541+
1542+
public function testGetDraft()
1543+
{
1544+
// First create a draft
1545+
$draftMessage = ["text" => "This is a draft to retrieve"];
1546+
$this->channel->createDraft($draftMessage, $this->user1["id"]);
1547+
1548+
// Then get the draft
1549+
$response = $this->channel->getDraft($this->user1["id"]);
1550+
1551+
$this->assertTrue(array_key_exists("draft", (array)$response));
1552+
$this->assertSame($response["draft"]["message"]["text"], "This is a draft to retrieve");
1553+
$this->assertSame($response["draft"]["channel_cid"], $this->channel->getCID());
1554+
}
1555+
1556+
public function testDeleteDraft()
1557+
{
1558+
// First create a draft
1559+
$draftMessage = ["text" => "This is a draft to delete"];
1560+
$this->channel->createDraft($draftMessage, $this->user1["id"]);
1561+
1562+
// Then delete the draft
1563+
$this->channel->deleteDraft($this->user1["id"]);
1564+
1565+
// Verify it's deleted by trying to get it
1566+
try {
1567+
$this->channel->getDraft($this->user1["id"]);
1568+
$this->fail("Draft should be deleted");
1569+
} catch (\Exception $e) {
1570+
// Expected behavior, draft should not be found
1571+
}
1572+
}
1573+
1574+
public function testThreadDraft()
1575+
{
1576+
// First create a parent message
1577+
$msg = $this->channel->sendMessage(["text" => "Parent message"], $this->user1["id"]);
1578+
$parentId = $msg["message"]["id"];
1579+
1580+
// Create a draft reply
1581+
$draftReply = ["text" => "This is a draft reply", "parent_id" => $parentId];
1582+
$response = $this->channel->createDraft($draftReply, $this->user1["id"]);
1583+
1584+
$this->assertTrue(array_key_exists("draft", (array)$response));
1585+
$this->assertSame($response["draft"]["message"]["text"], "This is a draft reply");
1586+
$this->assertSame($response["draft"]["parent_id"], $parentId);
1587+
1588+
// Get the draft reply
1589+
$response = $this->channel->getDraft($this->user1["id"], $parentId);
1590+
1591+
$this->assertTrue(array_key_exists("draft", (array)$response));
1592+
$this->assertSame($response["draft"]["message"]["text"], "This is a draft reply");
1593+
$this->assertSame($response["draft"]["parent_id"], $parentId);
1594+
1595+
// Delete the draft reply
1596+
$this->channel->deleteDraft($this->user1["id"], $parentId);
1597+
1598+
// Verify it's deleted
1599+
try {
1600+
$this->channel->getDraft($this->user1["id"], $parentId);
1601+
$this->fail("Thread draft should be deleted");
1602+
} catch (\Exception $e) {
1603+
// Expected behavior
1604+
}
1605+
}
1606+
1607+
public function testQueryDrafts()
1608+
{
1609+
// Create multiple drafts in different channels
1610+
$draft1 = ["text" => "Draft in channel 1"];
1611+
$this->channel->createDraft($draft1, $this->user1["id"]);
1612+
1613+
// Create another channel with a draft
1614+
$channel2 = $this->client->Channel("messaging", $this->generateGuid());
1615+
$channel2->create($this->user1["id"]);
1616+
1617+
$draft2 = ["text" => "Draft in channel 2"];
1618+
$channel2->createDraft($draft2, $this->user1["id"]);
1619+
1620+
// Query all drafts for the user
1621+
$response = $this->client->queryDrafts($this->user1["id"]);
1622+
1623+
$this->assertArrayHasKey("drafts", $response);
1624+
$this->assertCount(2, $response["drafts"]);
1625+
1626+
// Query drafts for a specific channel
1627+
$response = $this->client->queryDrafts(
1628+
$this->user1["id"],
1629+
["channel_cid" => $channel2->getCID()]
1630+
);
1631+
1632+
$this->assertArrayHasKey("drafts", $response);
1633+
$this->assertCount(1, $response["drafts"]);
1634+
$draft = $response["drafts"][0];
1635+
$this->assertEquals($channel2->getCID(), $draft["channel_cid"]);
1636+
$this->assertEquals("Draft in channel 2", $draft["message"]["text"]);
1637+
1638+
// Query drafts with sort
1639+
$response = $this->client->queryDrafts(
1640+
$this->user1["id"],
1641+
sort: [["field" => "created_at", "direction" => 1]]
1642+
);
1643+
1644+
$this->assertArrayHasKey("drafts", $response);
1645+
$this->assertCount(2, $response["drafts"]);
1646+
$this->assertEquals($this->channel->getCID(), $response["drafts"][0]["channel_cid"]);
1647+
$this->assertEquals($channel2->getCID(), $response["drafts"][1]["channel_cid"]);
1648+
1649+
// Query drafts with pagination
1650+
$response = $this->client->queryDrafts(
1651+
$this->user1["id"],
1652+
options: ["limit" => 1]
1653+
);
1654+
1655+
$this->assertArrayHasKey("drafts", $response);
1656+
$this->assertCount(1, $response["drafts"]);
1657+
$this->assertEquals($channel2->getCID(), $response["drafts"][0]["channel_cid"]);
1658+
1659+
$this->assertArrayHasKey("next", $response);
1660+
$this->assertNotNull($response["next"]);
1661+
1662+
// Query drafts with pagination and next
1663+
$response = $this->client->queryDrafts(
1664+
$this->user1["id"],
1665+
options: ["limit" => 1, "next" => $response["next"]]
1666+
);
1667+
1668+
$this->assertArrayHasKey("drafts", $response);
1669+
$this->assertCount(1, $response["drafts"]);
1670+
$this->assertEquals($this->channel->getCID(), $response["drafts"][0]["channel_cid"]);
1671+
1672+
// Cleanup
1673+
try {
1674+
$channel2->delete();
1675+
} catch (\Exception $e) {
1676+
// ignore
1677+
}
1678+
}
15231679
}

0 commit comments

Comments
 (0)