Conversation
…ling total count in database queries
…eter for total count control in database queries
…ntrol total count in responses
📝 WalkthroughWalkthroughAdds a boolean query parameter Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas needing extra attention:
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
There was a problem hiding this comment.
Actionable comments posted: 47
🧹 Nitpick comments (2)
app/controllers/api/projects.php (1)
1247-1254: LGTM - Consider future query optimization.The implementation correctly conditionally gates the total count. Note that the optimization benefit is currently limited since the data is already fetched from the database and count() on a PHP array is O(1). For more substantial performance gains, consider modifying the database query itself when
includeTotalis false in future optimizations.app/controllers/api/users.php (1)
695-695: Consider consistent approach for count queries.There's an inconsistency in how queries are passed to count operations:
- Lines 695 and 1077 pass
$queriesdirectly- Line 1148 uses extracted
$filterQueriesWhile the database layer handles filter separation internally (per learnings), mixing approaches within the same file reduces clarity. Consider standardizing on one pattern across all list endpoints in this file for consistency.
Based on learnings
Also applies to: 1077-1077, 1145-1148
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
app/controllers/api/account.php(2 hunks)app/controllers/api/messaging.php(8 hunks)app/controllers/api/migrations.php(2 hunks)app/controllers/api/projects.php(6 hunks)app/controllers/api/storage.php(4 hunks)app/controllers/api/teams.php(5 hunks)app/controllers/api/users.php(6 hunks)app/controllers/api/vcs.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php(2 hunks)src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php(3 hunks)src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php(3 hunks)src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php(3 hunks)src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php(3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
app/controllers/api/migrations.phpsrc/Appwrite/Platform/Modules/Functions/Http/Functions/XList.phpsrc/Appwrite/Platform/Modules/Projects/Http/Projects/XList.phpapp/controllers/api/users.phpapp/controllers/api/teams.phpapp/controllers/api/storage.phpapp/controllers/api/vcs.php
🧬 Code graph analysis (27)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
action(68-136)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/migrations.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
action(64-119)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (1)
action(66-130)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php (1)
action(68-136)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (4)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
action(68-136)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
action(64-119)src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php (1)
action(62-120)src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (1)
action(64-114)
src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/projects.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/users.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/teams.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/storage.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Databases/TransactionState.php (2)
TransactionState(20-745)countDocuments(156-210)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/messaging.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/account.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)
app/controllers/api/vcs.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (4)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
🪛 GitHub Actions: Linter
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
app/controllers/api/teams.php
[error] 1-1: PSR-12: ordered_imports failed.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php
[error] 1-1: PSR-12: ordered_imports failed.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: Unit Test
- GitHub Check: E2E General Test
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (12)
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (1)
64-64: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 105-105
src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php (1)
63-63: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 91-91
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
70-70: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 127-127
src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
67-67: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 110-110
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
69-69: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 109-109
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
73-73: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation.
Also applies to: 117-117
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
79-79: LGTM! The includeTotal parameter implementation is correct.The parameter is properly integrated into the action signature and the conditional total calculation correctly gates the count operation across all three code paths (transaction, with selects, and without selects).
Also applies to: 134-144
app/controllers/api/projects.php (2)
1537-1552: LGTM - Consistent implementation.The parameter handling and conditional logic correctly follow the same pattern established for webhooks.
1841-1856: LGTM - Consistent implementation.The parameter handling and conditional logic correctly follow the established pattern. The default value of
trueensures backward compatibility.app/controllers/api/account.php (2)
5311-5311: LGTM!The function signature correctly includes the
bool $includeTotalparameter with proper typing.
5352-5352: LGTM!The conditional count logic correctly implements the
includeTotalflag, allowing callers to skip the potentially expensive count operation when the total is not needed.app/controllers/api/storage.php (1)
846-855: LGTM: Conditional count logic correctly implemented.The implementation properly gates the count operation on
includeTotalin both authorization paths (with and without fileSecurity), ensuring expensive count queries are skipped when not needed.
src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php
Outdated
Show resolved
Hide resolved
✨ Benchmark results
⚡ Benchmark Comparison
|
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
app/controllers/api/users.php (3)
649-649: Fix typo in parameter description.The description contains "countreturend" which should be "count returned".
This issue was already identified in a previous review.
1034-1034: Fix typo in parameter description.Same typo: "countreturend" should be "count returned".
This issue was already identified in a previous review.
1106-1106: Fix typo in parameter description.Same typo: "countreturend" should be "count returned".
This issue was already identified in a previous review.
🧹 Nitpick comments (4)
app/controllers/api/account.php (1)
5346-5353: Simplify count: pass full $queries; drop manual filter splitDatabase count already handles non-filter parts; align with other modules and reduce code.
Apply:
- $filterQueries = Query::groupByType($queries)['filters']; ... - $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('identities', $queries, APP_LIMIT_COUNT) : 0;Then remove the now-unused assignment:
- $filterQueries = Query::groupByType($queries)['filters'];Based on learnings.
app/controllers/api/teams.php (2)
216-220: Use $queries directly in count; remove $filterQueriesManual separation is unnecessary; DB handles it. Matches pattern in other modules.
Apply:
- $filterQueries = Query::groupByType($queries)['filters']; ... - $total = $includeTotal ? $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('teams', $queries, APP_LIMIT_COUNT) : 0;Based on learnings.
898-909: Same refactor for memberships countDrop filter split; count with $queries for consistency and less code.
Apply:
- $filterQueries = Query::groupByType($queries)['filters']; ... - $total = $includeTotal ? $dbForProject->count( - collection: 'memberships', - queries: $filterQueries, - max: APP_LIMIT_COUNT - ) : 0; + $total = $includeTotal ? $dbForProject->count( + collection: 'memberships', + queries: $queries, + max: APP_LIMIT_COUNT + ) : 0;Based on learnings.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
134-134: Counts correctly guarded byincludeTotal; avoids unnecessary DB work.All code paths skip
count()when false, including transaction-aware counting. Consider adding an integration test that:
- Creates N documents; asserts list with
includeTotal=falsereturnstotal=0and N items.- Asserts
includeTotal=truereturnstotal=N.I can draft the test cases if you share the preferred test harness (E2E vs. module-level).
Also applies to: 138-138, 143-143
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
app/controllers/api/account.php(2 hunks)app/controllers/api/messaging.php(8 hunks)app/controllers/api/migrations.php(2 hunks)app/controllers/api/projects.php(6 hunks)app/controllers/api/storage.php(4 hunks)app/controllers/api/teams.php(5 hunks)app/controllers/api/users.php(6 hunks)app/controllers/api/vcs.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php(2 hunks)src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php(3 hunks)src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php(3 hunks)src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php(3 hunks)src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
- src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php
- src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php
- app/controllers/api/messaging.php
- src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php
- app/controllers/api/projects.php
- src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php
- app/controllers/api/storage.php
- app/controllers/api/migrations.php
- src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php
- src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
PR: appwrite/appwrite#9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php:57-59
Timestamp: 2025-06-19T09:20:03.312Z
Learning: In table-related endpoints (such as `src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php`), parameter descriptions should use "table" and "row" terminology instead of "collection" and "document" for clarity and consistency.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.phpsrc/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.phpsrc/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.phpapp/controllers/api/vcs.phpapp/controllers/api/users.phpapp/controllers/api/teams.php
🧬 Code graph analysis (15)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (6)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)src/Appwrite/Databases/TransactionState.php (2)
TransactionState(20-745)countDocuments(156-210)
app/controllers/api/account.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php (1)
action(68-136)src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php (1)
action(65-121)
src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php (4)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (1)
action(66-130)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php (1)
action(68-136)
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/vcs.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
action(69-117)
app/controllers/api/users.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)
src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/teams.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: E2E Service Test (Users)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Storage)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Projects)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: Benchmark
- GitHub Check: scan
🔇 Additional comments (27)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (4)
21-21: LGTM: Boolean validator import added correctly.The import is necessary for the new
includeTotalparameter validation and is appropriately placed.
64-64: Parameter definition looks correct.The
includeTotalparameter is properly configured with appropriate default value (truefor backward compatibility), Boolean validator, and clear description. The typo mentioned in previous reviews appears to have been addressed.
70-70: LGTM: Action signature correctly updated.The
bool $includeTotalparameter is properly positioned after route parameters and before injected dependencies, consistent with the pattern across other list endpoints in the codebase.
127-127: LGTM: Conditional total calculation implemented correctly.The ternary logic properly gates the expensive count operation based on the
includeTotalparameter, maintaining backward compatibility (defaulttrue) while enabling performance optimization when the total is not needed.src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (4)
23-23: Import order is correct.The
Booleanvalidator import is properly positioned in alphabetical order after theUtopia\Platformimports. The past concern about import ordering has been resolved.
58-60: Parameter definition looks good.The
includeTotalparameter is well-defined with appropriate validation, clear description, and a sensible default value (true) that maintains backward compatibility. The past typo concern has been resolved.
66-72: Action signature correctly updated.The method signature properly includes the new
bool $includeTotalparameter with correct type declaration, matching the route parameter configuration.
117-122: Test coverage forincludeTotalparameter is missing.While tests exist for the executions list endpoint and validate the 'total' field, there are no test cases covering the conditional behavior of the
includeTotalparameter. The helper methodlistExecutions()intests/e2e/Services/Functions/FunctionsBase.phpsupports passing arbitrary parameters, enabling easy addition of tests.Add test cases to verify:
includeTotal=falsereturnstotal=0without database countincludeTotal=truereturns calculated total count as beforeapp/controllers/api/vcs.php (1)
1461-1461: LGTM! TheincludeTotalparameter implementation is correct.The implementation follows the established pattern used in other list endpoints (Projects, Collections, etc.) and maintains backward compatibility with the default value of
true. The conditional count logic properly uses$filterQueriesfor the count operation, and the typo from the previous review has been corrected.Also applies to: 1466-1466, 1507-1507
app/controllers/api/account.php (2)
5307-5307: includeTotal param looks goodClear description and defaults. Matches SDK/GraphQL expectations.
5311-5311: Action wiring OKBoolean includeTotal correctly threaded into handler.
app/controllers/api/teams.php (5)
58-60: Imports OKBoolean import added and order complies with PSR-12.
176-176: includeTotal param added — goodClear behavior and default true.
179-179: Handler signature updated correctlyincludeTotal threaded into list action.
848-848: includeTotal for memberships — goodConsistent param and description.
852-852: Memberships handler signature updated correctlyBoolean includeTotal included.
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php (1)
14-14: LGTM! Clean implementation of includeTotal parameter.The Boolean import and parameter declaration are correct, with proper validation and clear documentation. The parameter defaults to
truefor backward compatibility.Also applies to: 56-56
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (1)
20-20: LGTM! Complete and correct implementation.The includeTotal parameter is properly:
- Imported and validated with Boolean
- Declared with appropriate defaults and description
- Added to the action signature
- Used to conditionally compute totals
The logic correctly returns
0whenincludeTotalisfalse, avoiding the performance cost of counting.Also applies to: 58-58, 64-64, 105-105
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php (1)
13-13: LGTM! Correct parameter addition.The includeTotal parameter is properly declared with Boolean validation and clear documentation. The implementation follows the established pattern.
Also applies to: 52-52
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php (1)
14-14: LGTM! Proper parameter declaration.The includeTotal parameter is correctly added with Boolean validation and appropriate documentation, following the consistent pattern across the codebase.
Also applies to: 55-55
src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php (1)
22-22: LGTM! Well-implemented conditional total calculation.The implementation correctly:
- Imports and validates the parameter with Boolean
- Adds it to the action signature in the appropriate position
- Uses it to conditionally skip the count operation when set to
falseThis provides a performance optimization for clients that don't need the total count.
Also applies to: 59-59, 65-65, 112-112
src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php (1)
18-18: LGTM! Consistent implementation across the proxy module.The includeTotal parameter is properly integrated:
- Boolean validation at the API boundary
- Action signature updated correctly
- Ternary conditional used inline for clean response construction
The pattern aligns well with other modules in this PR.
Also applies to: 55-55, 65-65, 118-118
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
21-21: LGTM! Correctly implemented for the projects module.The includeTotal parameter addition is clean and follows the established pattern:
- Boolean validator ensures type safety
- Default
truepreserves backward compatibility- Conditional logic correctly bypasses expensive count when not needed
Also applies to: 63-63, 69-69, 109-109
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
22-22: LGTM! Final file completes the consistent pattern.The includeTotal implementation in the deployments endpoint is correct and mirrors the approach across all other modules:
- Proper Boolean validation
- Clear parameter documentation
- Action signature updated appropriately
- Performance-conscious conditional counting
This completes a well-coordinated PR that uniformly adds optional total-count suppression across multiple list endpoints.
Also applies to: 61-61, 72-72, 126-126
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (3)
25-26: Import order is now PSR-12 compliant.
Booleancorrectly precedesText. Good fix.
79-80: Signature/injection order is correct.Parameter order aligns with defined params and injections; no routing mismatch expected.
71-71: Code changes are consistent; verify API spec and schema updates are planned.Internal consistency verified:
includeTotalparam definition, Boolean validator, description text, and conditional count guards are identical across all 40+ list endpoints. The change at line 71 aligns with existing patterns.However, SDK and GraphQL updates won't auto-regenerate from this code change alone. The SDK preview workflow (
.github/workflows/sdk-preview.yml) only triggers on changes toapp/config/specs/*-latest-console.json, which this PR does not modify. Confirm that:
- API spec files will be updated separately to expose
includeTotaland trigger SDK regeneration- Or SDKs/schema updates are being handled in a follow-up PR or external process
…ontrol total count in responses, ensuring consistent behavior in session, log, and membership retrievals.
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/controllers/api/messaging.php (2)
2697-2705: Missing includeTotal support on subscribers listThis endpoint doesn’t accept includeTotal and always computes total. For parity with the PR goal, add the includeTotal param and gate the count.
Proposed diff:
- ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) + ->param('includeTotal', true, new Boolean(), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ... - ->action(function (string $topicId, array $queries, string $search, Database $dbForProject, Response $response) { + ->action(function (string $topicId, array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { ... - 'total' => $dbForProject->count('subscribers', $queries, APP_LIMIT_COUNT), + 'total' => $includeTotal ? $dbForProject->count('subscribers', $queries, APP_LIMIT_COUNT) : 0,Also applies to: 2762-2766
3384-3394: Undefined variable in push image URL expiry$currentScheduledAt is used but never defined in this action, causing a notice/error.
Apply:
- $scheduleTime = $currentScheduledAt ?? $scheduledAt; + $scheduleTime = $scheduledAt;Or define $currentScheduledAt earlier if intended.
♻️ Duplicate comments (1)
app/controllers/api/users.php (1)
1148-1151: Inconsistent query handling for count operation.This endpoint uses
$filterQueriesfor count (line 1151) while using$queriesfor find (line 1150), making it inconsistent with other list endpoints in this file (users at lines 694-695, targets at lines 1079-1080) which use$queriesfor both operations. The manual filter separation on line 1148 is unnecessary as the database layer in v0.77.x+ handles this automatically.Based on learnings.
This issue was already flagged in a previous review comment.
🧹 Nitpick comments (11)
tests/e2e/Services/Teams/TeamsBase.php (1)
325-341: Good coverage for includeTotal=false on /teams.Consider extracting a small helper/assert to reuse this pattern across suites to reduce duplication.
tests/e2e/Services/Messaging/MessagingBase.php (1)
636-653: LGTM for subscribers includeTotal=false.Optionally assert the first subscriber ID matches the earlier list to ensure data parity when only total is gated.
src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php (1)
56-56: Correct wiring of includeTotal; minor polish and coverage suggestion.
- Param registration and action signature order are correct; total is skipped when includeTotal=false. Good.
- Nit: align variable naming with the request param for readability.
Apply this small rename for clarity:
- public function action(array $runtimes, array $usecases, int $limit, int $offset, bool $includeTotal, Response $response) + public function action(array $runtimes, array $useCases, int $limit, int $offset, bool $includeTotal, Response $response) @@ - if (!empty($usecases)) { - $templates = \array_filter($templates, function ($template) use ($usecases) { - return \count(\array_intersect($usecases, $template['useCases'])) > 0; + if (!empty($useCases)) { + $templates = \array_filter($templates, function ($template) use ($useCases) { + return \count(\array_intersect($useCases, $template['useCases'])) > 0; }); }Also, please add a small E2E/unit test for listTemplates with includeTotal=false to keep parity with other endpoints.
Also applies to: 61-86
app/controllers/api/messaging.php (2)
3311-3311: Doc vs validation mismatch for push image typesDocs allow jpeg/png/bmp; validation allows only image/png and image/jpeg. Either update docs or include image/bmp in the allowed list.
Also applies to: 3379-3381
3606-3610: Hard-coded “Temp fix for logs” date filtersConsider replacing the hard-coded OR date filter with a feature flag or removing it before release to avoid surprising log gaps.
app/controllers/api/teams.php (3)
176-180: Simplify count() usage; no manual filter grouping neededYou can pass $queries directly to count(); the DB layer separates filters internally.
Apply:
- $filterQueries = Query::groupByType($queries)['filters']; try { $results = $dbForProject->find('teams', $queries); - $total = $includeTotal ? $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('teams', $queries, APP_LIMIT_COUNT) : 0;Based on learnings
Also applies to: 216-220
848-852: Memberships list: align count() call with queriesSame as above; pass $queries to count() directly, no need for groupByType.
- $filterQueries = Query::groupByType($queries)['filters']; ... - $total = $includeTotal ? $dbForProject->count( - collection: 'memberships', - queries: $filterQueries, - max: APP_LIMIT_COUNT - ) : 0; + $total = $includeTotal ? $dbForProject->count( + collection: 'memberships', + queries: $queries, + max: APP_LIMIT_COUNT + ) : 0;Based on learnings
Also applies to: 898-909
1448-1454: Team logs: includeTotal gating — LGTMGating is consistent. Consider removing the hard-coded “Temp fix for logs” date filter before release.
Also applies to: 1521-1525
tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php (1)
68-68: AlignassertEqualsparameter order.
assertEqualsexpects the expected value first; passing the actual value first flips the diff/context when the assertion fails. Please swap the arguments so the failure output remains intuitive.- $this->assertEquals($databasesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $databasesWithIncludeTotalFalse['headers']['status-code']);tests/e2e/Services/Account/AccountCustomClientTest.php (1)
239-257: Test logic forincludeTotal=falselooks good.The test correctly verifies that when
includeTotal=false, the API returnstotal=0while still providing session data. This validates the feature objective.Minor style consideration: Line 251 uses
assertEquals($actual, $expected)while the rest of the file consistently usesassertEquals($expected, $actual). Consider standardizing:- $this->assertEquals($sessionsWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $sessionsWithIncludeTotalFalse['headers']['status-code']);tests/e2e/Services/Functions/FunctionsCustomClientTest.php (1)
379-395: Test validatesincludeTotal=falsecorrectly.The test confirms that
includeTotal=falsesuppresses the total count (returns 0) while still returning template data. The logic is sound and consistent with the first test file.Minor style consideration: Line 389 uses
assertEquals($actual, $expected)which differs from the convention used in the rest of the test suite. Consider aligning for consistency:- $this->assertEquals($templatesWithIncludeTotalFalse['headers']['status-code'], 200); + $this->assertEquals(200, $templatesWithIncludeTotalFalse['headers']['status-code']);
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
app/controllers/api/account.php(6 hunks)app/controllers/api/messaging.php(16 hunks)app/controllers/api/teams.php(7 hunks)app/controllers/api/users.php(12 hunks)src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php(3 hunks)tests/e2e/Services/Account/AccountCustomClientTest.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesBase.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(3 hunks)tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomClientTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomServerTest.php(2 hunks)tests/e2e/Services/Messaging/MessagingBase.php(1 hunks)tests/e2e/Services/Storage/StorageBase.php(1 hunks)tests/e2e/Services/Teams/TeamsBase.php(1 hunks)tests/e2e/Services/Users/UsersBase.php(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
app/controllers/api/users.phpapp/controllers/api/teams.php
🧬 Code graph analysis (15)
tests/e2e/Services/Account/AccountCustomClientTest.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/ProjectCustom.php (1)
getProject(21-185)
tests/e2e/Services/Databases/Legacy/DatabasesBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
tests/e2e/Services/Messaging/MessagingBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Storage/StorageBase.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Functions/FunctionsCustomClientTest.php (2)
tests/e2e/Client.php (2)
call(181-302)Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Teams/TeamsBase.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Users/UsersBase.php (3)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/ProjectCustom.php (1)
getProject(21-185)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
tests/e2e/Services/Sites/SitesBase.php (1)
listDeployments(217-225)
app/controllers/api/messaging.php (4)
src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php (1)
action(61-87)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
action(64-119)
app/controllers/api/account.php (6)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php (1)
action(61-87)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php (1)
action(72-145)
app/controllers/api/users.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php (1)
action(61-87)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
app/controllers/api/teams.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: CodeQL
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (16)
tests/e2e/Services/Users/UsersBase.php (1)
801-817: LGTM: includeTotal=false behavior covered for /users.As a sanity check, confirm the GET param encodes false as expected by the Boolean validator (http_build_query can emit an empty value). If needed, normalize to '0'/'1' or 'false'/'true' at parsing.
tests/e2e/Services/Storage/StorageBase.php (1)
382-398: LGTM: includeTotal=false on bucket files list behaves as expected.app/controllers/api/messaging.php (7)
988-992: Providers list: includeTotal gating — LGTMConditionally computing total with includeTotal is correct and consistent with other modules.
Also applies to: 1026-1034
1057-1063: Provider logs: includeTotal gating — LGTMTotal is gated; response shape preserved.
Also applies to: 1129-1133
2366-2372: Topic logs: includeTotal gating — LGTMTotal correctly gated.
Also applies to: 2439-2443
2788-2794: Subscriber logs: includeTotal gating — LGTMLooks consistent with other logs endpoints.
Also applies to: 2861-2865
3519-3523: Messages list: includeTotal gating — LGTMParsing, search, cursor handling, and total gating look correct.
Also applies to: 3556-3565
3588-3594: Message logs: includeTotal gating — LGTMAll good.
Also applies to: 3661-3665
3687-3691: Message targets list: includeTotal gating — LGTMEarly return with total 0 for empty targets is fine; gating correct otherwise.
Also applies to: 3739-3747
app/controllers/api/users.php (5)
647-707: LGTM! Clean implementation of the includeTotal feature.The parameter is properly defined with appropriate validator, default value, and description. The conditional total calculation correctly skips the count query when
includeTotalis false, providing the intended performance benefit.
828-857: LGTM! Appropriate implementation for nested collection.The
includeTotalparameter is correctly implemented. Since sessions are already loaded as part of the user document (line 841), usingcount($sessions)on the in-memory array is appropriate. The conditional logic correctly returns 0 whenincludeTotalis false.
876-918: LGTM! Consistent implementation.The
includeTotalparameter is properly added and the conditional total calculation is correct. The in-memorycount()is appropriate here since memberships are already fetched and transformed for the response payload.
937-1016: LGTM! Proper integration with Audit service.The
includeTotalparameter is correctly implemented, and the conditional logic appropriately calls$audit->countLogsByUser()only when needed, providing the intended performance benefit.
1035-1088: LGTM! Consistent with other list endpoints.The
includeTotalparameter implementation is clean and consistent. Bothfind()andcount()correctly use the same$queriesarray, which aligns with the database layer's automatic filter handling.tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)
421-432: LGTM! Well-structured test forincludeTotal=falseparameter.The test correctly validates that when
includeTotal=false, the API returnstotal=0while still populating thedeploymentsarray. Good placement alongside the default behavior test.
1019-1030: LGTM! Consistent test pattern for executions list.The test mirrors the deployments test pattern at lines 421-432, ensuring consistent validation of the
includeTotal=falsebehavior across different list endpoints. The assertions comprehensively verify the expected behavior.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (1)
65-65: PassincludeTotalas the string'false'so the API actually disables totals
Client::call()turns GET params into a query string withhttp_build_query; when you pass the booleanfalseit serializes to an empty value (e.g.,includeTotal=), so the backend never receives a literal"false"and can fall back to the defaulttrue. That makes these tests flaky with respect to the feature they’re asserting. Please send the parameter as the string'false'in all three spots so the request is deterministic.- 'includeTotal' => false + 'includeTotal' => 'false'Apply the same change to the collections and documents calls.
Also applies to: 422-422, 4593-4593
🧹 Nitpick comments (3)
tests/e2e/Services/Teams/TeamsBase.php (1)
325-341: LGTM! Test correctly validatesincludeTotal=falsebehavior.The test appropriately validates that when
includeTotal=falseis passed, the API returnstotal=0while still populating theteamsarray with actual data. The assertions are comprehensive and align with the PR's objectives.Optional enhancement: Consider adding custom assertion messages for easier debugging when tests fail. For example:
- $this->assertEquals(0, $teamsWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $teamsWithIncludeTotalFalse['body']['total'], 'Expected total to be 0 when includeTotal=false'); - $this->assertGreaterThan(0, count($teamsWithIncludeTotalFalse['body']['teams'])); + $this->assertGreaterThan(0, count($teamsWithIncludeTotalFalse['body']['teams']), 'Expected teams array to be populated even when includeTotal=false');tests/e2e/Services/Messaging/MessagingBase.php (1)
636-653: LGTM! Test correctly validatesincludeTotal=falsebehavior for subscribers.The test appropriately validates that when
includeTotal=falseis passed, the API returnstotal=0while still populating thesubscribersarray with actual data. The implementation is consistent with the parallel test inTeamsBase.phpand aligns with the PR's objectives.Optional enhancement: Similar to the teams test, consider adding custom assertion messages for improved debugging:
- $this->assertEquals(0, $subscribersWithIncludeTotalFalse['body']['total']); + $this->assertEquals(0, $subscribersWithIncludeTotalFalse['body']['total'], 'Expected total to be 0 when includeTotal=false'); - $this->assertGreaterThan(0, count($subscribersWithIncludeTotalFalse['body']['subscribers'])); + $this->assertGreaterThan(0, count($subscribersWithIncludeTotalFalse['body']['subscribers']), 'Expected subscribers array to be populated even when includeTotal=false');tests/e2e/Services/Storage/StorageBase.php (1)
382-398: includeTotal=false happy-path covered; add edge coverage with queries and string inputThis block looks good and validates the intended response shape and values when includeTotal=false. Consider two small additions to harden coverage:
- Combine includeTotal=false with a query (e.g., limit(1)) to ensure gating the total doesn’t affect items returned.
- Optionally pass 'false' (string) to guard server-side boolean coercion.
Example snippet to add after Line 399:
$filesLimitIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ Query::limit(1)->toString() ], 'includeTotal' => false, ]); $this->assertEquals(200, $filesLimitIncludeTotalFalse['headers']['status-code']); $this->assertEquals(1, count($filesLimitIncludeTotalFalse['body']['files'])); $this->assertSame(0, $filesLimitIncludeTotalFalse['body']['total']); // Optional: accept string boolean $filesStringFalse = $this->client->call(Client::METHOD_GET, '/storage/buckets/' . $data['bucketId'] . '/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'includeTotal' => 'false', ]); $this->assertEquals(200, $filesStringFalse['headers']['status-code']); $this->assertSame(0, $filesStringFalse['body']['total']); $this->assertGreaterThan(0, count($filesStringFalse['body']['files']));
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
tests/e2e/Services/Account/AccountCustomClientTest.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesBase.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(3 hunks)tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomClientTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomServerTest.php(2 hunks)tests/e2e/Services/Messaging/MessagingBase.php(1 hunks)tests/e2e/Services/Storage/StorageBase.php(1 hunks)tests/e2e/Services/Teams/TeamsBase.php(1 hunks)tests/e2e/Services/Users/UsersBase.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- tests/e2e/Services/Functions/FunctionsCustomServerTest.php
- tests/e2e/Services/Databases/Legacy/DatabasesBase.php
- tests/e2e/Services/Users/UsersBase.php
- tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php
- tests/e2e/Services/Functions/FunctionsCustomClientTest.php
- tests/e2e/Services/Account/AccountCustomClientTest.php
🧰 Additional context used
🧬 Code graph analysis (4)
tests/e2e/Services/Storage/StorageBase.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Teams/TeamsBase.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
tests/e2e/Services/Messaging/MessagingBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php (2)
tests/e2e/Client.php (1)
Client(8-342)tests/e2e/Scopes/Scope.php (1)
getHeaders(145-145)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Storage)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: Benchmark
- GitHub Check: scan
…ehavior across API endpoints, enhancing response handling for sessions, logs, memberships, and more.
…e-count # Conflicts: # app/controllers/api/account.php
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
app/controllers/api/users.php (1)
1108-1111: Remove manual filter separation for consistency with other endpoints.The identities endpoint manually separates filters on Line 1108 and uses
$filterQueriesfor count on Line 1111, whilefind()uses$querieson Line 1110. This is inconsistent with the users endpoint (Lines 653-654) and targets endpoint (Lines 1038-1039), which both use$queriesfor find and count operations.Per the retrieved learning, the database layer in utopia-php/database v0.77.x+ automatically handles filter separation for count operations, making manual separation unnecessary.
Based on learnings.
Apply this diff to align with other endpoints:
- $filterQueries = Query::groupByType($queries)['filters']; try { $identities = $dbForProject->find('identities', $queries); - $total = $includeTotal ? $dbForProject->count('identities', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('identities', $queries, APP_LIMIT_COUNT) : 0;
🧹 Nitpick comments (2)
app/controllers/api/teams.php (2)
213-216: Consider passing$queriesdirectly tocount().The manual extraction of filter queries using
Query::groupByType($queries)['filters']is unnecessary. The database layer in utopia-php/database (version 0.77.*+) automatically handles filter separation for count operations.Based on learnings
Apply this diff to simplify the code:
- $filterQueries = Query::groupByType($queries)['filters']; try { $results = $dbForProject->find('teams', $queries); - $total = $includeTotal ? $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('teams', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) {
893-903: Consider passing$queriesdirectly tocount().Similar to the
/v1/teamsendpoint, the manual extraction of filter queries is unnecessary. The database layer automatically handles filter separation for count operations.Based on learnings
Apply this diff:
- $filterQueries = Query::groupByType($queries)['filters']; try { $memberships = $dbForProject->find( collection: 'memberships', queries: $queries, ); - $total = $includeTotal ? $dbForProject->count( - collection: 'memberships', - queries: $filterQueries, - max: APP_LIMIT_COUNT - ) : 0; + $total = $includeTotal ? $dbForProject->count( + collection: 'memberships', + queries: $queries, + max: APP_LIMIT_COUNT + ) : 0; } catch (OrderException $e) {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
app/controllers/api/projects.php(6 hunks)app/controllers/api/teams.php(7 hunks)app/controllers/api/users.php(12 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
app/controllers/api/teams.phpapp/controllers/api/users.php
🧬 Code graph analysis (3)
app/controllers/api/teams.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
app/controllers/api/projects.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
action(69-117)
app/controllers/api/users.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: E2E Service Test (Webhooks)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Storage)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: scan
🔇 Additional comments (5)
app/controllers/api/projects.php (3)
1237-1237: Implementation looks good for the webhooks endpoint.The
includeTotalparameter is properly implemented with correct validator, default value, and description. The conditional total calculation correctly avoids the count operation whenincludeTotalis false, aligning with the PR objective.Also applies to: 1240-1240, 1255-1255
1535-1535: Implementation looks good for the keys endpoint.The changes are consistent with the webhooks endpoint implementation. The
includeTotalparameter follows the same pattern with correct validator, default value, and conditional logic.Also applies to: 1538-1538, 1553-1553
1839-1839: Implementation looks good for the platforms endpoint.The changes maintain consistency with the other endpoints in this file. The
includeTotalparameter is correctly implemented with appropriate validator, default value, and conditional total calculation.Also applies to: 1842-1842, 1857-1857
app/controllers/api/teams.php (2)
55-55: LGTM! Import is correctly ordered.The
Booleanvalidator import is properly placed in alphabetical order betweenAssocandText, maintaining PSR-12 compliance.
1436-1441: LGTM! Correct implementation for audit logs.The
includeTotalparameter is correctly implemented for the logs endpoint. The conditional total calculation using$audit->countLogsByResource()is appropriate and follows the expected pattern.Also applies to: 1510-1510
…ccount endpoints, allowing control over total count calculation for sessions, logs, and identities. Updated tests to verify functionality.
…d' of github.com:appwrite/appwrite into feat-disable-count # Conflicts: # composer.lock
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/controllers/api/messaging.php (1)
2310-2346: APNS update: wrong credential key breaks enablement checksKey is saved as 'bundle' but later enablement checks require 'bundleId', making enablement impossible after update.
Apply:
- if (!empty($bundleId)) { - $credentials['bundle'] = $bundleId; - } + if (!empty($bundleId)) { + $credentials['bundleId'] = $bundleId; + }
♻️ Duplicate comments (1)
app/controllers/api/messaging.php (1)
2477-2480: Topics list: includeTotal change is fine; fix cursor assignment bugCursor should receive the Document, not an array index.
Apply:
- $cursor->setValue($cursorDocument[0]); + $cursor->setValue($cursorDocument);Also applies to: 2516-2517
🧹 Nitpick comments (1)
tests/e2e/Services/Messaging/MessagingBase.php (1)
647-664: IncludeTotal=false test looks good; consider extracting a tiny helper to reuse across list endpointsAssertions are correct and match the new contract. To avoid repeating this pattern elsewhere (targets/logs), consider a small helper like assertIncludeTotalDisabled($resp, $groupKey) and call it in similar tests.
Example helper:
+private function assertIncludeTotalDisabled(array $response, string $groupKey): void +{ + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsArray($response['body'][$groupKey]); + $this->assertIsInt($response['body']['total']); + $this->assertEquals(0, $response['body']['total']); + $this->assertGreaterThan(0, count($response['body'][$groupKey])); +}And usage here:
-$this->assertEquals(200, $subscribersWithIncludeTotalFalse['headers']['status-code']); -... -$this->assertGreaterThan(0, count($subscribersWithIncludeTotalFalse['body']['subscribers'])); +$this->assertIncludeTotalDisabled($subscribersWithIncludeTotalFalse, 'subscribers');
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
app/controllers/api/messaging.php(18 hunks)app/controllers/api/vcs.php(2 hunks)tests/e2e/Services/Messaging/MessagingBase.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/controllers/api/vcs.php
🧰 Additional context used
🧬 Code graph analysis (2)
app/controllers/api/messaging.php (5)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php (1)
action(64-119)
tests/e2e/Services/Messaging/MessagingBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: Setup & Build Appwrite Image
- GitHub Check: scan
🔇 Additional comments (7)
app/controllers/api/messaging.php (7)
1070-1074: Providers: includeTotal gating is correctParam, signature, and conditional count look consistent with the new behavior.
Also applies to: 1108-1110
1139-1140: Provider logs: includeTotal added and respectedLooks good; total is only computed when requested.
Also applies to: 1145-1145, 1212-1213
2546-2552: Topic logs: includeTotal gating is correctNo further issues spotted here.
Also applies to: 2620-2621
2969-2974: Subscriber logs: includeTotal gating is correctAll good.
Also applies to: 3043-3044
3769-3775: Message logs: includeTotal gating is correctNo issues.
Also applies to: 3843-3845
3868-3872: Message targets: includeTotal gating is correct; early empty-targets return handledReturning total=0 for empty targets aligns with includeTotal=false semantics too. Good.
If you want to exercise the includeTotal=false path here in e2e, mirror the subscribers test with 'groupKey' => 'targets'.
Also applies to: 3920-3922
3700-3704: Add filterQueries extraction before count call; messaging.php doesn't follow established patternLine 3739 passes full
$queriestocount(), but the correct pattern across the codebase (teams, storage, migrations, users, etc.) is to extract and use only filter queries:$filterQueries = Query::groupByType($queries)['filters']; $total = $includeTotal ? $dbForProject->count('messages', $filterQueries, APP_LIMIT_COUNT) : 0;Currently, limit/offset/selections get included in the count call, producing incorrect totals. Apply the same pattern used in all other list endpoints.
⛔ Skipped due to learnings
Learnt from: abnegate PR: appwrite/appwrite#10297 File: app/controllers/api/users.php:649-657 Timestamp: 2025-08-11T10:32:38.142Z Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
…1' of github.com:appwrite/appwrite into feat-disable-count # Conflicts: # composer.lock
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
app/controllers/api/account.php(4 hunks)app/controllers/api/migrations.php(2 hunks)app/controllers/api/users.php(12 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/controllers/api/migrations.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
app/controllers/api/users.php
🧬 Code graph analysis (2)
app/controllers/api/account.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
app/controllers/api/users.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: E2E Service Test (Messaging)
- GitHub Check: E2E Service Test (Teams)
- GitHub Check: E2E Service Test (Sites)
- GitHub Check: E2E Service Test (Realtime)
- GitHub Check: E2E Service Test (Proxy)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Avatars)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Databases/Legacy)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: Benchmark
- GitHub Check: scan
🔇 Additional comments (8)
app/controllers/api/account.php (3)
2823-2871: LGTM! Conditional count logic correctly implemented.The implementation correctly gates the expensive
countLogsByUsercall behind theincludeTotalcheck. WhenincludeTotalis false, the total is set to 0 without performing the count operation, which aligns with the PR objectives and matches the pattern used in other modules.
5219-5266: LGTM! Consistent implementation with logs endpoint.The
includeTotalparameter is correctly integrated into the action signature and the conditional count logic properly skips the database count when false. The implementation is consistent with the/v1/account/logsendpoint and follows the established pattern from other XList implementations.
2817-2817: Verify the Boolean validator instantiation.The
includeTotalparameter usesnew Boolean(true), but other Boolean parameters in this file (e.g., line 4081 for themfaparameter) usenew Boolean()without arguments. Please verify whether the Boolean validator accepts a parameter and if this usage is correct, or if it should benew Boolean()for consistency.app/controllers/api/users.php (5)
608-612: includeTotal wiring for users list looks correct.Parameter, action signature, and gated count are consistent and avoid DB count when false.
Also applies to: 651-655
788-789: Sessions list: correct conditional total.Local count of in-memory sessions is fine (no query/limit here).
Also applies to: 792-793, 814-815
996-997: Targets list: matches pattern used elsewhere.includeTotal parameter, signature, and DB count gating look good.
Also applies to: 999-1000, 1039-1040
1068-1071: Identities list uses unified $queries for find/count.Aligned with DB layer’s automatic filter handling; consistent with other endpoints.
Based on learnings
Also applies to: 1109-1111
898-899: Confirm Audit::countLogsByUser ignores limit/offset.If it honors limit/offset, returned total would be page size; ensure it computes the unbounded total for the same filters.
Also applies to: 903-904, 971-973
… multiple endpoints for consistency in response handling.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
app/controllers/api/messaging.php (1)
2877-2879: Fix Subscribers doc: wrong ALLOWED_ATTRIBUTES reference.Doc string references
Providers::ALLOWED_ATTRIBUTES; should beSubscribers::ALLOWED_ATTRIBUTES.- ->param('queries', [], new Subscribers(), '... You may filter on the following attributes: ' . implode(', ', Providers::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Subscribers(), '... You may filter on the following attributes: ' . implode(', ', Subscribers::ALLOWED_ATTRIBUTES), true)app/controllers/api/users.php (1)
871-876: Use database count instead of array count for accurate totals.Counting the PHP array
$membershipson Line 875 returns the page size when$queriesincludes limit/offset, not the total count of all memberships. This should use$dbForProject->count()to get the actual total.Apply this diff:
$memberships = array_map(function ($membership) use ($dbForProject, $user) { $team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId')); $membership ->setAttribute('teamName', $team->getAttribute('name')) ->setAttribute('userName', $user->getAttribute('name')) ->setAttribute('userEmail', $user->getAttribute('email')); return $membership; }, $dbForProject->find('memberships', $queries)); + $total = $includeTotal ? $dbForProject->count('memberships', $queries, APP_LIMIT_COUNT) : 0; + $response->dynamic(new Document([ 'memberships' => $memberships, - 'total' => $includeTotal ? count($memberships) : 0, + 'total' => $total, ]), Response::MODEL_MEMBERSHIP_LIST);
🧹 Nitpick comments (10)
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
106-109: Inconsistent query handling compared to other XList implementations.This implementation manually extracts filter queries on line 106 and passes
$filterQueriesto the count operation on line 109, while the find operation on line 108 uses the full$queriesarray. Other XList implementations in the codebase (e.g.,Databases/XList.php,Databases/Collections/Documents/XList.php) pass$queriesdirectly to bothfind()andcount()operations, letting the database layer handle filter separation internally.Consider aligning with the established pattern by passing
$queriesdirectly to the count operation:- $filterQueries = Query::groupByType($queries)['filters']; try { $projects = $dbForPlatform->find('projects', $queries); - $total = $includeTotal ? $dbForPlatform->count('projects', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForPlatform->count('projects', $queries, APP_LIMIT_COUNT) : 0; } catch (Order $e) {Based on learnings
tests/e2e/Services/Databases/Legacy/DatabasesBase.php (1)
964-981: Use explicit scalar for GET boolean and tidy naming.http_build_query may serialize false as an empty value. Send 0 (or 'false') to avoid ambiguity, rename the local for clarity, and use \count for consistency.
- $attributesWithIncludeTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes', array_merge([ + $attributesWithTotalFalse = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'] ]), [ - 'total' => false + 'total' => 0 ]); - $this->assertEquals(200, $attributesWithIncludeTotalFalse['headers']['status-code']); - $this->assertIsArray($attributesWithIncludeTotalFalse['body']); - $this->assertIsArray($attributesWithIncludeTotalFalse['body']['attributes']); - $this->assertIsInt($attributesWithIncludeTotalFalse['body']['total']); - $this->assertEquals(0, $attributesWithIncludeTotalFalse['body']['total']); - $this->assertGreaterThan(0, count($attributesWithIncludeTotalFalse['body']['attributes'])); + $this->assertEquals(200, $attributesWithTotalFalse['headers']['status-code']); + $this->assertIsArray($attributesWithTotalFalse['body']); + $this->assertIsArray($attributesWithTotalFalse['body']['attributes']); + $this->assertIsInt($attributesWithTotalFalse['body']['total']); + $this->assertEquals(0, $attributesWithTotalFalse['body']['total']); + $this->assertGreaterThan(0, \count($attributesWithTotalFalse['body']['attributes']));src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
101-104: Use grouped filter queries for count (consistency + safety).Other endpoints compute filters via Query::groupByType($queries)['filters'] before counting. Align here to avoid selection/order artifacts in count.
Apply:
try { $databases = $dbForProject->find('databases', $queries); - $total = $includeTotal ? $dbForProject->count('databases', $queries, APP_LIMIT_COUNT) : 0; + $filterQueries = Query::groupByType($queries)['filters'] ?? []; + $total = $includeTotal ? $dbForProject->count('databases', $filterQueries, APP_LIMIT_COUNT) : 0;src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
131-144: Align counts to use grouped filters across all branches.To mirror other endpoints and avoid selection/order interference, compute filters once and reuse for count.
try { $selectQueries = Query::groupByType($queries)['selections'] ?? []; $collectionTableId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + $filterQueries = Query::groupByType($queries)['filters'] ?? []; // Use transaction-aware document retrieval if transactionId is provided if ($transactionId !== null) { $documents = $transactionState->listDocuments($collectionTableId, $transactionId, $queries); - $total = $includeTotal ? $transactionState->countDocuments($collectionTableId, $transactionId, $queries) : 0; + $total = $includeTotal ? $transactionState->countDocuments($collectionTableId, $transactionId, $filterQueries) : 0; } elseif (! empty($selectQueries)) { // has selects, allow relationship on documents $documents = $dbForProject->find($collectionTableId, $queries); - $total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count($collectionTableId, $filterQueries, APP_LIMIT_COUNT) : 0; } else { // has no selects, disable relationship loading on documents /* @type Document[] $documents */ $documents = $dbForProject->skipRelationships(fn () => $dbForProject->find($collectionTableId, $queries)); - $total = $includeTotal ? $dbForProject->count($collectionTableId, $queries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count($collectionTableId, $filterQueries, APP_LIMIT_COUNT) : 0; }src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (2)
115-118: Use grouped filters for count (parity with other modules).Align with other XList handlers by passing only filters to count.
- $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); - $total = $includeTotal ? $dbForProject->count('database_' . $database->getSequence(), $queries, APP_LIMIT_COUNT) : 0; + $collections = $dbForProject->find('database_' . $database->getSequence(), $queries); + $filterQueries = Query::groupByType($queries)['filters'] ?? []; + $total = $includeTotal ? $dbForProject->count('database_' . $database->getSequence(), $filterQueries, APP_LIMIT_COUNT) : 0;
105-110: Rename $collectionIdId for clarity.Minor nit: $collectionIdId likely meant $collectionId. Rename to avoid confusion.
app/controllers/api/messaging.php (2)
1070-1070: Providers list: includeTotal gating looks correct; consider filter-only count.Wiring of
totalparam to$includeTotaland conditional count is good. For resilience with cursor/limit/order queries, consider counting on filter-only queries:Query::groupByType($queries)['filters'].- $total = $includeTotal ? $dbForProject->count('providers', $queries, APP_LIMIT_COUNT) : 0; + $filters = Query::groupByType($queries)['filters']; + $total = $includeTotal ? $dbForProject->count('providers', $filters, APP_LIMIT_COUNT) : 0;Also applies to: 1073-1073, 1109-1116
3700-3701: Messages list: includeTotal gating OK; consider filter-only count.Same suggestion as providers list to count on filters only.
- $total = $includeTotal ? $dbForProject->count('messages', $queries, APP_LIMIT_COUNT) : 0; + $filters = Query::groupByType($queries)['filters']; + $total = $includeTotal ? $dbForProject->count('messages', $filters, APP_LIMIT_COUNT) : 0;Also applies to: 3703-3704, 3739-3746
app/controllers/api/teams.php (2)
213-216: Consider using$queriesdirectly for count for consistency.The manual filter separation on Line 213 and subsequent use of
$filterQueriesfor count on Line 216 may be unnecessary. Based on learnings, the database layer internally handles filter separation for count operations in version 0.77.* and later. Other list endpoints (e.g.,usersat lines 651-654, anddatabasesin XList.php) use$queriesdirectly for both find and count operations.Consider applying this diff for consistency:
- $filterQueries = Query::groupByType($queries)['filters']; try { $results = $dbForProject->find('teams', $queries); - $total = $includeTotal ? $dbForProject->count('teams', $filterQueries, APP_LIMIT_COUNT) : 0; + $total = $includeTotal ? $dbForProject->count('teams', $queries, APP_LIMIT_COUNT) : 0; } catch (OrderException $e) {Based on learnings.
893-903: Consider using$queriesdirectly for count for consistency.Similar to the teams list endpoint, manual filter separation on Line 893 may be unnecessary. For consistency with other endpoints and to align with the database layer's automatic filter handling (v0.77.x+), consider using
$queriesdirectly for both find and count operations.Apply this diff:
- $filterQueries = Query::groupByType($queries)['filters']; try { $memberships = $dbForProject->find( collection: 'memberships', queries: $queries, ); - $total = $includeTotal ? $dbForProject->count( - collection: 'memberships', - queries: $filterQueries, - max: APP_LIMIT_COUNT - ) : 0; + $total = $includeTotal ? $dbForProject->count( + collection: 'memberships', + queries: $queries, + max: APP_LIMIT_COUNT + ) : 0; } catch (OrderException $e) {Based on learnings.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (38)
app/controllers/api/account.php(4 hunks)app/controllers/api/messaging.php(18 hunks)app/controllers/api/migrations.php(2 hunks)app/controllers/api/projects.php(6 hunks)app/controllers/api/storage.php(4 hunks)app/controllers/api/teams.php(7 hunks)app/controllers/api/users.php(12 hunks)app/controllers/api/vcs.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php(3 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php(2 hunks)src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php(2 hunks)src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php(4 hunks)src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php(3 hunks)src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php(3 hunks)src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php(4 hunks)src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php(3 hunks)src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php(3 hunks)src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php(3 hunks)tests/e2e/Services/Account/AccountCustomClientTest.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesBase.php(1 hunks)tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php(3 hunks)tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomClientTest.php(1 hunks)tests/e2e/Services/Functions/FunctionsCustomServerTest.php(2 hunks)tests/e2e/Services/Messaging/MessagingBase.php(1 hunks)tests/e2e/Services/Storage/StorageBase.php(1 hunks)tests/e2e/Services/Teams/TeamsBase.php(1 hunks)tests/e2e/Services/Users/UsersBase.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (20)
- tests/e2e/Services/Databases/Legacy/DatabasesCustomServerTest.php
- src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Indexes/XList.php
- src/Appwrite/Platform/Modules/Functions/Http/Functions/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/XList.php
- tests/e2e/Services/Databases/TablesDB/DatabasesCustomServerTest.php
- tests/e2e/Services/Functions/FunctionsCustomServerTest.php
- tests/e2e/Services/Teams/TeamsBase.php
- src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php
- src/Appwrite/Platform/Modules/Functions/Http/Templates/XList.php
- src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php
- tests/e2e/Services/Account/AccountCustomClientTest.php
- src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php
- src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php
- tests/e2e/Services/Users/UsersBase.php
- tests/e2e/Services/Storage/StorageBase.php
- app/controllers/api/vcs.php
- src/Appwrite/Platform/Modules/Proxy/Http/Rules/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Indexes/XList.php
- src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Columns/XList.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-11T10:32:38.142Z
Learnt from: abnegate
PR: appwrite/appwrite#10297
File: app/controllers/api/users.php:649-657
Timestamp: 2025-08-11T10:32:38.142Z
Learning: In Appwrite's utopia-php/database (version 0.77.* and later), the database layer internally handles filter separation for count operations. When using `$dbForProject->count()` within a `skipFilters` closure, there's no need to manually separate filter queries using `Query::groupByType($queries)['filters']` as the database handles this automatically.
Applied to files:
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.phpapp/controllers/api/teams.phpapp/controllers/api/users.phpapp/controllers/api/storage.phpapp/controllers/api/migrations.php
📚 Learning: 2025-06-19T09:20:03.312Z
Learnt from: ItzNotABug
PR: appwrite/appwrite#9693
File: src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php:57-59
Timestamp: 2025-06-19T09:20:03.312Z
Learning: In table-related endpoints (such as `src/Appwrite/Platform/Modules/Databases/Http/Databases/Tables/Update.php`), parameter descriptions should use "table" and "row" terminology instead of "collection" and "document" for clarity and consistency.
Applied to files:
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.phpsrc/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php
🧬 Code graph analysis (18)
tests/e2e/Services/Functions/FunctionsCustomClientTest.php (1)
tests/e2e/Client.php (2)
call(181-302)Client(8-342)
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php (1)
action(68-136)src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php (1)
action(65-121)
tests/e2e/Services/Messaging/MessagingBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
app/controllers/api/messaging.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
tests/e2e/Services/Databases/Legacy/DatabasesBase.php (1)
tests/e2e/Client.php (1)
Client(8-342)
app/controllers/api/account.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
action(73-128)
app/controllers/api/teams.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (3)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
app/controllers/api/users.php (2)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)
app/controllers/api/storage.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
app/controllers/api/projects.php (2)
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
action(69-117)src/Appwrite/Utopia/Response.php (1)
Response(158-980)
app/controllers/api/migrations.php (3)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
action(79-176)src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
action(68-114)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (2)
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Attributes/XList.php (1)
action(70-148)src/Appwrite/Databases/TransactionState.php (2)
TransactionState(20-745)countDocuments(156-210)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)
param(255-356)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
- GitHub Check: E2E Service Test (GraphQL)
- GitHub Check: E2E Service Test (Webhooks)
- GitHub Check: E2E Service Test (Locale)
- GitHub Check: E2E Service Test (Tokens)
- GitHub Check: E2E Service Test (Health)
- GitHub Check: E2E Service Test (VCS)
- GitHub Check: E2E Service Test (FunctionsSchedule)
- GitHub Check: E2E Service Test (Functions)
- GitHub Check: E2E Service Test (Console)
- GitHub Check: E2E Service Test (Account)
- GitHub Check: E2E Service Test (Databases/TablesDB)
- GitHub Check: E2E Service Test (Dev Keys)
- GitHub Check: E2E Service Test (Site Screenshots)
- GitHub Check: E2E General Test
- GitHub Check: Unit Test
- GitHub Check: scan
🔇 Additional comments (35)
src/Appwrite/Platform/Modules/Databases/Http/TablesDB/Tables/Rows/XList.php (2)
14-14: LGTM: Import correctly ordered.The Boolean validator import is properly positioned in alphabetical order between ArrayList and Text, satisfying PSR-12.
56-56: Code changes verified—parameter declaration and consumption pattern is correct and consistent.The verification confirms both concerns from the original comment:
Boolean validator pattern: The
new Boolean(true)instantiation is standard and consistently used across 50+ parameter declarations throughout the codebase for controlling list result totals. This is the established pattern in this codebase.Parameter consumption: The
totalparameter will be automatically mapped to thebool $includeTotalparameter in the action method by the framework. This convention is verified across identical implementations in Tokens, Sites, Functions, and Databases modules, where the value controls conditional total-count computation ($total = $includeTotal ? $db->count(...) : 0).No issues found. The implementation follows established conventions and is consistent with the codebase patterns.
src/Appwrite/Platform/Modules/Projects/Http/Projects/XList.php (1)
63-63: Remove the concern about Boolean(true) — the constructor accepts a bool parameter.The Utopia\Validator\Boolean class constructor accepts an optional
bool $looseparameter (default false). Passingtrueenables "loose" validation that accepts string representations like'true'/'false'and integers0/1, which is appropriate for query string parameters. The usagenew Boolean(true)is valid and intentional, not an error.Likely an incorrect or invalid review comment.
tests/e2e/Services/Functions/FunctionsCustomClientTest.php (1)
379-395: LGTM! Clean test implementation fortotal=falsebehavior.The test properly validates the new
includeTotal=falsefunctionality by confirming:
- HTTP 200 response
- Response structure integrity
totalfield is 0 whentotal=false- Templates array is still populated
The assertions are comprehensive and the test follows the established pattern in this file.
tests/e2e/Services/Messaging/MessagingBase.php (1)
647-664: LGTM! Consistent test implementation for subscribers endpoint.The test correctly validates the
total=falsebehavior with comprehensive assertions:
- HTTP 200 response
- Response structure validation
- Type checking for
totalfield- Confirms
totalequals 0- Verifies
subscribersarray remains populatedThe implementation is consistent with the pattern used in
FunctionsCustomClientTest.php, ensuring uniformity across the test suite.tests/e2e/Services/Databases/Legacy/DatabasesBase.php (1)
964-981: Public query param is "total" — original concern is incorrect.Routes declare the public query parameter as 'total' (->param('total', ...); e.g. app/controllers/api/*.php) and tests pass 'total' => false; $includeTotal is only the internal handler variable name. No change required.
Likely an incorrect or invalid review comment.
src/Appwrite/Platform/Modules/Sites/Http/Sites/XList.php (2)
103-106: LGTM: count gating behind includeTotal is correct and consistent.Using filters for count and skipping it when includeTotal is false looks good and avoids unnecessary DB work.
58-65: No internal codebase issues found; manual verification of SDKs and GraphQL required.The PHP codebase is internally consistent: all 50+ list endpoints uniformly expose the public param as
'total'while accepting it as method arg$includeTotal. No legacyincludeTotalpublic params remain. However, verification of SDK implementations, GraphQL schema mapping, and changelog documentation cannot be completed from codebase inspection alone and requires manual review.src/Appwrite/Platform/Modules/Databases/Http/Databases/XList.php (1)
62-69: LGTM on the new “total” param and signature wire-up.Defaults, Boolean(true) for loose parsing, and arg positioning are correct.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php (1)
71-80: LGTM on new param and signature; gating is correct.Transaction-aware listing and stats are preserved; total is skipped when false.
src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/XList.php (1)
67-74: LGTM on param wiring and signature change.Boolean(true) for query parsing and arg ordering look correct.
src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php (2)
119-129: LGTM: correct use of filters for count and gating.Matches the intended behavior and avoids unnecessary counting when disabled.
58-70: Manual verification required for downstream SDK/GraphQL parameter exposure.The parameter naming pattern (
->param('total', ...)withbool $includeTotalin the function signature) is consistent with all other list endpoints in the codebase (Databases, Storage, Teams, Users, Functions, Sites, etc.). However, SDK and GraphQL schema definitions are generated at build time and cannot be verified through source inspection. Confirm that the "total" parameter name is correctly exposed in downstream SDK clients and GraphQL schema, and that documentation reflects this consistently.src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php (4)
22-22: LGTM - Boolean validator import added correctly.The import is properly placed and necessary for the new parameter validation.
61-61: LGTM - Parameter declaration is correct and well-documented.The
totalparameter provides a clean API to control total count calculation, with sensible defaults for backward compatibility.
68-76: LGTM - Action signature properly updated.The
includeTotalparameter is correctly typed and positioned in the method signature, maintaining good parameter organization.
122-129: LGTM - Conditional total calculation implemented correctly.The ternary operator elegantly gates the count query based on
includeTotal, providing the performance optimization intended by this feature. Filter extraction and count operation follow established patterns.app/controllers/api/migrations.php (3)
598-600: LGTM - Parameter declaration follows established pattern.The
totalparameter is correctly defined with appropriate validation and documentation.
603-603: LGTM - Action signature properly updated.The
includeTotalparameter is correctly integrated into the endpoint's parameter list.
639-645: LGTM - Conditional count logic implemented correctly.The implementation efficiently skips the count query when not needed, following the same pattern as other endpoints in this PR.
app/controllers/api/storage.php (6)
181-183: LGTM - Parameter declaration is correct.The
totalparameter follows the established pattern with proper validation and documentation.
186-186: LGTM - Action signature properly updated.The
includeTotalparameter is correctly added to the listBuckets endpoint signature.
223-231: LGTM - Conditional count logic correctly implemented.The listBuckets endpoint properly gates the count query based on
includeTotal, maintaining consistency with the broader pattern.
787-789: LGTM - Parameter declaration follows the pattern.The
totalparameter is correctly defined for the listFiles endpoint.
793-793: LGTM - Action signature updated correctly.The
includeTotalparameter is properly integrated into the listFiles endpoint.
846-862: LGTM - Both authorization branches handle includeTotal correctly.The implementation properly gates the count query in both the file-security-enabled and bucket-level-permission branches. The Authorization::skip() wrapping in the else branch correctly mirrors the find() operation's authorization handling.
app/controllers/api/account.php (2)
2817-2868: LGTM! Thetotalparameter implementation is correct.The changes correctly implement the feature to disable total count calculation:
- Public API parameter named
total(line 2817) with defaulttruefor backward compatibility- Internal parameter
$includeTotalproperly passed to action (line 2823)- Count query correctly skipped when
$includeTotalis false (line 2868):$includeTotal ? $audit->countLogsByUser(...) : 0This implementation matches the PR objectives and follows the established pattern from other endpoints.
5215-5260: LGTM! Thetotalparameter implementation is correct.The changes correctly implement the feature to disable total count calculation:
- Public API parameter named
total(line 5215) with defaulttruefor backward compatibility- Internal parameter
$includeTotalproperly passed to action (line 5219)- Count query correctly skipped when
$includeTotalis false (line 5260):$includeTotal ? $dbForProject->count(...) : 0The implementation is consistent with the logs endpoint and follows the established pattern across the codebase.
app/controllers/api/messaging.php (6)
1139-1140: Provider logs: conditional total OK.
$includeTotal ? $audit->countLogsByResource(...) : 0is correct and avoids unnecessary work when false.Also applies to: 1144-1145, 1212-1214
2546-2547: Topic logs: includeTotal gating LGTM.Also applies to: 2551-2552, 2620-2621
2880-2881: Subscribers list: includeTotal gating OK.Logic and response shape look consistent.
Also applies to: 2883-2884, 2944-2946
2970-2970: Subscriber logs: conditional total OK.Also applies to: 2974-2975, 3043-3045
3769-3770: Message logs: conditional total OK.Also applies to: 3774-3775, 3843-3845
3868-3869: Message targets list: includeTotal gating OK; empty-target fast path is fine.Also applies to: 3871-3872, 3921-3923
app/controllers/api/projects.php (1)
1237-1237: Projects lists (webhooks/keys/platforms): includeTotal gating LGTM and efficient.
- Using
count($items)avoids a second DB hit and matches the contract whentotal=false.- Param wiring and signatures are consistent.
Also applies to: 1240-1241, 1255-1256, 1535-1535, 1538-1539, 1553-1554, 1840-1840, 1842-1843, 1857-1858
| ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) | ||
| ->inject('dbForProject') | ||
| ->inject('response') | ||
| ->action(function (array $queries, string $search, Database $dbForProject, Response $response) { | ||
| ->action(function (array $queries, string $search, bool $includeTotal, Database $dbForProject, Response $response) { | ||
| try { |
There was a problem hiding this comment.
Fix cursor assignment in topics list (breaks pagination).
$dbForProject->getDocument() returns a Document, not an array. Using $cursorDocument[0] causes a runtime error and broken pagination. Keep the includeTotal change as-is.
- $cursor->setValue($cursorDocument[0]);
+ $cursor->setValue($cursorDocument);Also applies to: 2505-2513, 2516-2516
🤖 Prompt for AI Agents
In app/controllers/api/messaging.php around lines 2477-2481 (and also at
2505-2513 and 2516), the code treats the result of $dbForProject->getDocument()
as an array and uses $cursorDocument[0], which is incorrect because
getDocument() returns a Document object and this breaks pagination; update the
assignment to extract the cursor from the Document using the Document API (e.g.,
call the appropriate getter or property accessor on the Document to read the
cursor field) instead of indexing into it, and ensure the rest of the pagination
logic uses that extracted scalar cursor value.
Disable list total response given, includeTotal param === false