mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Fix transactions + operators
This commit is contained in:
@@ -2,9 +2,13 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Databases\Http\Databases;
|
||||
|
||||
use Utopia\Platform\Action as UtopiaAction;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action as AppwriteAction;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Operator;
|
||||
|
||||
class Action extends UtopiaAction
|
||||
class Action extends AppwriteAction
|
||||
{
|
||||
private string $context = 'legacy';
|
||||
|
||||
@@ -13,11 +17,72 @@ class Action extends UtopiaAction
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
public function setHttpPath(string $path): UtopiaAction
|
||||
public function setHttpPath(string $path): AppwriteAction
|
||||
{
|
||||
if (\str_contains($path, '/tablesdb')) {
|
||||
$this->context = 'tablesdb';
|
||||
}
|
||||
return parent::setHttpPath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse operator strings in data array and convert them to Operator objects.
|
||||
*
|
||||
* @param array $data The data array that may contain operator JSON strings or arrays
|
||||
* @param Document $collection The collection document to check for relationship attributes
|
||||
* @return array The data array with operators converted to Operator objects
|
||||
* @throws Exception If an operator string is invalid
|
||||
*/
|
||||
protected function parseOperators(array $data, Document $collection): array
|
||||
{
|
||||
$relationshipKeys = [];
|
||||
foreach ($collection->getAttribute('attributes', []) as $attribute) {
|
||||
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
|
||||
$relationshipKeys[$attribute->getAttribute('key')] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (\str_starts_with($key, '$')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($relationshipKeys[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle operator as JSON string (from API requests)
|
||||
if (\is_string($value)) {
|
||||
$decoded = \json_decode($value, true);
|
||||
|
||||
if (
|
||||
\is_array($decoded) &&
|
||||
isset($decoded['method']) &&
|
||||
\is_string($decoded['method']) &&
|
||||
Operator::isMethod($decoded['method'])
|
||||
) {
|
||||
try {
|
||||
$data[$key] = Operator::parse($value);
|
||||
} catch (\Exception $e) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid operator for attribute "' . $key . '": ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle operator as array (from transaction logs after serialization)
|
||||
elseif (
|
||||
\is_array($value) &&
|
||||
isset($value['method']) &&
|
||||
\is_string($value['method']) &&
|
||||
Operator::isMethod($value['method'])
|
||||
) {
|
||||
try {
|
||||
$data[$key] = Operator::parseOperator($value);
|
||||
} catch (\Exception $e) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid operator for attribute "' . $key . '": ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-51
@@ -4,13 +4,12 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections\Documen
|
||||
|
||||
use Appwrite\Event\Event;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Platform\Action as AppwriteAction;
|
||||
use Appwrite\Platform\Modules\Databases\Http\Databases\Action as DatabasesAction;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Operator;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
|
||||
abstract class Action extends AppwriteAction
|
||||
abstract class Action extends DatabasesAction
|
||||
{
|
||||
/**
|
||||
* @var string|null The current context (either 'row' or 'document')
|
||||
@@ -22,7 +21,7 @@ abstract class Action extends AppwriteAction
|
||||
*/
|
||||
abstract protected function getResponseModel(): string;
|
||||
|
||||
public function setHttpPath(string $path): AppwriteAction
|
||||
public function setHttpPath(string $path): DatabasesAction
|
||||
{
|
||||
if (str_contains($path, '/tablesdb/')) {
|
||||
$this->context = ROWS;
|
||||
@@ -339,53 +338,6 @@ abstract class Action extends AppwriteAction
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse operator strings in data array and convert them to Operator objects.
|
||||
*
|
||||
* @param array $data The data array that may contain operator JSON strings
|
||||
* @param Document $collection The collection document to check for relationship attributes
|
||||
* @return array The data array with operators converted to Operator objects
|
||||
* @throws Exception If an operator string is invalid
|
||||
*/
|
||||
protected function parseOperators(array $data, Document $collection): array
|
||||
{
|
||||
$relationshipKeys = [];
|
||||
foreach ($collection->getAttribute('attributes', []) as $attribute) {
|
||||
if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) {
|
||||
$relationshipKeys[$attribute->getAttribute('key')] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (\str_starts_with($key, '$')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($relationshipKeys[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (\is_string($value)) {
|
||||
$decoded = \json_decode($value, true);
|
||||
|
||||
if (
|
||||
\is_array($decoded) &&
|
||||
isset($decoded['method']) &&
|
||||
\is_string($decoded['method']) &&
|
||||
Operator::isMethod($decoded['method'])
|
||||
) {
|
||||
try {
|
||||
$data[$key] = Operator::parse($value);
|
||||
} catch (\Exception $e) {
|
||||
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid operator for attribute "' . $key . '": ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* For triggering different queues for each document for a bulk documents
|
||||
* @param string $event
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
namespace Appwrite\Platform\Modules\Databases\Http\Databases\Transactions;
|
||||
|
||||
use Utopia\Platform\Action as UtopiaAction;
|
||||
use Appwrite\Platform\Modules\Databases\Http\Databases\Action as DatabasesAction;
|
||||
|
||||
abstract class Action extends UtopiaAction
|
||||
abstract class Action extends DatabasesAction
|
||||
{
|
||||
/**
|
||||
* The current API context (either 'table' or 'collection').
|
||||
*/
|
||||
private ?string $context = COLLECTIONS;
|
||||
|
||||
public function setHttpPath(string $path): UtopiaAction
|
||||
public function setHttpPath(string $path): DatabasesAction
|
||||
{
|
||||
if (\str_contains($path, '/tablesdb')) {
|
||||
$this->context = TABLES;
|
||||
|
||||
@@ -149,6 +149,7 @@ class Update extends Action
|
||||
]));
|
||||
|
||||
$state = [];
|
||||
$collections = [];
|
||||
|
||||
foreach ($operations as $operation) {
|
||||
$databaseInternalId = $operation['databaseInternalId'];
|
||||
@@ -159,6 +160,17 @@ class Update extends Action
|
||||
$action = $operation['action'];
|
||||
$data = $operation['data'];
|
||||
|
||||
if (!isset($collections[$collectionId])) {
|
||||
$collections[$collectionId] = Authorization::skip(
|
||||
fn () => $dbForProject->getCollection($collectionId)
|
||||
);
|
||||
}
|
||||
$collection = $collections[$collectionId];
|
||||
|
||||
if (\is_array($data) && !empty($data)) {
|
||||
$data = $this->parseOperators($data, $collection);
|
||||
}
|
||||
|
||||
if ($action === 'delete' && $documentId && empty($data)) {
|
||||
$doc = $dbForProject->getDocument($collectionId, $documentId);
|
||||
if (!$doc->isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user