Skip to content
48 changes: 48 additions & 0 deletions .github/workflows/neo4j.2025.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Tests with Neo4j^2025 on PHP^8

on:
pull_request:
branches: [ master ]

jobs:
db-tests-2025-2204:
runs-on: ubuntu-22.04
name: "Running Integration tests for PHP ${{ matrix.php-version }} on Neo4j ${{ matrix.neo4j-version }}"
strategy:
fail-fast: false
matrix:
neo4j-version: ['2025.09', '2025']
php-version: ['8.1', '8.2', '8.3', '8.4']

services:
neo4j:
image: neo4j:${{ matrix.neo4j-version }}
env:
NEO4J_AUTH: neo4j/nothing123
NEO4J_PLUGINS: '["apoc"]'
ports:
- 7687:7687
- 7474:7474
options: >-
--health-cmd "wget http://localhost:7474 || exit 1"

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: mbstring, sockets
coverage: xdebug
ini-values: max_execution_time=0

- name: Install dependencies
run: composer install --no-progress

- name: Test with phpunit
env:
GDB_USERNAME: neo4j
GDB_PASSWORD: nothing123
run: vendor/bin/phpunit --configuration phpunit.xml --testsuite "Database"
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
neo4j-version: ['5.4', '5.6', '5.8', '5.12', '5.13', '5.23', '5.26', '2025']
neo4j-version: ['5.4', '5.6', '5.8', '5.12', '5.22', '5.25', '5.26']
php-version: ['8.1', '8.2', '8.3', '8.4']

services:
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Website: https://stefanak.serv00.net/

## :label: Version support

We are trying to keep up and this library supports **Bolt <= 5.8**.
We are trying to keep up and this library supports **Bolt <= 6**.

## :books: Supported ecosystems

Expand Down Expand Up @@ -199,7 +199,7 @@ foreach ($protocol->getResponses() as $response) {
}
```

:information_source: Default settings for bolt protocol version is 4.3, 4.4 and 5.0 to 5.8. If you are within this list you can ommit calling `$bolt->setProtocolVersions();`.
:information_source: Default settings for bolt protocol version is 4.3, 4.4, 5.0 to 5.8 and 6. If you are within this list you can ommit calling `$bolt->setProtocolVersions();`.

### Autoload

Expand Down
2 changes: 1 addition & 1 deletion src/Bolt.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function __construct(private IConnection $connection)
$this->track();
}

$this->setProtocolVersions('5.8.8', '4.4.4');
$this->setProtocolVersions(6, '5.8.8', '4.4.4');
}

private function track(): void
Expand Down
13 changes: 3 additions & 10 deletions src/packstream/v1/Packer.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ private function packString(string $str): iterable

private function packFloat(float $value): iterable
{
$packed = pack('d', $value);
yield chr(0xC1) . ($this->littleEndian ? strrev($packed) : $packed);
yield chr(0xC1) . pack('E', $value);
}

/**
Expand Down Expand Up @@ -227,13 +226,7 @@ private function packStructure(IStructure $structure): iterable
throw new PackException('Undefined parameter type in structure ' . $structure);
}

$packerMethod = $type->getName();
if ($packerMethod === 'int') {
$packerMethod = 'integer';
}
$packerMethod = 'pack' . ucfirst($packerMethod);

yield from [$this, $packerMethod]($structure->{$parameter->getName()});
yield from $this->p($structure->{$parameter->getName()});
}
}

Expand All @@ -242,7 +235,7 @@ private function packStructure(IStructure $structure): iterable
*/
private function packByteArray(Bytes $bytes): iterable
{
$size = count($bytes);
$size = mb_strlen($bytes, '8bit');
if ($size < self::MEDIUM) {
yield chr(0xCC) . pack('C', $size) . $bytes;
} elseif ($size < self::LARGE) {
Expand Down
6 changes: 3 additions & 3 deletions src/packstream/v1/Unpacker.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private function u(): mixed
if ($output !== null) {
return $output;
}
$output = $this->unpackStruct($marker);
$output = $this->unpackStructure($marker);
if ($output !== null) {
return $output;
}
Expand All @@ -120,7 +120,7 @@ private function u(): mixed
* @return array|IStructure|null
* @throws UnpackException
*/
private function unpackStruct(int $marker): array|IStructure|null
private function unpackStructure(int $marker): array|IStructure|null
{
if ($marker >> 4 == 0b1011) { //TINY_STRUCT
$size = 0b10110000 ^ $marker;
Expand Down Expand Up @@ -238,7 +238,7 @@ private function unpackFloat(int $marker): ?float
{
if ($marker == 0xC1) {
$value = $this->next(8);
return (float)unpack('d', $this->littleEndian ? strrev($value) : $value)[1];
return (float)unpack('E', $value)[1];
} else {
return null;
}
Expand Down
37 changes: 37 additions & 0 deletions src/protocol/V6.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Bolt\protocol;

/**
* Class Protocol version 6
*
* @author Michal Stefanak
* @link https://github.com/neo4j-php/Bolt
* @see https://www.neo4j.com/docs/bolt/current/bolt/message/
* @package Bolt\protocol
*/
class V6 extends AProtocol
{
use \Bolt\protocol\v6\AvailableStructures;
use \Bolt\protocol\v5_1\ServerStateTransition;

use \Bolt\protocol\v1\ResetMessage;

use \Bolt\protocol\v3\RunMessage;
use \Bolt\protocol\v3\BeginMessage;
use \Bolt\protocol\v3\CommitMessage;
use \Bolt\protocol\v3\RollbackMessage;
use \Bolt\protocol\v3\GoodbyeMessage;

use \Bolt\protocol\v4\PullMessage;
use \Bolt\protocol\v4\DiscardMessage;

use \Bolt\protocol\v4_4\RouteMessage;

use \Bolt\protocol\v5_1\LogonMessage;
use \Bolt\protocol\v5_1\LogoffMessage;

use \Bolt\protocol\v5_3\HelloMessage;

use \Bolt\protocol\v5_4\TelemetryMessage;
}
2 changes: 1 addition & 1 deletion src/protocol/v3/HelloMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait HelloMessage
* The HELLO message request the connection to be authorized for use with the remote database.
*
* @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-hello
* @param array $extra Use \Bolt\helpers\Auth to generate appropriate array
* @param array $extra
* @throws BoltException
*/
public function hello(array $extra): static
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/v4_1/HelloMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ trait HelloMessage
* The HELLO message request the connection to be authorized for use with the remote database.
*
* @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-hello
* @param array $extra Use \Bolt\helpers\Auth to generate appropiate array
* @param array $extra
* @throws BoltException
*/
public function hello(array $extra): static
Expand Down
63 changes: 63 additions & 0 deletions src/protocol/v6/AvailableStructures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace Bolt\protocol\v6;

use Bolt\protocol\v1\structures\{
Date,
Duration,
LocalDateTime,
LocalTime,
Path,
Point2D,
Point3D,
Time,
};
use Bolt\protocol\v5\structures\{
DateTime,
DateTimeZoneId,
Node,
Relationship,
UnboundRelationship
};
use Bolt\protocol\v6\structures\Vector;

/**
* Trait to set available structures
*
* @author Michal Stefanak
* @link https://github.com/neo4j-php/Bolt
* @see https://www.neo4j.com/docs/bolt/current/bolt/structure-semantics/
* @package Bolt\protocol
*/
trait AvailableStructures
{
protected array $packStructuresLt = [
0x44 => Date::class,
0x54 => Time::class,
0x74 => LocalTime::class,
0x49 => DateTime::class,
0x69 => DateTimeZoneId::class,
0x64 => LocalDateTime::class,
0x45 => Duration::class,
0x58 => Point2D::class,
0x59 => Point3D::class,
0x56 => Vector::class,
];

protected array $unpackStructuresLt = [
0x4E => Node::class,
0x52 => Relationship::class,
0x72 => UnboundRelationship::class,
0x50 => Path::class,
0x44 => Date::class,
0x54 => Time::class,
0x74 => LocalTime::class,
0x49 => DateTime::class,
0x69 => DateTimeZoneId::class,
0x64 => LocalDateTime::class,
0x45 => Duration::class,
0x58 => Point2D::class,
0x59 => Point3D::class,
0x56 => Vector::class,
];
}
Loading