diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index c7b433b658..1d86623016 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -916,7 +916,9 @@ App::get('/v1/account/identities') $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index f0b0783b02..121824379f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -496,7 +496,9 @@ App::get('/v1/databases') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -827,7 +829,9 @@ App::get('/v1/databases/:databaseId/collections') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -1666,7 +1670,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - + /** @var Document $database */ $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { @@ -1687,22 +1691,23 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') \array_push( $queries, - Query::equal('collectionId', [$collectionId]), - Query::equal('databaseId', [$databaseId]) + Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]) ); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); - $cursor = \reset($cursor); if ($cursor) { $attributeId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [ - Query::equal('collectionId', [$collectionId]), - Query::equal('databaseId', [$databaseId]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('key', [$attributeId]), Query::limit(1), ])); @@ -2521,7 +2526,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') ->inject('response') ->inject('dbForProject') ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { - + /** @var Document $database */ $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { @@ -2542,7 +2547,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -2551,8 +2558,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') if ($cursor) { $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn() => $dbForProject->find('indexes', [ - Query::equal('collectionId', [$collectionId]), - Query::equal('databaseId', [$databaseId]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('key', [$indexId]), Query::limit(1) ])); @@ -2953,7 +2960,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index ea7571c6b8..3aae36f98a 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -377,7 +377,9 @@ App::get('/v1/functions') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -1275,7 +1277,9 @@ App::get('/v1/functions/:functionId/deployments') $queries[] = Query::equal('resourceId', [$function->getId()]); $queries[] = Query::equal('resourceType', ['functions']); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -1816,7 +1820,9 @@ App::get('/v1/functions/:functionId/executions') // Set internal queries $queries[] = Query::equal('functionId', [$function->getId()]); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 056bc3648c..39659fd2b3 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -848,8 +848,12 @@ App::get('/v1/messaging/providers') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { @@ -1964,8 +1968,12 @@ App::get('/v1/messaging/topics') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { @@ -2295,8 +2303,12 @@ App::get('/v1/messaging/topics/:topicId/subscribers') \array_push($queries, Query::equal('topicInternalId', [$topic->getInternalId()])); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { @@ -2883,8 +2895,12 @@ App::get('/v1/messaging/messages') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { @@ -3008,9 +3024,7 @@ App::get('/v1/messaging/messages/:messageId/targets') ->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Targets::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->inject('locale') - ->inject('geodb') - ->action(function (string $messageId, array $queries, Response $response, Database $dbForProject, Locale $locale, Reader $geodb) { + ->action(function (string $messageId, array $queries, Response $response, Database $dbForProject) { $message = $dbForProject->getDocument('messages', $messageId); if ($message->isEmpty()) { @@ -3035,8 +3049,12 @@ App::get('/v1/messaging/messages/:messageId/targets') $queries[] = Query::equal('$id', $targetIDs); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 7ccf531411..312e52d528 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -395,7 +395,9 @@ App::get('/v1/migrations') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index c8aab0829f..bea893064f 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -249,7 +249,9 @@ App::get('/v1/projects') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 85e52599e6..075be70b3c 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -169,8 +169,12 @@ App::get('/v1/proxy/rules') $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { /** @var Query $cursor */ diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index ac4b3a5086..c96fd90e93 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -170,7 +170,9 @@ App::get('/v1/storage/buckets') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -750,7 +752,9 @@ App::get('/v1/storage/buckets/:bucketId/files') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index eea7217912..897e2a421e 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -157,7 +157,9 @@ App::get('/v1/teams') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -717,7 +719,9 @@ App::get('/v1/teams/:teamId/memberships') // Set internal queries $queries[] = Query::equal('teamId', [$teamId]); - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d2838ffe1f..e9a8a42025 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -547,7 +547,9 @@ App::get('/v1/users') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); @@ -852,9 +854,13 @@ App::get('/v1/users/:userId/targets') $queries[] = Query::equal('userId', [$userId]); - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); - $cursor = reset($cursor); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); + $cursor = reset($cursor); if ($cursor) { $targetId = $cursor->getValue(); @@ -900,7 +906,9 @@ App::get('/v1/users/identities') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 6a9397eaef..2bc94885b1 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -982,8 +982,12 @@ App::get('/v1/vcs/installations') $queries[] = Query::search('search', $search); } - // Get cursor document if there was a cursor query - $cursor = Query::getByType($queries, [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + /** + * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries + */ + $cursor = \array_filter($queries, function ($query) { + return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); + }); $cursor = reset($cursor); if ($cursor) { /** @var Query $cursor */ diff --git a/tests/e2e/Services/Messaging/MessagingBase.php b/tests/e2e/Services/Messaging/MessagingBase.php index 59a5d5dec2..111f0294fc 100644 --- a/tests/e2e/Services/Messaging/MessagingBase.php +++ b/tests/e2e/Services/Messaging/MessagingBase.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Messaging; use Appwrite\Messaging\Status as MessageStatus; use Tests\E2E\Client; use Utopia\App; +use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\DSN\DSN; @@ -682,12 +683,27 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ]); - $this->assertEquals(200, $response['headers']['status-code']); - $targetList = $response['body']; - $this->assertEquals(1, $targetList['total']); - $this->assertEquals(1, count($targetList['targets'])); + $this->assertEquals(2, $targetList['total']); + $this->assertEquals(2, count($targetList['targets'])); $this->assertEquals($message['targets'][0], $targetList['targets'][0]['$id']); + $this->assertEquals($message['targets'][1], $targetList['targets'][1]['$id']); + + /** + * Cursor Test + */ + $response = $this->client->call(Client::METHOD_GET, '/messaging/messages/' . $message['$id'] . '/targets', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'queries' => [ + Query::cursorAfter(new Document(['$id' => $targetList['targets'][0]['$id']]))->toString(), + ] + ]); + $this->assertEquals(2, $response['body']['total']); + $this->assertEquals(1, count($response['body']['targets'])); + $this->assertEquals($targetList['targets'][1]['$id'], $response['body']['targets'][0]['$id']); // Test for empty targets $response = $this->client->call(Client::METHOD_POST, '/messaging/messages/email', [ @@ -719,7 +735,7 @@ trait MessagingBase public function testCreateDraftEmail() { - // Create User + // Create User 1 $response = $this->client->call(Client::METHOD_POST, '/users', [ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -728,15 +744,33 @@ trait MessagingBase 'userId' => ID::unique(), 'email' => uniqid() . "@example.com", 'password' => 'password', - 'name' => 'Messaging User', + 'name' => 'Messaging User 1', ]); $this->assertEquals(201, $response['headers']['status-code'], "Error creating user: " . var_export($response['body'], true)); - $user = $response['body']; + $user1 = $response['body']; - $this->assertEquals(1, \count($user['targets'])); - $targetId = $user['targets'][0]['$id']; + $this->assertEquals(1, \count($user1['targets'])); + $targetId1 = $user1['targets'][0]['$id']; + + // Create User 2 + $response = $this->client->call(Client::METHOD_POST, '/users', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ], [ + 'userId' => ID::unique(), + 'email' => uniqid() . "@example.com", + 'password' => 'password', + 'name' => 'Messaging User 2', + ]); + + $this->assertEquals(201, $response['headers']['status-code'], "Error creating user: " . var_export($response['body'], true)); + $user2 = $response['body']; + + $this->assertEquals(1, \count($user2['targets'])); + $targetId2 = $user2['targets'][0]['$id']; // Create Email $response = $this->client->call(Client::METHOD_POST, '/messaging/messages/email', [ @@ -745,13 +779,12 @@ trait MessagingBase 'x-appwrite-key' => $this->getProject()['apiKey'], ], [ 'messageId' => ID::unique(), - 'targets' => [$targetId], + 'targets' => [$targetId1, $targetId2], 'subject' => 'New blog post', 'content' => 'Check out the new blog post at http://localhost', ]); $this->assertEquals(201, $response['headers']['status-code']); - $message = $response['body']; $this->assertEquals(MessageStatus::DRAFT, $message['status']);