diff --git a/.gitignore b/.gitignore index 077bbcc..9d3964a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ cert/ *.lock *.cache phpunit.dev.xml +temp/ +tmp/ diff --git a/README.md b/README.md index c1cbc2d..bb67766 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ # Bolt -PHP library for communication with graph database over TCP socket with Bolt protocol specification. Bolt protocol was -created by [Neo4j](https://neo4j.com/) and documentation is available -at [https://www.neo4j.com/](https://www.neo4j.com/docs/bolt/current/). This library is aimed to be low level, support +PHP library for communication with graph database over TCP socket with Bolt protocol specification. Bolt protocol was created by [Neo4j](https://neo4j.com/) and documentation is available at [https://www.neo4j.com/](https://www.neo4j.com/docs/bolt/current/). This library is aimed to be low level, support all available versions and keep up with protocol messages architecture and specifications. [![](https://img.shields.io/github/stars/stefanak-michal/Bolt)](https://github.com/neo4j-php/Bolt/stargazers) @@ -16,28 +14,24 @@ all available versions and keep up with protocol messages architecture and speci JetBrains Logo (Main) logo. -## Version support +## :label: Version support We are trying to keep up and this library supports **Bolt <= 5.4**. https://www.neo4j.com/docs/bolt/current/bolt-compatibility/ -## Requirements +## :white_check_mark: Requirements -Keep up with [PHP supported versions](https://www.php.net/supported-versions.php) means we are at **PHP^8**. +This library keep up with [PHP supported versions](https://www.php.net/supported-versions.php) what means it is at **PHP^8.1**. -_If you need support for PHP < 7.4 you can use latest v3.x release and if you need support for PHP 7.4 you can use v5.x. -Not all new features are implement backwards and this readme is updated to latest released version._ - -### Extensions +### PHP Extensions - [mbstring](https://www.php.net/manual/en/book.mbstring.php) - [sockets](https://www.php.net/manual/en/book.sockets.php) (optional) - Required when you use Socket connection class - [openssl](https://www.php.net/manual/en/book.openssl.php) (optional) - Required when you use StreamSocket connection class with enabled SSL -- [phpunit](https://phpunit.de/) (development) -## Installation +## :floppy_disk: Installation You can use composer or download this repository from github and manually implement it. @@ -55,47 +49,14 @@ Run the following command in your project to install the latest applicable versi 2. Unpack 3. Copy content of `src` directory into your project -## Usage +## :desktop_computer: Usage -Concept of usage is based on Bolt messages. Available protocol methods depends on Bolt version. Communication works -in [pipeline](https://www.neo4j.com/docs/bolt/current/bolt/message/#pipelining) and you can chain multiple Bolt messages -before fetching response from the server. +Concept of usage is based on Bolt messages. Bolt messages are mapped 1:1 as protocol methods. Available protocol methods depends on Bolt version. Communication works in [pipeline](https://www.neo4j.com/docs/bolt/current/bolt/message/#pipelining) and you can chain multiple Bolt messages before consuming response from the server. -Main `Bolt` class serves as Factory design pattern and it returns instance of protocol class by requested Bolt version. Query execution and fetching response is split in two methods. First message `run` is for -sending queries. Second message `pull` is for fetching response from last executed query on database. -Response from database for Bolt message `pull` always contains n+1 rows because last entry is `success` message with +Main `Bolt` class serves as Factory design pattern and it returns instance of protocol class by requested Bolt version. Basic usage consist of query execution and fetching response which is split in two methods. First message `run` is for sending queries. Second message `pull` is for fetching response from executed query on database. Response from database for Bolt message `pull` always contains n+1 rows because last entry is `success` message with meta informations. -More info about available Bolt messages: https://www.neo4j.com/docs/bolt/current/bolt/message/ - -### Example - -```php -// Create connection class and specify target host and port. -$conn = new \Bolt\connection\Socket('127.0.0.1', 7687); -// Create new Bolt instance and provide connection object. -$bolt = new \Bolt\Bolt($conn); -// Set requested protocol versions -$bolt->setProtocolVersions(5.1, 5, 4.4); -// Build and get protocol version instance which creates connection and executes handshake. -$protocol = $bolt->build(); -// Connect and login into database -$protocol->hello(); -$protocol->logon(['scheme' => 'basic', 'principal' => 'neo4j', 'credentials' => 'neo4j']); - -// Pipeline two messages. One to execute query with parameters and second to pull records. -$protocol - ->run('RETURN $a AS num, $b AS str', ['a' => 123, 'b' => 'text']) - ->pull(); - -// Fetch waiting server responses for pipelined messages. -foreach ($protocol->getResponses() as $response) { - // $response is instance of \Bolt\protocol\Response. - // First response is SUCCESS message for RUN message. - // Second response is RECORD message for PULL message. - // Third response is SUCCESS message for PULL message. -} -``` +:information_source: More info about available Bolt messages: https://www.neo4j.com/docs/bolt/current/bolt/message/ ### Available methods @@ -132,12 +93,12 @@ foreach ($protocol->getResponses() as $response) { | pullAll | @see pull | | | discardAll | @see discard | | -Many methods accept argument called `$extra`. This argument can contain any of key-value by Bolt specification. This +Multiple methods accept argument called `$extra`. This argument can contain any of key-value by Bolt specification. This argument was extended during Neo4j development which means the content of it changed. You should keep in mind what version you are working with when using this argument. You can read more about extra parameter in Bolt documentation where you can look into your version and bolt message. -Annotation of methods in protocol classes contains direct link to specific version and message from mentioned +:information_source: Annotation of methods in protocol classes contains direct link to specific version and message from mentioned documentation website. ### Authentification @@ -179,34 +140,55 @@ of data. To learn more you can check [performance test](https://github.com/neo4j-php/Bolt/blob/master/tests/PerformanceTest.php) or [packer test](https://github.com/neo4j-php/Bolt/blob/master/tests/PackStream/v1/PackerTest.php). -Structures `Node`, `Relationship`, `UnboundRelationship` and `Path` cannot be used as parameter. They are available only +:warning: Structures `Node`, `Relationship`, `UnboundRelationship` and `Path` cannot be used as parameter. They are available only as received data from database. -Server state is not available from server but we assume it. Library contains `\Bolt\helpers\ServerState` and you can get -used instance of this class with `$bolt->serverState` or `$protocol->serverState` (after you call `build()`). +### Example -### Autoload +```php +// Choose and create connection class and specify target host and port. +$conn = new \Bolt\connection\Socket('127.0.0.1', 7687); +// Create new Bolt instance and provide connection object. +$bolt = new \Bolt\Bolt($conn); +// Set requested protocol versions ..you can add up to 4 versions +$bolt->setProtocolVersions(5.4); +// Build and get protocol version instance which creates connection and executes handshake. +$protocol = $bolt->build(); -Directory `src` contains autoload file which accepts only Bolt library namespaces. Main Bolt namespace points to this -directory. If you have installed this project with composer, you have to load `vendor/autoload.php`. +// Initialize communication with database +$response = $protocol->hello()->getResponse(); +// verify $response for successful initialization -## Server state +// Login into database +$response = $protocol->logon(['scheme' => 'basic', 'principal' => 'neo4j', 'credentials' => 'neo4j'])->getResponse(); +// verify $response for successful login -If assumed server state is different than expected, library does not throw exception. This logic is silent but you can -change it and if you would like to implement own logic when assumed server state is different than expected you can -assign callable into class property `$serverState->expectedServerStateMismatchCallback`. +// Pipeline two messages. One to execute query with parameters and second to pull records. +$protocol + ->run('RETURN $a AS num, $b AS str', ['a' => 123, 'b' => 'text']) + ->pull(); + +// Fetch waiting server responses for pipelined messages. +foreach ($protocol->getResponses() as $response) { + // $response is instance of \Bolt\protocol\Response. + // First response is SUCCESS message for RUN message. + // Second response is RECORD message for PULL message. + // Third response is SUCCESS message for PULL message. +} +``` -## Connection +### Autoload -Bolt class constructor accepts connection argument. This argument has to be instance of class which implements -IConnection interface. Currently exists two predefined classes `Socket` and `StreamSocket`. +Directory `src` contains autoload file which accepts only Bolt library namespaces. Main Bolt namespace points to this +directory. If you have installed this project with composer, you have to load `vendor/autoload.php`. + +## :chains: Connection -_We provide two connection classes. `Socket` was created first and it has better memory usage. `StreamSocket` was made -because of need to accept TLS._ +Bolt class constructor accepts connection argument. This argument has to be instance of class which implements IConnection interface. Library offers few options. **\Bolt\connection\Socket** -This class use php extension sockets. More informations +This class use php extension sockets and has better memory usage. More informations here: [https://www.php.net/manual/en/book.sockets.php](https://www.php.net/manual/en/book.sockets.php) **\Bolt\connection\StreamSocket** @@ -214,16 +196,21 @@ here: [https://www.php.net/manual/en/book.sockets.php](https://www.php.net/manua This class uses php stream functions. Which is a part of php and there is no extensions needed. More informations here: [https://www.php.net/manual/en/ref.stream.php](https://www.php.net/manual/en/ref.stream.php) -StreamSocket besides of implemented methods from interface has method to configure SSL. When you want to activate SSL +StreamSocket besides of implemented methods from interface has method to configure SSL. SSL option requires php extension openssl. When you want to activate SSL you have to call method `setSslContextOptions`. This method accept array by php specification available here: [https://www.php.net/manual/en/context.ssl.php](https://www.php.net/manual/en/context.ssl.php). -_If you want to use it, you have to enable openssl php extension._ +**\Bolt\connection\PStreamSocket** + +This class extends StreamSocket and adds support for persistent connections. Upon reuse of connection remaining buffer is consumed and message RESET is automatically sent. PHP is stateless therefore using this connection class requires storing meta information about active TCP connection. Default storage is `\Bolt\helper\FileCache` which you can change with method `setCache` (PSR-16 Simple Cache). + +:warning: If your system reuse persistent connection and meta information about it was lost for some reason, your attemt to connect will end with ConnectionTimeoutException. Repeated attempt to connect will succeed. + +## :lock: SSL ### Neo4j Aura -Connecting to Aura requires encryption which is provided with SSL. To connect to Aura you have to use `StreamSocket` -connection class and enable SSL. +Connecting to Aura requires encryption which is provided with SSL. To connect to Aura you have to use `StreamSocket` connection class and enable SSL. ```php $conn = new \Bolt\connection\StreamSocket('helloworld.databases.neo4j.io'); @@ -251,10 +238,10 @@ $conn->setSslContextOptions([ $bolt = new \Bolt\Bolt($conn); ``` -You can also take a look at my article on how to implement SSL for Neo4j running on localhost +:bookmark: You can also take a look at my article on how to implement SSL for Neo4j running on localhost at [Neo4j and self signed certificate](https://ko-fi.com/post/Neo4j-and-self-signed-certificate-on-Windows-S6S2I0KQT). -### Timeout +## :stopwatch: Timeout Connection class constructor contains `$timeout` argument. This timeout is for established socket connection. To set up timeout for establishing socket connection itself you have to set ini directive `default_socket_timeout`. @@ -262,7 +249,11 @@ timeout for establishing socket connection itself you have to set ini directive _Setting up ini directive isn't part of connection class because function `ini_set` can be disabled on production environments for security reasons._ -## Another solutions +## :vertical_traffic_light: Server state + +Server state is not reported by server but it is evaluated by received response. You can access current state through property `$protocol->serverState`. This property is updated with every call `getResponse(s)`. + +## :pushpin: More solutions If you need simple class to cover basic functionality you can use: [neo4j-bolt-wrapper](https://packagist.org/packages/stefanak-michal/neo4j-bolt-wrapper) @@ -273,3 +264,11 @@ on: [php-client](https://packagist.org/packages/laudis/neo4j-php-client) PDO implementation is available at [pdo-bolt](https://github.com/stefanak-michal/pdo-bolt) More informations can be found at: https://neo4j.com/developer/php/ + +## :recycle: Old versions + +If you need support for end-of-life PHP versions, here is a short info list. Not all new features are implement backwards and this readme is updated to latest released version. + +* PHP < 7.4 - v3.x +* PHP 7.4 - v5.x +* PHP 8.0 - v6.x diff --git a/composer.json b/composer.json index f75e1cf..89e0c6e 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,9 @@ "license": "MIT", "minimum-stability": "stable", "require": { - "php": "^8", - "ext-mbstring": "*" + "php": "^8.1", + "ext-mbstring": "*", + "psr/simple-cache": "^3.0" }, "require-dev": { "phpunit/phpunit": "^9" diff --git a/phpunit.xml b/phpunit.xml index a4af24e..2550fb6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -15,6 +15,6 @@ - + diff --git a/src/Bolt.php b/src/Bolt.php index dc859fc..48f1c3d 100644 --- a/src/Bolt.php +++ b/src/Bolt.php @@ -4,7 +4,8 @@ use Bolt\error\ConnectException; use Bolt\error\BoltException; -use Bolt\protocol\{AProtocol, ServerState}; +use Bolt\protocol\AProtocol; +use Bolt\enum\{Signature, ServerState}; use Bolt\connection\IConnection; /** @@ -22,11 +23,10 @@ final class Bolt private int $packStreamVersion = 1; public static bool $debug = false; - public ServerState $serverState; public function __construct(private IConnection $connection) { - $this->setProtocolVersions(5, 4.4); + $this->setProtocolVersions(5.4, 5, 4.4); } /** @@ -35,27 +35,69 @@ public function __construct(private IConnection $connection) */ public function build(): AProtocol { - $this->serverState = new ServerState(); - $this->serverState->is(ServerState::DISCONNECTED, ServerState::DEFUNCT); + $protocol = null; try { if (!$this->connection->connect()) { throw new ConnectException('Connection failed'); } - $version = $this->handshake(); + if ($this->connection instanceof \Bolt\connection\PStreamSocket) { + $protocol = $this->persistentBuild(); + } - $protocolClass = "\\Bolt\\protocol\\V" . str_replace('.', '_', $version); - if (!class_exists($protocolClass)) { - throw new ConnectException('Requested Protocol version (' . $version . ') not yet implemented'); + if (empty($protocol)) { + $protocol = $this->normalBuild(); } - } catch (ConnectException $e) { - $this->serverState->set(ServerState::DEFUNCT); + } catch (BoltException $e) { + $this->connection->disconnect(); throw $e; } - $this->serverState->set(ServerState::CONNECTED); - return new $protocolClass($this->packStreamVersion, $this->connection, $this->serverState); + if ($this->connection instanceof \Bolt\connection\PStreamSocket) { + $this->connection->getCache()->set($this->connection->getIdentifier(), $protocol->getVersion()); + } + + return $protocol; + } + + private function normalBuild(): AProtocol + { + $version = $this->handshake(); + + $protocolClass = "\\Bolt\\protocol\\V" . str_replace('.', '_', $version); + if (!class_exists($protocolClass)) { + throw new ConnectException('Requested Protocol version (' . $version . ') not yet implemented'); + } + + $protocol = new $protocolClass($this->packStreamVersion, $this->connection); + $protocol->serverState = version_compare($version, '5.1', '>=') ? ServerState::NEGOTIATION : ServerState::CONNECTED; + return $protocol; + } + + private function persistentBuild(): ?AProtocol + { + $version = $this->connection->getCache()->get($this->connection->getIdentifier()); + if (empty($version)) { + return null; + } + + $protocolClass = "\\Bolt\\protocol\\V" . str_replace('.', '_', $version); + if (!class_exists($protocolClass)) { + throw new ConnectException('Requested Protocol version (' . $version . ') not yet implemented'); + } + + /** @var AProtocol $protocol */ + $protocol = new $protocolClass($this->packStreamVersion, $this->connection); + $protocol->serverState = ServerState::INTERRUPTED; + + if ($protocol->reset()->getResponse()->signature != Signature::SUCCESS) { + $this->connection->disconnect(); + $this->connection->connect(); + return null; + } + + return $protocol; } public function setProtocolVersions(int|float|string ...$v): Bolt @@ -72,12 +114,6 @@ public function setPackStreamVersion(int $version = 1): Bolt return $this; } - public function setConnection(IConnection $connection): Bolt - { - $this->connection = $connection; - return $this; - } - /** * @link https://www.neo4j.com/docs/bolt/current/bolt/handshake/ * @throws BoltException diff --git a/src/connection/PStreamSocket.php b/src/connection/PStreamSocket.php new file mode 100644 index 0000000..773cfe2 --- /dev/null +++ b/src/connection/PStreamSocket.php @@ -0,0 +1,73 @@ +cache = $cache; + } + + public function getCache(): CacheInterface + { + if (empty($this->cache)) + $this->cache = new FileCache(); + return $this->cache; + } + + public function connect(): bool + { + $result = parent::connect(); + + //dump TCP buffer leftovers + $read = [$this->stream]; + $write = $except = null; + if (stream_select($read, $write, $except, 0) === 1) { + do { + $r = fread($this->stream, 1024); + } while ($r !== false && mb_strlen($r) == 1024); + } + + return $result; + } + + public function getIdentifier(): string + { + if (empty($this->identifier)) + $this->identifier = str_replace(':', '_', stream_socket_get_name($this->stream, false)) . '_' . str_replace(':', '_', stream_socket_get_name($this->stream, true)); + return $this->identifier; + } + + public function disconnect(): void + { + if (is_resource($this->stream)) { + stream_socket_shutdown($this->stream, STREAM_SHUT_RDWR); + fclose($this->stream); + unset($this->stream); + $this->getCache()->delete($this->getIdentifier()); + } + } +} diff --git a/src/connection/StreamSocket.php b/src/connection/StreamSocket.php index 7af7d7f..68947fb 100644 --- a/src/connection/StreamSocket.php +++ b/src/connection/StreamSocket.php @@ -16,12 +16,14 @@ */ class StreamSocket extends AConnection { - private array $sslContextOptions = []; + protected array $sslContextOptions = []; /** * @var resource */ - private $stream; + protected $stream; + + protected int $connectionFlags = STREAM_CLIENT_CONNECT; /** * Set SSL Context options @@ -41,7 +43,7 @@ public function connect(): bool 'ssl' => $this->sslContextOptions ]); - $this->stream = @stream_socket_client('tcp://' . $this->ip . ':' . $this->port, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context); + $this->stream = @stream_socket_client('tcp://' . $this->ip . ':' . $this->port, $errno, $errstr, $this->timeout, $this->connectionFlags, $context); if ($this->stream === false) { throw new ConnectException($errstr, $errno); @@ -107,8 +109,10 @@ public function read(int $length = 2048): string public function disconnect(): void { - if (is_resource($this->stream)) + if (is_resource($this->stream)) { stream_socket_shutdown($this->stream, STREAM_SHUT_RDWR); + unset($this->stream); + } } /** @@ -123,7 +127,7 @@ public function setTimeout(float $timeout): void /** * @throws ConnectException */ - private function configureTimeout(): void + protected function configureTimeout(): void { if (is_resource($this->stream)) { $timeout = (int)floor($this->timeout); diff --git a/src/enum/Message.php b/src/enum/Message.php new file mode 100644 index 0000000..6ded406 --- /dev/null +++ b/src/enum/Message.php @@ -0,0 +1,29 @@ + signal will set the connection in the DEFUNCT server state. */ - public const DEFUNCT = 'DEFUNCT'; + case DEFUNCT; /** * The READY state can handle the request messages RUN and BEGIN and receive a query. */ - public const READY = 'READY'; + case READY; /** * When STREAMING, a result is available for streaming from server to client. * This result must be fully consumed or discarded by a client before the server can re-enter the READY state and allow any further queries to be executed. */ - public const STREAMING = 'STREAMING'; + case STREAMING; /** * When transaction started */ - public const TX_READY = 'TX_READY'; + case TX_READY; /** * When TX_STREAMING, a result is available for streaming from server to client. This result must be fully consumed or discarded by a client before the server can transition to the TX_READY state. */ - public const TX_STREAMING = 'TX_STREAMING'; + case TX_STREAMING; /** * When FAILED, a connection is in a temporarily unusable state. This is generally as the result of encountering a recoverable error. * This mode ensures that only one failure can exist at a time, preventing cascading issues from batches of work. */ - public const FAILED = 'FAILED'; + case FAILED; /** * This state occurs between the server receiving the jump-ahead and the queued RESET message, (the RESET message triggers an ). * Most incoming messages are ignored when the server are in an INTERRUPTED state, with the exception of the RESET that allows transition back to READY. * The signal will set the connection in the INTERRUPTED server state. */ - public const INTERRUPTED = 'INTERRUPTED'; + case INTERRUPTED; /** * Connection has been established and metadata has been sent back from the HELLO message or a LOGOFF message was received whilst in ready state. Ready to accept a LOGON message with authentication information. */ - public const UNAUTHENTICATED = 'UNAUTHENTICATED'; - - /** - * Internal pointer for current server state - */ - private string $current = self::DISCONNECTED; - - /** - * @var callable(string $current, array $expected) - */ - public $expectedServerStateMismatchCallback; - - /** - * Internal enum to verify valid server state - * @var string[] - */ - private static array $lt = [ - self::DISCONNECTED, - self::CONNECTED, - self::DEFUNCT, - self::READY, - self::STREAMING, - self::TX_READY, - self::TX_STREAMING, - self::FAILED, - self::INTERRUPTED, - self::UNAUTHENTICATED - ]; - - /** - * Get current server state - */ - public function get(): string - { - return $this->current; - } - - /** - * Set current server state - */ - public function set(string $state): void - { - if (in_array($state, self::$lt)) - $this->current = $state; - } - - /** - * Check if current server state equals one of requested - */ - public function is(string ...$states): bool - { - foreach ($states as $state) { - if (in_array($state, self::$lt) && $this->current === $state) - return true; - } - - if (is_callable($this->expectedServerStateMismatchCallback)) - ($this->expectedServerStateMismatchCallback)($this->get(), $states); - return false; - } + case AUTHENTICATION; } diff --git a/src/enum/Signature.php b/src/enum/Signature.php new file mode 100644 index 0000000..bdaa09e --- /dev/null +++ b/src/enum/Signature.php @@ -0,0 +1,35 @@ + $userAgent ?? self::$defaultUserAgent, - 'scheme' => 'none' - ]; - } - - /** - * Basic authorization with username and password - */ - public static function basic(string $username, string $password, ?string $userAgent = null): array - { - return [ - 'user_agent' => $userAgent ?? self::$defaultUserAgent, - 'scheme' => 'basic', - 'principal' => $username, - 'credentials' => $password - ]; - } - - /** - * OIDC authorization with token - */ - public static function bearer(string $token, ?string $userAgent = null): array - { - return [ - 'user_agent' => $userAgent ?? self::$defaultUserAgent, - 'scheme' => 'bearer', - 'credentials' => $token - ]; - } - - /** - * Kerberos authorization with token - */ - public static function kerberos(string $token, ?string $userAgent = null): array - { - return [ - 'user_agent' => $userAgent ?? self::$defaultUserAgent, - 'scheme' => 'kerberos', - 'principal' => '', - 'credentials' => $token - ]; - } -} diff --git a/src/helpers/FileCache.php b/src/helpers/FileCache.php new file mode 100644 index 0000000..57b77f3 --- /dev/null +++ b/src/helpers/FileCache.php @@ -0,0 +1,148 @@ +has($key) ? file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $key) : $default; + } + + /** + * Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time. + * + * @param string $key The key of the item to store. + * @param mixed $value The value of the item to store, must be serializable. + * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and + * the driver supports TTL then the library may set a default value + * for it or let the driver take care of that. + * + * @return bool True on success and false on failure. + */ + public function set(string $key, mixed $value, \DateInterval|int|null $ttl = null): bool + { + return is_int(file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $key, $value)); + } + + /** + * Delete an item from the cache by its unique key. + * + * @param string $key The unique cache key of the item to delete. + * + * @return bool True if the item was successfully removed. False if there was an error. + */ + public function delete(string $key): bool + { + return $this->has($key) && unlink(__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $key); + } + + /** + * @inheritDoc + */ + public function clear(): bool + { + foreach (scandir(__DIR__ . DIRECTORY_SEPARATOR . 'temp') as $file) { + if ($file == '.' || $file == '..') + continue; + unlink(__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $file); + } + return true; + } + + /** + * Obtains multiple cache items by their unique keys. + * + * @param iterable $keys A list of keys that can be obtained in a single operation. + * @param mixed $default Default value to return for keys that do not exist. + * + * @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value. + */ + public function getMultiple(iterable $keys, mixed $default = null): iterable + { + foreach ($keys as $key) { + yield $this->get($key, $default); + } + } + + /** + * Persists a set of key => value pairs in the cache, with an optional TTL. + * + * @param iterable $values A list of key => value pairs for a multiple-set operation. + * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and + * the driver supports TTL then the library may set a default value + * for it or let the driver take care of that. + * + * @return bool True on success and false on failure. + */ + public function setMultiple(iterable $values, \DateInterval|int|null $ttl = null): bool + { + foreach ($values as $key => $value) { + $this->set($key, $value, $ttl); + } + return true; + } + + /** + * Deletes multiple cache items in a single operation. + * + * @param iterable $keys A list of string-based keys to be deleted. + * + * @return bool True if the items were successfully removed. False if there was an error. + */ + public function deleteMultiple(iterable $keys): bool + { + foreach ($keys as $key) { + $this->delete($key); + } + return true; + } + + /** + * Determines whether an item is present in the cache. + * + * NOTE: It is recommended that has() is only to be used for cache warming type purposes + * and not to be used within your live applications operations for get/set, as this method + * is subject to a race condition where your has() will return true and immediately after, + * another script can remove it making the state of your app out of date. + * + * @param string $key The cache item key. + * + * @return bool + */ + public function has(string $key): bool + { + return file_exists(__DIR__ . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $key); + } +} diff --git a/src/packstream/v1/Packer.php b/src/packstream/v1/Packer.php index f425f99..4318c1a 100644 --- a/src/packstream/v1/Packer.php +++ b/src/packstream/v1/Packer.php @@ -25,7 +25,7 @@ class Packer implements IPacker /** * @inheritDoc */ - public function __construct(private array $structuresLt = []) + public function __construct(private readonly array $structuresLt = []) { $this->littleEndian = unpack('S', "\x01\x00")[1] === 1; } @@ -84,7 +84,7 @@ private function p(mixed $param): iterable yield from $this->packString($param); break; case 'array': - if ($param === array_values($param)) { + if (array_is_list($param)) { yield from $this->packList($param); } else { yield from $this->packDictionary($param); @@ -233,8 +233,7 @@ private function packStructure(IStructure $structure): iterable } $packerMethod = 'pack' . ucfirst($packerMethod); - $methodName = $parameter->getName(); - yield from $this->{$packerMethod}($structure->{$methodName}()); + yield from [$this, $packerMethod]($structure->{$parameter->getName()}); } } diff --git a/src/packstream/v1/Unpacker.php b/src/packstream/v1/Unpacker.php index aa2fbdd..7468cbd 100644 --- a/src/packstream/v1/Unpacker.php +++ b/src/packstream/v1/Unpacker.php @@ -24,7 +24,7 @@ class Unpacker implements IUnpacker /** * @inheritDoc */ - public function __construct(private array $structuresLt = []) + public function __construct(private readonly array $structuresLt = []) { $this->littleEndian = unpack('S', "\x01\x00")[1] === 1; } diff --git a/src/protocol/AProtocol.php b/src/protocol/AProtocol.php index c9a41fa..d053adc 100644 --- a/src/protocol/AProtocol.php +++ b/src/protocol/AProtocol.php @@ -2,6 +2,8 @@ namespace Bolt\protocol; +use Bolt\enum\{Message, Signature, ServerState}; +use Bolt\error\BoltException; use Bolt\error\PackException; use Bolt\error\UnpackException; use Bolt\packstream\{IPacker, IUnpacker}; @@ -17,12 +19,14 @@ */ abstract class AProtocol { - /** @var string[] */ + /** @var Message[] */ protected array $pipelinedMessages = []; protected IPacker $packer; protected IUnpacker $unpacker; + public ServerState $serverState; + /** * @throws UnpackException * @throws PackException @@ -30,7 +34,6 @@ abstract class AProtocol public function __construct( int $packStreamVersion, protected IConnection $connection, - public ServerState $serverState ) { $packerClass = "\\Bolt\\packstream\\v" . $packStreamVersion . "\\Packer"; @@ -58,9 +61,9 @@ protected function write(iterable $generator): void /** * Read from connection - * @throws ConnectException + * @throws BoltException */ - protected function read(?int &$signature): array + protected function read(?Signature &$signature = Signature::NONE): array { $msg = ''; while (true) { @@ -72,15 +75,12 @@ protected function read(?int &$signature): array } $output = []; - $signature = 0; if (!empty($msg)) { $output = $this->unpacker->unpack($msg); - $signature = $this->unpacker->getSignature(); + $s = $this->unpacker->getSignature(); + $signature = Signature::from($s); - if ($signature == Response::SIGNATURE_FAILURE) { - $this->serverState->set(ServerState::FAILED); - } elseif ($signature == Response::SIGNATURE_IGNORED) { - $this->serverState->set(ServerState::INTERRUPTED); + if ($signature == Signature::IGNORED) { // Ignored doesn't have any response content $output = []; } @@ -106,11 +106,8 @@ public function getVersion(): string */ public function getResponses(): \Iterator { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); while (count($this->pipelinedMessages) > 0) { - $message = reset($this->pipelinedMessages); - yield from $this->{'_' . $message}(); - array_shift($this->pipelinedMessages); + yield $this->getResponse(); } } @@ -119,12 +116,39 @@ public function getResponses(): \Iterator */ public function getResponse(): Response { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); + $serverState = $this->serverState; + $message = reset($this->pipelinedMessages); - /** @var Response $response */ - $response = $this->{'_' . $message}()->current(); - if ($response->getSignature() != Response::SIGNATURE_RECORD) + if ($message === false) + throw new ConnectException('No response waiting to be consumed'); + + $methodName = '_' . ( + str_contains($message->name, '_') + ? preg_replace("/_([a-z])/", "strtoupper('$1')", strtolower($message->name)) + : strtolower($message->name) + ); + if (method_exists($this, $methodName)) { + /** @var Response $response */ + $response = $this->$methodName()->current(); + } else { + $content = $this->read($signature); + $response = new Response($message, $signature, $content); + } + + if ($response->signature != Signature::RECORD) array_shift($this->pipelinedMessages); + + foreach (($this->serverStateTransition ?? []) as $transition) { + if ($transition[0] === $serverState && $transition[1] === $response->message && $transition[2] === $response->signature) { + $this->serverState = $transition[3]; + if ($response->signature === Signature::SUCCESS && ($response->content['has_more'] ?? false)) + $this->serverState = ($serverState === ServerState::TX_READY || $serverState === ServerState::TX_STREAMING) ? ServerState::TX_STREAMING : ServerState::STREAMING; + if ($transition[3] === ServerState::DEFUNCT) + $this->connection->disconnect(); + break; + } + } + return $response; } } diff --git a/src/protocol/Response.php b/src/protocol/Response.php index 9e5f70b..fd0a1dd 100644 --- a/src/protocol/Response.php +++ b/src/protocol/Response.php @@ -2,6 +2,8 @@ namespace Bolt\protocol; +use Bolt\enum\{Message, Signature}; + /** * Class Response * @author Michal Stefanak @@ -10,57 +12,16 @@ */ class Response { - public const MESSAGE_INIT = 'INIT'; - public const MESSAGE_HELLO = 'HELLO'; - public const MESSAGE_RESET = 'RESET'; - public const MESSAGE_RUN = 'RUN'; - public const MESSAGE_PULL = 'PULL'; - public const MESSAGE_PULL_ALL = 'PULL_ALL'; - public const MESSAGE_DISCARD = 'DISCARD'; - public const MESSAGE_DISCARD_ALL = 'DISCARD_ALL'; - public const MESSAGE_BEGIN = 'BEGIN'; - public const MESSAGE_COMMIT = 'COMMIT'; - public const MESSAGE_ROLLBACK = 'ROLLBACK'; - public const MESSAGE_ROUTE = 'ROUTE'; - public const MESSAGE_ACK_FAILURE = 'ACK_FAILURE'; - public const MESSAGE_LOGON = 'LOGON'; - public const MESSAGE_LOGOFF = 'LOGOFF'; - public const MESSAGE_TELEMETRY = 'TELEMETRY'; - - public const SIGNATURE_SUCCESS = 0x70; //112 - public const SIGNATURE_FAILURE = 0x7F; //127 - public const SIGNATURE_IGNORED = 0x7E; //126 - public const SIGNATURE_RECORD = 0x71; //113 - - public function __construct( - private string $message, - private int $signature, - private array $content = [] - ) - { - } - - /** - * Get requested bolt message name - */ - public function getMessage(): string - { - return $this->message; - } - - /** - * Signature tells you result of your request - */ - public function getSignature(): int - { - return $this->signature; - } - /** - * Get response content + * @param Message $message Requested bolt message name + * @param Signature $signature Signature tells you result of your request + * @param array $content Response content */ - public function getContent(): array + public function __construct( + public readonly Message $message, + public readonly Signature $signature, + public readonly array $content = [] + ) { - return $this->content; } } diff --git a/src/protocol/V1.php b/src/protocol/V1.php index e861988..705aeea 100644 --- a/src/protocol/V1.php +++ b/src/protocol/V1.php @@ -12,6 +12,7 @@ class V1 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v1\ServerStateTransition; use \Bolt\protocol\v1\InitMessage; use \Bolt\protocol\v1\RunMessage; diff --git a/src/protocol/V2.php b/src/protocol/V2.php index fce7dbf..51e3540 100644 --- a/src/protocol/V2.php +++ b/src/protocol/V2.php @@ -12,6 +12,7 @@ class V2 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v1\ServerStateTransition; use \Bolt\protocol\v1\InitMessage; use \Bolt\protocol\v1\RunMessage; diff --git a/src/protocol/V3.php b/src/protocol/V3.php index c850e38..4ecc186 100644 --- a/src/protocol/V3.php +++ b/src/protocol/V3.php @@ -13,6 +13,7 @@ class V3 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v3\ServerStateTransition; use \Bolt\protocol\v1\PullAllMessage; use \Bolt\protocol\v1\DiscardAllMessage; diff --git a/src/protocol/V4.php b/src/protocol/V4.php index 9914602..c26325f 100644 --- a/src/protocol/V4.php +++ b/src/protocol/V4.php @@ -13,6 +13,7 @@ class V4 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V4_1.php b/src/protocol/V4_1.php index d525d7d..63477d6 100644 --- a/src/protocol/V4_1.php +++ b/src/protocol/V4_1.php @@ -13,6 +13,7 @@ class V4_1 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V4_2.php b/src/protocol/V4_2.php index a9ef34b..aa258a1 100644 --- a/src/protocol/V4_2.php +++ b/src/protocol/V4_2.php @@ -13,6 +13,7 @@ class V4_2 extends AProtocol { use \Bolt\protocol\v1\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V4_3.php b/src/protocol/V4_3.php index d949b2c..474f010 100644 --- a/src/protocol/V4_3.php +++ b/src/protocol/V4_3.php @@ -13,6 +13,7 @@ class V4_3 extends AProtocol { use \Bolt\protocol\v4_3\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V4_4.php b/src/protocol/V4_4.php index d2c62c0..7c66e54 100644 --- a/src/protocol/V4_4.php +++ b/src/protocol/V4_4.php @@ -13,6 +13,7 @@ class V4_4 extends AProtocol { use \Bolt\protocol\v4_3\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V5.php b/src/protocol/V5.php index c2f6c10..e40235e 100644 --- a/src/protocol/V5.php +++ b/src/protocol/V5.php @@ -13,6 +13,7 @@ class V5 extends AProtocol { use \Bolt\protocol\v5\AvailableStructures; + use \Bolt\protocol\v4\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V5_1.php b/src/protocol/V5_1.php index 431c2b7..a2e6233 100644 --- a/src/protocol/V5_1.php +++ b/src/protocol/V5_1.php @@ -13,6 +13,7 @@ class V5_1 extends AProtocol { use \Bolt\protocol\v5\AvailableStructures; + use \Bolt\protocol\v5_1\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V5_2.php b/src/protocol/V5_2.php index 378d2fa..863179d 100644 --- a/src/protocol/V5_2.php +++ b/src/protocol/V5_2.php @@ -13,6 +13,7 @@ class V5_2 extends AProtocol { use \Bolt\protocol\v5\AvailableStructures; + use \Bolt\protocol\v5_1\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V5_3.php b/src/protocol/V5_3.php index cd0130b..f875456 100644 --- a/src/protocol/V5_3.php +++ b/src/protocol/V5_3.php @@ -13,6 +13,7 @@ class V5_3 extends AProtocol { use \Bolt\protocol\v5\AvailableStructures; + use \Bolt\protocol\v5_1\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/V5_4.php b/src/protocol/V5_4.php index 11f4e17..c14770b 100644 --- a/src/protocol/V5_4.php +++ b/src/protocol/V5_4.php @@ -13,6 +13,7 @@ class V5_4 extends AProtocol { use \Bolt\protocol\v5\AvailableStructures; + use \Bolt\protocol\v5_1\ServerStateTransition; use \Bolt\protocol\v1\ResetMessage; diff --git a/src/protocol/v1/AckFailureMessage.php b/src/protocol/v1/AckFailureMessage.php index 74abf8e..fc9fc76 100644 --- a/src/protocol/v1/AckFailureMessage.php +++ b/src/protocol/v1/AckFailureMessage.php @@ -2,12 +2,8 @@ namespace Bolt\protocol\v1; -use Bolt\protocol\{ - ServerState, - Response, - V1, - V2 -}; +use Bolt\enum\Message; +use Bolt\protocol\{V1, V2}; use Bolt\error\BoltException; trait AckFailureMessage @@ -22,28 +18,8 @@ trait AckFailureMessage */ public function ackFailure(): V1|V2 { - $this->serverState->is(ServerState::FAILED); $this->write($this->packer->pack(0x0E)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::READY); + $this->pipelinedMessages[] = Message::ACK_FAILURE; return $this; } - - /** - * Read ACK_FAILURE response - * @throws BoltException - */ - protected function _ackFailure(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - - yield new Response(Response::MESSAGE_ACK_FAILURE, $signature, $content); - } } diff --git a/src/protocol/v1/DiscardAllMessage.php b/src/protocol/v1/DiscardAllMessage.php index b6e4b18..cb5a6d2 100644 --- a/src/protocol/v1/DiscardAllMessage.php +++ b/src/protocol/v1/DiscardAllMessage.php @@ -2,13 +2,8 @@ namespace Bolt\protocol\v1; -use Bolt\protocol\{ - ServerState, - Response, - V1, - V2, - V3 -}; +use Bolt\enum\Message; +use Bolt\protocol\{V1, V2, V3}; use Bolt\error\BoltException; trait DiscardAllMessage @@ -22,25 +17,8 @@ trait DiscardAllMessage */ public function discardAll(): V1|V2|V3 { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); $this->write($this->packer->pack(0x2F)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); + $this->pipelinedMessages[] = Message::DISCARD_ALL; return $this; } - - /** - * Read DISCARD_ALL response - * @throws BoltException - */ - protected function _discardAll(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); - } - - yield new Response(Response::MESSAGE_DISCARD_ALL, $signature, $content); - } } diff --git a/src/protocol/v1/InitMessage.php b/src/protocol/v1/InitMessage.php index 79f8001..01bf110 100644 --- a/src/protocol/v1/InitMessage.php +++ b/src/protocol/v1/InitMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v1; -use Bolt\protocol\{ServerState, Response}; +use Bolt\enum\Message; +use Bolt\protocol\{V1, V2}; use Bolt\error\BoltException; trait InitMessage @@ -14,21 +15,10 @@ trait InitMessage * @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-init * @throws BoltException */ - public function init(string $userAgent, array $authToken): Response + public function init(string $userAgent, array $authToken): V1|V2 { - $this->serverState->is(ServerState::CONNECTED); - $this->write($this->packer->pack(0x01, $userAgent, $authToken)); - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - // ..but must immediately close the connection after the failure has been sent. - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - - return new Response(Response::MESSAGE_INIT, $signature, $content); + $this->pipelinedMessages[] = Message::INIT; + return $this; } } diff --git a/src/protocol/v1/PullAllMessage.php b/src/protocol/v1/PullAllMessage.php index f12f31d..7c59a4e 100644 --- a/src/protocol/v1/PullAllMessage.php +++ b/src/protocol/v1/PullAllMessage.php @@ -2,8 +2,8 @@ namespace Bolt\protocol\v1; +use Bolt\enum\{Message, Signature}; use Bolt\protocol\{ - ServerState, Response, V1, V2, @@ -22,10 +22,8 @@ trait PullAllMessage */ public function pullAll(): V1|V2|V3 { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); $this->write($this->packer->pack(0x3F)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); + $this->pipelinedMessages[] = Message::PULL_ALL; return $this; } @@ -37,12 +35,7 @@ protected function _pullAll(): iterable { do { $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); - } - - yield new Response(Response::MESSAGE_PULL_ALL, $signature, $content); - } while ($signature == Response::SIGNATURE_RECORD); + yield new Response(Message::PULL_ALL, $signature, $content); + } while ($signature == Signature::RECORD); } } diff --git a/src/protocol/v1/ResetMessage.php b/src/protocol/v1/ResetMessage.php index 44078ae..f465a05 100644 --- a/src/protocol/v1/ResetMessage.php +++ b/src/protocol/v1/ResetMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v1; -use Bolt\protocol\{ServerState, Response, V1, V2, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V1, V2, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait ResetMessage @@ -17,26 +18,7 @@ trait ResetMessage public function reset(): V1|V2|V3|V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { $this->write($this->packer->pack(0x0F)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::READY); + $this->pipelinedMessages[] = Message::RESET; return $this; } - - /** - * Read RESET response - * @throws BoltException - */ - protected function _reset(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - - yield new Response(Response::MESSAGE_RESET, $signature, $content); - } } diff --git a/src/protocol/v1/RunMessage.php b/src/protocol/v1/RunMessage.php index 2297ba2..f2f0aea 100644 --- a/src/protocol/v1/RunMessage.php +++ b/src/protocol/v1/RunMessage.php @@ -2,12 +2,8 @@ namespace Bolt\protocol\v1; -use Bolt\protocol\{ - ServerState, - Response, - V1, - V2 -}; +use Bolt\enum\Message; +use Bolt\protocol\{V1, V2}; use Bolt\error\BoltException; trait RunMessage @@ -21,25 +17,8 @@ trait RunMessage */ public function run(string $query, array $parameters = []): V1|V2 { - $this->serverState->is(ServerState::READY); $this->write($this->packer->pack(0x10, $query, (object)$parameters)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::STREAMING); + $this->pipelinedMessages[] = Message::RUN; return $this; } - - /** - * Read RUN response - * @throws BoltException - */ - protected function _run(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::STREAMING); - } - - yield new Response(Response::MESSAGE_RUN, $signature, $content); - } } diff --git a/src/protocol/v1/ServerStateTransition.php b/src/protocol/v1/ServerStateTransition.php new file mode 100644 index 0000000..17a670d --- /dev/null +++ b/src/protocol/v1/ServerStateTransition.php @@ -0,0 +1,38 @@ +days; } public function __toString(): string diff --git a/src/protocol/v1/structures/DateTime.php b/src/protocol/v1/structures/DateTime.php index bc0d2a6..b0bebb6 100644 --- a/src/protocol/v1/structures/DateTime.php +++ b/src/protocol/v1/structures/DateTime.php @@ -21,33 +21,17 @@ */ class DateTime implements IStructure { - public function __construct( - private int $seconds, - private int $nanoseconds, - private int $tz_offset_seconds - ) - { - } - /** - * seconds since the adjusted Unix epoch. This is not UTC + * @param int $seconds seconds since the adjusted Unix epoch. This is not UTC + * @param int $nanoseconds + * @param int $tz_offset_seconds specifies the offset in seconds from UTC */ - public function seconds(): int - { - return $this->seconds; - } - - public function nanoseconds(): int - { - return $this->nanoseconds; - } - - /** - * specifies the offset in seconds from UTC - */ - public function tz_offset_seconds(): int + public function __construct( + public readonly int $seconds, + public readonly int $nanoseconds, + public readonly int $tz_offset_seconds + ) { - return $this->tz_offset_seconds; } public function __toString(): string diff --git a/src/protocol/v1/structures/DateTimeZoneId.php b/src/protocol/v1/structures/DateTimeZoneId.php index 412450c..03e0c10 100644 --- a/src/protocol/v1/structures/DateTimeZoneId.php +++ b/src/protocol/v1/structures/DateTimeZoneId.php @@ -21,33 +21,17 @@ */ class DateTimeZoneId implements IStructure { - public function __construct( - private int $seconds, - private int $nanoseconds, - private string $tz_id - ) - { - } - /** - * seconds since the adjusted Unix epoch. This is not UTC + * @param int $seconds seconds since the adjusted Unix epoch. This is not UTC + * @param int $nanoseconds + * @param string $tz_id identifier for a specific time zone */ - public function seconds(): int - { - return $this->seconds; - } - - public function nanoseconds(): int - { - return $this->nanoseconds; - } - - /** - * identifier for a specific time zone - */ - public function tz_id(): string + public function __construct( + public readonly int $seconds, + public readonly int $nanoseconds, + public readonly string $tz_id + ) { - return $this->tz_id; } public function __toString(): string diff --git a/src/protocol/v1/structures/Duration.php b/src/protocol/v1/structures/Duration.php index 5399f06..47b46fa 100644 --- a/src/protocol/v1/structures/Duration.php +++ b/src/protocol/v1/structures/Duration.php @@ -18,34 +18,14 @@ class Duration implements IStructure { public function __construct( - private int $months, - private int $days, - private int $seconds, - private int $nanoseconds + public readonly int $months, + public readonly int $days, + public readonly int $seconds, + public readonly int $nanoseconds ) { } - public function months(): int - { - return $this->months; - } - - public function days(): int - { - return $this->days; - } - - public function seconds(): int - { - return $this->seconds; - } - - public function nanoseconds(): int - { - return $this->nanoseconds; - } - public function __toString(): string { $output = 'P'; diff --git a/src/protocol/v1/structures/LocalDateTime.php b/src/protocol/v1/structures/LocalDateTime.php index f038290..aa7bad1 100644 --- a/src/protocol/v1/structures/LocalDateTime.php +++ b/src/protocol/v1/structures/LocalDateTime.php @@ -17,24 +17,15 @@ */ class LocalDateTime implements IStructure { - public function __construct( - private int $seconds, - private int $nanoseconds - ) - { - } - /** - * seconds since the Unix epoch + * @param int $seconds seconds since the Unix epoch + * @param int $nanoseconds */ - public function seconds(): int - { - return $this->seconds; - } - - public function nanoseconds(): int + public function __construct( + public readonly int $seconds, + public readonly int $nanoseconds + ) { - return $this->nanoseconds; } public function __toString(): string diff --git a/src/protocol/v1/structures/LocalTime.php b/src/protocol/v1/structures/LocalTime.php index 806a464..eba9434 100644 --- a/src/protocol/v1/structures/LocalTime.php +++ b/src/protocol/v1/structures/LocalTime.php @@ -17,16 +17,11 @@ */ class LocalTime implements IStructure { - public function __construct(private int $nanoseconds) - { - } - /** - * nanosecond since midnight + * @param int $nanoseconds nanosecond since midnight */ - public function nanoseconds(): int + public function __construct(public readonly int $nanoseconds) { - return $this->nanoseconds; } public function __toString(): string diff --git a/src/protocol/v1/structures/Node.php b/src/protocol/v1/structures/Node.php index 0685291..77e04f4 100644 --- a/src/protocol/v1/structures/Node.php +++ b/src/protocol/v1/structures/Node.php @@ -16,28 +16,13 @@ class Node implements IStructure { public function __construct( - private int $id, - private array $labels, - private array $properties + public readonly int $id, + public readonly array $labels, + public readonly array $properties ) { } - public function id(): int - { - return $this->id; - } - - public function labels(): array - { - return $this->labels; - } - - public function properties(): array - { - return $this->properties; - } - public function __toString(): string { return json_encode([ diff --git a/src/protocol/v1/structures/Path.php b/src/protocol/v1/structures/Path.php index cb15e69..8a16c87 100644 --- a/src/protocol/v1/structures/Path.php +++ b/src/protocol/v1/structures/Path.php @@ -17,43 +17,17 @@ class Path implements IStructure { /** * @param Node[] $nodes - * @param UnboundRelationship[] $rels - * @param int[] $ids + * @param UnboundRelationship[] $rels list of unbound relationships + * @param int[] $ids relationship id and node id to represent the path */ public function __construct( - private array $nodes, - private array $rels, - private array $ids + public readonly array $nodes, + public readonly array $rels, + public readonly array $ids ) { } - /** - * @return Node[] - */ - public function nodes(): array - { - return $this->nodes; - } - - /** - * list of unbound relationships - * @return UnboundRelationship[] - */ - public function rels(): array - { - return $this->rels; - } - - /** - * relationship id and node id to represent the path - * @return int[] - */ - public function ids(): array - { - return $this->ids; - } - public function __toString(): string { $obj = [ @@ -66,7 +40,7 @@ public function __toString(): string for ($i = 0; $i < count($this->nodes) - 1; $i++) { $obj['segments'][] = [ 'start' => json_decode($this->nodes[$i], true), - 'relationship' => array_merge(json_decode($this->rels[$i], true), ['start' => $this->nodes[$i]->id(), 'end' => $this->nodes[$i + 1]->id()]), + 'relationship' => array_merge(json_decode($this->rels[$i], true), ['start' => $this->nodes[$i]->id, 'end' => $this->nodes[$i + 1]->id()]), 'end' => json_decode($this->nodes[$i + 1], true) ]; } diff --git a/src/protocol/v1/structures/Point2D.php b/src/protocol/v1/structures/Point2D.php index 5012ae4..c26a74c 100644 --- a/src/protocol/v1/structures/Point2D.php +++ b/src/protocol/v1/structures/Point2D.php @@ -17,30 +17,17 @@ */ class Point2D implements IStructure { - public function __construct( - private int $srid, - private float $x, - private float $y - ) - { - } - /** - * Spatial Reference System Identifier + * @param int $srid Spatial Reference System Identifier + * @param float $x + * @param float $y */ - public function srid(): int - { - return $this->srid; - } - - public function x(): float - { - return $this->x; - } - - public function y(): float + public function __construct( + public readonly int $srid, + public readonly float $x, + public readonly float $y + ) { - return $this->y; } public function __toString(): string diff --git a/src/protocol/v1/structures/Point3D.php b/src/protocol/v1/structures/Point3D.php index 1cf6433..e0dadc9 100644 --- a/src/protocol/v1/structures/Point3D.php +++ b/src/protocol/v1/structures/Point3D.php @@ -17,36 +17,19 @@ */ class Point3D implements IStructure { - public function __construct( - private int $srid, - private float $x, - private float $y, - private float $z - ) - { - } - /** - * Spatial Reference System Identifier + * @param int $srid Spatial Reference System Identifier + * @param float $x + * @param float $y + * @param float $z */ - public function srid(): int - { - return $this->srid; - } - - public function x(): float - { - return $this->x; - } - - public function y(): float - { - return $this->y; - } - - public function z(): float + public function __construct( + public readonly int $srid, + public readonly float $x, + public readonly float $y, + public readonly float $z + ) { - return $this->z; } public function __toString(): string diff --git a/src/protocol/v1/structures/Relationship.php b/src/protocol/v1/structures/Relationship.php index 7acb4b4..662111d 100644 --- a/src/protocol/v1/structures/Relationship.php +++ b/src/protocol/v1/structures/Relationship.php @@ -16,40 +16,15 @@ class Relationship implements IStructure { public function __construct( - private int $id, - private int $startNodeId, - private int $endNodeId, - private string $type, - private array $properties + public readonly int $id, + public readonly int $startNodeId, + public readonly int $endNodeId, + public readonly string $type, + public readonly array $properties ) { } - public function id(): int - { - return $this->id; - } - - public function startNodeId(): int - { - return $this->startNodeId; - } - - public function endNodeId(): int - { - return $this->endNodeId; - } - - public function type(): string - { - return $this->type; - } - - public function properties(): array - { - return $this->properties; - } - public function __toString(): string { return json_encode([ diff --git a/src/protocol/v1/structures/Time.php b/src/protocol/v1/structures/Time.php index 7577b33..47c57ca 100644 --- a/src/protocol/v1/structures/Time.php +++ b/src/protocol/v1/structures/Time.php @@ -20,27 +20,15 @@ */ class Time implements IStructure { - public function __construct( - private int $nanoseconds, - private int $tz_offset_seconds - ) - { - } - - /** - * nanoseconds since midnight. This time is not UTC - */ - public function nanoseconds(): int - { - return $this->nanoseconds; - } - /** - * offset in seconds from UTC + * @param int $nanoseconds nanoseconds since midnight. This time is not UTC + * @param int $tz_offset_seconds offset in seconds from UTC */ - public function tz_offset_seconds(): int + public function __construct( + public readonly int $nanoseconds, + public readonly int $tz_offset_seconds + ) { - return $this->tz_offset_seconds; } public function __toString(): string diff --git a/src/protocol/v1/structures/UnboundRelationship.php b/src/protocol/v1/structures/UnboundRelationship.php index 4b066bb..825ff69 100644 --- a/src/protocol/v1/structures/UnboundRelationship.php +++ b/src/protocol/v1/structures/UnboundRelationship.php @@ -16,28 +16,13 @@ class UnboundRelationship implements IStructure { public function __construct( - private int $id, - private string $type, - private array $properties + public readonly int $id, + public readonly string $type, + public readonly array $properties ) { } - public function id(): int - { - return $this->id; - } - - public function type(): string - { - return $this->type; - } - - public function properties(): array - { - return $this->properties; - } - public function __toString(): string { return json_encode([ diff --git a/src/protocol/v3/BeginMessage.php b/src/protocol/v3/BeginMessage.php index 809a7ba..487f6d3 100644 --- a/src/protocol/v3/BeginMessage.php +++ b/src/protocol/v3/BeginMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\{ServerState, Response, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait BeginMessage @@ -16,25 +17,8 @@ trait BeginMessage */ public function begin(array $extra = []): V3|V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::READY); $this->write($this->packer->pack(0x11, (object)$extra)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::TX_READY); + $this->pipelinedMessages[] = Message::BEGIN; return $this; } - - /** - * Read BEGIN response - * @throws BoltException - */ - protected function _begin(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::TX_READY); - } - - yield new Response(Response::MESSAGE_BEGIN, $signature, $content); - } } diff --git a/src/protocol/v3/CommitMessage.php b/src/protocol/v3/CommitMessage.php index 5e9565d..e5c6978 100644 --- a/src/protocol/v3/CommitMessage.php +++ b/src/protocol/v3/CommitMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\{ServerState, Response, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait CommitMessage @@ -16,26 +17,8 @@ trait CommitMessage */ public function commit(): V3|V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::TX_READY, ServerState::TX_STREAMING); $this->write($this->packer->pack(0x12)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::READY); - + $this->pipelinedMessages[] = Message::COMMIT; return $this; } - - /** - * Read COMMIT response - * @throws BoltException - */ - protected function _commit(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } - - yield new Response(Response::MESSAGE_COMMIT, $signature, $content); - } } diff --git a/src/protocol/v3/GoodbyeMessage.php b/src/protocol/v3/GoodbyeMessage.php index 13a2171..4d31b40 100644 --- a/src/protocol/v3/GoodbyeMessage.php +++ b/src/protocol/v3/GoodbyeMessage.php @@ -2,7 +2,7 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\ServerState; +use Bolt\enum\ServerState; use Bolt\error\BoltException; trait GoodbyeMessage @@ -18,6 +18,6 @@ public function goodbye(): void { $this->write($this->packer->pack(0x02)); $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); + $this->serverState = ServerState::DEFUNCT; } } diff --git a/src/protocol/v3/HelloMessage.php b/src/protocol/v3/HelloMessage.php index 500e05d..2afc6af 100644 --- a/src/protocol/v3/HelloMessage.php +++ b/src/protocol/v3/HelloMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\{ServerState, Response}; +use Bolt\enum\Message; +use Bolt\protocol\{V3, V4, V4_1, V4_2, V4_3, V4_4, V5}; use Bolt\error\BoltException; trait HelloMessage @@ -15,20 +16,10 @@ trait HelloMessage * @param array $extra Use \Bolt\helpers\Auth to generate appropriate array * @throws BoltException */ - public function hello(array $extra): Response + public function hello(array $extra): V3|V4|V4_1|V4_2|V4_3|V4_4|V5 { - $this->serverState->is(ServerState::CONNECTED); - $this->write($this->packer->pack(0x01, $extra)); - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - - return new Response(Response::MESSAGE_HELLO, $signature, $content); + $this->pipelinedMessages[] = Message::HELLO; + return $this; } } diff --git a/src/protocol/v3/RollbackMessage.php b/src/protocol/v3/RollbackMessage.php index 1cb8dc8..b84133a 100644 --- a/src/protocol/v3/RollbackMessage.php +++ b/src/protocol/v3/RollbackMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\{ServerState, Response, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait RollbackMessage @@ -16,25 +17,8 @@ trait RollbackMessage */ public function rollback(): V3|V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::TX_READY, ServerState::TX_STREAMING); $this->write($this->packer->pack(0x13)); - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(ServerState::READY); + $this->pipelinedMessages[] = Message::ROLLBACK; return $this; } - - /** - * Read ROLLBACK response - * @throws BoltException - */ - protected function _rollback(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } - - yield new Response(Response::MESSAGE_ROLLBACK, $signature, $content); - } } diff --git a/src/protocol/v3/RunMessage.php b/src/protocol/v3/RunMessage.php index 177a662..b92ffdb 100644 --- a/src/protocol/v3/RunMessage.php +++ b/src/protocol/v3/RunMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v3; -use Bolt\protocol\{ServerState, Response, V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V3, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait RunMessage @@ -16,32 +17,13 @@ trait RunMessage */ public function run(string $query, array $parameters = [], array $extra = []): V3|V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); - $this->write($this->packer->pack( 0x10, $query, (object)$parameters, (object)$extra )); - - $this->pipelinedMessages[] = __FUNCTION__; - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_STREAMING : ServerState::STREAMING); + $this->pipelinedMessages[] = Message::RUN; return $this; } - - /** - * Read RUN response - * @throws BoltException - */ - protected function _run(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_STREAMING : ServerState::STREAMING); - } - - yield new Response(Response::MESSAGE_RUN, $signature, $content); - } } diff --git a/src/protocol/v3/ServerStateTransition.php b/src/protocol/v3/ServerStateTransition.php new file mode 100644 index 0000000..9ec2fa5 --- /dev/null +++ b/src/protocol/v3/ServerStateTransition.php @@ -0,0 +1,54 @@ +serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); - if (!array_key_exists('n', $extra)) $extra['n'] = -1; - $this->write($this->packer->pack(0x2F, $extra)); - - $this->pipelinedMessages[] = __FUNCTION__; - //we assume all records were discarded - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); + $this->pipelinedMessages[] = Message::DISCARD; return $this; } - - /** - * Read DISCARD response - * @throws BoltException - */ - protected function _discard(): iterable - { - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - if ($content['has_more'] ?? false) { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_STREAMING : ServerState::STREAMING); - } else { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); - } - } - - yield new Response(Response::MESSAGE_DISCARD, $signature, $content); - } } diff --git a/src/protocol/v4/PullMessage.php b/src/protocol/v4/PullMessage.php index 56de33c..82be37b 100644 --- a/src/protocol/v4/PullMessage.php +++ b/src/protocol/v4/PullMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v4; -use Bolt\protocol\{ServerState, Response, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\{Message, Signature}; +use Bolt\protocol\{Response, V4, V4_1, V4_2, V4_3, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait PullMessage @@ -17,16 +18,10 @@ trait PullMessage */ public function pull(array $extra = []): V4|V4_1|V4_2|V4_3|V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::READY, ServerState::TX_READY, ServerState::STREAMING, ServerState::TX_STREAMING); - if (!array_key_exists('n', $extra)) $extra['n'] = -1; - $this->write($this->packer->pack(0x3F, $extra)); - - $this->pipelinedMessages[] = __FUNCTION__; - //we assume all records were pulled - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); + $this->pipelinedMessages[] = Message::PULL; return $this; } @@ -39,16 +34,7 @@ protected function _pull(): iterable { do { $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - if ($content['has_more'] ?? false) { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_STREAMING : ServerState::STREAMING); - } else { - $this->serverState->set(str_starts_with($this->serverState->get(), 'TX_') ? ServerState::TX_READY : ServerState::READY); - } - } - - yield new Response(Response::MESSAGE_PULL, $signature, $content); - } while ($signature == Response::SIGNATURE_RECORD); + yield new Response(Message::PULL, $signature, $content); + } while ($signature == Signature::RECORD); } } diff --git a/src/protocol/v4/ServerStateTransition.php b/src/protocol/v4/ServerStateTransition.php new file mode 100644 index 0000000..2e6e8b6 --- /dev/null +++ b/src/protocol/v4/ServerStateTransition.php @@ -0,0 +1,59 @@ +serverState->is(ServerState::READY); $this->write($this->packer->pack(0x66, (object)$routing, $bookmarks, $db)); - $this->pipelinedMessages[] = __FUNCTION__; + $this->pipelinedMessages[] = Message::ROUTE; return $this; } - - /** - * Read ROUTE response - * @throws BoltException - */ - protected function _route(): iterable - { - $content = $this->read($signature); - yield new Response(Response::MESSAGE_ROUTE, $signature, $content); - } } diff --git a/src/protocol/v4_4/RouteMessage.php b/src/protocol/v4_4/RouteMessage.php index 49b0a3b..3078232 100644 --- a/src/protocol/v4_4/RouteMessage.php +++ b/src/protocol/v4_4/RouteMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v4_4; -use Bolt\protocol\{ServerState, Response, V4_4, V5, V5_1, V5_2, V5_3, V5_4}; +use Bolt\enum\Message; +use Bolt\protocol\{V4_4, V5, V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait RouteMessage @@ -17,19 +18,8 @@ trait RouteMessage */ public function route(array $routing, array $bookmarks = [], array $extra = []): V4_4|V5|V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::READY); $this->write($this->packer->pack(0x66, (object)$routing, $bookmarks, (object)$extra)); - $this->pipelinedMessages[] = __FUNCTION__; + $this->pipelinedMessages[] = Message::ROUTE; return $this; } - - /** - * Read ROUTE response - * @throws BoltException - */ - protected function _route(): iterable - { - $content = $this->read($signature); - yield new Response(Response::MESSAGE_ROUTE, $signature, $content); - } } diff --git a/src/protocol/v5/structures/DateTime.php b/src/protocol/v5/structures/DateTime.php index c3ea05b..1b64616 100644 --- a/src/protocol/v5/structures/DateTime.php +++ b/src/protocol/v5/structures/DateTime.php @@ -20,9 +20,9 @@ class DateTime extends v1_DateTime { public function __toString(): string { - $datetime = sprintf("%d", $this->seconds()) . '.' . substr(sprintf("%09d", $this->nanoseconds()), 0, 6); + $datetime = sprintf("%d", $this->seconds) . '.' . substr(sprintf("%09d", $this->nanoseconds), 0, 6); return \DateTime::createFromFormat('U.u', $datetime, new \DateTimeZone('UTC')) - ->setTimezone(new \DateTimeZone(sprintf("%+'05d", $this->tz_offset_seconds() / 3600 * 100))) + ->setTimezone(new \DateTimeZone(sprintf("%+'05d", $this->tz_offset_seconds / 3600 * 100))) ->format('Y-m-d\TH:i:s.uP'); } } diff --git a/src/protocol/v5/structures/DateTimeZoneId.php b/src/protocol/v5/structures/DateTimeZoneId.php index b6c33d5..8fb03ea 100644 --- a/src/protocol/v5/structures/DateTimeZoneId.php +++ b/src/protocol/v5/structures/DateTimeZoneId.php @@ -20,9 +20,9 @@ class DateTimeZoneId extends v1_DateTimeZoneId { public function __toString(): string { - $datetime = sprintf("%d", $this->seconds()) . '.' . substr(sprintf("%09d", $this->nanoseconds()), 0, 6); + $datetime = sprintf("%d", $this->seconds) . '.' . substr(sprintf("%09d", $this->nanoseconds), 0, 6); return \DateTime::createFromFormat('U.u', $datetime, new \DateTimeZone('UTC')) - ->setTimezone(new \DateTimeZone($this->tz_id())) - ->format('Y-m-d\TH:i:s.u') . '[' . $this->tz_id() . ']'; + ->setTimezone(new \DateTimeZone($this->tz_id)) + ->format('Y-m-d\TH:i:s.u') . '[' . $this->tz_id . ']'; } } diff --git a/src/protocol/v5/structures/Node.php b/src/protocol/v5/structures/Node.php index fe5bf2c..0bb3922 100644 --- a/src/protocol/v5/structures/Node.php +++ b/src/protocol/v5/structures/Node.php @@ -16,27 +16,22 @@ class Node extends v1_Node { public function __construct( - int $id, - array $labels, - array $properties, - private string $element_id + int $id, + array $labels, + array $properties, + public readonly string $element_id ) { parent::__construct($id, $labels, $properties); } - public function element_id(): string - { - return $this->element_id; - } - public function __toString(): string { return json_encode([ - 'identity' => $this->id(), - 'labels' => $this->labels(), - 'properties' => $this->properties(), - 'element_id' => $this->element_id() + 'identity' => $this->id, + 'labels' => $this->labels, + 'properties' => $this->properties, + 'element_id' => $this->element_id ]); } } diff --git a/src/protocol/v5/structures/Relationship.php b/src/protocol/v5/structures/Relationship.php index 85efb10..5133775 100644 --- a/src/protocol/v5/structures/Relationship.php +++ b/src/protocol/v5/structures/Relationship.php @@ -16,45 +16,30 @@ class Relationship extends v1_Relationship { public function __construct( - int $id, - int $startNodeId, - int $endNodeId, - string $type, - array $properties, - private string $element_id, - private string $start_node_element_id, - private string $end_node_element_id + int $id, + int $startNodeId, + int $endNodeId, + string $type, + array $properties, + public readonly string $element_id, + public readonly string $start_node_element_id, + public readonly string $end_node_element_id ) { parent::__construct($id, $startNodeId, $endNodeId, $type, $properties); } - public function element_id(): string - { - return $this->element_id; - } - - public function start_node_element_id(): string - { - return $this->start_node_element_id; - } - - public function end_node_element_id(): string - { - return $this->end_node_element_id; - } - public function __toString(): string { return json_encode([ - 'identity' => $this->id(), - 'start' => $this->startNodeId(), - 'end' => $this->endNodeId(), - 'type' => $this->type(), - 'properties' => $this->properties(), - 'element_id' => $this->element_id(), - 'start_node_element_id' => $this->start_node_element_id(), - 'end_node_element_id' => $this->end_node_element_id() + 'identity' => $this->id, + 'start' => $this->startNodeId, + 'end' => $this->endNodeId, + 'type' => $this->type, + 'properties' => $this->properties, + 'element_id' => $this->element_id, + 'start_node_element_id' => $this->start_node_element_id, + 'end_node_element_id' => $this->end_node_element_id ]); } } diff --git a/src/protocol/v5/structures/UnboundRelationship.php b/src/protocol/v5/structures/UnboundRelationship.php index 498e629..13f6334 100644 --- a/src/protocol/v5/structures/UnboundRelationship.php +++ b/src/protocol/v5/structures/UnboundRelationship.php @@ -16,27 +16,22 @@ class UnboundRelationship extends v1_UnboundRelationship { public function __construct( - int $id, - string $type, - array $properties, - private string $element_id + int $id, + string $type, + array $properties, + public readonly string $element_id ) { parent::__construct($id, $type, $properties); } - public function element_id(): string - { - return $this->element_id; - } - public function __toString(): string { return json_encode([ - 'identity' => $this->id(), - 'type' => $this->type(), - 'properties' => $this->properties(), - 'element_id' => $this->element_id() + 'identity' => $this->id, + 'type' => $this->type, + 'properties' => $this->properties, + 'element_id' => $this->element_id ]); } } diff --git a/src/protocol/v5_1/HelloMessage.php b/src/protocol/v5_1/HelloMessage.php index d763b2d..06a2649 100644 --- a/src/protocol/v5_1/HelloMessage.php +++ b/src/protocol/v5_1/HelloMessage.php @@ -2,7 +2,8 @@ namespace Bolt\protocol\v5_1; -use Bolt\protocol\{ServerState, Response}; +use Bolt\enum\Message; +use Bolt\protocol\{V5_1, V5_2, V5_3, V5_4}; use Bolt\error\BoltException; trait HelloMessage @@ -14,25 +15,15 @@ trait HelloMessage * @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-hello * @throws BoltException */ - public function hello(array $extra = []): Response + public function hello(array $extra = []): V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::CONNECTED); - if (empty($extra['user_agent'])) - $extra['user_agent'] = \Bolt\helpers\Auth::$defaultUserAgent; + $extra['user_agent'] = 'bolt-php'; if (isset($extra['routing']) && is_array($extra['routing'])) $extra['routing'] = (object)$extra['routing']; $this->write($this->packer->pack(0x01, (object)$extra)); - $content = $this->read($signature); - - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::UNAUTHENTICATED); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - - return new Response(Response::MESSAGE_HELLO, $signature, $content); + $this->pipelinedMessages[] = Message::HELLO; + return $this; } } diff --git a/src/protocol/v5_1/LogoffMessage.php b/src/protocol/v5_1/LogoffMessage.php index f5044cd..7c43ba8 100644 --- a/src/protocol/v5_1/LogoffMessage.php +++ b/src/protocol/v5_1/LogoffMessage.php @@ -2,10 +2,9 @@ namespace Bolt\protocol\v5_1; +use Bolt\enum\Message; use Bolt\error\BoltException; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; -use Bolt\protocol\V5_1; +use Bolt\protocol\{V5_1, V5_2, V5_3, V5_4}; trait LogoffMessage { @@ -16,17 +15,10 @@ trait LogoffMessage * @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-logoff * @throws BoltException */ - public function logoff(): Response + public function logoff(): V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::READY); $this->write($this->packer->pack(0x6B)); - $content = $this->read($signature); - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::UNAUTHENTICATED); - } else { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - return new Response(Response::MESSAGE_LOGOFF, $signature, $content); + $this->pipelinedMessages[] = Message::LOGOFF; + return $this; } } diff --git a/src/protocol/v5_1/LogonMessage.php b/src/protocol/v5_1/LogonMessage.php index d8500cd..1b5d85a 100644 --- a/src/protocol/v5_1/LogonMessage.php +++ b/src/protocol/v5_1/LogonMessage.php @@ -2,9 +2,9 @@ namespace Bolt\protocol\v5_1; +use Bolt\enum\Message; use Bolt\error\BoltException; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; +use Bolt\protocol\{V5_1, V5_2, V5_3, V5_4}; trait LogonMessage { @@ -15,17 +15,10 @@ trait LogonMessage * @link https://www.neo4j.com/docs/bolt/current/bolt/message/#messages-logon * @throws BoltException */ - public function logon(array $auth): Response + public function logon(array $auth): V5_1|V5_2|V5_3|V5_4 { - $this->serverState->is(ServerState::UNAUTHENTICATED); $this->write($this->packer->pack(0x6A, (object)$auth)); - $content = $this->read($signature); - if ($signature == Response::SIGNATURE_SUCCESS) { - $this->serverState->set(ServerState::READY); - } elseif ($signature == Response::SIGNATURE_FAILURE) { - $this->connection->disconnect(); - $this->serverState->set(ServerState::DEFUNCT); - } - return new Response(Response::MESSAGE_LOGON, $signature, $content); + $this->pipelinedMessages[] = Message::LOGON; + return $this; } } diff --git a/src/protocol/v5_1/ServerStateTransition.php b/src/protocol/v5_1/ServerStateTransition.php new file mode 100644 index 0000000..c9a211d --- /dev/null +++ b/src/protocol/v5_1/ServerStateTransition.php @@ -0,0 +1,65 @@ + 'php-bolt/' . \Composer\InstalledVersions::getPrettyVersion('stefanak-michal/bolt'), diff --git a/src/protocol/v5_4/TelemetryMessage.php b/src/protocol/v5_4/TelemetryMessage.php index f23112f..ace38cc 100644 --- a/src/protocol/v5_4/TelemetryMessage.php +++ b/src/protocol/v5_4/TelemetryMessage.php @@ -2,9 +2,9 @@ namespace Bolt\protocol\v5_4; +use Bolt\protocol\V5_4; +use Bolt\enum\Message; use Bolt\error\BoltException; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; trait TelemetryMessage { @@ -13,19 +13,12 @@ trait TelemetryMessage * The TELEMETRY message contains an integer representing which driver API was used. * * @link https://neo4j.com/docs/bolt/current/bolt/message/#messages-telemetry - * @param int $api - * @return Response * @throws BoltException */ - public function telemetry(int $api): Response + public function telemetry(int $api): V5_4 { $this->write($this->packer->pack(0x54, $api)); - $content = $this->read($signature); - - if ($signature === Response::SIGNATURE_FAILURE) { - $this->serverState->set(ServerState::FAILED); - } - - return new Response(Response::MESSAGE_TELEMETRY, $signature, $content); + $this->pipelinedMessages[] = Message::TELEMETRY; + return $this; } } diff --git a/tests/ATest.php b/tests/ATest.php index 5f8b556..a0912b4 100644 --- a/tests/ATest.php +++ b/tests/ATest.php @@ -2,8 +2,8 @@ namespace Bolt\tests; -use Bolt\protocol\{AProtocol, Response}; -use Bolt\helpers\Auth; +use Bolt\protocol\AProtocol; +use Bolt\enum\Signature; /** * Class ATest @@ -34,23 +34,28 @@ public static function setUpBeforeClass(): void * @param string $name * @param string $password */ - protected function sayHello(AProtocol $protocol, string $name, string $password) + protected function sayHello(AProtocol $protocol, string $name, string $password): void { if (method_exists($protocol, 'init')) { - $this->assertEquals(Response::SIGNATURE_SUCCESS, $protocol->init(Auth::$defaultUserAgent, [ + $this->assertEquals(Signature::SUCCESS, $protocol->init('bolt-php', [ 'scheme' => 'basic', 'principal' => $name, 'credentials' => $password - ])->getSignature()); + ])->getResponse()->signature); } elseif (method_exists($protocol, 'logon')) { - $this->assertEquals(Response::SIGNATURE_SUCCESS, $protocol->hello()->getSignature()); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $protocol->logon([ + $this->assertEquals(Signature::SUCCESS, $protocol->hello()->getResponse()->signature); + $this->assertEquals(Signature::SUCCESS, $protocol->logon([ 'scheme' => 'basic', 'principal' => $name, 'credentials' => $password - ])->getSignature()); + ])->getResponse()->signature); } else { - $this->assertEquals(Response::SIGNATURE_SUCCESS, $protocol->hello(Auth::basic($name, $password))->getSignature()); + $this->assertEquals(Signature::SUCCESS, $protocol->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => $name, + 'credentials' => $password, + ])->getResponse()->signature); } } diff --git a/tests/BoltTest.php b/tests/BoltTest.php index 7181347..c7646f1 100644 --- a/tests/BoltTest.php +++ b/tests/BoltTest.php @@ -3,8 +3,9 @@ namespace Bolt\tests; use Bolt\Bolt; +use Bolt\enum\Signature; use Exception; -use Bolt\protocol\{AProtocol, Response}; +use Bolt\protocol\AProtocol; /** * Class BoltTest @@ -80,9 +81,9 @@ public function testPull(AProtocol $protocol): void ->run('RETURN 1 AS num, 2 AS cnt', [], ['mode' => 'r']) ->pull(); - $this->assertArrayHasKey('fields', $protocol->getResponse()->getContent()); + $this->assertArrayHasKey('fields', $protocol->getResponse()->content); - $res = $protocol->getResponse()->getContent(); + $res = $protocol->getResponse()->content; $this->assertEquals(1, $res[0] ?? 0); $this->assertEquals(2, $res[1] ?? 0); $protocol->getResponse(); // last success message @@ -99,7 +100,7 @@ public function testDiscard(AProtocol $protocol): void ->getResponses(); foreach ($gen as $response) { - $this->assertEquals(Response::SIGNATURE_SUCCESS, $response->getSignature()); + $this->assertEquals(Signature::SUCCESS, $response->signature); } } @@ -123,7 +124,7 @@ public function testTransaction(AProtocol $protocol): void false ); - $id = $res[2]->getContent()[1]; + $id = $res[2]->content[1]; $this->assertIsInt($id); $res = iterator_to_array( @@ -138,7 +139,7 @@ public function testTransaction(AProtocol $protocol): void false ); - $this->assertEquals(0, $res[1]->getContent()[0]); + $this->assertEquals(0, $res[1]->content[0]); } /** @@ -152,7 +153,7 @@ public function testRoute(AProtocol $protocol): void 'address' => ($GLOBALS['NEO_HOST'] ?? '127.0.0.1') . ':' . ($GLOBALS['NEO_PORT'] ?? 7687) ]) ->getResponse(); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $response->getSignature()); + $this->assertEquals(Signature::SUCCESS, $response->signature); } else { $this->markTestSkipped('Old Neo4j version does not support route message'); } @@ -166,7 +167,7 @@ public function testReset(AProtocol $protocol): void $response = $protocol ->reset() ->getResponse(); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $response->getSignature()); + $this->assertEquals(Signature::SUCCESS, $response->signature); } /** @@ -181,7 +182,7 @@ public function testChunking(AProtocol $protocol): void ->run('CREATE (a:Test) RETURN ID(a)') ->pull() ->getResponses(); - $id = iterator_to_array($gen, false)[2]->getContent()[0]; + $id = iterator_to_array($gen, false)[2]->content[0]; $data = []; while (strlen(serialize($data)) < 65535 * 2) { @@ -194,24 +195,10 @@ public function testChunking(AProtocol $protocol): void ->pull() ->getResponses(); $result = iterator_to_array($gen, false); - $this->assertInstanceOf(\Bolt\protocol\v1\structures\Node::class, $result[1]->getContent()[0]); - $this->assertCount(count($data), $result[1]->getContent()[0]->properties()); + $this->assertInstanceOf(\Bolt\protocol\v1\structures\Node::class, $result[1]->content[0]); + $this->assertCount(count($data), $result[1]->content[0]->properties); } $protocol->rollback(); } - - /** - * @depends testHello - */ - public function testServerStateMismatchCallback(AProtocol $protocol): void - { - $protocol->serverState->set(\Bolt\protocol\ServerState::FAILED); - $protocol->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - throw new Exception('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; - - $this->expectException(Exception::class); - iterator_to_array($protocol->run('RETURN 1 as num')->getResponses(), false); - } } diff --git a/tests/PerformanceTest.php b/tests/PerformanceTest.php index 0bda885..e2c8807 100644 --- a/tests/PerformanceTest.php +++ b/tests/PerformanceTest.php @@ -4,6 +4,7 @@ use Bolt\Bolt; use Bolt\connection\Socket; +use Bolt\enum\Signature; use Bolt\protocol\Response; use Bolt\tests\packstream\v1\generators\RandomDataGenerator; @@ -29,10 +30,10 @@ public function test50KRecords(): void $protocol->run('MATCH (n:Test50k) RETURN count(n)')->getResponse(); /** @var Response $response */ $response = $protocol->pull()->getResponse(); - if ($response->getSignature() !== Response::SIGNATURE_RECORD) + if ($response->signature !== Signature::RECORD) $this->markTestSkipped(); $protocol->getResponse(); - if ($response->getContent()[0] > 0) { + if ($response->content[0] > 0) { sleep(60); } else { iterator_to_array($protocol->run('CREATE (n:Test50k)')->pull()->getResponses(), false); @@ -46,13 +47,13 @@ public function test50KRecords(): void ->run('UNWIND $x as x RETURN x', ['x' => $generator]) ->getResponse(); - if ($response->getSignature() !== Response::SIGNATURE_SUCCESS) - $this->markTestIncomplete('[' . $response->getContent()['code'] . '] ' . $response->getContent()['message']); + if ($response->signature !== Signature::SUCCESS) + $this->markTestIncomplete('[' . $response->content['code'] . '] ' . $response->content['message']); $count = 0; /** @var Response $response */ foreach ($protocol->pull()->getResponses() as $response) { - if ($response->getSignature() === Response::SIGNATURE_RECORD) + if ($response->signature === Signature::RECORD) $count++; } diff --git a/tests/connection/ConnectionTest.php b/tests/connection/ConnectionTest.php index 49951cc..a247feb 100644 --- a/tests/connection/ConnectionTest.php +++ b/tests/connection/ConnectionTest.php @@ -3,7 +3,6 @@ namespace Bolt\tests\connection; use Bolt\Bolt; -use Bolt\protocol\Response; use Bolt\tests\ATest; use Bolt\connection\{ IConnection, @@ -11,6 +10,7 @@ StreamSocket }; use Bolt\error\ConnectionTimeoutException; +use Bolt\enum\Signature; /** * Class ConnectionTest @@ -101,7 +101,7 @@ public function testTimeoutRecoverAndReset(string $alias): void ->reset() ->getResponse(); - $this->assertEquals(Response::SIGNATURE_FAILURE, $response->getSignature()); + $this->assertEquals(Signature::FAILURE, $response->signature); $protocol = (new Bolt($conn))->setProtocolVersions($this->getCompatibleBoltVersion())->build(); $this->sayHello($protocol, $GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']); diff --git a/tests/packstream/v1/BytesTest.php b/tests/packstream/v1/BytesTest.php index 052f66d..a954a42 100644 --- a/tests/packstream/v1/BytesTest.php +++ b/tests/packstream/v1/BytesTest.php @@ -42,7 +42,7 @@ public function testBytes(Bytes $arr, AProtocol $protocol) ->getResponses(), false ); - $this->assertEquals($arr, $res[1]->getContent()[0]); + $this->assertEquals($arr, $res[1]->content[0]); } public function providerBytes(): \Generator diff --git a/tests/packstream/v1/PackerTest.php b/tests/packstream/v1/PackerTest.php index 8c76531..b5a9563 100644 --- a/tests/packstream/v1/PackerTest.php +++ b/tests/packstream/v1/PackerTest.php @@ -43,7 +43,7 @@ public function testNull(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } /** @@ -58,7 +58,7 @@ public function testBoolean(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); $res = iterator_to_array( $protocol @@ -67,7 +67,7 @@ public function testBoolean(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } /** @@ -83,7 +83,7 @@ public function testInteger(int $i, AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } public function providerInteger(): \Generator @@ -108,7 +108,7 @@ public function testFloat(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } } @@ -133,7 +133,7 @@ public function testString(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } } @@ -151,7 +151,7 @@ public function testList(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } } @@ -178,7 +178,7 @@ public function testDictionary(AProtocol $protocol): void ->getResponses(), false ); - $this->assertTrue($res[1]->getContent()[0]); + $this->assertTrue($res[1]->content[0]); } } @@ -201,7 +201,7 @@ public function testListGenerator(AProtocol $protocol): void false ); foreach ($data as $i => $value) - $this->assertEquals($value, $result[1 + $i]->getContent()[0]); + $this->assertEquals($value, $result[1 + $i]->content[0]); } /** @@ -222,7 +222,7 @@ public function testDictionaryGenerator(AProtocol $protocol): void ->getResponses(), false ); - $this->assertEquals($data, $result[1]->getContent()[0]); + $this->assertEquals($data, $result[1]->content[0]); } } diff --git a/tests/packstream/v1/UnpackerTest.php b/tests/packstream/v1/UnpackerTest.php index 73a6dd4..55b9b16 100644 --- a/tests/packstream/v1/UnpackerTest.php +++ b/tests/packstream/v1/UnpackerTest.php @@ -5,6 +5,7 @@ use Bolt\Bolt; use Bolt\protocol\{AProtocol, Response}; use Bolt\tests\ATest; +use Bolt\enum\Signature; /** * Class UnpackerTest @@ -44,8 +45,8 @@ public function testNull(AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) - $this->assertNull($response->getContent()[0]); + if ($response->signature == Signature::RECORD) + $this->assertNull($response->content[0]); } } @@ -61,9 +62,9 @@ public function testBoolean(AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { - $this->assertTrue($response->getContent()[0]); - $this->assertFalse($response->getContent()[1]); + if ($response->signature == Signature::RECORD) { + $this->assertTrue($response->content[0]); + $this->assertFalse($response->content[1]); } } } @@ -80,9 +81,9 @@ public function testInteger(AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { + if ($response->signature == Signature::RECORD) { foreach ([-16, 0, 127, -17, -128, 128, 32767, 32768, 2147483647, 2147483648, 9223372036854775807, -129, -32768, -32769, -2147483648, -2147483649, -9223372036854775808] as $i => $value) { - $this->assertEquals($value, $response->getContent()[$i]); + $this->assertEquals($value, $response->content[$i]); } } } @@ -103,8 +104,8 @@ public function testFloat(AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { - $this->assertEqualsWithDelta($num, $response->getContent()[0], 0.000001); + if ($response->signature == Signature::RECORD) { + $this->assertEqualsWithDelta($num, $response->content[0], 0.000001); } } } @@ -123,8 +124,8 @@ public function testString(string $str, AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { - $this->assertEquals($str, $response->getContent()[0]); + if ($response->signature == Signature::RECORD) { + $this->assertEquals($str, $response->content[0]); } } } @@ -156,8 +157,8 @@ public function testList(int $size, AProtocol $protocol): void /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { - $this->assertEquals(range(0, $size), $response->getContent()[0]); + if ($response->signature == Signature::RECORD) { + $this->assertEquals(range(0, $size), $response->content[0]); } } } @@ -181,10 +182,10 @@ public function testDictionary(string $query, int $size, AProtocol $protocol): v /** @var Response $response */ foreach ($gen as $response) { - if ($response->getSignature() == Response::SIGNATURE_RECORD) { - $this->assertCount($size, $response->getContent()[0]); - } elseif ($response->getSignature() == Response::SIGNATURE_FAILURE) { - $this->markTestIncomplete(print_r($response->getContent(), true)); + if ($response->signature == Signature::RECORD) { + $this->assertCount($size, $response->content[0]); + } elseif ($response->signature == Signature::FAILURE) { + $this->markTestIncomplete(print_r($response->content, true)); } } } diff --git a/tests/protocol/ATest.php b/tests/protocol/ATest.php index 1476d27..1f371cf 100644 --- a/tests/protocol/ATest.php +++ b/tests/protocol/ATest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Bolt\connection\AConnection; use Bolt\packstream\v1\Packer; +use Bolt\enum\Signature; /** * Class ATest @@ -109,8 +110,8 @@ protected function setUp(): void protected function checkFailure(Response $response): void { - $this->assertEquals(Response::SIGNATURE_FAILURE, $response->getSignature()); - $this->assertEquals('some error message', $response->getContent()['message']); - $this->assertEquals('Neo.ClientError.Statement.SyntaxError', $response->getContent()['code']); + $this->assertEquals(Signature::FAILURE, $response->signature); + $this->assertEquals('some error message', $response->content['message']); + $this->assertEquals('Neo.ClientError.Statement.SyntaxError', $response->content['code']); } } diff --git a/tests/protocol/V1Test.php b/tests/protocol/V1Test.php index ddaca87..8de674d 100644 --- a/tests/protocol/V1Test.php +++ b/tests/protocol/V1Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; +use Bolt\enum\{ServerState, Signature}; use Bolt\protocol\V1; -use Bolt\packstream\v1\{Packer, Unpacker}; /** * Class V1Test @@ -18,11 +16,8 @@ class V1Test extends ATest { public function test__construct(): V1 { - $cls = new V1(1, $this->mockConnection(), new ServerState()); + $cls = new V1(1, $this->mockConnection()); $this->assertInstanceOf(V1::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -48,17 +43,20 @@ public function testInit(V1 $cls): void '00098870617373776f7264', ]; - $auth = \Bolt\helpers\Auth::basic('user', 'password'); - unset($auth['user_agent']); + $auth = [ + 'scheme' => 'basic', + 'principal' => 'user', + 'credentials' => 'password' + ]; - $cls->serverState->set(ServerState::CONNECTED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->init(\Bolt\helpers\Auth::$defaultUserAgent, $auth)->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::CONNECTED; + $this->assertEquals(Signature::SUCCESS, $cls->init('bolt-php', $auth)->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::CONNECTED); - $response = $cls->init(\Bolt\helpers\Auth::$defaultUserAgent, $auth); + $cls->serverState = ServerState::CONNECTED; + $response = $cls->init('bolt-php', $auth)->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } /** @@ -88,19 +86,19 @@ public function testRun(V1 $cls): void '00 01 a0' ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->run('RETURN 1')->getResponse()->getSignature()); - $this->assertEquals(ServerState::STREAMING, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->run('RETURN 1')->getResponse()->signature); + $this->assertEquals(ServerState::STREAMING, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::READY; $response = $cls->run('not a CQL')->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->run('not a CQL')->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -119,21 +117,21 @@ public function testPullAll(V1 $cls): void '00013f', ]; - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $res = iterator_to_array($cls->pullAll()->getResponses(), false); $this->assertIsArray($res); $this->assertCount(2, $res); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $responses = iterator_to_array($cls->pullAll()->getResponses(), false); $this->checkFailure($responses[0]); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::INTERRUPTED; $responses = iterator_to_array($cls->pullAll()->getResponses(), false); - $this->assertEquals(Response::SIGNATURE_IGNORED, $responses[0]->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $responses[0]->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -151,19 +149,19 @@ public function testDiscardAll(V1 $cls): void '00012f', ]; - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $cls->discardAll()->getResponse(); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $response = $cls->discardAll()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->discardAll()->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -181,11 +179,11 @@ public function testReset(V1 $cls): void ]; $cls->reset()->getResponse(); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $this->assertEquals(ServerState::READY, $cls->serverState); $response = $cls->reset()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } /** @@ -202,13 +200,13 @@ public function testAckFailure(V1 $cls): void '00010e', ]; - $cls->serverState->set(ServerState::FAILED); + $cls->serverState = ServerState::FAILED; $cls->ackFailure()->getResponse(); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::FAILED); + $cls->serverState = ServerState::FAILED; $response = $cls->ackFailure()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } } diff --git a/tests/protocol/V2Test.php b/tests/protocol/V2Test.php index b50f3ff..cb55f05 100644 --- a/tests/protocol/V2Test.php +++ b/tests/protocol/V2Test.php @@ -16,11 +16,8 @@ class V2Test extends ATest { public function test__construct(): V2 { - $cls = new V2(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V2(1, $this->mockConnection()); $this->assertInstanceOf(V2::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } } diff --git a/tests/protocol/V3Test.php b/tests/protocol/V3Test.php index e11c4e7..38dea6b 100644 --- a/tests/protocol/V3Test.php +++ b/tests/protocol/V3Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; use Bolt\protocol\V3; -use Bolt\packstream\v1\{Packer, Unpacker}; +use Bolt\enum\{Signature, ServerState}; /** * Class V3Test @@ -18,11 +16,8 @@ class V3Test extends ATest { public function test__construct(): V3 { - $cls = new V3(1, $this->mockConnection(), new ServerState()); + $cls = new V3(1, $this->mockConnection()); $this->assertInstanceOf(V3::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -49,14 +44,24 @@ public function testHello(V3 $cls): void '00098870617373776f7264', ]; - $cls->serverState->set(ServerState::CONNECTED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->hello(\Bolt\helpers\Auth::basic('user', 'password'))->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); - - $cls->serverState->set(ServerState::CONNECTED); - $response = $cls->hello(\Bolt\helpers\Auth::basic('user', 'password')); + $cls->serverState = ServerState::CONNECTED; + $this->assertEquals(Signature::SUCCESS, $cls->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => 'user', + 'credentials' => 'password', + ])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); + + $cls->serverState = ServerState::CONNECTED; + $response = $cls->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => 'user', + 'credentials' => 'password', + ])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } /** @@ -89,19 +94,19 @@ public function testRun(V3 $cls): void '00 01 a0', ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->run('RETURN 1')->getResponse()->getSignature()); - $this->assertEquals(ServerState::STREAMING, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->run('RETURN 1')->getResponse()->signature); + $this->assertEquals(ServerState::STREAMING, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::READY; $response = $cls->run('not a CQL')->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->run('not a CQL')->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -120,19 +125,19 @@ public function testBegin(V3 $cls): void '00 01 a0', ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->begin()->getResponse()->getSignature()); - $this->assertEquals(ServerState::TX_READY, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->begin()->getResponse()->signature); + $this->assertEquals(ServerState::TX_READY, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::READY; $response = $cls->begin()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->begin()->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -150,19 +155,19 @@ public function testCommit(V3 $cls): void '00 01 12', ]; - $cls->serverState->set(ServerState::TX_READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->commit()->getResponse()->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::TX_READY; + $this->assertEquals(Signature::SUCCESS, $cls->commit()->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::TX_READY); + $cls->serverState = ServerState::TX_READY; $response = $cls->commit()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::TX_READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->commit()->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -180,19 +185,19 @@ public function testRollback(V3 $cls): void '00 01 13', ]; - $cls->serverState->set(ServerState::TX_READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->rollback()->getResponse()->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::TX_READY; + $this->assertEquals(Signature::SUCCESS, $cls->rollback()->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::TX_READY); + $cls->serverState = ServerState::TX_READY; $response = $cls->rollback()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::TX_READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->rollback()->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -207,7 +212,7 @@ public function testGoodbye(V3 $cls): void ]; $cls->goodbye(); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } } diff --git a/tests/protocol/V4Test.php b/tests/protocol/V4Test.php index ad3e21f..c4326b5 100644 --- a/tests/protocol/V4Test.php +++ b/tests/protocol/V4Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; use Bolt\protocol\V4; -use Bolt\packstream\v1\{Packer, Unpacker}; +use Bolt\enum\{Signature, ServerState}; /** * Class V4Test @@ -18,11 +16,8 @@ class V4Test extends ATest { public function test__construct(): V4 { - $cls = new V4(1, $this->mockConnection(), new ServerState()); + $cls = new V4(1, $this->mockConnection()); $this->assertInstanceOf(V4::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -47,21 +42,21 @@ public function testPull(V4 $cls): void '00 01 ff', ]; - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $res = iterator_to_array($cls->pull(['n' => -1, 'qid' => -1])->getResponses(), false); $this->assertIsArray($res); $this->assertCount(2, $res); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $responses = iterator_to_array($cls->pull(['n' => -1, 'qid' => -1])->getResponses(), false); $this->checkFailure($responses[0]); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::INTERRUPTED; $responses = iterator_to_array($cls->pull(['n' => -1, 'qid' => -1])->getResponses(), false); - $this->assertEquals(Response::SIGNATURE_IGNORED, $responses[0]->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $responses[0]->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } /** @@ -84,18 +79,18 @@ public function testDiscard(V4 $cls): void '0001ff', ]; - $cls->serverState->set(ServerState::STREAMING); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->discard(['n' => -1, 'qid' => -1])->getResponse()->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::STREAMING; + $this->assertEquals(Signature::SUCCESS, $cls->discard(['n' => -1, 'qid' => -1])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::STREAMING; $response = $cls->discard(['n' => -1, 'qid' => -1])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::STREAMING); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->discard(['n' => -1, 'qid' => -1])->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } } diff --git a/tests/protocol/V4_1Test.php b/tests/protocol/V4_1Test.php index aa641e9..fc8b8cf 100644 --- a/tests/protocol/V4_1Test.php +++ b/tests/protocol/V4_1Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; use Bolt\protocol\V4_1; -use Bolt\packstream\v1\{Packer, Unpacker}; +use Bolt\enum\{Signature, ServerState}; /** * Class V4_1Test @@ -18,11 +16,8 @@ class V4_1Test extends ATest { public function test__construct(): V4_1 { - $cls = new V4_1(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V4_1(1, $this->mockConnection()); $this->assertInstanceOf(V4_1::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -49,13 +44,23 @@ public function testHello(V4_1 $cls): void '00098870617373776f7264', ]; - $cls->serverState->set(ServerState::CONNECTED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->hello(\Bolt\helpers\Auth::basic('user', 'password'))->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::CONNECTED; + $this->assertEquals(Signature::SUCCESS, $cls->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => 'user', + 'credentials' => 'password', + ])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::CONNECTED); - $response = $cls->hello(\Bolt\helpers\Auth::basic('user', 'password')); + $cls->serverState = ServerState::CONNECTED; + $response = $cls->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => 'user', + 'credentials' => 'password', + ])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } } diff --git a/tests/protocol/V4_2Test.php b/tests/protocol/V4_2Test.php index cbd1e89..0e761db 100644 --- a/tests/protocol/V4_2Test.php +++ b/tests/protocol/V4_2Test.php @@ -16,11 +16,8 @@ class V4_2Test extends ATest { public function test__construct(): V4_2 { - $cls = new V4_2(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V4_2(1, $this->mockConnection()); $this->assertInstanceOf(V4_2::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } diff --git a/tests/protocol/V4_3Test.php b/tests/protocol/V4_3Test.php index a435e7f..3fef831 100644 --- a/tests/protocol/V4_3Test.php +++ b/tests/protocol/V4_3Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; use Bolt\protocol\V4_3; -use Bolt\packstream\v1\{Packer, Unpacker}; +use Bolt\enum\{Signature, ServerState}; /** * Class V4_3Test @@ -18,11 +16,8 @@ class V4_3Test extends ATest { public function test__construct(): V4_3 { - $cls = new V4_3(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V4_3(1, $this->mockConnection()); $this->assertInstanceOf(V4_3::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -46,19 +41,19 @@ public function testRoute(V4_3 $cls): void '0001c0', ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->route(['address' => 'localhost:7687'])->getResponse()->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->route(['address' => 'localhost:7687'])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::READY; $response = $cls->route(['address' => 'localhost:7687'])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->route(['address' => 'localhost:7687'])->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } } diff --git a/tests/protocol/V4_4Test.php b/tests/protocol/V4_4Test.php index 5d3d6e7..9c1e467 100644 --- a/tests/protocol/V4_4Test.php +++ b/tests/protocol/V4_4Test.php @@ -2,10 +2,8 @@ namespace Bolt\tests\protocol; -use Bolt\protocol\Response; -use Bolt\protocol\ServerState; use Bolt\protocol\V4_4; -use Bolt\packstream\v1\{Packer, Unpacker}; +use Bolt\enum\{Signature, ServerState}; /** * Class V4_4Test @@ -18,11 +16,8 @@ class V4_4Test extends ATest { public function test__construct(): V4_4 { - $cls = new V4_4(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V4_4(1, $this->mockConnection()); $this->assertInstanceOf(V4_4::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -48,19 +43,19 @@ public function testRoute(V4_4 $cls): void '0001c0', ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->route(['address' => 'localhost:7687'], [], ['db' => null])->getResponse()->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->route(['address' => 'localhost:7687'], [], ['db' => null])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::READY; $response = $cls->route(['address' => 'localhost:7687'], [], ['db' => null])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::FAILED, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); - $cls->serverState->set(ServerState::READY); + $cls->serverState = ServerState::INTERRUPTED; $response = $cls->route(['address' => 'localhost:7687'], [], ['db' => null])->getResponse(); - $this->assertEquals(Response::SIGNATURE_IGNORED, $response->getSignature()); - $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState->get()); + $this->assertEquals(Signature::IGNORED, $response->signature); + $this->assertEquals(ServerState::INTERRUPTED, $cls->serverState); } } diff --git a/tests/protocol/V5Test.php b/tests/protocol/V5Test.php index a9b2b51..d018ab3 100644 --- a/tests/protocol/V5Test.php +++ b/tests/protocol/V5Test.php @@ -16,11 +16,8 @@ class V5Test extends ATest { public function test__construct(): V5 { - $cls = new V5(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V5(1, $this->mockConnection()); $this->assertInstanceOf(V5::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } } diff --git a/tests/protocol/V5_1Test.php b/tests/protocol/V5_1Test.php index d43c5ba..c5d5395 100644 --- a/tests/protocol/V5_1Test.php +++ b/tests/protocol/V5_1Test.php @@ -1,8 +1,9 @@ mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V5_1(1, $this->mockConnection()); $this->assertInstanceOf(V5_1::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -40,14 +38,14 @@ public function testHello(V5_1 $cls): void '000988626f6c742d706870', ]; - $cls->serverState->set(ServerState::CONNECTED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->hello()->getSignature()); - $this->assertEquals(ServerState::UNAUTHENTICATED, $cls->serverState->get()); + $cls->serverState = ServerState::NEGOTIATION; + $this->assertEquals(Signature::SUCCESS, $cls->hello()->getResponse()->signature); + $this->assertEquals(ServerState::AUTHENTICATION, $cls->serverState); - $cls->serverState->set(ServerState::CONNECTED); - $response = $cls->hello(); + $cls->serverState = ServerState::NEGOTIATION; + $response = $cls->hello()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } /** @@ -71,22 +69,22 @@ public function testLogon(V5_1 $cls): void '00098870617373776f7264', ]; - $cls->serverState->set(ServerState::UNAUTHENTICATED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->logon([ + $cls->serverState = ServerState::AUTHENTICATION; + $this->assertEquals(Signature::SUCCESS, $cls->logon([ 'scheme' => 'basic', 'principal' => 'user', 'credentials' => 'password' - ])->getSignature()); - $this->assertEquals(ServerState::READY, $cls->serverState->get()); + ])->getResponse()->signature); + $this->assertEquals(ServerState::READY, $cls->serverState); - $cls->serverState->set(ServerState::UNAUTHENTICATED); + $cls->serverState = ServerState::AUTHENTICATION; $response = $cls->logon([ 'scheme' => 'basic', 'principal' => 'user', 'credentials' => 'password' - ]); + ])->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } /** @@ -103,13 +101,13 @@ public function testLogoff(V5_1 $cls): void '00016b', ]; - $cls->serverState->set(ServerState::READY); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->logoff()->getSignature()); - $this->assertEquals(ServerState::UNAUTHENTICATED, $cls->serverState->get()); + $cls->serverState = ServerState::READY; + $this->assertEquals(Signature::SUCCESS, $cls->logoff()->getResponse()->signature); + $this->assertEquals(ServerState::AUTHENTICATION, $cls->serverState); - $cls->serverState->set(ServerState::READY); - $response = $cls->logoff(); + $cls->serverState = ServerState::READY; + $response = $cls->logoff()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::FAILED, $cls->serverState); } } diff --git a/tests/protocol/V5_2Test.php b/tests/protocol/V5_2Test.php index 1f859d5..fb23fb5 100644 --- a/tests/protocol/V5_2Test.php +++ b/tests/protocol/V5_2Test.php @@ -13,11 +13,8 @@ class V5_2Test extends \Bolt\tests\protocol\ATest { public function test__construct(): V5_2 { - $cls = new V5_2(1, $this->mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V5_2(1, $this->mockConnection()); $this->assertInstanceOf(V5_2::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } } diff --git a/tests/protocol/V5_3Test.php b/tests/protocol/V5_3Test.php index fec469f..c4bb26a 100644 --- a/tests/protocol/V5_3Test.php +++ b/tests/protocol/V5_3Test.php @@ -1,8 +1,9 @@ mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V5_3(1, $this->mockConnection()); $this->assertInstanceOf(V5_3::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -33,13 +31,13 @@ public function testHello(V5_3 $cls): void [0x7F, (object)['message' => 'some error message', 'code' => 'Neo.ClientError.Statement.SyntaxError']] ]; - $cls->serverState->set(ServerState::CONNECTED); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $cls->hello()->getSignature()); - $this->assertEquals(ServerState::UNAUTHENTICATED, $cls->serverState->get()); + $cls->serverState = ServerState::NEGOTIATION; + $this->assertEquals(Signature::SUCCESS, $cls->hello()->getResponse()->signature); + $this->assertEquals(ServerState::AUTHENTICATION, $cls->serverState); - $cls->serverState->set(ServerState::CONNECTED); - $response = $cls->hello(); + $cls->serverState = ServerState::NEGOTIATION; + $response = $cls->hello()->getResponse(); $this->checkFailure($response); - $this->assertEquals(ServerState::DEFUNCT, $cls->serverState->get()); + $this->assertEquals(ServerState::DEFUNCT, $cls->serverState); } } diff --git a/tests/protocol/V5_4Test.php b/tests/protocol/V5_4Test.php index 2fed86e..0f4ca40 100644 --- a/tests/protocol/V5_4Test.php +++ b/tests/protocol/V5_4Test.php @@ -1,7 +1,5 @@ mockConnection(), new \Bolt\protocol\ServerState()); + $cls = new V5_4(1, $this->mockConnection()); $this->assertInstanceOf(V5_4::class, $cls); - $cls->serverState->expectedServerStateMismatchCallback = function (string $current, array $expected) { - $this->markTestIncomplete('Server in ' . $current . ' state. Expected ' . implode(' or ', $expected) . '.'); - }; return $cls; } @@ -29,5 +24,6 @@ public function test__construct(): V5_4 public function testTelemetry(V5_4 $cls): void { // todo + $this->markTestSkipped(); } } diff --git a/tests/structures/v1/DateTimeTrait.php b/tests/structures/v1/DateTimeTrait.php index dbbdc90..7e37bc5 100644 --- a/tests/structures/v1/DateTimeTrait.php +++ b/tests/structures/v1/DateTimeTrait.php @@ -30,7 +30,7 @@ public function testDateTime(int $timestamp, string $timezone, AProtocol|V1|V4_3 ->getResponses(), false ); - $dateTimeStructure = $res[1]->getContent()[0]; + $dateTimeStructure = $res[1]->content[0]; $this->assertInstanceOf($this->expectedDateTimeClass, $dateTimeStructure); $this->assertEquals($datetime, (string)$dateTimeStructure, 'unpack ' . $datetime . ' != ' . $dateTimeStructure); @@ -48,6 +48,6 @@ public function testDateTime(int $timestamp, string $timezone, AProtocol|V1|V4_3 // neo4j returns fraction of seconds not padded with zeros ... zero timezone offset returns as Z $datetime = preg_replace(["/\.?0+(.\d{2}:\d{2})$/", "/\+00:00$/"], ['$1', 'Z'], $datetime); - $this->assertEquals($datetime, $res[1]->getContent()[0], 'pack ' . $datetime . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($datetime, $res[1]->content[0], 'pack ' . $datetime . ' != ' . $res[1]->content[0]); } } diff --git a/tests/structures/v1/DateTimeZoneIdTrait.php b/tests/structures/v1/DateTimeZoneIdTrait.php index 1696c47..0593fb0 100644 --- a/tests/structures/v1/DateTimeZoneIdTrait.php +++ b/tests/structures/v1/DateTimeZoneIdTrait.php @@ -9,6 +9,7 @@ V4_3, V5 }; +use Bolt\enum\Signature; use Exception; trait DateTimeZoneIdTrait @@ -37,12 +38,12 @@ public function testDateTimeZoneId(int $timestamp, string $timezone, AProtocol|V /** @var Response $response */ foreach ($res as $response) { - if ($response->getSignature() == Response::SIGNATURE_FAILURE) { - throw new Exception($response->getContent()['message']); + if ($response->signature == Signature::FAILURE) { + throw new Exception($response->content['message']); } } - $dateTimeZoneIdStructure = $res[1]->getContent()[0]; + $dateTimeZoneIdStructure = $res[1]->content[0]; $this->assertInstanceOf($this->expectedDateTimeZoneIdClass, $dateTimeZoneIdStructure); $this->assertEquals($datetime, (string)$dateTimeZoneIdStructure, 'unpack ' . $datetime . ' != ' . $dateTimeZoneIdStructure); @@ -60,7 +61,7 @@ public function testDateTimeZoneId(int $timestamp, string $timezone, AProtocol|V // neo4j returns fraction of seconds not padded with zeros ... also contains timezone offset before timezone id $datetime = preg_replace("/\.?0+\[/", '[', $datetime); - $dateTimeZoneIdStructure = preg_replace("/([+\-]\d{2}:\d{2}|Z)\[/", '[', $res[1]->getContent()[0]); + $dateTimeZoneIdStructure = preg_replace("/([+\-]\d{2}:\d{2}|Z)\[/", '[', $res[1]->content[0]); $this->assertEquals($datetime, $dateTimeZoneIdStructure, 'pack ' . $datetime . ' != ' . $dateTimeZoneIdStructure); } catch (Exception $e) { if (str_starts_with($e->getMessage(), 'Invalid value for TimeZone: Text \'' . $timezone . '\'')) { diff --git a/tests/structures/v1/StructuresTest.php b/tests/structures/v1/StructuresTest.php index 6926535..874684d 100644 --- a/tests/structures/v1/StructuresTest.php +++ b/tests/structures/v1/StructuresTest.php @@ -5,7 +5,6 @@ use Bolt\Bolt; use Bolt\protocol\{ AProtocol, - Response, V3, V4_2, V4_3, @@ -26,6 +25,7 @@ Time, UnboundRelationship }; +use Bolt\enum\Signature; /** * Class StructuresTest @@ -49,7 +49,12 @@ public function testInit(): AProtocol|V4_4|V4_3|V4_2|V3 $protocol = $bolt->build(); $this->assertInstanceOf(AProtocol::class, $protocol); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $protocol->hello(\Bolt\helpers\Auth::basic($GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']))->getSignature()); + $this->assertEquals(Signature::SUCCESS, $protocol->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => $GLOBALS['NEO_USER'], + 'credentials' => $GLOBALS['NEO_PASS'], + ])->getResponse()->signature); return $protocol; } @@ -72,7 +77,7 @@ public function testDate(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $protocol): ->getResponses(), false ); - $dateStructure = $res[1]->getContent()[0]; + $dateStructure = $res[1]->content[0]; $this->assertInstanceOf(Date::class, $dateStructure); $this->assertEquals($date, (string)$dateStructure, 'unpack ' . $date . ' != ' . $dateStructure); @@ -87,7 +92,7 @@ public function testDate(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $protocol): ->getResponses(), false ); - $this->assertEquals($date, $res[1]->getContent()[0], 'pack ' . $date . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($date, $res[1]->content[0], 'pack ' . $date . ' != ' . $res[1]->content[0]); } private string $expectedDateTimeClass = DateTime::class; @@ -110,7 +115,7 @@ public function testDuration(string $duration, AProtocol|V4_4|V4_3|V4_2|V3 $prot ->getResponses(), false ); - $durationStructure = $res[1]->getContent()[0]; + $durationStructure = $res[1]->content[0]; $this->assertInstanceOf(Duration::class, $durationStructure); $this->assertEquals($duration, (string)$durationStructure, 'unpack ' . $duration . ' != ' . $durationStructure); @@ -126,7 +131,7 @@ public function testDuration(string $duration, AProtocol|V4_4|V4_3|V4_2|V3 $prot false ); - $this->assertEquals($duration, $res[1]->getContent()[0], 'pack ' . $duration . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($duration, $res[1]->content[0], 'pack ' . $duration . ' != ' . $res[1]->content[0]); } public function durationProvider(): \Generator @@ -163,7 +168,7 @@ public function testLocalDateTime(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $p ->getResponses(), false ); - $localDateTimeStructure = $res[1]->getContent()[0]; + $localDateTimeStructure = $res[1]->content[0]; $this->assertInstanceOf(LocalDateTime::class, $localDateTimeStructure); $this->assertEquals($datetime, (string)$localDateTimeStructure, 'unpack ' . $datetime . ' != ' . $localDateTimeStructure); @@ -179,7 +184,7 @@ public function testLocalDateTime(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $p false ); $datetime = rtrim($datetime, '.0'); - $this->assertEquals($datetime, $res[1]->getContent()[0], 'pack ' . $datetime . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($datetime, $res[1]->content[0], 'pack ' . $datetime . ' != ' . $res[1]->content[0]); } /** @@ -202,7 +207,7 @@ public function testLocalTime(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $proto ->getResponses(), false ); - $localTimeStructure = $res[1]->getContent()[0]; + $localTimeStructure = $res[1]->content[0]; $this->assertInstanceOf(LocalTime::class, $localTimeStructure); $this->assertEquals($time, (string)$localTimeStructure, 'unpack ' . $time . ' != ' . $localTimeStructure); @@ -218,7 +223,7 @@ public function testLocalTime(int $timestamp, AProtocol|V4_4|V4_3|V4_2|V3 $proto false ); $time = rtrim($time, '.0'); - $this->assertEquals($time, $res[1]->getContent()[0], 'pack ' . $time . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($time, $res[1]->content[0], 'pack ' . $time . ' != ' . $res[1]->content[0]); } /** @@ -236,11 +241,11 @@ public function testNode(AProtocol|V4_4|V4_3|V4_2|V3 $protocol): void ->getResponses(), false ); - $this->assertInstanceOf(Node::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Node::class, $res[1]->content[0]); - $this->assertEquals($res[1]->getContent()[1], $res[1]->getContent()[0]->id()); - $this->assertEquals(['Test'], $res[1]->getContent()[0]->labels()); - $this->assertEquals(['param1' => 123], $res[1]->getContent()[0]->properties()); + $this->assertEquals($res[1]->content[1], $res[1]->content[0]->id); + $this->assertEquals(['Test'], $res[1]->content[0]->labels); + $this->assertEquals(['param1' => 123], $res[1]->content[0]->properties); //pack not supported @@ -262,14 +267,14 @@ public function testPath(AProtocol|V4_4|V4_3|V4_2|V3 $protocol): void ->getResponses(), false ); - $this->assertInstanceOf(Path::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Path::class, $res[1]->content[0]); - foreach ($res[1]->getContent()[0]->rels() as $rel) { + foreach ($res[1]->content[0]->rels as $rel) { $this->assertInstanceOf(UnboundRelationship::class, $rel); - $this->assertEquals($res[1]->getContent()[1], $rel->id()); - $this->assertEquals('HAS', $rel->type()); - $this->assertEquals(['param1' => 123], $rel->properties()); + $this->assertEquals($res[1]->content[1], $rel->id); + $this->assertEquals('HAS', $rel->type); + $this->assertEquals(['param1' => 123], $rel->properties); } //pack not supported @@ -290,19 +295,19 @@ public function testPoint2D(AProtocol|V4_4|V4_3|V4_2|V3 $protocol): void ->getResponses(), false ); - $this->assertInstanceOf(Point2D::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Point2D::class, $res[1]->content[0]); //pack $res = iterator_to_array( $protocol ->run('RETURN toString($p)', [ - 'p' => $res[1]->getContent()[0] + 'p' => $res[1]->content[0] ], ['mode' => 'r']) ->pull() ->getResponses(), false ); - $this->assertStringStartsWith('point(', $res[1]->getContent()[0]); + $this->assertStringStartsWith('point(', $res[1]->content[0]); } /** @@ -318,19 +323,19 @@ public function testPoint3D(AProtocol|V4_4|V4_3|V4_2|V3 $protocol): void ->getResponses(), false ); - $this->assertInstanceOf(Point3D::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Point3D::class, $res[1]->content[0]); //pack $res = iterator_to_array( $protocol ->run('RETURN toString($p)', [ - 'p' => $res[1]->getContent()[0] + 'p' => $res[1]->content[0] ], ['mode' => 'r']) ->pull() ->getResponses(), false ); - $this->assertStringStartsWith('point(', $res[1]->getContent()[0]); + $this->assertStringStartsWith('point(', $res[1]->content[0]); } /** @@ -348,13 +353,13 @@ public function testRelationship(AProtocol|V4_4|V4_3|V4_2|V3 $protocol): void ->getResponses(), false ); - $this->assertInstanceOf(Relationship::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Relationship::class, $res[1]->content[0]); - $this->assertEquals($res[1]->getContent()[1], $res[1]->getContent()[0]->id()); - $this->assertEquals('HAS', $res[1]->getContent()[0]->type()); - $this->assertEquals(['param1' => 123], $res[1]->getContent()[0]->properties()); - $this->assertEquals($res[1]->getContent()[2], $res[1]->getContent()[0]->startNodeId()); - $this->assertEquals($res[1]->getContent()[3], $res[1]->getContent()[0]->endNodeId()); + $this->assertEquals($res[1]->content[1], $res[1]->content[0]->id); + $this->assertEquals('HAS', $res[1]->content[0]->type); + $this->assertEquals(['param1' => 123], $res[1]->content[0]->properties); + $this->assertEquals($res[1]->content[2], $res[1]->content[0]->startNodeId); + $this->assertEquals($res[1]->content[3], $res[1]->content[0]->endNodeId); //pack not supported @@ -381,7 +386,7 @@ public function testTime(int $timestamp, string $timezone, AProtocol|V4_4|V4_3|V ->getResponses(), false ); - $timeStructure = $res[1]->getContent()[0]; + $timeStructure = $res[1]->content[0]; $this->assertInstanceOf(Time::class, $timeStructure); $this->assertEquals($time, (string)$timeStructure, 'unpack ' . $time . ' != ' . $timeStructure); @@ -399,6 +404,6 @@ public function testTime(int $timestamp, string $timezone, AProtocol|V4_4|V4_3|V // neo4j returns fraction of seconds not padded with zeros ... zero timezone offset returns as Z $time = preg_replace(["/\.?0+(.\d{2}:\d{2})$/", "/\+00:00$/"], ['$1', 'Z'], $time); - $this->assertEquals($time, $res[1]->getContent()[0], 'pack ' . $time . ' != ' . $res[1]->getContent()[0]); + $this->assertEquals($time, $res[1]->content[0], 'pack ' . $time . ' != ' . $res[1]->content[0]); } } diff --git a/tests/structures/v4_3/StructuresTest.php b/tests/structures/v4_3/StructuresTest.php index 48a0035..b8afd62 100644 --- a/tests/structures/v4_3/StructuresTest.php +++ b/tests/structures/v4_3/StructuresTest.php @@ -17,6 +17,7 @@ DateTimeTrait, DateTimeZoneIdTrait }; +use Bolt\enum\Signature; /** * Class StructuresTest @@ -40,17 +41,21 @@ public function testInit(): AProtocol|V4_4|V4_3 $protocol = $bolt->build(); $this->assertInstanceOf(AProtocol::class, $protocol); - $extra = \Bolt\helpers\Auth::basic($GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']); - $extra['patch_bolt'] = ['utc']; /** @var Response $helloResponse */ - $helloResponse = $protocol->hello($extra); - $this->assertEquals(Response::SIGNATURE_SUCCESS, $helloResponse->getSignature()); + $helloResponse = $protocol->hello([ + 'user_agent' => 'bolt-php', + 'scheme' => 'basic', + 'principal' => $GLOBALS['NEO_USER'], + 'credentials' => $GLOBALS['NEO_PASS'], + 'patch_bolt' => ['utc'] + ])->getResponse(); + $this->assertEquals(Signature::SUCCESS, $helloResponse->signature); if (version_compare($protocol->getVersion(), '5', '>=') || version_compare($protocol->getVersion(), '4.3', '<')) { $this->markTestSkipped('You are not running Neo4j version with patch_bolt support.'); } - if (($helloResponse->getContent()['patch_bolt'] ?? null) !== ['utc']) { + if (($helloResponse->content['patch_bolt'] ?? null) !== ['utc']) { $this->markTestSkipped('Currently used Neo4j version does not support patch_bolt.'); } diff --git a/tests/structures/v5/StructuresTest.php b/tests/structures/v5/StructuresTest.php index c1ca21f..762be31 100644 --- a/tests/structures/v5/StructuresTest.php +++ b/tests/structures/v5/StructuresTest.php @@ -66,12 +66,12 @@ public function testNode(AProtocol|V4_3|V4_4|V5|V5_1 $protocol) ->getResponses(), false ); - $this->assertInstanceOf(Node::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Node::class, $res[1]->content[0]); - $this->assertEquals($res[1]->getContent()[1], $res[1]->getContent()[0]->id()); - $this->assertEquals($res[1]->getContent()[2], $res[1]->getContent()[0]->element_id()); - $this->assertEquals(['Test'], $res[1]->getContent()[0]->labels()); - $this->assertEquals(['param1' => 123], $res[1]->getContent()[0]->properties()); + $this->assertEquals($res[1]->content[1], $res[1]->content[0]->id); + $this->assertEquals($res[1]->content[2], $res[1]->content[0]->element_id); + $this->assertEquals(['Test'], $res[1]->content[0]->labels); + $this->assertEquals(['param1' => 123], $res[1]->content[0]->properties); //pack not supported @@ -93,15 +93,15 @@ public function testPath(AProtocol|V4_3|V4_4|V5|V5_1 $protocol) ->getResponses(), false ); - $this->assertInstanceOf(Path::class, $res[1]->getContent()[0]); + $this->assertInstanceOf(Path::class, $res[1]->content[0]); - foreach ($res[1]->getContent()[0]->rels() as $rel) { + foreach ($res[1]->content[0]->rels as $rel) { $this->assertInstanceOf(UnboundRelationship::class, $rel); - $this->assertEquals($res[1]->getContent()[1], $rel->id()); - $this->assertEquals($res[1]->getContent()[2], $rel->element_id()); - $this->assertEquals('HAS', $rel->type()); - $this->assertEquals(['param1' => 123], $rel->properties()); + $this->assertEquals($res[1]->content[1], $rel->id); + $this->assertEquals($res[1]->content[2], $rel->element_id); + $this->assertEquals('HAS', $rel->type); + $this->assertEquals(['param1' => 123], $rel->properties); } //pack not supported @@ -124,16 +124,16 @@ public function testRelationship(AProtocol|V4_3|V4_4|V5|V5_1 $protocol) ->getResponses(), false ); - $this->assertInstanceOf(Relationship::class, $res[1]->getContent()[0]); - - $this->assertEquals($res[1]->getContent()[1], $res[1]->getContent()[0]->id()); - $this->assertEquals($res[1]->getContent()[2], $res[1]->getContent()[0]->element_id()); - $this->assertEquals('HAS', $res[1]->getContent()[0]->type()); - $this->assertEquals(['param1' => 123], $res[1]->getContent()[0]->properties()); - $this->assertEquals($res[1]->getContent()[3], $res[1]->getContent()[0]->startNodeId()); - $this->assertEquals($res[1]->getContent()[4], $res[1]->getContent()[0]->endNodeId()); - $this->assertEquals($res[1]->getContent()[5], $res[1]->getContent()[0]->start_node_element_id()); - $this->assertEquals($res[1]->getContent()[6], $res[1]->getContent()[0]->end_node_element_id()); + $this->assertInstanceOf(Relationship::class, $res[1]->content[0]); + + $this->assertEquals($res[1]->content[1], $res[1]->content[0]->id); + $this->assertEquals($res[1]->content[2], $res[1]->content[0]->element_id); + $this->assertEquals('HAS', $res[1]->content[0]->type); + $this->assertEquals(['param1' => 123], $res[1]->content[0]->properties); + $this->assertEquals($res[1]->content[3], $res[1]->content[0]->startNodeId); + $this->assertEquals($res[1]->content[4], $res[1]->content[0]->endNodeId); + $this->assertEquals($res[1]->content[5], $res[1]->content[0]->start_node_element_id); + $this->assertEquals($res[1]->content[6], $res[1]->content[0]->end_node_element_id); //pack not supported