Skip to content

Commit 547d940

Browse files
committed
correctly transalte to date timezone id depending on bolt version
1 parent 0ca4a2a commit 547d940

File tree

5 files changed

+51
-28
lines changed

5 files changed

+51
-28
lines changed

src/Bolt/BoltUnmanagedTransaction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ public function run(string $statement, iterable $parameters = [])
9696
*/
9797
public function runStatement(Statement $statement)
9898
{
99-
$parameters = ParameterHelper::formatParameters($statement->getParameters(), true);
99+
$parameters = ParameterHelper::formatParameters($statement->getParameters(), $this->connection->getProtocol());
100100
$start = microtime(true);
101101

102102
try {

src/Enum/ConnectionProtocol.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ final class ConnectionProtocol extends TypedEnum implements JsonSerializable
5252
private const BOLT_V5 = '5';
5353
private const HTTP = 'http';
5454

55+
public function isBolt(): bool
56+
{
57+
/** @psalm-suppress ImpureMethodCall */
58+
return $this !== self::HTTP();
59+
}
60+
5561
/**
5662
* @pure
5763
*

src/Http/HttpHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ public static function statementsToJson(ConnectionInterface $connection, Formatt
208208
'includeStats' => false,
209209
];
210210
$st = array_merge($st, $formatter->statementConfigOverride($connection));
211-
$parameters = ParameterHelper::formatParameters($statement->getParameters());
211+
$parameters = ParameterHelper::formatParameters($statement->getParameters(), $connection->getProtocol());
212212
$st['parameters'] = $parameters->count() === 0 ? new stdClass() : $parameters->toArray();
213213
$tbr[] = $st;
214214
}

src/ParameterHelper.php

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use function is_string;
3434

3535
use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
36+
use Laudis\Neo4j\Enum\ConnectionProtocol;
3637
use Laudis\Neo4j\Types\CypherList;
3738
use Laudis\Neo4j\Types\CypherMap;
3839
use stdClass;
@@ -80,13 +81,13 @@ public static function asMap(iterable $iterable): CypherMap
8081
*/
8182
public static function asParameter(
8283
mixed $value,
83-
bool $boltDriver = false
84+
ConnectionProtocol $protocol
8485
): iterable|int|float|bool|string|stdClass|IStructure|null {
8586
return self::cypherMapToStdClass($value) ??
8687
self::emptySequenceToArray($value) ??
87-
self::convertBoltConvertibles($value, $boltDriver) ??
88-
self::convertTemporalTypes($value, $boltDriver) ??
89-
self::filledIterableToArray($value, $boltDriver) ??
88+
self::convertBoltConvertibles($value, $protocol) ??
89+
self::convertTemporalTypes($value, $protocol) ??
90+
self::filledIterableToArray($value, $protocol) ??
9091
self::stringAbleToString($value) ??
9192
self::filterInvalidType($value);
9293
}
@@ -148,10 +149,10 @@ private static function cypherMapToStdClass(mixed $value): ?stdClass
148149
return null;
149150
}
150151

151-
private static function filledIterableToArray(mixed $value, bool $boltDriver): ?array
152+
private static function filledIterableToArray(mixed $value, ConnectionProtocol $protocol): ?array
152153
{
153154
if (is_iterable($value)) {
154-
return self::iterableToArray($value, $boltDriver);
155+
return self::iterableToArray($value, $protocol);
155156
}
156157

157158
return null;
@@ -162,7 +163,7 @@ private static function filledIterableToArray(mixed $value, bool $boltDriver): ?
162163
*
163164
* @return CypherMap<iterable|scalar|stdClass|null>
164165
*/
165-
public static function formatParameters(iterable $parameters, bool $boltDriver = false): CypherMap
166+
public static function formatParameters(iterable $parameters, ConnectionProtocol $connection): CypherMap
166167
{
167168
/** @var array<string, iterable|scalar|stdClass|null> $tbr */
168169
$tbr = [];
@@ -175,13 +176,13 @@ public static function formatParameters(iterable $parameters, bool $boltDriver =
175176
$msg = 'The parameters must have an integer or string as key values, '.gettype($key).' received.';
176177
throw new InvalidArgumentException($msg);
177178
}
178-
$tbr[(string) $key] = self::asParameter($value, $boltDriver);
179+
$tbr[(string) $key] = self::asParameter($value, $connection);
179180
}
180181

181182
return new CypherMap($tbr);
182183
}
183184

184-
private static function iterableToArray(iterable $value, bool $boltDriver): array
185+
private static function iterableToArray(iterable $value, ConnectionProtocol $protocol): array
185186
{
186187
$tbr = [];
187188
/**
@@ -190,7 +191,7 @@ private static function iterableToArray(iterable $value, bool $boltDriver): arra
190191
*/
191192
foreach ($value as $key => $val) {
192193
if (is_int($key) || is_string($key)) {
193-
$tbr[$key] = self::asParameter($val, $boltDriver);
194+
$tbr[$key] = self::asParameter($val, $protocol);
194195
} else {
195196
$msg = 'Iterable parameters must have an integer or string as key values, '.gettype($key).' received.';
196197
throw new InvalidArgumentException($msg);
@@ -200,19 +201,27 @@ private static function iterableToArray(iterable $value, bool $boltDriver): arra
200201
return $tbr;
201202
}
202203

203-
private static function convertBoltConvertibles(mixed $value, bool $boltDriver): ?IStructure
204+
private static function convertBoltConvertibles(mixed $value, ConnectionProtocol $protocol): ?IStructure
204205
{
205-
if ($boltDriver && $value instanceof BoltConvertibleInterface) {
206+
if ($protocol->isBolt() && $value instanceof BoltConvertibleInterface) {
206207
return $value->convertToBolt();
207208
}
208209

209210
return null;
210211
}
211212

212-
private static function convertTemporalTypes(mixed $value, bool $boltDriver): ?IStructure
213+
private static function convertTemporalTypes(mixed $value, ConnectionProtocol $protocol): ?IStructure
213214
{
214-
if ($boltDriver) {
215+
if ($protocol->isBolt()) {
215216
if ($value instanceof DateTimeInterface) {
217+
if ($protocol->compare(ConnectionProtocol::BOLT_V44()) > 0) {
218+
return new \Bolt\protocol\v5\structures\DateTimeZoneId(
219+
$value->getTimestamp(),
220+
((int) $value->format('u')) * 1000,
221+
$value->getTimezone()->getName()
222+
);
223+
}
224+
216225
return new DateTimeZoneId(
217226
$value->getTimestamp(),
218227
((int) $value->format('u')) * 1000,

tests/Unit/ParameterHelperTest.php

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use DateTimeZone;
1919
use InvalidArgumentException;
2020
use Iterator;
21+
use Laudis\Neo4j\Enum\ConnectionProtocol;
2122
use Laudis\Neo4j\ParameterHelper;
2223
use PHPUnit\Framework\TestCase;
2324
use stdClass;
@@ -77,36 +78,36 @@ public function testFormatParameterString(): void
7778
self::assertEquals(['a' => 'b', 'c' => 'd'], ParameterHelper::formatParameters([
7879
'a' => 'b',
7980
'c' => 'd',
80-
])->toArray());
81+
], ConnectionProtocol::BOLT_V44())->toArray());
8182
}
8283

8384
public function testFormatParameterInteger(): void
8485
{
8586
self::assertEquals([2 => 'b', 3 => 'd'], ParameterHelper::formatParameters([
8687
2 => 'b',
8788
3 => 'd',
88-
])->toArray());
89+
], ConnectionProtocol::BOLT_V44())->toArray());
8990
}
9091

9192
public function testFormatParameterVector(): void
9293
{
9394
self::assertEquals(['b', 'd'], ParameterHelper::formatParameters([
9495
'b',
9596
'd',
96-
])->toArray());
97+
], ConnectionProtocol::BOLT_V44())->toArray());
9798
}
9899

99100
public function testFormatParameterIterable(): void
100101
{
101102
self::assertEquals([[1, 2]], ParameterHelper::formatParameters([
102103
[1, 2],
103-
])->toArray());
104+
], ConnectionProtocol::BOLT_V44())->toArray());
104105
}
105106

106107
public function testFormatParameterInvalidIterable(): void
107108
{
108109
$this->expectException(InvalidArgumentException::class);
109-
ParameterHelper::formatParameters(self::$invalidIterable);
110+
ParameterHelper::formatParameters(self::$invalidIterable, ConnectionProtocol::BOLT_V44());
110111
}
111112

112113
public function testFormatParameterInvalidIterable2(): void
@@ -116,25 +117,25 @@ public function testFormatParameterInvalidIterable2(): void
116117
'a' => [
117118
self::$invalidIterable,
118119
],
119-
]);
120+
], ConnectionProtocol::BOLT_V44());
120121
}
121122

122123
public function testAsParameterEmptyVector(): void
123124
{
124-
$result = ParameterHelper::asParameter([]);
125+
$result = ParameterHelper::asParameter([], ConnectionProtocol::BOLT_V44());
125126
self::assertIsArray($result);
126127
self::assertCount(0, $result);
127128
}
128129

129130
public function testAsParameterEmptyMap(): void
130131
{
131-
$result = ParameterHelper::asParameter([]);
132+
$result = ParameterHelper::asParameter([], ConnectionProtocol::BOLT_V44());
132133
self::assertIsArray($result);
133134
}
134135

135136
public function testAsParameterEmptyArray(): void
136137
{
137-
$result = ParameterHelper::asParameter([]);
138+
$result = ParameterHelper::asParameter([], ConnectionProtocol::BOLT_V44());
138139
self::assertIsArray($result);
139140
}
140141

@@ -145,22 +146,29 @@ public function __toString(): string
145146
{
146147
return 'abc';
147148
}
148-
});
149+
}, ConnectionProtocol::BOLT_V44());
149150
self::assertEquals('abc', $result);
150151
}
151152

152153
public function testInvalidType(): void
153154
{
154155
$this->expectException(InvalidArgumentException::class);
155156
$this->expectExceptionMessage('Cannot format parameter of type: stdClass to work with Neo4J');
156-
ParameterHelper::asParameter(new stdClass());
157+
ParameterHelper::asParameter(new stdClass(), ConnectionProtocol::BOLT_V44());
157158
}
158159

159160
public function testDateTime(): void
160161
{
161-
$date = ParameterHelper::asParameter(new DateTime('now', new DateTimeZone('Europe/Brussels')), true);
162+
$date = ParameterHelper::asParameter(new DateTime('now', new DateTimeZone('Europe/Brussels')), ConnectionProtocol::BOLT_V44());
162163

163164
self::assertInstanceOf(DateTimeZoneId::class, $date);
164165
self::assertEquals('Europe/Brussels', $date->tz_id());
165166
}
167+
168+
public function testDateTime5(): void
169+
{
170+
$date = ParameterHelper::asParameter(new DateTime('now', new DateTimeZone('Europe/Brussels')), ConnectionProtocol::BOLT_V5());
171+
172+
self::assertInstanceOf(\Bolt\protocol\v5\structures\DateTime::class, $date);
173+
}
166174
}

0 commit comments

Comments
 (0)