From c59cd97eb86617857938790410d933aeb9ee8f31 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 4 Nov 2024 20:57:08 +1300 Subject: [PATCH] Not found exception --- app/controllers/api/databases.php | 163 ++++++++++++++---------------- app/controllers/general.php | 2 + composer.json | 2 +- composer.lock | 24 ++--- 4 files changed, 89 insertions(+), 102 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5b2c2080cb..13cc4e5ed7 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3,7 +3,6 @@ use Appwrite\Auth\Auth; use Appwrite\Detector\Detector; use Appwrite\Event\Database as EventDatabase; -use Appwrite\Event\Delete; use Appwrite\Event\Event; use Appwrite\Event\Usage; use Appwrite\Extend\Exception; @@ -26,6 +25,7 @@ use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Conflict as ConflictException; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Limit as LimitException; +use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Exception\Structure as StructureException; @@ -352,13 +352,16 @@ function updateAttribute( if ($type === Database::VAR_RELATIONSHIP) { $primaryDocumentOptions = \array_merge($attribute->getAttribute('options', []), $options); $attribute->setAttribute('options', $primaryDocumentOptions); - - $dbForProject->updateRelationship( - collection: $collectionId, - id: $key, - newKey: $newKey, - onDelete: $primaryDocumentOptions['onDelete'], - ); + try { + $dbForProject->updateRelationship( + collection: $collectionId, + id: $key, + newKey: $newKey, + onDelete: $primaryDocumentOptions['onDelete'], + ); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } if ($primaryDocumentOptions['twoWay']) { $relatedCollection = $dbForProject->getDocument('database_' . $db->getInternalId(), $primaryDocumentOptions['relatedCollection']); @@ -388,6 +391,8 @@ function updateAttribute( ); } catch (TruncateException) { throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } } @@ -530,12 +535,7 @@ App::get('/v1/databases') ->inject('response') ->inject('dbForProject') ->action(function (array $queries, string $search, Response $response, Database $dbForProject) { - - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } + $queries = Query::parseQueries($queries); if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -849,7 +849,7 @@ App::post('/v1/databases/:databaseId/collections') }); App::get('/v1/databases/:databaseId/collections') - ->alias('/v1/database/collections', ['databaseId' => 'default']) + ->alias('/v1/database/collections') ->desc('List collections') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -875,11 +875,7 @@ App::get('/v1/databases/:databaseId/collections') throw new Exception(Exception::DATABASE_NOT_FOUND); } - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } + $queries = Query::parseQueries($queries); if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -919,7 +915,7 @@ App::get('/v1/databases/:databaseId/collections') }); App::get('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId') ->desc('Get collection') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -954,7 +950,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') }); App::get('/v1/databases/:databaseId/collections/:collectionId/logs') - ->alias('/v1/database/collections/:collectionId/logs', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/logs') ->desc('List collection logs') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -988,12 +984,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } - + $queries = Query::parseQueries($queries); $grouped = Query::groupByType($queries); $limit = $grouped['limit'] ?? APP_LIMIT_COUNT; $offset = $grouped['offset'] ?? 0; @@ -1055,7 +1046,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') App::put('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId') ->desc('Update collection') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -1106,7 +1097,8 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->setAttribute('$permissions', $permissions) ->setAttribute('documentSecurity', $documentSecurity) ->setAttribute('enabled', $enabled) - ->setAttribute('search', implode(' ', [$collectionId, $name]))); + ->setAttribute('search', \implode(' ', [$collectionId, $name])) + ); $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); @@ -1119,7 +1111,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') }); App::delete('/v1/databases/:databaseId/collections/:collectionId') - ->alias('/v1/database/collections/:collectionId', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId') ->desc('Delete collection') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -1175,7 +1167,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string') - ->alias('/v1/database/collections/:collectionId/attributes/string', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/string') ->desc('Create string attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1226,14 +1218,13 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email') - ->alias('/v1/database/collections/:collectionId/attributes/email', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/email') ->desc('Create email attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1276,7 +1267,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email' }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') - ->alias('/v1/database/collections/:collectionId/attributes/enum', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/enum') ->desc('Create enum attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1324,7 +1315,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/enum') }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') - ->alias('/v1/database/collections/:collectionId/attributes/ip', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/ip') ->desc('Create IP address attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1367,7 +1358,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/ip') }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') - ->alias('/v1/database/collections/:collectionId/attributes/url', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/url') ->desc('Create URL attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1410,7 +1401,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/url') }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/integer') - ->alias('/v1/database/collections/:collectionId/attributes/integer', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/integer') ->desc('Create integer attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1440,8 +1431,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?int $min, ?int $max, ?int $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range - $min = (is_null($min)) ? PHP_INT_MIN : \intval($min); - $max = (is_null($max)) ? PHP_INT_MAX : \intval($max); + $min = \is_null($min) ? PHP_INT_MIN : $min; + $max = \is_null($max) ? PHP_INT_MAX : $max; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); @@ -1482,7 +1473,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/intege }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float') - ->alias('/v1/database/collections/:collectionId/attributes/float', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/float') ->desc('Create float attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1512,21 +1503,16 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' ->action(function (string $databaseId, string $collectionId, string $key, ?bool $required, ?float $min, ?float $max, ?float $default, bool $array, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within range - $min = (is_null($min)) ? -PHP_FLOAT_MAX : \floatval($min); - $max = (is_null($max)) ? PHP_FLOAT_MAX : \floatval($max); + $min = \is_null($min) ? -PHP_FLOAT_MAX : $min; + $max = \is_null($max) ? PHP_FLOAT_MAX : $max; if ($min > $max) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, 'Minimum value must be lesser than maximum value'); } - // Ensure default value is a float - if (!is_null($default)) { - $default = \floatval($default); - } - $validator = new Range($min, $max, Database::VAR_FLOAT); - if (!is_null($default) && !$validator->isValid($default)) { + if (!\is_null($default) && !$validator->isValid($default)) { throw new Exception(Exception::ATTRIBUTE_VALUE_INVALID, $validator->getDescription()); } @@ -1557,7 +1543,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/float' }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolean') - ->alias('/v1/database/collections/:collectionId/attributes/boolean', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/boolean') ->desc('Create boolean attribute') ->groups(['api', 'database', 'schema']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1599,7 +1585,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/boolea }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/datetime') - ->alias('/v1/database/collections/:collectionId/attributes/datetime', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/datetime') ->desc('Create datetime attribute') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1644,7 +1630,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/dateti }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relationship') - ->alias('/v1/database/collections/:collectionId/attributes/relationship', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/relationship') ->desc('Create relationship attribute') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].attributes.[attributeId].create') @@ -1773,7 +1759,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') - ->alias('/v1/database/collections/:collectionId/attributes', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes') ->desc('List attributes') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -1804,16 +1790,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } + $queries = Query::parseQueries($queries); \array_push( $queries, + Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]) ); /** @@ -1822,6 +1804,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); }); + $cursor = \reset($cursor); if ($cursor) { @@ -1832,8 +1815,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') $attributeId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('attributes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('key', [$attributeId]), Query::limit(1), ])); @@ -1857,7 +1840,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') - ->alias('/v1/database/collections/:collectionId/attributes/:key', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/:key') ->desc('Get attribute') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -2390,7 +2373,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/attributes/:key/ }); App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') - ->alias('/v1/database/collections/:collectionId/attributes/:key', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/attributes/:key') ->desc('Delete attribute') ->groups(['api', 'database', 'schema']) ->label('scope', 'collections.write') @@ -2504,7 +2487,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key }); App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') - ->alias('/v1/database/collections/:collectionId/indexes', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/indexes') ->desc('Create index') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].indexes.[indexId].create') @@ -2675,7 +2658,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') }); App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') - ->alias('/v1/database/collections/:collectionId/indexes', ['databaseId' => 'default']) + ->alias('/v1/database/collections/:collectionId/indexes') ->desc('List indexes') ->groups(['api', 'database']) ->label('scope', 'collections.read') @@ -2706,13 +2689,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - try { - $queries = Query::parseQueries($queries); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } + $queries = Query::parseQueries($queries); - \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); + \array_push( + $queries, + Query::equal('databaseId', [$databaseId]), + Query::equal('collectionId', [$collectionId]), + ); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -3042,10 +3025,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $document = $dbForProject->createDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document); - } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); - } catch (DuplicateException $exception) { + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } catch (DuplicateException $e) { throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } catch (NotFoundException $e) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Add $collectionId and $databaseId for all documents @@ -3176,14 +3161,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $cursor->setValue($cursorDocument); } - try { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); - } catch (AuthorizationException) { - throw new Exception(Exception::USER_UNAUTHORIZED); - } catch (QueryException $e) { - throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); - } + $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); // Add $collectionId and $databaseId for all documents $processDocument = (function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database): bool { @@ -3647,8 +3626,10 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::USER_UNAUTHORIZED); } catch (DuplicateException) { throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); - } catch (StructureException $exception) { - throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $exception->getMessage()); + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } catch (NotFoundException $e) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Add $collectionId and $databaseId for all documents @@ -3757,12 +3738,16 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DOCUMENT_NOT_FOUND); } - $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { - $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $documentId - ); - }); + try { + $dbForProject->withRequestTimestamp($requestTimestamp, function () use ($dbForProject, $database, $collection, $documentId) { + $dbForProject->deleteDocument( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $documentId + ); + }); + } catch (NotFoundException $e) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } // Add $collectionId and $databaseId for all documents $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { diff --git a/app/controllers/general.php b/app/controllers/general.php index 7763566159..b08ecb3d12 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -775,6 +775,8 @@ App::error() case 'Utopia\Database\Exception\Relationship': $error = new AppwriteException(AppwriteException::RELATIONSHIP_VALUE_INVALID, $error->getMessage(), previous: $error); break; + case 'Utopia\Database\Exception\NotFound': + $error = new AppwriteException(AppwriteException::COLLECTION_NOT_FOUND, $error->getMessage(), previous: $error); } $code = $error->getCode(); diff --git a/composer.json b/composer.json index 2fc43f7cd0..f122149ec2 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.10.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.53.10", + "utopia-php/database": "0.53.12", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index aab67e93eb..0650710611 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f77f899f6250f080406151dc4cb29f92", + "content-hash": "102bab0efa76adc92312b9c5a7f488e3", "packages": [ { "name": "adhocore/jwt", @@ -1724,32 +1724,32 @@ }, { "name": "utopia-php/database", - "version": "0.53.10", + "version": "0.53.12", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "39550cb0e32cac45bf5ea1deb96569b837c028b1" + "reference": "4068d0c5c503ec4562f8c0aa9cfd095889418b83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/39550cb0e32cac45bf5ea1deb96569b837c028b1", - "reference": "39550cb0e32cac45bf5ea1deb96569b837c028b1", + "url": "https://api.github.com/repos/utopia-php/database/zipball/4068d0c5c503ec4562f8c0aa9cfd095889418b83", + "reference": "4068d0c5c503ec4562f8c0aa9cfd095889418b83", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-pdo": "*", - "php": ">=8.0", + "php": ">=8.3", "utopia-php/cache": "0.10.*", "utopia-php/framework": "0.33.*", "utopia-php/mongo": "0.3.*" }, "require-dev": { "fakerphp/faker": "1.23.*", - "laravel/pint": "1.17.*", - "pcov/clobber": "2.0.*", - "phpstan/phpstan": "1.11.*", - "phpunit/phpunit": "9.6.*", + "laravel/pint": "1.*", + "pcov/clobber": "2.*", + "phpstan/phpstan": "1.*", + "phpunit/phpunit": "9.*", "rregeer/phpunit-coverage-check": "0.3.*", "swoole/ide-helper": "5.1.3", "utopia-php/cli": "0.14.*" @@ -1774,9 +1774,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.53.10" + "source": "https://github.com/utopia-php/database/tree/0.53.12" }, - "time": "2024-11-04T02:02:23+00:00" + "time": "2024-11-04T07:51:44+00:00" }, { "name": "utopia-php/domains",