Skip to content

Commit 264893c

Browse files
authored
fixes #24 (#25)
* added ssl context options
1 parent 970efd4 commit 264893c

File tree

4 files changed

+106
-9
lines changed

4 files changed

+106
-9
lines changed

src/Databags/StatementStatistics.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@
1313

1414
namespace Laudis\Neo4j\Databags;
1515

16+
use ArrayIterator;
17+
use IteratorAggregate;
18+
1619
/**
1720
* @psalm-immutable
18-
* @codeCoverageIgnore Not used yet
21+
*
22+
* @implements IteratorAggregate<string, int|bool>
23+
*
24+
* @codeCoverageIgnore
1925
*/
20-
final class StatementStatistics
26+
final class StatementStatistics implements IteratorAggregate
2127
{
2228
private int $nodesCreated;
2329

@@ -149,7 +155,7 @@ public function systemUpdates(): int
149155
return $this->systemUpdates;
150156
}
151157

152-
public function mergeStats(StatementStatistics $resultStats): StatementStatistics
158+
public function merge(StatementStatistics $resultStats): StatementStatistics
153159
{
154160
return new StatementStatistics(
155161
$this->nodesCreated + $resultStats->nodesCreated,
@@ -168,4 +174,24 @@ public function mergeStats(StatementStatistics $resultStats): StatementStatistic
168174
$this->systemUpdates + $resultStats->systemUpdates
169175
);
170176
}
177+
178+
public function getIterator(): ArrayIterator
179+
{
180+
return new ArrayIterator([
181+
'nodesCreated' => $this->nodesCreated,
182+
'nodesDeleted' => $this->nodesDeleted,
183+
'relationshipsCreated' => $this->relationshipsCreated,
184+
'relationshipsDeleted' => $this->relationshipsDeleted,
185+
'propertiesSet' => $this->propertiesSet,
186+
'labelsAdded' => $this->labelsAdded,
187+
'labelsRemoved' => $this->labelsRemoved,
188+
'indexesAdded' => $this->indexesAdded,
189+
'indexesRemoved' => $this->indexesRemoved,
190+
'constraintsAdded' => $this->constraintsAdded,
191+
'constraintsRemoved' => $this->constraintsRemoved,
192+
'containsUpdates' => $this->containsUpdates,
193+
'containsSystemUpdates' => $this->containsSystemUpdates,
194+
'systemUpdates' => $this->systemUpdates,
195+
]);
196+
}
171197
}

src/Network/Bolt/BoltDriver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,16 @@ public function aquireSession(): SessionInterface
6565
$this->parsedUrl['host'] = $ip;
6666
try {
6767
$sock = new StreamSocket($this->parsedUrl['host'], $this->parsedUrl['port'] ?? self::DEFAULT_TCP_PORT);
68+
$options = $this->injections->sslContextOptions();
69+
if ($options) {
70+
$sock->setSslContextOptions($options);
71+
}
6872
$bolt = new Bolt($sock);
6973
$bolt->init('LaudisNeo4j/'.ClientInterface::VERSION, $this->parsedUrl['user'], $this->parsedUrl['pass']);
7074
} catch (Exception $e) {
7175
throw new Neo4jException(new Vector([new Neo4jError($e->getMessage(), '')]), $e);
7276
}
77+
7378
$this->session = new BoltSession($this->parsedUrl, $bolt, new BoltCypherFormatter(), $this->injections);
7479

7580
return $this->session;

src/Network/Bolt/BoltInjections.php

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,56 @@
1313

1414
namespace Laudis\Neo4j\Network\Bolt;
1515

16+
/**
17+
* @psalm-type SSLContextOptions = null|array{
18+
* peer_name?: string,
19+
* verify_peer?: bool,
20+
* verify_peer_name?: bool,
21+
* allow_self_signed?: bool,
22+
* cafile?: string,
23+
* capath?: string,
24+
* local_cert?: string,
25+
* local_pk?: string,
26+
* passphrase?: string,
27+
* verify_depth?: int,
28+
* ciphers?: string,
29+
* capture_peer_cert?: bool,
30+
* capture_peer_cert_chain?: bool,
31+
* SNI_enabled?: bool,
32+
* disable_compression?: bool,
33+
* peer_fingerprint?: string|array,
34+
* security_level?: int
35+
* }
36+
*
37+
* @psalm-type LazySSLContextOptions = callable():SSLContextOptions|SSLContextOptions
38+
*/
1639
final class BoltInjections
1740
{
1841
/** @var callable():string|string */
1942
private $database;
43+
/** @var LazySSLContextOptions */
44+
private $sslContextOptions;
2045

2146
/**
22-
* BoltInjections constructor.
23-
*
24-
* @param callable():string|string|null $database
47+
* @param callable():string|?string $database
48+
* @param LazySSLContextOptions $sslContextOptions
2549
*/
26-
public function __construct($database = null)
50+
public function __construct($database = null, $sslContextOptions = null)
2751
{
2852
$this->database = $database ?? static function (): string { return 'neo4j'; };
53+
$this->sslContextOptions = $sslContextOptions;
2954
}
3055

31-
public static function create(?string $database = null): self
56+
/**
57+
* @param SSLContextOptions|null $sslContextOptions
58+
*
59+
* @see https://www.php.net/manual/en/context.ssl.php for ssl connections
60+
*
61+
* @return static
62+
*/
63+
public static function create(?string $database = null, ?array $sslContextOptions = null): self
3264
{
33-
return new self($database);
65+
return new self($database, $sslContextOptions);
3466
}
3567

3668
/**
@@ -41,6 +73,14 @@ public function withDatabase($database): self
4173
return new self($database);
4274
}
4375

76+
/**
77+
* @param LazySSLContextOptions $options
78+
*/
79+
public function withSslContextOptions($options): self
80+
{
81+
return new self($this->database, $options);
82+
}
83+
4484
public function database(): string
4585
{
4686
if (is_callable($this->database)) {
@@ -49,4 +89,17 @@ public function database(): string
4989

5090
return $this->database;
5191
}
92+
93+
/**
94+
* @return SSLContextOptions
95+
*/
96+
public function sslContextOptions(): ?array
97+
{
98+
if (is_callable($this->sslContextOptions)) {
99+
/** @psalm-suppress PossiblyInvalidFunctionCall */
100+
$this->sslContextOptions = call_user_func($this->sslContextOptions);
101+
}
102+
103+
return $this->sslContextOptions;
104+
}
52105
}

tests/Unit/BoltInjectionsTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,17 @@ public function testWithDatabase(): void
3131
$injections = new BoltInjections('abc');
3232
self::assertEquals('test', $injections->withDatabase('test')->database());
3333
}
34+
35+
public function testWithSslContext(): void
36+
{
37+
$injections = new BoltInjections('abc', ['passphrase' => 'test']);
38+
self::assertEquals(['passphrase' => 'test'], $injections->sslContextOptions());
39+
self::assertNull(BoltInjections::create()->sslContextOptions());
40+
41+
self::assertEquals(['passphrase' => 'x'], $injections->withSslContextOptions(['passphrase' => 'x'])->sslContextOptions());
42+
self::assertEquals(
43+
['passphrase' => 'y'],
44+
$injections->withSslContextOptions(static fn () => ['passphrase' => 'y'])->sslContextOptions()
45+
);
46+
}
3447
}

0 commit comments

Comments
 (0)