diff --git a/app/controllers/general.php b/app/controllers/general.php index 6c6a05794f..49f4dda705 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -874,7 +874,7 @@ App::init() } if (version_compare($requestFormat, '1.8.0', '<')) { $dbForProject = $getProjectDB($project); - $request->addFilter(new RequestV20($dbForProject, $request->getParams())); + $request->addFilter(new RequestV20($dbForProject, $route->getPathValues($request))); } } diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 8e165e45e5..ed4de38d2b 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -179,7 +179,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:6.2.0 + image: /console:7.0.2 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 3471690a5b..87385aa086 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -219,7 +219,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:7.0.0-qa.8 + image: appwrite/console:7.0.2 restart: unless-stopped networks: - appwrite diff --git a/src/Appwrite/Utopia/Request/Filters/V20.php b/src/Appwrite/Utopia/Request/Filters/V20.php index 30de1fb2d3..2683d600ef 100644 --- a/src/Appwrite/Utopia/Request/Filters/V20.php +++ b/src/Appwrite/Utopia/Request/Filters/V20.php @@ -96,36 +96,74 @@ class V20 extends Filter /** * Returns all relationship attribute keys in `key.*` format for use with `Query::select`. */ - private function getRelatedCollectionKeys(): array - { - $dbForProject = $this->getDbForProject(); + private function getRelatedCollectionKeys( + ?string $databaseId = null, + ?string $collectionId = null, + ?string $prefix = null, + int $depth = 1, + ): array { + $databaseId ??= $this->getParamValue('databaseId'); + $collectionId ??= $this->getParamValue('collectionId'); + if ( + empty($databaseId) || + empty($collectionId) || + $depth > Database::RELATION_MAX_DEPTH + ) { + return []; + } + + $dbForProject = $this->getDbForProject(); if ($dbForProject === null) { return []; } - $databaseId = $this->getParamValue('databaseId'); - $collectionId = $this->getParamValue('collectionId'); - - if (empty($databaseId) || empty($collectionId)) { + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty()) { return []; } - $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); - - $collection = $dbForProject->getDocument( + $collection = Authorization::skip(fn () => $dbForProject->getDocument( 'database_' . $database->getSequence(), $collectionId - ); + )); + if ($collection->isEmpty()) { + return []; + } $attributes = $collection->getAttribute('attributes', []); + $relationshipKeys = []; - return \array_values(\array_map( - fn ($attr) => $attr['key'] . '.*', - \array_filter( - $attributes, - fn ($attr) => ($attr['type'] ?? null) === Database::VAR_RELATIONSHIP - ) - )); + foreach ($attributes as $attr) { + if ( + ($attr['type'] ?? null) !== Database::VAR_RELATIONSHIP || + $attr['status'] !== 'available' + ) { + continue; + } + + $key = $attr['key']; + $fullKey = $prefix ? $prefix . '.' . $key : $key; + + // Add the wildcard select for this relationship + $relationshipKeys[] = $fullKey . '.*'; + + // Get the related collection for nested relationships + $relatedCollectionId = $attr['relatedCollection'] ?? null; + + if ($relatedCollectionId) { + // Recursively get nested relationship keys + $nestedKeys = $this->getRelatedCollectionKeys( + $databaseId, + $relatedCollectionId, + $fullKey, + $depth + 1, + ); + + $relationshipKeys = \array_merge($relationshipKeys, $nestedKeys); + } + } + + return \array_values(\array_unique($relationshipKeys)); } }