@@ -60,7 +60,7 @@ class Database
6060 public const VAR_LINESTRING = 'linestring ' ;
6161 public const VAR_POLYGON = 'polygon ' ;
6262
63- public const SPATIAL_TYPES = [self ::VAR_POINT ,self ::VAR_LINESTRING , self ::VAR_POLYGON ];
63+ public const SPATIAL_TYPES = [self ::VAR_POINT , self ::VAR_LINESTRING , self ::VAR_POLYGON ];
6464
6565 // Index Types
6666 public const INDEX_KEY = 'key ' ;
@@ -3826,7 +3826,7 @@ public function createDocument(string $collection, Document $document): Document
38263826 * @param string $collection
38273827 * @param array<Document> $documents
38283828 * @param int $batchSize
3829- * @param callable|null $onNext
3829+ * @param ( callable(Document): void) |null $onNext
38303830 * @return int
38313831 * @throws AuthorizationException
38323832 * @throws StructureException
@@ -4283,7 +4283,7 @@ public function updateDocument(string $collection, string $id, Document $documen
42834283
42844284 if ($ document ->offsetExists ('$permissions ' )) {
42854285 $ originalPermissions = $ old ->getPermissions ();
4286- $ currentPermissions = $ document ->getPermissions ();
4286+ $ currentPermissions = $ document ->getPermissions ();
42874287
42884288 sort ($ originalPermissions );
42894289 sort ($ currentPermissions );
@@ -4473,8 +4473,8 @@ public function updateDocument(string $collection, string $id, Document $documen
44734473 * @param Document $updates
44744474 * @param array<Query> $queries
44754475 * @param int $batchSize
4476- * @param callable|null $onNext
4477- * @param callable|null $onError
4476+ * @param ( callable(Document $updated, Document $old): void) |null $onNext
4477+ * @param ( callable(Throwable): void) |null $onError
44784478 * @return int
44794479 * @throws AuthorizationException
44804480 * @throws ConflictException
@@ -4592,17 +4592,17 @@ public function updateDocuments(
45924592 array_merge ($ new , $ queries ),
45934593 forPermission: Database::PERMISSION_UPDATE
45944594 ));
4595-
4595+
45964596 if (empty ($ batch )) {
45974597 break ;
45984598 }
45994599
4600- $ currentPermissions = $ updates ->getPermissions ();
4600+ $ old = array_map (fn ($ doc ) => clone $ doc , $ batch );
4601+ $ currentPermissions = $ updates ->getPermissions ();
46014602 sort ($ currentPermissions );
46024603
46034604 $ this ->withTransaction (function () use ($ collection , $ updates , &$ batch , $ currentPermissions ) {
46044605 foreach ($ batch as $ index => $ document ) {
4605-
46064606 $ skipPermissionsUpdate = true ;
46074607
46084608 if ($ updates ->offsetExists ('$permissions ' )) {
@@ -4647,13 +4647,12 @@ public function updateDocuments(
46474647 );
46484648 });
46494649
4650- foreach ($ batch as $ doc ) {
4650+ foreach ($ batch as $ index => $ doc ) {
46514651 $ doc ->removeAttribute ('$skipPermissionsUpdate ' );
4652-
46534652 $ this ->purgeCachedDocument ($ collection ->getId (), $ doc ->getId ());
46544653 $ doc = $ this ->decode ($ collection , $ doc );
46554654 try {
4656- $ onNext && $ onNext ($ doc );
4655+ $ onNext && $ onNext ($ doc, $ old [ $ index ] );
46574656 } catch (Throwable $ th ) {
46584657 $ onError ? $ onError ($ th ) : throw $ th ;
46594658 }
@@ -5069,28 +5068,58 @@ private function getJunctionCollection(Document $collection, Document $relatedCo
50695068 : '_ ' . $ relatedCollection ->getSequence () . '_ ' . $ collection ->getSequence ();
50705069 }
50715070
5071+ /**
5072+ * Create or update a document.
5073+ *
5074+ * @param string $collection
5075+ * @param Document $document
5076+ * @return Document
5077+ * @throws StructureException
5078+ * @throws Throwable
5079+ */
5080+ public function upsertDocument (
5081+ string $ collection ,
5082+ Document $ document ,
5083+ ): Document {
5084+ $ result = null ;
5085+
5086+ $ this ->upsertDocumentsWithIncrease (
5087+ $ collection ,
5088+ '' ,
5089+ [$ document ],
5090+ function (Document $ doc ) use (&$ result ) {
5091+ $ result = $ doc ;
5092+ }
5093+ );
5094+
5095+ return $ result ;
5096+ }
5097+
50725098 /**
50735099 * Create or update documents.
50745100 *
50755101 * @param string $collection
50765102 * @param array<Document> $documents
50775103 * @param int $batchSize
5078- * @param callable|null $onNext
5104+ * @param (callable(Document): void)|null $onNext
5105+ * @param (callable(Throwable): void)|null $onError
50795106 * @return int
50805107 * @throws StructureException
50815108 * @throws \Throwable
50825109 */
5083- public function createOrUpdateDocuments (
5110+ public function upsertDocuments (
50845111 string $ collection ,
50855112 array $ documents ,
50865113 int $ batchSize = self ::INSERT_BATCH_SIZE ,
50875114 ?callable $ onNext = null ,
5115+ ?callable $ onError = null
50885116 ): int {
5089- return $ this ->createOrUpdateDocumentsWithIncrease (
5117+ return $ this ->upsertDocumentsWithIncrease (
50905118 $ collection ,
50915119 '' ,
50925120 $ documents ,
50935121 $ onNext ,
5122+ $ onError ,
50945123 $ batchSize
50955124 );
50965125 }
@@ -5108,11 +5137,12 @@ public function createOrUpdateDocuments(
51085137 * @throws \Throwable
51095138 * @throws Exception
51105139 */
5111- public function createOrUpdateDocumentsWithIncrease (
5140+ public function upsertDocumentsWithIncrease (
51125141 string $ collection ,
51135142 string $ attribute ,
51145143 array $ documents ,
51155144 ?callable $ onNext = null ,
5145+ ?callable $ onError = null ,
51165146 int $ batchSize = self ::INSERT_BATCH_SIZE
51175147 ): int {
51185148 if (empty ($ documents )) {
@@ -5144,7 +5174,7 @@ public function createOrUpdateDocumentsWithIncrease(
51445174
51455175 if ($ document ->offsetExists ('$permissions ' )) {
51465176 $ originalPermissions = $ old ->getPermissions ();
5147- $ currentPermissions = $ document ->getPermissions ();
5177+ $ currentPermissions = $ document ->getPermissions ();
51485178
51495179 sort ($ originalPermissions );
51505180 sort ($ currentPermissions );
@@ -5274,7 +5304,7 @@ public function createOrUpdateDocumentsWithIncrease(
52745304 /**
52755305 * @var array<Change> $chunk
52765306 */
5277- $ batch = $ this ->withTransaction (fn () => Authorization::skip (fn () => $ this ->adapter ->createOrUpdateDocuments (
5307+ $ batch = $ this ->withTransaction (fn () => Authorization::skip (fn () => $ this ->adapter ->upsertDocuments (
52785308 $ collection ,
52795309 $ attribute ,
52805310 $ chunk
@@ -5972,8 +6002,8 @@ private function deleteCascade(Document $collection, Document $relatedCollection
59726002 * @param string $collection
59736003 * @param array<Query> $queries
59746004 * @param int $batchSize
5975- * @param callable|null $onNext
5976- * @param callable|null $onError
6005+ * @param ( callable(Document): void) |null $onNext
6006+ * @param ( callable(Throwable): void) |null $onError
59776007 * @return int
59786008 * @throws AuthorizationException
59796009 * @throws DatabaseException
@@ -6520,7 +6550,7 @@ public static function addFilter(string $name, callable $encode, callable $decod
65206550 public function encode (Document $ collection , Document $ document ): Document
65216551 {
65226552 $ attributes = $ collection ->getAttribute ('attributes ' , []);
6523- $ internalDateAttributes = ['$createdAt ' ,'$updatedAt ' ];
6553+ $ internalDateAttributes = ['$createdAt ' , '$updatedAt ' ];
65246554 foreach ($ this ->getInternalAttributes () as $ attribute ) {
65256555 $ attributes [] = $ attribute ;
65266556 }
@@ -6937,7 +6967,7 @@ public static function convertQuery(Document $collection, Query $query): Query
69376967 }
69386968 }
69396969
6940- if (! $ attribute ->isEmpty ()) {
6970+ if (!$ attribute ->isEmpty ()) {
69416971 $ query ->setOnArray ($ attribute ->getAttribute ('array ' , false ));
69426972
69436973 if ($ attribute ->getAttribute ('type ' ) == Database::VAR_DATETIME ) {
@@ -7195,7 +7225,7 @@ public function decodeSpatialData(string $wkt): array
71957225 // POINT(x y)
71967226 if (str_starts_with ($ upper , 'POINT( ' )) {
71977227 $ start = strpos ($ wkt , '( ' ) + 1 ;
7198- $ end = strrpos ($ wkt , ') ' );
7228+ $ end = strrpos ($ wkt , ') ' );
71997229 $ inside = substr ($ wkt , $ start , $ end - $ start );
72007230
72017231 $ coords = explode (' ' , trim ($ inside ));
@@ -7205,7 +7235,7 @@ public function decodeSpatialData(string $wkt): array
72057235 // LINESTRING(x1 y1, x2 y2, ...)
72067236 if (str_starts_with ($ upper , 'LINESTRING( ' )) {
72077237 $ start = strpos ($ wkt , '( ' ) + 1 ;
7208- $ end = strrpos ($ wkt , ') ' );
7238+ $ end = strrpos ($ wkt , ') ' );
72097239 $ inside = substr ($ wkt , $ start , $ end - $ start );
72107240
72117241 $ points = explode (', ' , $ inside );
@@ -7218,7 +7248,7 @@ public function decodeSpatialData(string $wkt): array
72187248 // POLYGON((x1,y1),(x2,y2))
72197249 if (str_starts_with ($ upper , 'POLYGON(( ' )) {
72207250 $ start = strpos ($ wkt , '(( ' ) + 2 ;
7221- $ end = strrpos ($ wkt , ')) ' );
7251+ $ end = strrpos ($ wkt , ')) ' );
72227252 $ inside = substr ($ wkt , $ start , $ end - $ start );
72237253
72247254 $ rings = explode ('),( ' , $ inside );
0 commit comments