@@ -3536,6 +3536,26 @@ private function cleanupRelationship(
35363536 );
35373537 }
35383538
3539+ private function getOneWayRelationshipInternalKey (string $ collectionId , string $ id ): string
3540+ {
3541+ $ candidate = $ collectionId . '_ ' . $ id ;
3542+
3543+ if (\strlen ($ candidate ) <= self ::LENGTH_KEY ) {
3544+ return $ candidate ;
3545+ }
3546+
3547+ return 'rel_ ' . \md5 ($ collectionId . ': ' . $ id );
3548+ }
3549+
3550+ private function getRelationshipTwoWayKey (array |Document $ relationship ): string
3551+ {
3552+ $ options = \is_array ($ relationship )
3553+ ? ($ relationship ['options ' ] ?? [])
3554+ : $ relationship ->getAttribute ('options ' , []);
3555+
3556+ return $ options ['internalTwoWayKey ' ] ?? $ options ['twoWayKey ' ] ?? '' ;
3557+ }
3558+
35393559 /**
35403560 * Create a relationship attribute
35413561 *
@@ -3576,6 +3596,7 @@ public function createRelationship(
35763596 }
35773597
35783598 $ id ??= $ relatedCollection ->getId ();
3599+ $ publicTwoWayKey = $ twoWay ? ($ twoWayKey ?? $ collection ->getId ()) : null ;
35793600
35803601 $ attributes = $ collection ->getAttribute ('attributes ' , []);
35813602 /** @var array<Document> $attributes */
@@ -3588,14 +3609,16 @@ public function createRelationship(
35883609 $ twoWay
35893610 && $ attribute ->getAttribute ('type ' ) === self ::VAR_RELATIONSHIP
35903611 && isset ($ attribute ->getAttribute ('options ' )['twoWayKey ' ])
3591- && \strtolower ($ attribute ->getAttribute ('options ' )['twoWayKey ' ]) === \strtolower ($ twoWayKey )
3612+ && \strtolower ($ attribute ->getAttribute ('options ' )['twoWayKey ' ]) === \strtolower (( string ) $ publicTwoWayKey )
35923613 && $ attribute ->getAttribute ('options ' )['relatedCollection ' ] === $ relatedCollection ->getId ()
35933614 ) {
35943615 throw new DuplicateException ('Related attribute already exists ' );
35953616 }
35963617 }
35973618
3598- $ twoWayKey ??= $ collection ->getId ();
3619+ $ twoWayKey = $ twoWay
3620+ ? (string ) $ publicTwoWayKey
3621+ : $ this ->getOneWayRelationshipInternalKey ($ collection ->getId (), $ id );
35993622
36003623 $ relationship = new Document ([
36013624 '$id ' => ID ::custom ($ id ),
@@ -3607,7 +3630,8 @@ public function createRelationship(
36073630 'relatedCollection ' => $ relatedCollection ->getId (),
36083631 'relationType ' => $ type ,
36093632 'twoWay ' => $ twoWay ,
3610- 'twoWayKey ' => $ twoWayKey ,
3633+ 'twoWayKey ' => $ publicTwoWayKey ,
3634+ 'internalTwoWayKey ' => $ twoWayKey ,
36113635 'onDelete ' => $ onDelete ,
36123636 'side ' => Database::RELATION_SIDE_PARENT ,
36133637 ],
@@ -3623,7 +3647,8 @@ public function createRelationship(
36233647 'relatedCollection ' => $ collection ->getId (),
36243648 'relationType ' => $ type ,
36253649 'twoWay ' => $ twoWay ,
3626- 'twoWayKey ' => $ id ,
3650+ 'twoWayKey ' => $ twoWay ? $ id : null ,
3651+ 'internalTwoWayKey ' => $ id ,
36273652 'onDelete ' => $ onDelete ,
36283653 'side ' => Database::RELATION_SIDE_CHILD ,
36293654 ],
@@ -3898,23 +3923,27 @@ public function updateRelationship(
38983923
38993924 // Determine if we need to alter the database (rename columns/indexes)
39003925 $ oldAttribute = $ attributes [$ attributeIndex ];
3901- $ oldTwoWayKey = $ oldAttribute ['options ' ]['twoWayKey ' ];
3926+ $ oldTwoWayKey = $ this ->getRelationshipTwoWayKey ($ oldAttribute );
3927+ $ oldPublicTwoWayKey = $ oldAttribute ['options ' ]['twoWayKey ' ] ?? null ;
3928+ $ actualTwoWay = $ twoWay ?? $ oldAttribute ['options ' ]['twoWay ' ];
3929+ $ actualOnDelete = $ onDelete ?? $ oldAttribute ['options ' ]['onDelete ' ];
3930+ $ actualNewKey = $ newKey ?? $ id ;
3931+ $ actualPublicNewTwoWayKey = $ actualTwoWay ? ($ newTwoWayKey ?? $ oldPublicTwoWayKey ?? $ collection ->getId ()) : null ;
3932+ $ actualNewTwoWayKey = $ actualTwoWay
3933+ ? (string ) $ actualPublicNewTwoWayKey
3934+ : $ this ->getOneWayRelationshipInternalKey ($ collection ->getId (), $ actualNewKey );
39023935 $ altering = (!\is_null ($ newKey ) && $ newKey !== $ id )
3903- || (! \is_null ( $ newTwoWayKey ) && $ newTwoWayKey !== $ oldTwoWayKey );
3936+ || ($ actualNewTwoWayKey !== $ oldTwoWayKey );
39043937
39053938 // Validate new keys don't already exist
39063939 if (
3907- !\is_null ($ newTwoWayKey )
3908- && \in_array ($ newTwoWayKey , \array_map (fn ($ attribute ) => $ attribute ['key ' ], $ relatedCollection ->getAttribute ('attributes ' , [])))
3940+ $ actualTwoWay
3941+ && !\is_null ($ actualPublicNewTwoWayKey )
3942+ && \in_array ($ actualPublicNewTwoWayKey , \array_map (fn ($ attribute ) => $ attribute ['key ' ], $ relatedCollection ->getAttribute ('attributes ' , [])))
39093943 ) {
39103944 throw new DuplicateException ('Related attribute already exists ' );
39113945 }
39123946
3913- $ actualNewKey = $ newKey ?? $ id ;
3914- $ actualNewTwoWayKey = $ newTwoWayKey ?? $ oldTwoWayKey ;
3915- $ actualTwoWay = $ twoWay ?? $ oldAttribute ['options ' ]['twoWay ' ];
3916- $ actualOnDelete = $ onDelete ?? $ oldAttribute ['options ' ]['onDelete ' ];
3917-
39183947 $ adapterUpdated = false ;
39193948 if ($ altering ) {
39203949 try {
@@ -3959,22 +3988,24 @@ public function updateRelationship(
39593988 }
39603989
39613990 try {
3962- $ this ->updateAttributeMeta ($ collection ->getId (), $ id , function ($ attribute ) use ($ actualNewKey , $ actualNewTwoWayKey , $ actualTwoWay , $ actualOnDelete , $ relatedCollection , $ type , $ side ) {
3991+ $ this ->updateAttributeMeta ($ collection ->getId (), $ id , function ($ attribute ) use ($ actualNewKey , $ actualNewTwoWayKey , $ actualPublicNewTwoWayKey , $ actualTwoWay , $ actualOnDelete , $ relatedCollection , $ type , $ side ) {
39633992 $ attribute ->setAttribute ('$id ' , $ actualNewKey );
39643993 $ attribute ->setAttribute ('key ' , $ actualNewKey );
39653994 $ attribute ->setAttribute ('options ' , [
39663995 'relatedCollection ' => $ relatedCollection ->getId (),
39673996 'relationType ' => $ type ,
39683997 'twoWay ' => $ actualTwoWay ,
3969- 'twoWayKey ' => $ actualNewTwoWayKey ,
3998+ 'twoWayKey ' => $ actualPublicNewTwoWayKey ,
3999+ 'internalTwoWayKey ' => $ actualNewTwoWayKey ,
39704000 'onDelete ' => $ actualOnDelete ,
39714001 'side ' => $ side ,
39724002 ]);
39734003 });
39744004
39754005 $ this ->updateAttributeMeta ($ relatedCollection ->getId (), $ oldTwoWayKey , function ($ twoWayAttribute ) use ($ actualNewKey , $ actualNewTwoWayKey , $ actualTwoWay , $ actualOnDelete ) {
39764006 $ options = $ twoWayAttribute ->getAttribute ('options ' , []);
3977- $ options ['twoWayKey ' ] = $ actualNewKey ;
4007+ $ options ['twoWayKey ' ] = $ actualTwoWay ? $ actualNewKey : null ;
4008+ $ options ['internalTwoWayKey ' ] = $ actualNewKey ;
39784009 $ options ['twoWay ' ] = $ actualTwoWay ;
39794010 $ options ['onDelete ' ] = $ actualOnDelete ;
39804011
@@ -4111,7 +4142,8 @@ function ($index) use ($newKey) {
41114142 try {
41124143 $ this ->updateAttributeMeta ($ relatedCollection ->getId (), $ actualNewTwoWayKey , function ($ twoWayAttribute ) use ($ oldTwoWayKey , $ id , $ oldAttribute ) {
41134144 $ options = $ twoWayAttribute ->getAttribute ('options ' , []);
4114- $ options ['twoWayKey ' ] = $ id ;
4145+ $ options ['twoWayKey ' ] = $ oldAttribute ['options ' ]['twoWay ' ] ? $ id : null ;
4146+ $ options ['internalTwoWayKey ' ] = $ id ;
41154147 $ options ['twoWay ' ] = $ oldAttribute ['options ' ]['twoWay ' ];
41164148 $ options ['onDelete ' ] = $ oldAttribute ['options ' ]['onDelete ' ];
41174149 $ twoWayAttribute ->setAttribute ('$id ' , $ oldTwoWayKey );
@@ -4205,7 +4237,7 @@ public function deleteRelationship(string $collection, string $id): bool
42054237 $ relatedCollection = $ relationship ['options ' ]['relatedCollection ' ];
42064238 $ type = $ relationship ['options ' ]['relationType ' ];
42074239 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
4208- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
4240+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
42094241 $ side = $ relationship ['options ' ]['side ' ];
42104242
42114243 $ relatedCollection = $ this ->silent (fn () => $ this ->getCollection ($ relatedCollection ));
@@ -4989,7 +5021,7 @@ private function populateDocumentsRelationships(
49895021
49905022 // Get two-way relationship info
49915023 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
4992- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
5024+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
49935025
49945026 // Queue if:
49955027 // 1. No explicit selects (fetch all recursively), OR
@@ -5167,7 +5199,7 @@ private function populateOneToManyRelationshipsBatch(
51675199 ): array {
51685200 $ key = $ relationship ['key ' ];
51695201 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
5170- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
5202+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
51715203 $ side = $ relationship ['options ' ]['side ' ];
51725204 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
51735205
@@ -5265,7 +5297,7 @@ private function populateManyToOneRelationshipsBatch(
52655297 ): array {
52665298 $ key = $ relationship ['key ' ];
52675299 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
5268- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
5300+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
52695301 $ side = $ relationship ['options ' ]['side ' ];
52705302 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
52715303
@@ -5360,7 +5392,7 @@ private function populateManyToManyRelationshipsBatch(
53605392 ): array {
53615393 $ key = $ relationship ['key ' ];
53625394 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
5363- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
5395+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
53645396 $ side = $ relationship ['options ' ]['side ' ];
53655397 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
53665398 $ collection = $ this ->getCollection ($ relationship ->getAttribute ('collection ' ));
@@ -5756,7 +5788,7 @@ private function createDocumentRelationships(Document $collection, Document $doc
57565788 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
57575789 $ relationType = $ relationship ['options ' ]['relationType ' ];
57585790 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
5759- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
5791+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
57605792 $ side = $ relationship ['options ' ]['side ' ];
57615793
57625794 if ($ stackCount >= Database::RELATION_MAX_DEPTH - 1 && $ this ->relationshipWriteStack [$ stackCount - 1 ] !== $ relatedCollection ->getId ()) {
@@ -6585,7 +6617,7 @@ private function updateDocumentRelationships(Document $collection, Document $old
65856617 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
65866618 $ relationType = (string )$ relationship ['options ' ]['relationType ' ];
65876619 $ twoWay = (bool )$ relationship ['options ' ]['twoWay ' ];
6588- $ twoWayKey = ( string ) $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
6620+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
65896621 $ side = (string )$ relationship ['options ' ]['side ' ];
65906622
65916623 if (Operator::isOperator ($ value )) {
@@ -7673,7 +7705,7 @@ private function deleteDocumentRelationships(Document $collection, Document $doc
76737705 $ relatedCollection = $ this ->getCollection ($ relationship ['options ' ]['relatedCollection ' ]);
76747706 $ relationType = $ relationship ['options ' ]['relationType ' ];
76757707 $ twoWay = $ relationship ['options ' ]['twoWay ' ];
7676- $ twoWayKey = $ relationship[ ' options ' ][ ' twoWayKey ' ] ;
7708+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship) ;
76777709 $ onDelete = $ relationship ['options ' ]['onDelete ' ];
76787710 $ side = $ relationship ['options ' ]['side ' ];
76797711
@@ -7692,7 +7724,7 @@ private function deleteDocumentRelationships(Document $collection, Document $doc
76927724 $ existingKey = $ processedRelationship ['key ' ];
76937725 $ existingCollection = $ processedRelationship ['collection ' ];
76947726 $ existingRelatedCollection = $ processedRelationship ['options ' ]['relatedCollection ' ];
7695- $ existingTwoWayKey = $ processedRelationship[ ' options ' ][ ' twoWayKey ' ] ;
7727+ $ existingTwoWayKey = $ this -> getRelationshipTwoWayKey ( $ processedRelationship) ;
76967728 $ existingSide = $ processedRelationship ['options ' ]['side ' ];
76977729
76987730 // If this relationship has already been fetched for this document, skip it
@@ -9522,7 +9554,7 @@ private function processNestedRelationshipPath(string $startCollection, array $q
95229554 'toCollection ' => $ relationship ['options ' ]['relatedCollection ' ],
95239555 'relationType ' => $ relationship ['options ' ]['relationType ' ],
95249556 'side ' => $ relationship ['options ' ]['side ' ],
9525- 'twoWayKey ' => $ relationship[ ' options ' ][ ' twoWayKey ' ] ,
9557+ 'twoWayKey ' => $ this -> getRelationshipTwoWayKey ( $ relationship) ,
95269558 ];
95279559
95289560 $ currentCollection = $ relationship ['options ' ]['relatedCollection ' ];
@@ -9896,7 +9928,7 @@ private function resolveRelationshipGroupToIds(
98969928 return null ;
98979929 }
98989930
9899- $ twoWayKey = $ relationship -> getAttribute ( ' options ' )[ ' twoWayKey ' ] ;
9931+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship ) ;
99009932 $ relatedCollectionDoc = $ this ->silent (fn () => $ this ->getCollection ($ relatedCollection ));
99019933 $ junction = $ this ->getJunctionCollection ($ collection , $ relatedCollectionDoc , $ side );
99029934
@@ -9924,7 +9956,7 @@ private function resolveRelationshipGroupToIds(
99249956 ])
99259957 ));
99269958
9927- $ twoWayKey = $ relationship -> getAttribute ( ' options ' )[ ' twoWayKey ' ] ;
9959+ $ twoWayKey = $ this -> getRelationshipTwoWayKey ( $ relationship ) ;
99289960 $ parentIds = [];
99299961
99309962 foreach ($ matchingDocs as $ doc ) {
0 commit comments