diff --git a/src/Appwrite/Platform/Action.php b/src/Appwrite/Platform/Action.php index e5a7cf7984..056a33b320 100644 --- a/src/Appwrite/Platform/Action.php +++ b/src/Appwrite/Platform/Action.php @@ -25,6 +25,14 @@ class Action extends UtopiaAction 'subQueryVariables', // Sites ]; + /** + * Attributes to remove from relationship path documents per API + * Default is empty - APIs should set their specific attributes + * + * @var array + */ + protected array $removableAttributes = []; + /** * Foreach Document * Call provided callback for each document in the collection diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php index 059af0f3a7..4d4ea2c6e5 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Action.php @@ -4,12 +4,15 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documen use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\Platform\Action as AppwriteAction; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; -use Utopia\Platform\Action as UtopiaAction; -abstract class Action extends UtopiaAction +use const Appwrite\Platform\Modules\Databases\DOCUMENTS; +use const Appwrite\Platform\Modules\Databases\ROWS; + +abstract class Action extends AppwriteAction { /** * @var string|null The current context (either 'row' or 'document') @@ -21,10 +24,15 @@ abstract class Action extends UtopiaAction */ abstract protected function getResponseModel(): string; - public function setHttpPath(string $path): UtopiaAction + public function setHttpPath(string $path): AppwriteAction { if (str_contains($path, '/tablesdb/')) { $this->context = ROWS; + // Set removable attributes for TablesDB API + $this->removableAttributes = ['$databaseId', '$tableId']; + } else { + // Set removable attributes for Collections API + $this->removableAttributes = ['$databaseId', '$collectionId']; } return parent::setHttpPath($path); @@ -192,6 +200,17 @@ abstract class Action extends UtopiaAction return $this->isCollectionsAPI() ? 'collection' : 'table'; } + /** + * Remove configured removable attributes from a document. + * Used for relationship path handling to remove API-specific attributes. + */ + protected function removeReadonlyAttributes(Document $document): void + { + foreach ($this->removableAttributes as $attribute) { + $document->removeAttribute($attribute); + } + } + /** * Resolves relationships in a document and attaches metadata. */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php index a230bb1bca..1b398c0fa9 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Create.php @@ -318,8 +318,7 @@ class Create extends Action $relation['$id'] = ID::unique(); } } else { - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); + $this->removeReadonlyAttributes($relation); $relation->setAttribute('$collection', $relatedCollection->getId()); $type = Database::PERMISSION_UPDATE; } diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php index 711e3cc828..cd26a2920a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Update.php @@ -209,8 +209,7 @@ class Update extends Action 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); + $this->removeReadonlyAttributes($relation); // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php index cdd6e451ba..5b6132fc6a 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/Upsert.php @@ -213,8 +213,7 @@ class Upsert extends Action 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); - $relation->removeAttribute('$collectionId'); - $relation->removeAttribute('$databaseId'); + $this->removeReadonlyAttributes($relation); // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php index 59b540be2f..ec1c94bab3 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Collections/Documents/XList.php @@ -167,11 +167,10 @@ class XList extends Action return $result || ($query->getMethod() === Query::TYPE_SELECT); }, false); - // Check if the SELECT query includes $databaseId and $collectionId + // Check if the SELECT query includes the removable attributes $hasWildcard = false; - $hasDatabaseId = false; - $hasCollectionId = false; $hasSelectQueries = !empty($selectQueries); + $requestedAttributes = []; if ($hasSelectQueries) { foreach ($selectQueries as $query) { @@ -185,22 +184,21 @@ class XList extends Action break; } - if (\in_array('$databaseId', $values, true)) { - $hasDatabaseId = true; - } - - if (\in_array('$collectionId', $values, true)) { - $hasCollectionId = true; + // Check which removable attributes are explicitly requested + foreach ($this->removableAttributes as $attribute) { + if (\in_array($attribute, $values, true)) { + $requestedAttributes[$attribute] = true; + } } } if (!$hasWildcard) { foreach ($documents as $document) { - if (!$hasDatabaseId) { - $document->removeAttribute('$databaseId'); - } - if (!$hasCollectionId) { - $document->removeAttribute('$collectionId'); + // Remove attributes that are not explicitly requested + foreach ($this->removableAttributes as $attribute) { + if (!isset($requestedAttributes[$attribute])) { + $document->removeAttribute($attribute); + } } } }