@@ -33,6 +33,9 @@ final class CypherObject implements TestkitResponseInterface
3333 private $ value ;
3434 private string $ name ;
3535
36+ // Store element ID mappings for relationships created from paths
37+ private static array $ relationshipElementIdMap = [];
38+
3639 /**
3740 * @param CypherList|CypherMap|int|bool|float|string|Node|Relationship|Path|null $value
3841 */
@@ -103,12 +106,16 @@ public static function autoDetect($value): TestkitResponseInterface
103106 /** @psalm-suppress MixedArgumentTypeCoercion */
104107 $ props [$ key ] = self ::autoDetect ($ property );
105108 }
109+ $ elementId = $ value ->getElementId ();
110+ if ($ elementId === null ) {
111+ $ elementId = (string ) $ value ->getId ();
112+ }
106113
107114 $ tbr = new CypherNode (
108115 new CypherObject ('CypherInt ' , $ value ->getId ()),
109116 new CypherObject ('CypherList ' , new CypherList ($ labels )),
110117 new CypherObject ('CypherMap ' , new CypherMap ($ props )),
111- new CypherObject ('CypherString ' , $ value -> getElementId () )
118+ new CypherObject ('CypherString ' , $ elementId )
112119 );
113120 break ;
114121 case Relationship::class:
@@ -118,31 +125,73 @@ public static function autoDetect($value): TestkitResponseInterface
118125 $ props [$ key ] = self ::autoDetect ($ property );
119126 }
120127
128+ $ elementId = $ value ->getElementId ();
129+ if ($ elementId === null ) {
130+ $ elementId = (string ) $ value ->getId ();
131+ }
132+
133+ $ relationshipKey = $ value ->getId ().'_ ' .$ value ->getStartNodeId ().'_ ' .$ value ->getEndNodeId ();
134+
135+ $ startNodeElementId = self ::$ relationshipElementIdMap [$ relationshipKey ]['startNodeElementId ' ] ?? (string ) $ value ->getStartNodeId ();
136+ $ endNodeElementId = self ::$ relationshipElementIdMap [$ relationshipKey ]['endNodeElementId ' ] ?? (string ) $ value ->getEndNodeId ();
137+
121138 $ tbr = new CypherRelationship (
122139 new CypherObject ('CypherInt ' , $ value ->getId ()),
123140 new CypherObject ('CypherInt ' , $ value ->getStartNodeId ()),
124141 new CypherObject ('CypherInt ' , $ value ->getEndNodeId ()),
125142 new CypherObject ('CypherString ' , $ value ->getType ()),
126143 new CypherObject ('CypherMap ' , new CypherMap ($ props )),
127- new CypherObject ('CypherString ' , $ value ->getElementId ())
144+ new CypherObject ('CypherString ' , $ elementId ),
145+ new CypherObject ('CypherString ' , $ startNodeElementId ), // Use stored element ID
146+ new CypherObject ('CypherString ' , $ endNodeElementId ) // Use stored element ID
128147 );
129148 break ;
130149 case Path::class:
131150 $ nodes = [];
132151 foreach ($ value ->getNodes () as $ node ) {
133152 $ nodes [] = self ::autoDetect ($ node );
134153 }
154+
135155 $ rels = [];
156+ $ nodesList = $ value ->getNodes ();
157+
136158 foreach ($ value ->getRelationships () as $ i => $ rel ) {
137- $ rels [] = self ::autoDetect (new Relationship (
138- $ rel ->getId (),
139- $ value ->getNodes ()->get ($ i )->getId (),
140- $ value ->getNodes ()->get ($ i + 1 )->getId (),
141- $ rel ->getType (),
142- $ rel ->getProperties (),
143- $ rel ->getElementId ()
144- ));
159+ $ relElementId = $ rel ->getElementId () ?? (string ) $ rel ->getId ();
160+
161+ if ($ rel instanceof UnboundRelationship) {
162+ if ($ i < $ nodesList ->count () - 1 ) {
163+ $ startNode = $ nodesList ->get ($ i );
164+ $ endNode = $ nodesList ->get ($ i + 1 );
165+
166+ $ startNodeElementId = $ startNode ->getElementId () ?? (string ) $ startNode ->getId ();
167+ $ endNodeElementId = $ endNode ->getElementId () ?? (string ) $ endNode ->getId ();
168+
169+ $ boundRel = new Relationship (
170+ $ rel ->getId (),
171+ $ startNode ->getId (),
172+ $ endNode ->getId (),
173+ $ rel ->getType (),
174+ $ rel ->getProperties (),
175+ $ relElementId
176+ );
177+
178+ $ relationshipKey = $ boundRel ->getId ().'_ ' .$ boundRel ->getStartNodeId ().'_ ' .$ boundRel ->getEndNodeId ();
179+ self ::$ relationshipElementIdMap [$ relationshipKey ] = [
180+ 'startNodeElementId ' => $ startNodeElementId ,
181+ 'endNodeElementId ' => $ endNodeElementId ,
182+ ];
183+
184+ error_log ('DEBUG PATH: Stored mapping for key: ' .$ relationshipKey );
185+ error_log ('DEBUG PATH: Stored startNodeElementId: ' .$ startNodeElementId );
186+ error_log ('DEBUG PATH: Stored endNodeElementId: ' .$ endNodeElementId );
187+
188+ $ rels [] = self ::autoDetect ($ boundRel );
189+ }
190+ } else {
191+ $ rels [] = self ::autoDetect ($ rel );
192+ }
145193 }
194+
146195 $ tbr = new CypherPath (
147196 new CypherObject ('CypherList ' , new CypherList ($ nodes )),
148197 new CypherObject ('CypherList ' , new CypherList ($ rels ))
@@ -161,7 +210,9 @@ public static function autoDetect($value): TestkitResponseInterface
161210 new CypherObject ('CypherNull ' , null ),
162211 new CypherObject ('CypherString ' , $ value ->getType ()),
163212 new CypherObject ('CypherMap ' , new CypherMap ($ props )),
164- new CypherObject ('CypherString ' , $ value ->getElementId ())
213+ new CypherObject ('CypherString ' , $ value ->getElementId ()),
214+ new CypherObject ('CypherNull ' , null ),
215+ new CypherObject ('CypherNull ' , null )
165216 );
166217 break ;
167218 default :
0 commit comments