Skip to content

Commit 677939c

Browse files
committed
Replace dynamic property access (->{'prop'}) with direct access (->prop ?? null)
for element_id, startNodeElementId, and endNodeElementId properties.Restored the tests and fixed them
1 parent 4bb4176 commit 677939c

File tree

5 files changed

+66
-21
lines changed

5 files changed

+66
-21
lines changed

src/Databags/Notification.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/**
2020
* @psalm-immutable
2121
*
22-
* @template-extends AbstractCypherObject<string, string|Position>
22+
* @template-extends AbstractCypherObject<string, string|array<string, float|int|null|string>>
2323
*/
2424
final class Notification extends AbstractCypherObject
2525
{
@@ -82,13 +82,10 @@ public function getTitle(): string
8282
return $this->title;
8383
}
8484

85-
8685
/**
87-
* Matches inherited return type: array<string, string|Position>.
88-
*
8986
* @psalm-external-mutation-free
9087
*
91-
* @return array<string, string|Position>
88+
* @return array<string, string|array<string, float|int|string|null>>
9289
*/
9390
public function toArray(): array
9491
{
@@ -101,5 +98,4 @@ public function toArray(): array
10198
'category' => $this->category,
10299
];
103100
}
104-
105101
}

src/Formatter/Specialised/BoltOGMTranslator.php

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,12 @@ private function makeFromBoltNode(BoltNode $node): Node
102102
$properties[$name] = $this->mapValueToType($property);
103103
}
104104

105-
/** @var ?string|null $elementId */
106-
$elementId = null;
107-
if ($node instanceof \Bolt\protocol\v5\structures\Node) {
108-
$elementId = $node->element_id;
105+
/** @var string|null $elementId */
106+
if (property_exists($node, 'element_id')) {
107+
$elementIdValue = $node->element_id ?? null;
108+
$elementId = is_string($elementIdValue) ? $elementIdValue : (string) $node->id;
109+
} else {
110+
$elementId = (string) $node->id;
109111
}
110112

111113
/**
@@ -180,9 +182,27 @@ private function makeFromBoltRelationship(BoltRelationship $rel): Relationship
180182
}
181183

182184
/** @var string|null $elementId */
183-
$elementId = null;
184-
if ($rel instanceof \Bolt\protocol\v5\structures\Relationship) {
185-
$elementId = $rel->element_id;
185+
if (property_exists($rel, 'element_id')) {
186+
$elementIdValue = $rel->element_id ?? null;
187+
$elementId = is_string($elementIdValue) ? $elementIdValue : (string) $rel->id;
188+
} else {
189+
$elementId = (string) $rel->id;
190+
}
191+
192+
// For Neo4j 5+, try to get actual element IDs if available
193+
// For Neo4j 4, fallback to string representation of integer IDs
194+
if (property_exists($rel, 'startNodeElementId')) {
195+
$startNodeElementIdValue = $rel->startNodeElementId ?? null;
196+
$startNodeElementId = is_string($startNodeElementIdValue) ? $startNodeElementIdValue : (string) $rel->startNodeId;
197+
} else {
198+
$startNodeElementId = (string) $rel->startNodeId;
199+
}
200+
201+
if (property_exists($rel, 'endNodeElementId')) {
202+
$endNodeElementIdValue = $rel->endNodeElementId ?? null;
203+
$endNodeElementId = is_string($endNodeElementIdValue) ? $endNodeElementIdValue : (string) $rel->endNodeId;
204+
} else {
205+
$endNodeElementId = (string) $rel->endNodeId;
186206
}
187207

188208
return new Relationship(
@@ -191,7 +211,9 @@ private function makeFromBoltRelationship(BoltRelationship $rel): Relationship
191211
$rel->endNodeId,
192212
$rel->type,
193213
new CypherMap($map),
194-
$elementId
214+
$elementId,
215+
$startNodeElementId,
216+
$endNodeElementId
195217
);
196218
}
197219

@@ -207,9 +229,12 @@ private function makeFromBoltUnboundRelationship(BoltUnboundRelationship $rel):
207229
$map[$key] = $this->mapValueToType($property);
208230
}
209231

210-
$elementId = null;
211-
if ($rel instanceof \Bolt\protocol\v5\structures\UnboundRelationship) {
212-
$elementId = $rel->element_id;
232+
/** @var string|null $elementId */
233+
if (property_exists($rel, 'element_id')) {
234+
$elementIdValue = $rel->element_id ?? null;
235+
$elementId = is_string($elementIdValue) ? $elementIdValue : (string) $rel->id;
236+
} else {
237+
$elementId = (string) $rel->id;
213238
}
214239

215240
return new UnboundRelationship(

src/Types/Relationship.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public function __construct(
3434
string $type,
3535
CypherMap $properties,
3636
?string $elementId,
37+
private readonly ?string $startNodeElementId = null,
38+
private readonly ?string $endNodeElementId = null,
3739
) {
3840
parent::__construct($id, $type, $properties, $elementId);
3941
}
@@ -54,6 +56,22 @@ public function getEndNodeId(): int
5456
return $this->endNodeId;
5557
}
5658

59+
/**
60+
* Returns the element ID of the start node.
61+
*/
62+
public function getStartNodeElementId(): ?string
63+
{
64+
return $this->startNodeElementId;
65+
}
66+
67+
/**
68+
* Returns the element ID of the end node.
69+
*/
70+
public function getEndNodeElementId(): ?string
71+
{
72+
return $this->endNodeElementId;
73+
}
74+
5775
/**
5876
* @psalm-suppress ImplementedReturnTypeMismatch False positive.
5977
*
@@ -62,7 +80,9 @@ public function getEndNodeId(): int
6280
* type: string,
6381
* startNodeId: int,
6482
* endNodeId: int,
65-
* properties: CypherMap<OGMTypes>
83+
* properties: CypherMap<OGMTypes>,
84+
* startNodeElementId: ?string,
85+
* endNodeElementId: ?string
6686
* }
6787
*/
6888
public function toArray(): array
@@ -71,6 +91,8 @@ public function toArray(): array
7191

7292
$tbr['startNodeId'] = $this->getStartNodeId();
7393
$tbr['endNodeId'] = $this->getEndNodeId();
94+
$tbr['startNodeElementId'] = $this->getStartNodeElementId();
95+
$tbr['endNodeElementId'] = $this->getEndNodeElementId();
7496

7597
return $tbr;
7698
}

testkit-backend/src/Responses/Types/CypherObject.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,18 @@ public static function autoDetect($value): TestkitResponseInterface
133133
// First check if the relationship has methods to get start/end node element IDs
134134
$startNodeElementId = null;
135135
$endNodeElementId = null;
136-
136+
137137
if (method_exists($value, 'getStartNodeElementId')) {
138138
$startNodeElementId = $value->getStartNodeElementId();
139139
}
140140
if (method_exists($value, 'getEndNodeElementId')) {
141141
$endNodeElementId = $value->getEndNodeElementId();
142142
}
143-
143+
144144
// If not available directly, check our stored mappings from paths
145145
if ($startNodeElementId === null || $endNodeElementId === null) {
146146
$relationshipKey = $value->getId().'_'.$value->getStartNodeId().'_'.$value->getEndNodeId();
147-
147+
148148
if ($startNodeElementId === null) {
149149
$startNodeElementId = self::$relationshipElementIdMap[$relationshipKey]['startNodeElementId'] ?? (string) $value->getStartNodeId();
150150
}

tests/Integration/SummarizedResultFormatterTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ public function testRelationship(): void
421421
'properties' => $result->getProperties(),
422422
'startNodeId' => $result->getStartNodeId(),
423423
'endNodeId' => $result->getEndNodeId(),
424+
'startNodeElementId' => $result->getStartNodeElementId(),
425+
'endNodeElementId' => $result->getEndNodeElementId(),
424426
], JSON_THROW_ON_ERROR),
425427
json_encode($result, JSON_THROW_ON_ERROR)
426428
);

0 commit comments

Comments
 (0)