├── .env.example
├── Dockerfile
├── LICENSE
├── README.md
├── composer.json
├── docker-compose-neo4j-4.yml
├── docker-compose.yml
├── out
└── .gitignore
├── phpunit.coverage.xml.dist
├── psalm.xml
├── rector.php
├── src
├── Authentication
│ ├── Authenticate.php
│ ├── BasicAuth.php
│ ├── KerberosAuth.php
│ ├── NoAuth.php
│ └── OpenIDConnectAuth.php
├── Basic
│ ├── Client.php
│ ├── Driver.php
│ ├── Session.php
│ └── UnmanagedTransaction.php
├── Bolt
│ ├── BoltConnection.php
│ ├── BoltDriver.php
│ ├── BoltMessageFactory.php
│ ├── BoltResult.php
│ ├── BoltUnmanagedTransaction.php
│ ├── Connection.php
│ ├── ConnectionPool.php
│ ├── Messages
│ │ ├── BoltBeginMessage.php
│ │ ├── BoltCommitMessage.php
│ │ ├── BoltDiscardMessage.php
│ │ ├── BoltGoodbyeMessage.php
│ │ ├── BoltHelloMessage.php
│ │ ├── BoltLogoffMessage.php
│ │ ├── BoltLogonMessage.php
│ │ ├── BoltPullMessage.php
│ │ ├── BoltResetMessage.php
│ │ ├── BoltRollbackMessage.php
│ │ └── BoltRunMessage.php
│ ├── ProtocolFactory.php
│ ├── Session.php
│ ├── SocketConnectionFactory.php
│ ├── SslConfigurationFactory.php
│ ├── StreamConnectionFactory.php
│ ├── SystemWideConnectionFactory.php
│ └── UriConfiguration.php
├── BoltFactory.php
├── Client.php
├── ClientBuilder.php
├── Common
│ ├── Cache.php
│ ├── ConnectionConfiguration.php
│ ├── DNSAddressResolver.php
│ ├── DriverSetupManager.php
│ ├── GeneratorHelper.php
│ ├── Neo4jLogger.php
│ ├── Resolvable.php
│ ├── ResponseHelper.php
│ ├── SemaphoreFactory.php
│ ├── SingleThreadedSemaphore.php
│ ├── SysVSemaphore.php
│ ├── TransactionHelper.php
│ └── Uri.php
├── Contracts
│ ├── AddressResolverInterface.php
│ ├── AuthenticateInterface.php
│ ├── BasicConnectionFactoryInterface.php
│ ├── BoltConvertibleInterface.php
│ ├── BoltMessage.php
│ ├── ClientInterface.php
│ ├── ConnectionInterface.php
│ ├── ConnectionPoolInterface.php
│ ├── CypherSequence.php
│ ├── DriverInterface.php
│ ├── HasPropertiesInterface.php
│ ├── PointInterface.php
│ ├── SemaphoreFactoryInterface.php
│ ├── SemaphoreInterface.php
│ ├── SessionInterface.php
│ ├── TransactionInterface.php
│ └── UnmanagedTransactionInterface.php
├── Databags
│ ├── Bookmark.php
│ ├── BookmarkHolder.php
│ ├── ConnectionRequestData.php
│ ├── DatabaseInfo.php
│ ├── DriverConfiguration.php
│ ├── DriverSetup.php
│ ├── Neo4jError.php
│ ├── Notification.php
│ ├── Pair.php
│ ├── Plan.php
│ ├── PlanArguments.php
│ ├── Position.php
│ ├── ProfiledQueryPlan.php
│ ├── ResultSummary.php
│ ├── ServerInfo.php
│ ├── SessionConfiguration.php
│ ├── SslConfiguration.php
│ ├── Statement.php
│ ├── SummarizedResult.php
│ ├── SummaryCounters.php
│ └── TransactionConfiguration.php
├── DriverFactory.php
├── Enum
│ ├── AccessMode.php
│ ├── ConnectionProtocol.php
│ ├── QueryTypeEnum.php
│ ├── RoutingRoles.php
│ ├── SslMode.php
│ └── TransactionState.php
├── Exception
│ ├── ClientException.php
│ ├── ConnectionPoolException.php
│ ├── InvalidCacheArgumentException.php
│ ├── Neo4jException.php
│ ├── PropertyDoesNotExistException.php
│ ├── RuntimeTypeException.php
│ └── UnsupportedScheme.php
├── Formatter
│ ├── Specialised
│ │ └── BoltOGMTranslator.php
│ └── SummarizedResultFormatter.php
├── Neo4j
│ ├── Neo4jConnectionPool.php
│ ├── Neo4jDriver.php
│ └── RoutingTable.php
├── ParameterHelper.php
├── TypeCaster.php
└── Types
│ ├── Abstract3DPoint.php
│ ├── AbstractCypherObject.php
│ ├── AbstractPoint.php
│ ├── AbstractPropertyObject.php
│ ├── Cartesian3DPoint.php
│ ├── CartesianPoint.php
│ ├── CypherList.php
│ ├── CypherMap.php
│ ├── CypherSequenceTrait.php
│ ├── Date.php
│ ├── DateTime.php
│ ├── DateTimeZoneId.php
│ ├── Duration.php
│ ├── LocalDateTime.php
│ ├── LocalTime.php
│ ├── Node.php
│ ├── Path.php
│ ├── Relationship.php
│ ├── Time.php
│ ├── UnboundRelationship.php
│ ├── WGS843DPoint.php
│ └── WGS84Point.php
└── testkit-backend
├── blacklist.php
├── features.php
├── index.php
├── register.php
├── src
├── Backend.php
├── Contracts
│ ├── RequestHandlerInterface.php
│ └── TestkitResponseInterface.php
├── Handlers
│ ├── AbstractRunner.php
│ ├── CheckMultiDBSupport.php
│ ├── DomainNameResolutionCompleted.php
│ ├── DriverClose.php
│ ├── ForcedRoutingTableUpdate.php
│ ├── GetFeatures.php
│ ├── GetRoutingTable.php
│ ├── NewDriver.php
│ ├── NewSession.php
│ ├── ResolverResolutionCompleted.php
│ ├── ResultConsume.php
│ ├── ResultNext.php
│ ├── ResultSingle.php
│ ├── RetryableNegative.php
│ ├── RetryablePositive.php
│ ├── SessionBeginTransaction.php
│ ├── SessionClose.php
│ ├── SessionLastBookmarks.php
│ ├── SessionReadTransaction.php
│ ├── SessionRun.php
│ ├── SessionWriteTransaction.php
│ ├── StartTest.php
│ ├── TransactionCommit.php
│ ├── TransactionRollback.php
│ ├── TransactionRun.php
│ └── VerifyConnectivity.php
├── MainRepository.php
├── Request.php
├── RequestFactory.php
├── Requests
│ ├── AuthorizationTokenRequest.php
│ ├── CheckMultiDBSupportRequest.php
│ ├── DomainNameResolutionCompletedRequest.php
│ ├── DriverCloseRequest.php
│ ├── ForcedRoutingTableUpdateRequest.php
│ ├── GetFeaturesRequest.php
│ ├── GetRoutingTableRequest.php
│ ├── NewDriverRequest.php
│ ├── NewSessionRequest.php
│ ├── ResolverResolutionCompletedRequest.php
│ ├── ResultConsumeRequest.php
│ ├── ResultNextRequest.php
│ ├── ResultSingleRequest.php
│ ├── RetryableNegativeRequest.php
│ ├── RetryablePositiveRequest.php
│ ├── SessionBeginTransactionRequest.php
│ ├── SessionCloseRequest.php
│ ├── SessionLastBookmarksRequest.php
│ ├── SessionReadTransactionRequest.php
│ ├── SessionRunRequest.php
│ ├── SessionWriteTransactionRequest.php
│ ├── StartTestRequest.php
│ ├── TransactionCommitRequest.php
│ ├── TransactionRollbackRequest.php
│ ├── TransactionRunRequest.php
│ └── VerifyConnectivityRequest.php
├── Responses
│ ├── BackendErrorResponse.php
│ ├── BookmarksResponse.php
│ ├── DomainNameResolutionRequiredResponse.php
│ ├── DriverErrorResponse.php
│ ├── DriverResponse.php
│ ├── FeatureListResponse.php
│ ├── FrontendErrorResponse.php
│ ├── MultiDBSupportResponse.php
│ ├── NullRecordResponse.php
│ ├── RecordResponse.php
│ ├── ResolverResolutionRequiredResponse.php
│ ├── ResultResponse.php
│ ├── RetryableDoneResponse.php
│ ├── RetryableTryResponse.php
│ ├── RoutingTableResponse.php
│ ├── RunTestResponse.php
│ ├── SessionResponse.php
│ ├── SkipTestResponse.php
│ ├── SummaryResponse.php
│ ├── TransactionResponse.php
│ └── Types
│ │ ├── CypherNode.php
│ │ ├── CypherObject.php
│ │ ├── CypherPath.php
│ │ └── CypherRelationship.php
└── Socket.php
└── testkit.sh
/.env.example:
--------------------------------------------------------------------------------
1 | PHP_VERSION=8.1
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG PHP_VERSION
2 |
3 | FROM php:${PHP_VERSION}-cli
4 | RUN apt-get update \
5 | && apt-get install -y \
6 | libzip-dev \
7 | unzip \
8 | git \
9 | wget \
10 | && docker-php-ext-install -j$(nproc) bcmath sockets \
11 | && wget https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 \
12 | && mv test-reporter-latest-linux-amd64 /usr/bin/cc-test-reporter \
13 | && chmod +x /usr/bin/cc-test-reporter \
14 | && pecl install xdebug \
15 | && docker-php-ext-enable xdebug && \
16 | curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
17 |
18 | WORKDIR /opt/project
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2020 laudis
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/out/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/phpunit.coverage.xml.dist:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ./tests
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | src
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/psalm.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/rector.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use Rector\Config\RectorConfig;
15 | use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
16 |
17 | return RectorConfig::configure()
18 | ->withPaths([
19 | __DIR__.'/src',
20 | __DIR__.'/tests',
21 | ])
22 | ->withPhpSets(php81: true)
23 | ->withRules([
24 | AddVoidReturnTypeWhereNoReturnRector::class,
25 | ]);
26 |
--------------------------------------------------------------------------------
/src/Basic/Driver.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Basic;
15 |
16 | use Laudis\Neo4j\Contracts\AuthenticateInterface;
17 | use Laudis\Neo4j\Contracts\DriverInterface;
18 | use Laudis\Neo4j\Databags\DriverConfiguration;
19 | use Laudis\Neo4j\Databags\SessionConfiguration;
20 | use Laudis\Neo4j\DriverFactory;
21 | use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
22 | use Psr\Http\Message\UriInterface;
23 |
24 | final class Driver implements DriverInterface
25 | {
26 | /**
27 | * @psalm-external-mutation-free
28 | */
29 | public function __construct(
30 | private readonly DriverInterface $driver,
31 | ) {
32 | }
33 |
34 | /**
35 | * @psalm-mutation-free
36 | */
37 | public function createSession(?SessionConfiguration $config = null): Session
38 | {
39 | return new Session($this->driver->createSession($config));
40 | }
41 |
42 | public function verifyConnectivity(?SessionConfiguration $config = null): bool
43 | {
44 | return $this->driver->verifyConnectivity($config);
45 | }
46 |
47 | public static function create(string|UriInterface $uri, ?DriverConfiguration $configuration = null, ?AuthenticateInterface $authenticate = null): self
48 | {
49 | $driver = DriverFactory::create($uri, $configuration, $authenticate, SummarizedResultFormatter::create());
50 |
51 | return new self($driver);
52 | }
53 |
54 | public function closeConnections(): void
55 | {
56 | $this->driver->closeConnections();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Basic/UnmanagedTransaction.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Basic;
15 |
16 | use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface;
17 | use Laudis\Neo4j\Databags\Statement;
18 | use Laudis\Neo4j\Databags\SummarizedResult;
19 | use Laudis\Neo4j\Types\CypherList;
20 |
21 | final class UnmanagedTransaction implements UnmanagedTransactionInterface
22 | {
23 | public function __construct(
24 | private readonly UnmanagedTransactionInterface $tsx,
25 | ) {
26 | }
27 |
28 | /**
29 | * @param iterable $parameters
30 | */
31 | public function run(string $statement, iterable $parameters = []): SummarizedResult
32 | {
33 | return $this->tsx->run($statement, $parameters);
34 | }
35 |
36 | public function runStatement(Statement $statement): SummarizedResult
37 | {
38 | return $this->tsx->runStatement($statement);
39 | }
40 |
41 | /**
42 | * @param iterable $statements
43 | *
44 | * @return CypherList
45 | */
46 | public function runStatements(iterable $statements): CypherList
47 | {
48 | return $this->tsx->runStatements($statements);
49 | }
50 |
51 | /**
52 | * @param iterable $statements
53 | *
54 | * @return CypherList
55 | */
56 | public function commit(iterable $statements = []): CypherList
57 | {
58 | return $this->tsx->commit($statements);
59 | }
60 |
61 | public function rollback(): void
62 | {
63 | $this->tsx->rollback();
64 | }
65 |
66 | public function isCommitted(): bool
67 | {
68 | return $this->tsx->isCommitted();
69 | }
70 |
71 | public function isRolledBack(): bool
72 | {
73 | return $this->tsx->isRolledBack();
74 | }
75 |
76 | public function isFinished(): bool
77 | {
78 | return $this->tsx->isFinished();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Bolt/Connection.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | use Bolt\connection\IConnection;
17 |
18 | class Connection
19 | {
20 | /**
21 | * @param ''|'s'|'ssc' $ssl
22 | */
23 | public function __construct(
24 | private readonly IConnection $connection,
25 | private readonly string $ssl,
26 | ) {
27 | }
28 |
29 | public function getIConnection(): IConnection
30 | {
31 | return $this->connection;
32 | }
33 |
34 | public function write(string $buffer): void
35 | {
36 | $this->connection->write($buffer);
37 | }
38 |
39 | public function read(int $length = 2048): string
40 | {
41 | return $this->connection->read($length);
42 | }
43 |
44 | public function disconnect(): void
45 | {
46 | $this->connection->disconnect();
47 | }
48 |
49 | public function getIp(): string
50 | {
51 | return $this->connection->getIp();
52 | }
53 |
54 | public function getPort(): int
55 | {
56 | return $this->connection->getPort();
57 | }
58 |
59 | public function getTimeout(): float
60 | {
61 | return $this->connection->getTimeout();
62 | }
63 |
64 | public function setTimeout(float $timeout): void
65 | {
66 | $this->connection->setTimeout($timeout);
67 | }
68 |
69 | /**
70 | * @return ''|'s'|'ssc'
71 | */
72 | public function getEncryptionLevel(): string
73 | {
74 | return $this->ssl;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltBeginMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltBeginMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly array $extra,
31 | private readonly ?Neo4jLogger $logger,
32 | ) {
33 | parent::__construct($protocol);
34 | }
35 |
36 | public function send(): BoltBeginMessage
37 | {
38 | $this->logger?->log(LogLevel::DEBUG, 'BEGIN', $this->extra);
39 | $this->protocol->begin($this->extra);
40 |
41 | return $this;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltCommitMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\enum\ServerState;
17 | use Bolt\protocol\V4_4;
18 | use Bolt\protocol\V5;
19 | use Bolt\protocol\V5_1;
20 | use Bolt\protocol\V5_2;
21 | use Bolt\protocol\V5_3;
22 | use Bolt\protocol\V5_4;
23 | use Laudis\Neo4j\Common\Neo4jLogger;
24 | use Laudis\Neo4j\Contracts\BoltMessage;
25 | use Laudis\Neo4j\Databags\Bookmark;
26 | use Laudis\Neo4j\Databags\BookmarkHolder;
27 | use Psr\Log\LogLevel;
28 |
29 | final class BoltCommitMessage extends BoltMessage
30 | {
31 | public function __construct(
32 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
33 | private readonly ?Neo4jLogger $logger,
34 | private readonly BookmarkHolder $bookmarks,
35 | ) {
36 | parent::__construct($protocol);
37 | }
38 |
39 | public function send(): BoltCommitMessage
40 | {
41 | $this->logger?->log(LogLevel::DEBUG, 'COMMIT');
42 | $response = $this->protocol->commit()->getResponse();
43 | // TODO: This is an issue with the underlying bolt library.
44 | // The serverState should be READY after a successful commit but
45 | // it's still in TX_STREAMING if the results were not consumed
46 | //
47 | // This should be removed once it's fixed
48 | $this->protocol->serverState = ServerState::READY;
49 |
50 | /** @var array{bookmark?: string} $content */
51 | $content = $response->content;
52 | $bookmark = $content['bookmark'] ?? '';
53 |
54 | if (trim($bookmark) !== '') {
55 | $this->bookmarks->setBookmark(new Bookmark([$bookmark]));
56 | }
57 |
58 | $this->protocol->serverState = ServerState::READY;
59 |
60 | return $this;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltDiscardMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltDiscardMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly array $extra,
31 | private readonly ?Neo4jLogger $logger,
32 | ) {
33 | parent::__construct($protocol);
34 | }
35 |
36 | public function send(): BoltDiscardMessage
37 | {
38 | $this->logger?->log(LogLevel::DEBUG, 'DISCARD', $this->extra);
39 | $this->protocol->discard($this->extra);
40 |
41 | return $this;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltGoodbyeMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltGoodbyeMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly ?Neo4jLogger $logger,
31 | ) {
32 | parent::__construct($protocol);
33 | }
34 |
35 | public function send(): BoltGoodbyeMessage
36 | {
37 | $this->logger?->log(LogLevel::DEBUG, 'GOODBYE');
38 | $this->protocol->goodbye();
39 |
40 | return $this;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltHelloMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\error\BoltException;
17 | use Bolt\protocol\V4_4;
18 | use Bolt\protocol\V5;
19 | use Bolt\protocol\V5_1;
20 | use Bolt\protocol\V5_2;
21 | use Bolt\protocol\V5_3;
22 | use Bolt\protocol\V5_4;
23 | use Laudis\Neo4j\Common\Neo4jLogger;
24 | use Laudis\Neo4j\Contracts\BoltMessage;
25 | use Psr\Log\LogLevel;
26 |
27 | final class BoltHelloMessage extends BoltMessage
28 | {
29 | /**
30 | * Constructor for the BoltHelloMessage.
31 | *
32 | * @param V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol The protocol connection
33 | * @param array $metadata The metadata for the HELLO message (like user agent, supported versions)
34 | * @param Neo4jLogger|null $logger Optional logger for debugging purposes
35 | */
36 | public function __construct(
37 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
38 | private readonly array $metadata,
39 | private readonly ?Neo4jLogger $logger = null,
40 | ) {
41 | parent::__construct($protocol);
42 | }
43 |
44 | /**
45 | * Sends the HELLO message to the server.
46 | *
47 | * @throws BoltException
48 | */
49 | public function send(): BoltHelloMessage
50 | {
51 | $this->logger?->log(LogLevel::DEBUG, 'HELLO', $this->metadata);
52 |
53 | $this->protocol->hello($this->metadata);
54 |
55 | return $this;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltLogoffMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | /**
27 | * A message that issues a LOGOFF request to the server to terminate the connection.
28 | */
29 | class BoltLogoffMessage extends BoltMessage
30 | {
31 | /**
32 | * @param V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol The Bolt protocol version
33 | * @param Neo4jLogger|null $logger Optional logger for logging purposes
34 | */
35 | public function __construct(
36 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
37 | private readonly ?Neo4jLogger $logger = null,
38 | ) {
39 | parent::__construct($protocol);
40 | }
41 |
42 | /**
43 | * Sends the LOGOFF request to the server to disconnect.
44 | *
45 | * @return BoltLogoffMessage The current instance of the message
46 | */
47 | public function send(): BoltLogoffMessage
48 | {
49 | $this->logger?->log(LogLevel::DEBUG, 'LOGOFF', []);
50 | /** @psalm-suppress PossiblyUndefinedMethod */
51 | $this->protocol->logoff();
52 |
53 | return $this;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltLogonMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | /**
27 | * A message that issues a LOGON request to the server for authentication.
28 | */
29 | final class BoltLogonMessage extends BoltMessage
30 | {
31 | /**
32 | * @param V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol The Bolt protocol version
33 | * @param array $credentials The credentials for the LOGON request (e.g., username and password)
34 | * @param Neo4jLogger|null $logger Optional logger for logging purposes
35 | */
36 | public function __construct(
37 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
38 | private readonly array $credentials,
39 | private readonly ?Neo4jLogger $logger,
40 | ) {
41 | parent::__construct($protocol);
42 | }
43 |
44 | /**
45 | * Sends the LOGON request to the server with the provided credentials.
46 | *
47 | * @return BoltLogonMessage The current instance of the message
48 | */
49 | public function send(): BoltLogonMessage
50 | {
51 | $toLog = $this->credentials;
52 | unset($toLog['credentials']);
53 |
54 | $this->logger?->log(LogLevel::DEBUG, 'LOGON', $toLog);
55 | /** @psalm-suppress PossiblyUndefinedMethod */
56 | $this->protocol->logon($this->credentials);
57 |
58 | return $this;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltPullMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltPullMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly array $extra,
31 | private readonly ?Neo4jLogger $logger,
32 | ) {
33 | parent::__construct($protocol);
34 | }
35 |
36 | public function send(): BoltPullMessage
37 | {
38 | $this->logger?->log(LogLevel::DEBUG, 'PULL', $this->extra);
39 | $this->protocol->pull($this->extra);
40 |
41 | return $this;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltResetMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltResetMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly ?Neo4jLogger $logger,
31 | ) {
32 | parent::__construct($protocol);
33 | }
34 |
35 | public function send(): BoltResetMessage
36 | {
37 | $this->logger?->log(LogLevel::DEBUG, 'RESET');
38 | $this->protocol->reset();
39 |
40 | return $this;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltRollbackMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltRollbackMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly ?Neo4jLogger $logger,
31 | ) {
32 | parent::__construct($protocol);
33 | }
34 |
35 | public function send(): BoltRollbackMessage
36 | {
37 | $this->logger?->log(LogLevel::DEBUG, 'ROLLBACK');
38 | $this->protocol->rollback();
39 |
40 | return $this;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Bolt/Messages/BoltRunMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt\Messages;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Laudis\Neo4j\Common\Neo4jLogger;
23 | use Laudis\Neo4j\Contracts\BoltMessage;
24 | use Psr\Log\LogLevel;
25 |
26 | final class BoltRunMessage extends BoltMessage
27 | {
28 | public function __construct(
29 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
30 | private readonly string $text,
31 | private readonly array $parameters,
32 | private readonly array $extra,
33 | private readonly ?Neo4jLogger $logger,
34 | ) {
35 | parent::__construct($protocol);
36 | }
37 |
38 | public function send(): BoltRunMessage
39 | {
40 | $this->logger?->log(LogLevel::DEBUG, 'RUN', [
41 | 'text' => $this->text,
42 | 'parameters' => $this->parameters,
43 | 'extra' => $this->extra,
44 | ]);
45 | $this->protocol->run($this->text, $this->parameters, $this->extra);
46 |
47 | return $this;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Bolt/ProtocolFactory.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | use Bolt\Bolt;
17 | use Bolt\connection\IConnection;
18 | use Bolt\protocol\V4_4;
19 | use Bolt\protocol\V5;
20 | use Bolt\protocol\V5_1;
21 | use Bolt\protocol\V5_2;
22 | use Bolt\protocol\V5_3;
23 | use Bolt\protocol\V5_4;
24 | use Laudis\Neo4j\Contracts\AuthenticateInterface;
25 | use RuntimeException;
26 |
27 | class ProtocolFactory
28 | {
29 | /**
30 | * @return array{0: V4_4|V5|V5_1|V5_2|V5_3|V5_4, 1: array{server: string, connection_id: string, hints: list}}
31 | */
32 | public function createProtocol(IConnection $connection, AuthenticateInterface $auth, string $userAgent): array
33 | {
34 | $boltOptoutEnv = getenv('BOLT_ANALYTICS_OPTOUT');
35 | if ($boltOptoutEnv === false) {
36 | putenv('BOLT_ANALYTICS_OPTOUT=1');
37 | }
38 |
39 | $bolt = new Bolt($connection);
40 | $bolt->setProtocolVersions('5.4.4', 4.4);
41 | $protocol = $bolt->build();
42 |
43 | if (!($protocol instanceof V4_4 || $protocol instanceof V5 || $protocol instanceof V5_1 || $protocol instanceof V5_2 || $protocol instanceof V5_3 || $protocol instanceof V5_4)) {
44 | throw new RuntimeException('Client only supports bolt version 4.4 to 5.4');
45 | }
46 |
47 | $response = $auth->authenticateBolt($protocol, $userAgent);
48 |
49 | return [$protocol, $response];
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Bolt/SocketConnectionFactory.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | use Bolt\connection\Socket;
17 | use Laudis\Neo4j\Contracts\BasicConnectionFactoryInterface;
18 | use Laudis\Neo4j\Databags\TransactionConfiguration;
19 |
20 | final class SocketConnectionFactory implements BasicConnectionFactoryInterface
21 | {
22 | public function __construct(
23 | private readonly StreamConnectionFactory $factory,
24 | ) {
25 | }
26 |
27 | public function create(UriConfiguration $config): Connection
28 | {
29 | if ($config->getSslLevel() !== '') {
30 | return $this->factory->create($config);
31 | }
32 |
33 | $connection = new Socket($config->getHost(), $config->getPort() ?? 7687, $config->getTimeout() ?? TransactionConfiguration::DEFAULT_TIMEOUT);
34 |
35 | return new Connection($connection, '');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Bolt/StreamConnectionFactory.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | use Bolt\connection\StreamSocket;
17 | use Laudis\Neo4j\Contracts\BasicConnectionFactoryInterface;
18 | use Laudis\Neo4j\Databags\TransactionConfiguration;
19 |
20 | final class StreamConnectionFactory implements BasicConnectionFactoryInterface
21 | {
22 | public function create(UriConfiguration $config): Connection
23 | {
24 | $connection = new StreamSocket($config->getHost(), $config->getPort() ?? 7687, $config->getTimeout() ?? TransactionConfiguration::DEFAULT_TIMEOUT);
25 | if ($config->getSslLevel() !== '') {
26 | $connection->setSslContextOptions($config->getSslConfiguration());
27 | }
28 |
29 | return new Connection($connection, $config->getSslLevel());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Bolt/SystemWideConnectionFactory.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | use function extension_loaded;
17 |
18 | use Laudis\Neo4j\Contracts\BasicConnectionFactoryInterface;
19 |
20 | /**
21 | * Singleton connection factory based on the installed extensions.
22 | */
23 | class SystemWideConnectionFactory implements BasicConnectionFactoryInterface
24 | {
25 | private static ?SystemWideConnectionFactory $instance = null;
26 |
27 | /**
28 | * @param SocketConnectionFactory|StreamConnectionFactory $factory
29 | */
30 | private function __construct(
31 | private $factory,
32 | ) {
33 | }
34 |
35 | /**
36 | * @psalm-suppress InvalidNullableReturnType
37 | */
38 | public static function getInstance(): SystemWideConnectionFactory
39 | {
40 | if (self::$instance === null) {
41 | $factory = new StreamConnectionFactory();
42 | if (extension_loaded('sockets')) {
43 | self::$instance = new self(new SocketConnectionFactory($factory));
44 | } else {
45 | self::$instance = new self($factory);
46 | }
47 | }
48 |
49 | /** @psalm-suppress NullableReturnStatement */
50 | return self::$instance;
51 | }
52 |
53 | public function create(UriConfiguration $config): Connection
54 | {
55 | return $this->factory->create($config);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Bolt/UriConfiguration.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Bolt;
15 |
16 | final class UriConfiguration
17 | {
18 | /**
19 | * @param ''|'s'|'ssc' $sslLevel
20 | */
21 | public function __construct(
22 | private readonly string $host,
23 | private readonly ?int $port,
24 | private readonly string $sslLevel,
25 | private readonly array $sslConfiguration,
26 | private readonly ?float $timeout,
27 | ) {
28 | }
29 |
30 | public function getHost(): string
31 | {
32 | return $this->host;
33 | }
34 |
35 | public function getPort(): ?int
36 | {
37 | return $this->port;
38 | }
39 |
40 | /**
41 | * @return 's'|'ssc'|''
42 | */
43 | public function getSslLevel(): string
44 | {
45 | return $this->sslLevel;
46 | }
47 |
48 | public function getSslConfiguration(): array
49 | {
50 | return $this->sslConfiguration;
51 | }
52 |
53 | public function getTimeout(): ?float
54 | {
55 | return $this->timeout;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Common/ConnectionConfiguration.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Laudis\Neo4j\Databags\DatabaseInfo;
17 | use Laudis\Neo4j\Enum\AccessMode;
18 | use Laudis\Neo4j\Enum\ConnectionProtocol;
19 | use Psr\Http\Message\UriInterface;
20 |
21 | /**
22 | * @psalm-immutable
23 | */
24 | final class ConnectionConfiguration
25 | {
26 | /**
27 | * @param ''|'s'|'ssc' $encryptionLevel
28 | */
29 | public function __construct(
30 | private readonly string $serverAgent,
31 | private readonly UriInterface $serverAddress,
32 | private readonly string $serverVersion,
33 | private readonly ConnectionProtocol $protocol,
34 | private readonly AccessMode $accessMode,
35 | private readonly ?DatabaseInfo $databaseInfo,
36 | private readonly string $encryptionLevel,
37 | ) {
38 | }
39 |
40 | public function getServerAgent(): string
41 | {
42 | return $this->serverAgent;
43 | }
44 |
45 | public function getServerAddress(): UriInterface
46 | {
47 | return $this->serverAddress;
48 | }
49 |
50 | public function getServerVersion(): string
51 | {
52 | return $this->serverVersion;
53 | }
54 |
55 | public function getProtocol(): ConnectionProtocol
56 | {
57 | return $this->protocol;
58 | }
59 |
60 | public function getAccessMode(): AccessMode
61 | {
62 | return $this->accessMode;
63 | }
64 |
65 | public function getDatabaseInfo(): ?DatabaseInfo
66 | {
67 | return $this->databaseInfo;
68 | }
69 |
70 | /**
71 | * @return ''|'s'|'ssc'
72 | */
73 | public function getEncryptionLevel(): string
74 | {
75 | return $this->encryptionLevel;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Common/GeneratorHelper.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Generator;
17 |
18 | use function microtime;
19 |
20 | use RuntimeException;
21 |
22 | use function sprintf;
23 |
24 | final class GeneratorHelper
25 | {
26 | /**
27 | * @template T
28 | *
29 | * @param Generator $generator
30 | *
31 | * @return T
32 | */
33 | public static function getReturnFromGenerator(Generator $generator, ?float $timeout = null)
34 | {
35 | $start = microtime(true);
36 | while ($generator->valid()) {
37 | if ($timeout !== null) {
38 | self::guardTiming($start, $timeout);
39 | }
40 | $generator->next();
41 | }
42 |
43 | return $generator->getReturn();
44 | }
45 |
46 | public static function guardTiming(float $start, float $timeout): void
47 | {
48 | $elapsed = microtime(true) - $start;
49 | if ($elapsed > $timeout) {
50 | throw new RuntimeException(sprintf('Cannot generator timed out out after %s seconds', $elapsed));
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Common/Resolvable.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use function call_user_func;
17 |
18 | /**
19 | * @template Resolved
20 | */
21 | final class Resolvable
22 | {
23 | /** @var Resolved|null */
24 | private $resolved;
25 | private bool $isResolved = false;
26 | /** @var callable():Resolved */
27 | private $toResolve;
28 |
29 | /** @var array */
30 | private static array $cache = [];
31 |
32 | /**
33 | * @psalm-mutation-free
34 | *
35 | * @param callable():Resolved $toResolve
36 | */
37 | public function __construct($toResolve)
38 | {
39 | $this->toResolve = $toResolve;
40 | }
41 |
42 | /**
43 | * @pure
44 | *
45 | * @template U
46 | *
47 | * @param callable():U $toResolve
48 | *
49 | * @return Resolvable
50 | */
51 | public static function once(string $key, $toResolve): Resolvable
52 | {
53 | /** @psalm-suppress MissingClosureReturnType */
54 | $tbr = static function () use ($key, $toResolve) {
55 | if (!array_key_exists($key, self::$cache)) {
56 | self::$cache[$key] = call_user_func($toResolve);
57 | }
58 |
59 | /** @var U */
60 | return self::$cache[$key];
61 | };
62 |
63 | /** @var self */
64 | return new Resolvable($tbr);
65 | }
66 |
67 | /**
68 | * @return Resolved
69 | */
70 | public function resolve()
71 | {
72 | if (!$this->isResolved) {
73 | $this->resolved = call_user_func($this->toResolve);
74 | $this->isResolved = true;
75 | }
76 |
77 | return $this->resolved;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Common/ResponseHelper.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Bolt\enum\Signature;
17 | use Bolt\protocol\Response;
18 | use Bolt\protocol\V4_4;
19 | use Bolt\protocol\V5;
20 | use Bolt\protocol\V5_1;
21 | use Bolt\protocol\V5_2;
22 | use Bolt\protocol\V5_3;
23 | use Bolt\protocol\V5_4;
24 | use Laudis\Neo4j\Exception\Neo4jException;
25 |
26 | class ResponseHelper
27 | {
28 | public static function getResponse(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol): Response
29 | {
30 | $response = $protocol->getResponse();
31 | if ($response->signature === Signature::FAILURE) {
32 | throw Neo4jException::fromBoltResponse($response);
33 | }
34 |
35 | return $response;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Common/SemaphoreFactory.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use function extension_loaded;
17 |
18 | use Laudis\Neo4j\Contracts\SemaphoreFactoryInterface;
19 | use Laudis\Neo4j\Contracts\SemaphoreInterface;
20 | use Laudis\Neo4j\Databags\DriverConfiguration;
21 | use Psr\Http\Message\UriInterface;
22 |
23 | final class SemaphoreFactory implements SemaphoreFactoryInterface
24 | {
25 | private static ?SemaphoreFactory $instance = null;
26 | /** @var callable(string, int):SemaphoreInterface */
27 | private $constructor;
28 |
29 | /**
30 | * @param callable(string, int):SemaphoreInterface $constructor
31 | */
32 | private function __construct($constructor)
33 | {
34 | $this->constructor = $constructor;
35 | }
36 |
37 | public static function getInstance(): self
38 | {
39 | return self::$instance ??= (extension_loaded('ext-sysvsem')) ?
40 | new self([SysVSemaphore::class, 'create']) :
41 | new self([SingleThreadedSemaphore::class, 'create']);
42 | }
43 |
44 | public function create(UriInterface $uri, DriverConfiguration $config): SemaphoreInterface
45 | {
46 | // Because interprocess switching of connections between PHP sessions is impossible,
47 | // we have to build a key to limit the amount of open connections, potentially between ALL sessions.
48 | // because of this we have to settle on a configuration basis to limit the connection pool,
49 | // not on an object basis.
50 | // The combination is between the server and the user agent as it most closely resembles an "application"
51 | // connecting to a server. The application thus supports multiple authentication methods, but they have
52 | // to be shared between the same connection pool.
53 | $key = $uri->getHost().':'.($uri->getPort() ?? '').':'.$config->getUserAgent();
54 |
55 | return ($this->constructor)($key, $config->getMaxPoolSize());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Common/SingleThreadedSemaphore.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Generator;
17 | use Laudis\Neo4j\Contracts\SemaphoreInterface;
18 |
19 | use function microtime;
20 |
21 | use RuntimeException;
22 |
23 | class SingleThreadedSemaphore implements SemaphoreInterface
24 | {
25 | private int $amount = 0;
26 | /** @var array */
27 | private static array $instances = [];
28 |
29 | private function __construct(
30 | private readonly int $max,
31 | ) {
32 | }
33 |
34 | public static function create(string $key, int $max): self
35 | {
36 | if (!array_key_exists($key, self::$instances)) {
37 | self::$instances[$key] = new self($max);
38 | }
39 |
40 | return self::$instances[$key];
41 | }
42 |
43 | public function wait(): Generator
44 | {
45 | $start = microtime(true);
46 | while ($this->amount >= $this->max) {
47 | /** @var bool $continue */
48 | $continue = yield $start - microtime(true);
49 | if (!$continue) {
50 | return;
51 | }
52 | }
53 | ++$this->amount;
54 | }
55 |
56 | public function post(): void
57 | {
58 | if ($this->amount <= 0) {
59 | throw new RuntimeException('Semaphore underflow');
60 | }
61 | --$this->amount;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Common/SysVSemaphore.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Generator;
17 |
18 | use function hash;
19 |
20 | use Laudis\Neo4j\Contracts\SemaphoreInterface;
21 |
22 | use function microtime;
23 |
24 | use RuntimeException;
25 |
26 | use function sem_acquire;
27 | use function sem_get;
28 | use function sem_release;
29 |
30 | class SysVSemaphore implements SemaphoreInterface
31 | {
32 | private function __construct(
33 | private readonly \SysvSemaphore $semaphore,
34 | ) {
35 | }
36 |
37 | public static function create(string $key, int $max): self
38 | {
39 | $key = hash('sha512', $key, true);
40 | $key = substr($key, 0, 8);
41 |
42 | if (!function_exists('sem_get')) {
43 | throw new RuntimeException('Can only create a semaphore if the sysv extension is installed');
44 | }
45 |
46 | $semaphore = sem_get(hexdec($key), $max);
47 | if ($semaphore === false) {
48 | throw new RuntimeException('Could not create semaphore');
49 | }
50 |
51 | return new self($semaphore);
52 | }
53 |
54 | public function wait(): Generator
55 | {
56 | $start = microtime(true);
57 | while (!sem_acquire($this->semaphore, true)) {
58 | /** @var bool $continue */
59 | $continue = yield $start - microtime(true);
60 | if (!$continue) {
61 | return;
62 | }
63 | }
64 | }
65 |
66 | public function post(): void
67 | {
68 | if (!sem_release($this->semaphore)) {
69 | throw new RuntimeException('Cannot release semaphore');
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Common/TransactionHelper.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Common;
15 |
16 | use Laudis\Neo4j\Contracts\CypherSequence;
17 | use Laudis\Neo4j\Contracts\TransactionInterface;
18 | use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface;
19 | use Laudis\Neo4j\Exception\Neo4jException;
20 |
21 | final class TransactionHelper
22 | {
23 | public const ROLLBACK_CLASSIFICATIONS = ['ClientError', 'TransientError', 'DatabaseError'];
24 |
25 | /**
26 | * @template U
27 | *
28 | * @param callable():UnmanagedTransactionInterface $tsxFactory
29 | * @param callable(TransactionInterface):U $tsxHandler
30 | *
31 | * @return U
32 | */
33 | public static function retry(callable $tsxFactory, callable $tsxHandler)
34 | {
35 | while (true) {
36 | $transaction = null;
37 | try {
38 | $transaction = $tsxFactory();
39 | $tbr = $tsxHandler($transaction);
40 | self::triggerLazyResult($tbr);
41 | $transaction->commit();
42 |
43 | return $tbr;
44 | } catch (Neo4jException $e) {
45 | if ($transaction && !in_array($e->getClassification(), self::ROLLBACK_CLASSIFICATIONS)) {
46 | $transaction->rollback();
47 | }
48 |
49 | if ($e->getClassification() !== 'TransientError') {
50 | throw $e;
51 | }
52 | }
53 | }
54 | }
55 |
56 | private static function triggerLazyResult(mixed $tbr): void
57 | {
58 | if ($tbr instanceof CypherSequence) {
59 | $tbr->preload();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Contracts/AddressResolverInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Generator;
17 |
18 | interface AddressResolverInterface
19 | {
20 | /**
21 | * Returns the addresses.
22 | *
23 | * @return Generator
24 | */
25 | public function getAddresses(string $host): Generator;
26 | }
27 |
--------------------------------------------------------------------------------
/src/Contracts/AuthenticateInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Bolt\protocol\V4_4;
17 | use Bolt\protocol\V5;
18 | use Bolt\protocol\V5_1;
19 | use Bolt\protocol\V5_2;
20 | use Bolt\protocol\V5_3;
21 | use Bolt\protocol\V5_4;
22 | use Psr\Http\Message\UriInterface;
23 |
24 | interface AuthenticateInterface
25 | {
26 | /**
27 | * Authenticates a Bolt connection with the provided configuration Uri and userAgent.
28 | *
29 | * @return array{server: string, connection_id: string, hints: list}
30 | */
31 | public function authenticateBolt(V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol, string $userAgent): array;
32 |
33 | /**
34 | * Returns a string representation of the authentication.
35 | */
36 | public function toString(UriInterface $uri): string;
37 | }
38 |
--------------------------------------------------------------------------------
/src/Contracts/BasicConnectionFactoryInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Laudis\Neo4j\Bolt\Connection;
17 | use Laudis\Neo4j\Bolt\UriConfiguration;
18 |
19 | interface BasicConnectionFactoryInterface
20 | {
21 | public function create(UriConfiguration $config): Connection;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Contracts/BoltConvertibleInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Bolt\protocol\IStructure;
17 |
18 | interface BoltConvertibleInterface
19 | {
20 | public function convertToBolt(): IStructure;
21 | }
22 |
--------------------------------------------------------------------------------
/src/Contracts/BoltMessage.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Bolt\protocol\Response;
17 | use Bolt\protocol\V4_4;
18 | use Bolt\protocol\V5;
19 | use Bolt\protocol\V5_1;
20 | use Bolt\protocol\V5_2;
21 | use Bolt\protocol\V5_3;
22 | use Bolt\protocol\V5_4;
23 | use Iterator;
24 |
25 | abstract class BoltMessage
26 | {
27 | public function __construct(
28 | private readonly V4_4|V5|V5_1|V5_2|V5_3|V5_4 $protocol,
29 | ) {
30 | }
31 |
32 | /**
33 | * Sends the Bolt message.
34 | */
35 | abstract public function send(): BoltMessage;
36 |
37 | public function getResponse(): Response
38 | {
39 | return $this->protocol->getResponse();
40 | }
41 |
42 | /**
43 | * @return Iterator
44 | */
45 | public function getResponses(): Iterator
46 | {
47 | /**
48 | * @var Iterator
49 | */
50 | return $this->protocol->getResponses();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Contracts/ConnectionPoolInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Generator;
17 | use Laudis\Neo4j\Databags\SessionConfiguration;
18 |
19 | /**
20 | * A connection pool acts as a connection factory by managing multiple connections.
21 | *
22 | * @template Connection of ConnectionInterface
23 | */
24 | interface ConnectionPoolInterface
25 | {
26 | /**
27 | * Acquires a connection from the pool.
28 | *
29 | * A key will be the amount of times you have fetched the value of the generator.
30 | * The value will be the time in seconds that has passed since requesting the connection.
31 | * You can abort the process of acquiring a connection by sending false to the generator.
32 | * The returned value will be the actual connection.
33 | *
34 | * @return Generator<
35 | * int,
36 | * float,
37 | * bool,
38 | * Connection
39 | * >
40 | */
41 | public function acquire(SessionConfiguration $config): Generator;
42 |
43 | /**
44 | * Releases a connection back to the pool.
45 | */
46 | public function release(ConnectionInterface $connection): void;
47 |
48 | /**
49 | * Closes all connections in the pool.
50 | */
51 | public function close(): void;
52 | }
53 |
--------------------------------------------------------------------------------
/src/Contracts/DriverInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Laudis\Neo4j\Databags\SessionConfiguration;
17 | use Laudis\Neo4j\Types\CypherList;
18 | use Laudis\Neo4j\Types\CypherMap;
19 |
20 | /**
21 | * The driver creates sessions for carrying out work.
22 | *
23 | * @psalm-type ParsedUrl = array{host: string, pass: string|null, path: string, port: int, query: array, scheme: string, user: string|null}
24 | * @psalm-type BasicDriver = DriverInterface>>
25 | */
26 | interface DriverInterface
27 | {
28 | /**
29 | * @psalm-mutation-free
30 | */
31 | public function createSession(?SessionConfiguration $config = null): SessionInterface;
32 |
33 | /**
34 | * Returns true if the driver can make a valid connection with the server.
35 | */
36 | public function verifyConnectivity(?SessionConfiguration $config = null): bool;
37 |
38 | /**
39 | * Closes all connections in the pool.
40 | */
41 | public function closeConnections(): void;
42 | }
43 |
--------------------------------------------------------------------------------
/src/Contracts/HasPropertiesInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use BadMethodCallException;
17 | use Laudis\Neo4j\Types\CypherMap;
18 |
19 | /**
20 | * Defines how an object with properties should behave.
21 | *
22 | * @psalm-immutable
23 | *
24 | * @template T
25 | */
26 | interface HasPropertiesInterface
27 | {
28 | /**
29 | * Returns the properties a map.
30 | *
31 | * @return CypherMap
32 | */
33 | public function getProperties(): CypherMap;
34 |
35 | /**
36 | * @param string $name
37 | *
38 | * @return T
39 | */
40 | public function __get($name);
41 |
42 | /**
43 | * Always throws an exception as cypher objects are immutable.
44 | *
45 | * @param string $name
46 | * @param T $value
47 | *
48 | * @throws BadMethodCallException
49 | */
50 | public function __set($name, $value): void;
51 |
52 | /**
53 | * Checks to see if the property exists and is set.
54 | *
55 | * @param string $name
56 | */
57 | public function __isset($name): bool;
58 | }
59 |
--------------------------------------------------------------------------------
/src/Contracts/PointInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | /**
17 | * Defines a basic Point type in neo4j.
18 | *
19 | * @psalm-immutable
20 | *
21 | * @psalm-type Crs = 'wgs-84'|'wgs-84-3d'|'cartesian'|'cartesian-3d';
22 | */
23 | interface PointInterface
24 | {
25 | /**
26 | * Returns the x coordinate.
27 | */
28 | public function getX(): float;
29 |
30 | /**
31 | * Returns the y coordinate.
32 | */
33 | public function getY(): float;
34 |
35 | /**
36 | * Returns the Coordinates Reference System.
37 | *
38 | * @see https://en.wikipedia.org/wiki/Spatial_reference_system
39 | *
40 | * @return Crs
41 | */
42 | public function getCrs(): string;
43 |
44 | /**
45 | * Returns the spacial reference identifier.
46 | *
47 | * @see https://en.wikipedia.org/wiki/Spatial_reference_system
48 | */
49 | public function getSrid(): int;
50 | }
51 |
--------------------------------------------------------------------------------
/src/Contracts/SemaphoreFactoryInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Laudis\Neo4j\Databags\DriverConfiguration;
17 | use Psr\Http\Message\UriInterface;
18 |
19 | interface SemaphoreFactoryInterface
20 | {
21 | public function create(UriInterface $uri, DriverConfiguration $config): SemaphoreInterface;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Contracts/SemaphoreInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Generator;
17 |
18 | interface SemaphoreInterface
19 | {
20 | /**
21 | * Returns a generator that can be used to wait for the semaphore to be released.
22 | *
23 | * The key of the generator is the amount of times you have already received a value before this one.
24 | * The value of the generator is the amount of time in seconds that has passed since calling wait.
25 | * You can stop the wait by sending false to the generator.
26 | * There is no return value in this generator.
27 | *
28 | * @return Generator
29 | */
30 | public function wait(): Generator;
31 |
32 | /**
33 | * Releases the semaphore.
34 | */
35 | public function post(): void;
36 | }
37 |
--------------------------------------------------------------------------------
/src/Contracts/TransactionInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Laudis\Neo4j\Databags\Statement;
17 | use Laudis\Neo4j\Databags\SummarizedResult;
18 | use Laudis\Neo4j\Exception\Neo4jException;
19 | use Laudis\Neo4j\Types\CypherList;
20 |
21 | /**
22 | * Transactions are atomic units of work that may contain one or more query.
23 | *
24 | * @see https://neo4j.com/docs/cypher-manual/current/introduction/transactions/
25 | */
26 | interface TransactionInterface
27 | {
28 | /**
29 | * @param iterable $parameters
30 | */
31 | public function run(string $statement, iterable $parameters = []): SummarizedResult;
32 |
33 | public function runStatement(Statement $statement): SummarizedResult;
34 |
35 | /**
36 | * @param iterable $statements
37 | *
38 | * @throws Neo4jException
39 | *
40 | * @return CypherList
41 | */
42 | public function runStatements(iterable $statements): CypherList;
43 | }
44 |
--------------------------------------------------------------------------------
/src/Contracts/UnmanagedTransactionInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Contracts;
15 |
16 | use Laudis\Neo4j\Databags\Statement;
17 | use Laudis\Neo4j\Databags\SummarizedResult;
18 | use Laudis\Neo4j\Types\CypherList;
19 |
20 | /**
21 | * An unmanaged transaction needs to be committed or rolled back manually.
22 | *
23 | * @see https://neo4j.com/docs/cypher-manual/current/introduction/transactions/
24 | */
25 | interface UnmanagedTransactionInterface extends TransactionInterface
26 | {
27 | /**
28 | * Runs the final statements provided and then commits the entire transaction.
29 | *
30 | * @param iterable $statements
31 | *
32 | * @return CypherList
33 | */
34 | public function commit(iterable $statements = []): CypherList;
35 |
36 | /**
37 | * Rolls back the transaction.
38 | */
39 | public function rollback(): void;
40 |
41 | /**
42 | * Returns whether the transaction has been rolled back.
43 | */
44 | public function isRolledBack(): bool;
45 |
46 | /**
47 | * Returns whether the transaction has been committed.
48 | */
49 | public function isCommitted(): bool;
50 |
51 | /**
52 | * Returns whether the transaction is safe to use.
53 | */
54 | public function isFinished(): bool;
55 | }
56 |
--------------------------------------------------------------------------------
/src/Databags/Bookmark.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use function array_unique;
17 |
18 | final class Bookmark
19 | {
20 | /** @var list */
21 | private readonly array $values;
22 |
23 | /**
24 | * @param list $bookmarks
25 | */
26 | public function __construct(?array $bookmarks = null)
27 | {
28 | $this->values = $bookmarks ?? [];
29 | }
30 |
31 | public function isEmpty(): bool
32 | {
33 | return count($this->values) === 0;
34 | }
35 |
36 | /**
37 | * @return list
38 | */
39 | public function values(): array
40 | {
41 | return $this->values;
42 | }
43 |
44 | /**
45 | * @param iterable|null $bookmarks
46 | */
47 | public static function from(?iterable $bookmarks): self
48 | {
49 | $bookmarks ??= [];
50 | $values = [];
51 |
52 | foreach ($bookmarks as $bookmark) {
53 | array_push($values, ...$bookmark->values());
54 | $values = array_values(array_unique($values));
55 | }
56 |
57 | return new self($values);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Databags/BookmarkHolder.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | final class BookmarkHolder
17 | {
18 | public function __construct(
19 | private Bookmark $bookmark,
20 | ) {
21 | }
22 |
23 | public function getBookmark(): Bookmark
24 | {
25 | return $this->bookmark;
26 | }
27 |
28 | public function setBookmark(Bookmark $bookmark): void
29 | {
30 | $this->bookmark = $bookmark;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Databags/ConnectionRequestData.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Contracts\AuthenticateInterface;
17 | use Psr\Http\Message\UriInterface;
18 |
19 | /**
20 | * @internal
21 | */
22 | final class ConnectionRequestData
23 | {
24 | public function __construct(
25 | private readonly string $hostname,
26 | private readonly UriInterface $uri,
27 | private readonly AuthenticateInterface $auth,
28 | private readonly string $userAgent,
29 | private readonly SslConfiguration $config,
30 | ) {
31 | }
32 |
33 | public function getHostname(): string
34 | {
35 | return $this->hostname;
36 | }
37 |
38 | public function getUri(): UriInterface
39 | {
40 | return $this->uri;
41 | }
42 |
43 | public function getAuth(): AuthenticateInterface
44 | {
45 | return $this->auth;
46 | }
47 |
48 | public function getUserAgent(): string
49 | {
50 | return $this->userAgent;
51 | }
52 |
53 | public function getSslConfig(): SslConfiguration
54 | {
55 | return $this->config;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Databags/DatabaseInfo.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Types\AbstractCypherObject;
17 |
18 | /**
19 | * Stores relevant information of a database.
20 | *
21 | * @psalm-immutable
22 | *
23 | * @extends AbstractCypherObject
24 | */
25 | final class DatabaseInfo extends AbstractCypherObject
26 | {
27 | public function __construct(
28 | private readonly string $name,
29 | ) {
30 | }
31 |
32 | /**
33 | * Returns the name of the database.
34 | */
35 | public function getName(): string
36 | {
37 | return $this->name;
38 | }
39 |
40 | public function toArray(): array
41 | {
42 | return ['name' => $this->name];
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Databags/DriverSetup.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Contracts\AuthenticateInterface;
17 | use Psr\Http\Message\UriInterface;
18 |
19 | /**
20 | * Basic object containing all the information needed to setup a driver.
21 | *
22 | * @psalm-immutable
23 | */
24 | final class DriverSetup
25 | {
26 | public function __construct(
27 | private readonly UriInterface $uri,
28 | private readonly AuthenticateInterface $auth,
29 | ) {
30 | }
31 |
32 | public function getAuth(): AuthenticateInterface
33 | {
34 | return $this->auth;
35 | }
36 |
37 | public function getUri(): UriInterface
38 | {
39 | return $this->uri;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Databags/Pair.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | /**
17 | * A basic Key value Pair.
18 | *
19 | * @template TKey
20 | * @template TValue
21 | *
22 | * @psalm-immutable
23 | */
24 | final class Pair
25 | {
26 | /**
27 | * @param TKey $key
28 | * @param TValue $value
29 | */
30 | public function __construct(
31 | private $key,
32 | private $value,
33 | ) {
34 | }
35 |
36 | /**
37 | * @return TKey
38 | */
39 | public function getKey()
40 | {
41 | return $this->key;
42 | }
43 |
44 | /**
45 | * @return TValue
46 | */
47 | public function getValue()
48 | {
49 | return $this->value;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Databags/Plan.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | /**
17 | * This describes the plan that the database planner produced and used (or will use) to execute your query.
18 | *
19 | * @see https://neo4j.com/docs/cypher-manual/current/execution-plans/
20 | */
21 | final class Plan
22 | {
23 | /**
24 | * @param list $children
25 | * @param list $identifiers
26 | */
27 | public function __construct(
28 | private readonly PlanArguments $args,
29 | private readonly array $children,
30 | private readonly array $identifiers,
31 | private readonly string $operator,
32 | ) {
33 | }
34 |
35 | /**
36 | * Returns the arguments for the operator.
37 | */
38 | public function getArgs(): PlanArguments
39 | {
40 | return $this->args;
41 | }
42 |
43 | /**
44 | * Returns the sub-plans.
45 | *
46 | * @return list
47 | */
48 | public function getChildren(): array
49 | {
50 | return $this->children;
51 | }
52 |
53 | /**
54 | * Identifiers used by this part of the plan.
55 | *
56 | * @return list
57 | */
58 | public function getIdentifiers(): array
59 | {
60 | return $this->identifiers;
61 | }
62 |
63 | /**
64 | * The operation this plan is performing.
65 | */
66 | public function getOperator(): string
67 | {
68 | return $this->operator;
69 | }
70 |
71 | public function toArray(): array
72 | {
73 | return [
74 | 'arguments' => $this->args,
75 | 'list' => $this->children,
76 | 'identifiers' => $this->identifiers,
77 | 'operator' => $this->operator,
78 | ];
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Databags/Position.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | /**
17 | * @psalm-immutable
18 | */
19 | final class Position
20 | {
21 | public function __construct(
22 | private int $column,
23 | private int $offset,
24 | private int $line,
25 | ) {
26 | }
27 |
28 | public function getLine(): int
29 | {
30 | return $this->line;
31 | }
32 |
33 | public function getOffset(): int
34 | {
35 | return $this->offset;
36 | }
37 |
38 | public function getColumn(): int
39 | {
40 | return $this->column;
41 | }
42 |
43 | public function toArray(): array
44 | {
45 | return [
46 | 'column' => $this->column,
47 | 'offset' => $this->offset,
48 | 'line' => $this->line,
49 | ];
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Databags/ProfiledQueryPlan.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | final class ProfiledQueryPlan
17 | {
18 | /**
19 | * @param list $children
20 | * @param list $identifiers
21 | */
22 | public function __construct(
23 | public readonly PlanArguments $arguments,
24 | public readonly int $dbHits = 0,
25 | public readonly int $records = 0,
26 | public readonly bool $hasPageCacheStats = false,
27 | public readonly int $pageCacheHits = 0,
28 | public readonly int $pageCacheMisses = 0,
29 | public readonly float $pageCacheHitRatio = 0.0,
30 | public readonly int $time = 0,
31 | public readonly string $operatorType = '',
32 | public readonly array $children = [],
33 | public readonly array $identifiers = [],
34 | ) {
35 | }
36 |
37 | public function toArray(): array
38 | {
39 | return [
40 | 'arguments' => $this->arguments->toArray(),
41 | 'dbHits' => $this->dbHits,
42 | 'records' => $this->records,
43 | 'hasPageCacheStats' => $this->hasPageCacheStats,
44 | 'pageCacheHits' => $this->pageCacheHits,
45 | 'pageCacheMisses' => $this->pageCacheMisses,
46 | 'pageCacheHitRatio' => $this->pageCacheHitRatio,
47 | 'time' => $this->time,
48 | 'operatorType' => $this->operatorType,
49 | 'children' => array_map(
50 | static fn (ProfiledQueryPlan $child): array => $child->toArray(),
51 | $this->children
52 | ),
53 | 'identifiers' => $this->identifiers,
54 | ];
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Databags/ServerInfo.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Enum\ConnectionProtocol;
17 | use Laudis\Neo4j\Types\AbstractCypherObject;
18 | use Psr\Http\Message\UriInterface;
19 |
20 | /**
21 | * Provides some basic information of the server where the result is obtained from.
22 | *
23 | * @psalm-immutable
24 | *
25 | * @extends AbstractCypherObject
26 | */
27 | final class ServerInfo extends AbstractCypherObject
28 | {
29 | public function __construct(
30 | private readonly UriInterface $address,
31 | private readonly ConnectionProtocol $protocol,
32 | private readonly string $agent,
33 | ) {
34 | }
35 |
36 | /**
37 | * Returns the uri of the server the query was executed.
38 | */
39 | public function getAddress(): UriInterface
40 | {
41 | return $this->address;
42 | }
43 |
44 | /**
45 | * Returns Connection Protocol version with which the remote server communicates.
46 | */
47 | public function getProtocol(): ConnectionProtocol
48 | {
49 | return $this->protocol;
50 | }
51 |
52 | /**
53 | * Returns server agent string by which the remote server identifies itself.
54 | */
55 | public function getAgent(): string
56 | {
57 | return $this->agent;
58 | }
59 |
60 | public function toArray(): array
61 | {
62 | return [
63 | 'address' => $this->address,
64 | 'protocolVersion' => $this->protocol,
65 | 'agent' => $this->agent,
66 | ];
67 | }
68 |
69 | /**
70 | * @psalm-suppress ImpureMethodCall
71 | */
72 | public function jsonSerialize(): array
73 | {
74 | return [
75 | 'address' => "{$this->address->getHost()}:{$this->address->getPort()}",
76 | 'protocolVersion' => $this->protocol,
77 | 'agent' => $this->agent,
78 | ];
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Databags/SslConfiguration.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Enum\SslMode;
17 |
18 | /**
19 | * @psalm-immutable
20 | */
21 | final class SslConfiguration
22 | {
23 | public function __construct(
24 | private SslMode $mode,
25 | private bool $verifyPeer,
26 | ) {
27 | }
28 |
29 | public function getMode(): SslMode
30 | {
31 | return $this->mode;
32 | }
33 |
34 | public function isVerifyPeer(): bool
35 | {
36 | return $this->verifyPeer;
37 | }
38 |
39 | /**
40 | * @pure
41 | */
42 | public static function create(SslMode $mode, bool $verifyPeer): self
43 | {
44 | return new self($mode, $verifyPeer);
45 | }
46 |
47 | /**
48 | * @pure
49 | */
50 | public static function default(): self
51 | {
52 | /** @psalm-suppress ImpureMethodCall */
53 | return self::create(SslMode::FROM_URL(), true);
54 | }
55 |
56 | public function withMode(SslMode $mode): self
57 | {
58 | $tbr = clone $this;
59 | $tbr->mode = $mode;
60 |
61 | return $tbr;
62 | }
63 |
64 | public function withVerifyPeer(bool $verify): self
65 | {
66 | $tbr = clone $this;
67 | $tbr->verifyPeer = $verify;
68 |
69 | return $tbr;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Databags/Statement.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Laudis\Neo4j\Types\AbstractCypherObject;
17 |
18 | /**
19 | * The components of a Cypher query, containing the query text and parameter mapping.
20 | *
21 | * @todo deprecate and create Query Object
22 | *
23 | * @psalm-immutable
24 | *
25 | * @extends AbstractCypherObject
26 | */
27 | final class Statement extends AbstractCypherObject
28 | {
29 | /**
30 | * @param iterable $parameters
31 | */
32 | public function __construct(
33 | private readonly string $text,
34 | private readonly iterable $parameters,
35 | ) {
36 | }
37 |
38 | /**
39 | * @pure
40 | *
41 | * @param iterable|null $parameters
42 | */
43 | public static function create(string $text, ?iterable $parameters = null): Statement
44 | {
45 | return new self($text, $parameters ?? []);
46 | }
47 |
48 | /**
49 | * The query text.
50 | */
51 | public function getText(): string
52 | {
53 | return $this->text;
54 | }
55 |
56 | /**
57 | * The parameter mapping.
58 | *
59 | * @return iterable
60 | */
61 | public function getParameters(): iterable
62 | {
63 | return $this->parameters;
64 | }
65 |
66 | public function toArray(): array
67 | {
68 | return [
69 | 'text' => $this->text,
70 | 'parameters' => $this->parameters,
71 | ];
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/Databags/SummarizedResult.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Databags;
15 |
16 | use Generator;
17 | use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
18 | use Laudis\Neo4j\Types\CypherList;
19 | use Laudis\Neo4j\Types\CypherMap;
20 |
21 | /**
22 | * A result containing the values and the summary.
23 | *
24 | * @psalm-import-type OGMTypes from SummarizedResultFormatter
25 | *
26 | * @extends CypherList>
27 | */
28 | final class SummarizedResult extends CypherList
29 | {
30 | private ?ResultSummary $summary = null;
31 |
32 | /**
33 | * @param iterable>|callable():Generator> $iterable
34 | *
35 | * @psalm-mutation-free
36 | */
37 | public function __construct(?ResultSummary &$summary, iterable|callable $iterable = [])
38 | {
39 | parent::__construct($iterable);
40 | $this->summary = &$summary;
41 | }
42 |
43 | /**
44 | * Returns the result summary.
45 | */
46 | public function getSummary(): ResultSummary
47 | {
48 | while ($this->summary === null && $this->valid()) {
49 | $this->next();
50 | }
51 |
52 | /** @var ResultSummary */
53 | return $this->summary;
54 | }
55 |
56 | /**
57 | * @return CypherList>
58 | */
59 | public function getResults(): CypherList
60 | {
61 | return new CypherList($this);
62 | }
63 |
64 | /**
65 | * @return array{summary: ResultSummary|null, result: mixed}
66 | */
67 | public function jsonSerialize(): array
68 | {
69 | return [
70 | 'summary' => $this->summary,
71 | 'result' => parent::jsonSerialize(),
72 | ];
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/Enum/AccessMode.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Enum;
15 |
16 | use JsonSerializable;
17 | use Laudis\TypedEnum\TypedEnum;
18 |
19 | /**
20 | * Defines the access mode of a connection.
21 | *
22 | * @method static self READ()
23 | * @method static self WRITE()
24 | *
25 | * @extends TypedEnum
26 | *
27 | * @psalm-immutable
28 | *
29 | * @psalm-suppress MutableDependency
30 | */
31 | final class AccessMode extends TypedEnum implements JsonSerializable
32 | {
33 | private const READ = 'read';
34 | private const WRITE = 'write';
35 |
36 | public function jsonSerialize(): string
37 | {
38 | return $this->getValue();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Enum/QueryTypeEnum.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Enum;
15 |
16 | use JsonSerializable;
17 | use Laudis\Neo4j\Databags\SummaryCounters;
18 | use Laudis\TypedEnum\TypedEnum;
19 | use Stringable;
20 |
21 | /**
22 | * The actual type of query after is has been run.
23 | *
24 | * @method static self READ_ONLY()
25 | * @method static self READ_WRITE()
26 | * @method static self SCHEMA_WRITE()
27 | * @method static self WRITE_ONLY()
28 | *
29 | * @psalm-immutable
30 | *
31 | * @extends TypedEnum
32 | *
33 | * @psalm-suppress MutableDependency
34 | */
35 | final class QueryTypeEnum extends TypedEnum implements JsonSerializable, Stringable
36 | {
37 | private const READ_ONLY = 'r';
38 | private const READ_WRITE = 'rw';
39 | private const SCHEMA_WRITE = 's';
40 | private const WRITE_ONLY = 'w';
41 |
42 | /**
43 | * Decide the type of the query from the provided counters.
44 | *
45 | * @pure
46 | *
47 | * @psalm-suppress ImpureMethodCall
48 | */
49 | public static function fromCounters(SummaryCounters $counters): self
50 | {
51 | if ($counters->containsUpdates() || $counters->containsSystemUpdates()) {
52 | return self::READ_WRITE();
53 | }
54 |
55 | if ($counters->constraintsAdded() || $counters->constraintsRemoved() || $counters->indexesAdded() || $counters->indexesRemoved()) {
56 | return self::SCHEMA_WRITE();
57 | }
58 |
59 | return self::READ_ONLY();
60 | }
61 |
62 | public function __toString(): string
63 | {
64 | return $this->getValue();
65 | }
66 |
67 | public function jsonSerialize(): string
68 | {
69 | return $this->getValue();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Enum/RoutingRoles.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Enum;
15 |
16 | use JsonSerializable;
17 | use Laudis\TypedEnum\TypedEnum;
18 |
19 | /**
20 | * The possible routing roles.
21 | *
22 | * @method static RoutingRoles LEADER()
23 | * @method static RoutingRoles FOLLOWER()
24 | * @method static RoutingRoles ROUTE()
25 | *
26 | * @extends TypedEnum>
27 | *
28 | * @psalm-immutable
29 | *
30 | * @psalm-suppress MutableDependency
31 | */
32 | final class RoutingRoles extends TypedEnum implements JsonSerializable
33 | {
34 | private const LEADER = ['WRITE', 'LEADER'];
35 | private const FOLLOWER = ['READ', 'FOLLOWER'];
36 | private const ROUTE = ['ROUTE'];
37 |
38 | /**
39 | * @psalm-suppress ImpureMethodCall
40 | */
41 | public function jsonSerialize(): string
42 | {
43 | if ($this === self::LEADER()) {
44 | return 'LEADER';
45 | }
46 |
47 | if ($this === self::FOLLOWER()) {
48 | return 'FOLLOWER';
49 | }
50 |
51 | return 'ROUTE';
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Enum/SslMode.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Enum;
15 |
16 | use JsonSerializable;
17 | use Laudis\TypedEnum\TypedEnum;
18 | use Stringable;
19 |
20 | /**
21 | * @method static self ENABLE()
22 | * @method static self DISABLE()
23 | * @method static self FROM_URL()
24 | * @method static self ENABLE_WITH_SELF_SIGNED()
25 | *
26 | * @extends TypedEnum
27 | *
28 | * @psalm-immutable
29 | *
30 | * @psalm-suppress MutableDependency
31 | */
32 | final class SslMode extends TypedEnum implements JsonSerializable, Stringable
33 | {
34 | private const ENABLE = 'enable';
35 | private const ENABLE_WITH_SELF_SIGNED = 'enable_with_self_signed';
36 | private const DISABLE = 'disable';
37 | private const FROM_URL = 'from_url';
38 |
39 | public function __toString(): string
40 | {
41 | /** @noinspection MagicMethodsValidityInspection */
42 | return $this->getValue();
43 | }
44 |
45 | public function jsonSerialize(): string
46 | {
47 | return $this->getValue();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/Enum/TransactionState.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Enum;
15 |
16 | /**
17 | * The state of a transaction.
18 | */
19 | enum TransactionState
20 | {
21 | /**
22 | * The transaction is running with no explicit success or failure marked.
23 | */
24 | case ACTIVE;
25 |
26 | /**
27 | * This transaction has been terminated because of a fatal connection error.
28 | */
29 | case TERMINATED;
30 |
31 | /**
32 | * This transaction has successfully committed.
33 | */
34 | case COMMITTED;
35 |
36 | /**
37 | * This transaction has been rolled back.
38 | */
39 | case ROLLED_BACK;
40 | }
41 |
--------------------------------------------------------------------------------
/src/Exception/ClientException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use RuntimeException;
17 | use Throwable;
18 |
19 | /**
20 | * Exception when a Client Error occurs.
21 | *
22 | * @psalm-immutable
23 | *
24 | * @psalm-suppress MutableDependency
25 | */
26 | final class ClientException extends RuntimeException
27 | {
28 | public function __construct(string $message, ?Throwable $previous = null)
29 | {
30 | parent::__construct($message, 0, $previous);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Exception/ConnectionPoolException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use RuntimeException;
17 |
18 | final class ConnectionPoolException extends RuntimeException
19 | {
20 | }
21 |
--------------------------------------------------------------------------------
/src/Exception/InvalidCacheArgumentException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use Psr\SimpleCache\InvalidArgumentException;
17 | use RuntimeException;
18 |
19 | class InvalidCacheArgumentException extends RuntimeException implements InvalidArgumentException
20 | {
21 | }
22 |
--------------------------------------------------------------------------------
/src/Exception/Neo4jException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use Bolt\protocol\Response;
17 | use Laudis\Neo4j\Databags\Neo4jError;
18 | use RuntimeException;
19 | use Throwable;
20 |
21 | /**
22 | * Exception when a Neo4j Error occurs.
23 | *
24 | * @psalm-immutable
25 | *
26 | * @psalm-suppress MutableDependency
27 | */
28 | final class Neo4jException extends RuntimeException
29 | {
30 | private const MESSAGE_TEMPLATE = 'Neo4j errors detected. First one with code "%s" and message "%s"';
31 | /** @var non-empty-list */
32 | private array $errors;
33 |
34 | /**
35 | * @param non-empty-list $errors
36 | */
37 | public function __construct(array $errors, ?Throwable $previous = null)
38 | {
39 | $error = $errors[0];
40 | $message = sprintf(self::MESSAGE_TEMPLATE, $error->getCode(), $error->getMessage() ?? 'NULL');
41 | parent::__construct($message, 0, $previous);
42 | $this->errors = $errors;
43 | }
44 |
45 | /**
46 | * @pure
47 | */
48 | public static function fromBoltResponse(Response $response): self
49 | {
50 | return new self([Neo4jError::fromBoltResponse($response)]);
51 | }
52 |
53 | /**
54 | * @return non-empty-list
55 | */
56 | public function getErrors(): array
57 | {
58 | return $this->errors;
59 | }
60 |
61 | public function getNeo4jCode(): string
62 | {
63 | return $this->errors[0]->getCode();
64 | }
65 |
66 | public function getNeo4jMessage(): ?string
67 | {
68 | return $this->errors[0]->getMessage();
69 | }
70 |
71 | public function getCategory(): string
72 | {
73 | return $this->errors[0]->getCategory();
74 | }
75 |
76 | public function getClassification(): string
77 | {
78 | return $this->errors[0]->getClassification();
79 | }
80 |
81 | public function getTitle(): string
82 | {
83 | return $this->errors[0]->getTitle();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Exception/PropertyDoesNotExistException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use RuntimeException;
17 |
18 | /**
19 | * Exception when accessing a property which does not exist.
20 | *
21 | * @psalm-immutable
22 | *
23 | * @psalm-suppress MutableDependency
24 | */
25 | final class PropertyDoesNotExistException extends RuntimeException
26 | {
27 | }
28 |
--------------------------------------------------------------------------------
/src/Exception/RuntimeTypeException.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use function get_debug_type;
17 |
18 | use RuntimeException;
19 |
20 | final class RuntimeTypeException extends RuntimeException
21 | {
22 | public function __construct(mixed $value, string $type)
23 | {
24 | $actualType = get_debug_type($value);
25 | $message = sprintf('Cannot cast %s to type: %s', $actualType, $type);
26 | parent::__construct($message);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Exception/UnsupportedScheme.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Exception;
15 |
16 | use function implode;
17 |
18 | use RuntimeException;
19 |
20 | /**
21 | * Exception when a requested scheme cannot be handled by the drivers available in the client.
22 | *
23 | * @psalm-immutable
24 | *
25 | * @psalm-suppress MutableDependency
26 | */
27 | final class UnsupportedScheme extends RuntimeException
28 | {
29 | /**
30 | * @param list $supportedSchemas
31 | */
32 | public static function make(string $schema, array $supportedSchemas): self
33 | {
34 | return new self('Unsupported schema: '.$schema.', available schema\'s are: '.implode(',', $supportedSchemas));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Neo4j/RoutingTable.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Neo4j;
15 |
16 | use function in_array;
17 |
18 | use Laudis\Neo4j\Enum\RoutingRoles;
19 |
20 | /**
21 | * Table containing possible routes to nodes in the cluster.
22 | *
23 | * @psalm-immutable
24 | */
25 | final class RoutingTable
26 | {
27 | /**
28 | * @param iterable, role:string}> $servers
29 | */
30 | public function __construct(
31 | private readonly iterable $servers,
32 | private readonly int $ttl,
33 | ) {
34 | }
35 |
36 | /**
37 | * Returns the time to live in seconds.
38 | */
39 | public function getTtl(): int
40 | {
41 | return $this->ttl;
42 | }
43 |
44 | /**
45 | * Returns the routes with a given role. If no role is provided it will return all routes.
46 | *
47 | * @return list
48 | */
49 | public function getWithRole(?RoutingRoles $role = null): array
50 | {
51 | /** @psalm-var list $tbr */
52 | $tbr = [];
53 | foreach ($this->servers as $server) {
54 | if ($role === null || in_array($server['role'], $role->getValue(), true)) {
55 | foreach ($server['addresses'] as $address) {
56 | $tbr[] = $address;
57 | }
58 | }
59 | }
60 |
61 | return array_values(array_unique($tbr));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Types/Abstract3DPoint.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Bolt\protocol\IStructure;
17 | use Bolt\protocol\v1\structures\Point3D;
18 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
19 | use Laudis\Neo4j\Contracts\PointInterface;
20 |
21 | /**
22 | * A cartesian point in three-dimensional space.
23 | *
24 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-3d
25 | *
26 | * @psalm-immutable
27 | *
28 | * @psalm-import-type Crs from PointInterface
29 | */
30 | abstract class Abstract3DPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface
31 | {
32 | public function convertToBolt(): IStructure
33 | {
34 | return new Point3D($this->getSrid(), $this->getX(), $this->getY(), $this->getZ());
35 | }
36 |
37 | public function __construct(
38 | float $x,
39 | float $y,
40 | private float $z,
41 | ) {
42 | parent::__construct($x, $y);
43 | }
44 |
45 | public function getZ(): float
46 | {
47 | return $this->z;
48 | }
49 |
50 | /**
51 | * @psalm-suppress ImplementedReturnTypeMismatch
52 | *
53 | * @return array{x: float, y: float, z: float, srid: int, crs: Crs}
54 | */
55 | public function toArray(): array
56 | {
57 | $tbr = parent::toArray();
58 |
59 | $tbr['z'] = $this->z;
60 |
61 | return $tbr;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Types/AbstractPoint.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Bolt\protocol\IStructure;
17 | use Bolt\protocol\v1\structures\Point2D;
18 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
19 | use Laudis\Neo4j\Contracts\PointInterface;
20 |
21 | /**
22 | * A cartesian point in two-dimensional space.
23 | *
24 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-2d
25 | *
26 | * @psalm-immutable
27 | *
28 | * @psalm-import-type Crs from PointInterface
29 | *
30 | * @extends AbstractPropertyObject
31 | */
32 | abstract class AbstractPoint extends AbstractPropertyObject implements PointInterface, BoltConvertibleInterface
33 | {
34 | public function __construct(
35 | private readonly float $x,
36 | private readonly float $y,
37 | ) {
38 | }
39 |
40 | abstract public function getCrs(): string;
41 |
42 | abstract public function getSrid(): int;
43 |
44 | public function convertToBolt(): IStructure
45 | {
46 | return new Point2D($this->getSrid(), $this->getX(), $this->getY());
47 | }
48 |
49 | public function getX(): float
50 | {
51 | return $this->x;
52 | }
53 |
54 | public function getY(): float
55 | {
56 | return $this->y;
57 | }
58 |
59 | public function getProperties(): CypherMap
60 | {
61 | /** @psalm-suppress InvalidReturnStatement False positive */
62 | return new CypherMap($this);
63 | }
64 |
65 | /**
66 | * @psalm-suppress ImplementedReturnTypeMismatch False positive
67 | *
68 | * @return array{x: float, y: float, crs: Crs, srid: int}
69 | */
70 | public function toArray(): array
71 | {
72 | return [
73 | 'x' => $this->x,
74 | 'y' => $this->y,
75 | 'crs' => $this->getCrs(),
76 | 'srid' => $this->getSrid(),
77 | ];
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Types/AbstractPropertyObject.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use BadMethodCallException;
17 | use Laudis\Neo4j\Contracts\HasPropertiesInterface;
18 | use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
19 |
20 | use function sprintf;
21 |
22 | /**
23 | * @psalm-import-type OGMTypes from SummarizedResultFormatter
24 | *
25 | * @template PropertyTypes
26 | * @template ObjectTypes
27 | *
28 | * @extends AbstractCypherObject
29 | *
30 | * @implements HasPropertiesInterface
31 | *
32 | * @psalm-immutable
33 | */
34 | abstract class AbstractPropertyObject extends AbstractCypherObject implements HasPropertiesInterface
35 | {
36 | public function __get($name)
37 | {
38 | /** @psalm-suppress ImpureMethodCall */
39 | return $this->getProperties()->get($name);
40 | }
41 |
42 | public function __set($name, $value): void
43 | {
44 | throw new BadMethodCallException(sprintf('%s is immutable', static::class));
45 | }
46 |
47 | public function __isset($name): bool
48 | {
49 | /** @psalm-suppress ImpureMethodCall */
50 | return $this->getProperties()->offsetExists($name);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Types/Cartesian3DPoint.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
17 | use Laudis\Neo4j\Contracts\PointInterface;
18 |
19 | /**
20 | * A cartesian point in three dimensional space.
21 | *
22 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-3d
23 | *
24 | * @psalm-immutable
25 | *
26 | * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface
27 | */
28 | final class Cartesian3DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface
29 | {
30 | public const SRID = 9157;
31 | public const CRS = 'cartesian-3d';
32 |
33 | public function getSrid(): int
34 | {
35 | return self::SRID;
36 | }
37 |
38 | public function getCrs(): string
39 | {
40 | return self::CRS;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Types/CartesianPoint.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
17 | use Laudis\Neo4j\Contracts\PointInterface;
18 |
19 | /**
20 | * A cartesian point in two dimensional space.
21 | *
22 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-cartesian-2d
23 | *
24 | * @psalm-immutable
25 | *
26 | * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface
27 | */
28 | final class CartesianPoint extends AbstractPoint implements PointInterface, BoltConvertibleInterface
29 | {
30 | /** @var Crs */
31 | public const CRS = 'cartesian';
32 | public const SRID = 7203;
33 |
34 | public function getCrs(): string
35 | {
36 | return self::CRS;
37 | }
38 |
39 | public function getSrid(): int
40 | {
41 | return self::SRID;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Types/Date.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Bolt\protocol\IStructure;
17 | use DateTimeImmutable;
18 | use Exception;
19 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
20 | use UnexpectedValueException;
21 |
22 | /**
23 | * A date represented by days since unix epoch.
24 | *
25 | * @psalm-immutable
26 | *
27 | * @extends AbstractPropertyObject
28 | *
29 | * @psalm-suppress TypeDoesNotContainType
30 | */
31 | final class Date extends AbstractPropertyObject implements BoltConvertibleInterface
32 | {
33 | public function __construct(
34 | private readonly int $days,
35 | ) {
36 | }
37 |
38 | /**
39 | * The amount of days since unix epoch.
40 | */
41 | public function getDays(): int
42 | {
43 | return $this->days;
44 | }
45 |
46 | /**
47 | * Casts to an immutable date time.
48 | *
49 | * @throws Exception
50 | */
51 | public function toDateTime(): DateTimeImmutable
52 | {
53 | $dateTimeImmutable = (new DateTimeImmutable('@0'))->modify(sprintf('+%s days', $this->days));
54 |
55 | if ($dateTimeImmutable === false) {
56 | throw new UnexpectedValueException('Expected DateTimeImmutable');
57 | }
58 |
59 | return $dateTimeImmutable;
60 | }
61 |
62 | public function getProperties(): CypherMap
63 | {
64 | return new CypherMap($this);
65 | }
66 |
67 | public function toArray(): array
68 | {
69 | return ['days' => $this->days];
70 | }
71 |
72 | public function convertToBolt(): IStructure
73 | {
74 | return new \Bolt\protocol\v1\structures\Date($this->getDays());
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/Types/LocalTime.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Bolt\protocol\IStructure;
17 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
18 |
19 | /**
20 | * The time of day represented in nanoseconds.
21 | *
22 | * @psalm-immutable
23 | *
24 | * @extends AbstractPropertyObject
25 | */
26 | final class LocalTime extends AbstractPropertyObject implements BoltConvertibleInterface
27 | {
28 | public function __construct(
29 | private readonly int $nanoseconds,
30 | ) {
31 | }
32 |
33 | /**
34 | * The nanoseconds that have passed since midnight.
35 | */
36 | public function getNanoseconds(): int
37 | {
38 | return $this->nanoseconds;
39 | }
40 |
41 | /**
42 | * @return array{nanoseconds: int}
43 | */
44 | public function toArray(): array
45 | {
46 | return ['nanoseconds' => $this->nanoseconds];
47 | }
48 |
49 | public function getProperties(): CypherMap
50 | {
51 | return new CypherMap($this);
52 | }
53 |
54 | public function convertToBolt(): IStructure
55 | {
56 | return new \Bolt\protocol\v1\structures\LocalTime($this->getNanoseconds());
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Types/Path.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | /**
17 | * A Path class representing a Path in cypher.
18 | *
19 | * @psalm-immutable
20 | *
21 | * @extends AbstractPropertyObject|CypherList|CypherList, CypherList|CypherList|CypherList>
22 | */
23 | final class Path extends AbstractPropertyObject
24 | {
25 | /**
26 | * @param CypherList $nodes
27 | * @param CypherList $relationships
28 | * @param CypherList $ids
29 | */
30 | public function __construct(
31 | private readonly CypherList $nodes,
32 | private readonly CypherList $relationships,
33 | private readonly CypherList $ids,
34 | ) {
35 | }
36 |
37 | /**
38 | * Returns the node in the path.
39 | *
40 | * @return CypherList
41 | */
42 | public function getNodes(): CypherList
43 | {
44 | return $this->nodes;
45 | }
46 |
47 | /**
48 | * Returns the relationships in the path.
49 | *
50 | * @return CypherList
51 | */
52 | public function getRelationships(): CypherList
53 | {
54 | return $this->relationships;
55 | }
56 |
57 | /**
58 | * Returns the ids of the items in the path.
59 | *
60 | * @return CypherList
61 | */
62 | public function getIds(): CypherList
63 | {
64 | return $this->ids;
65 | }
66 |
67 | /**
68 | * @return array{ids: CypherList, nodes: CypherList, relationships: CypherList}
69 | */
70 | public function toArray(): array
71 | {
72 | return [
73 | 'ids' => $this->ids,
74 | 'nodes' => $this->nodes,
75 | 'relationships' => $this->relationships,
76 | ];
77 | }
78 |
79 | public function getProperties(): CypherMap
80 | {
81 | return new CypherMap($this);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Types/Relationship.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
17 |
18 | /**
19 | * A Relationship class representing a Relationship in cypher.
20 | *
21 | * @psalm-import-type OGMTypes from SummarizedResultFormatter
22 | *
23 | * @psalm-immutable
24 | */
25 | final class Relationship extends UnboundRelationship
26 | {
27 | /**
28 | * @param CypherMap $properties
29 | */
30 | public function __construct(
31 | int $id,
32 | private readonly int $startNodeId,
33 | private readonly int $endNodeId,
34 | string $type,
35 | CypherMap $properties,
36 | ?string $elementId,
37 | ) {
38 | parent::__construct($id, $type, $properties, $elementId);
39 | }
40 |
41 | /**
42 | * Returns the id of the start node.
43 | */
44 | public function getStartNodeId(): int
45 | {
46 | return $this->startNodeId;
47 | }
48 |
49 | /**
50 | * Returns the id of the end node.
51 | */
52 | public function getEndNodeId(): int
53 | {
54 | return $this->endNodeId;
55 | }
56 |
57 | /**
58 | * @psalm-suppress ImplementedReturnTypeMismatch False positive.
59 | *
60 | * @return array{
61 | * id: int,
62 | * type: string,
63 | * startNodeId: int,
64 | * endNodeId: int,
65 | * properties: CypherMap
66 | * }
67 | */
68 | public function toArray(): array
69 | {
70 | $tbr = parent::toArray();
71 |
72 | $tbr['startNodeId'] = $this->getStartNodeId();
73 | $tbr['endNodeId'] = $this->getEndNodeId();
74 |
75 | return $tbr;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Types/Time.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Bolt\protocol\IStructure;
17 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
18 |
19 | /**
20 | * A time object represented in seconds since the unix epoch.
21 | *
22 | * @psalm-immutable
23 | *
24 | * @extends AbstractPropertyObject
25 | */
26 | final class Time extends AbstractPropertyObject implements BoltConvertibleInterface
27 | {
28 | public function __construct(
29 | private readonly int $nanoSeconds,
30 | private readonly int $tzOffsetSeconds,
31 | ) {
32 | }
33 |
34 | /**
35 | * @return array{nanoSeconds: int, tzOffsetSeconds: int}
36 | */
37 | public function toArray(): array
38 | {
39 | return ['nanoSeconds' => $this->nanoSeconds, 'tzOffsetSeconds' => $this->tzOffsetSeconds];
40 | }
41 |
42 | public function getTzOffsetSeconds(): int
43 | {
44 | return $this->tzOffsetSeconds;
45 | }
46 |
47 | public function getNanoSeconds(): int
48 | {
49 | return $this->nanoSeconds;
50 | }
51 |
52 | public function getProperties(): CypherMap
53 | {
54 | return new CypherMap($this);
55 | }
56 |
57 | public function convertToBolt(): IStructure
58 | {
59 | return new \Bolt\protocol\v1\structures\Time($this->getNanoSeconds(), $this->getTzOffsetSeconds());
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Types/WGS843DPoint.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
17 | use Laudis\Neo4j\Contracts\PointInterface;
18 |
19 | /**
20 | * A WGS84 Point in three-dimensional space.
21 | *
22 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-3d
23 | *
24 | * @psalm-immutable
25 | *
26 | * @psalm-import-type Crs from PointInterface
27 | */
28 | final class WGS843DPoint extends Abstract3DPoint implements PointInterface, BoltConvertibleInterface
29 | {
30 | public const SRID = 4979;
31 | public const CRS = 'wgs-84-3d';
32 |
33 | public function getSrid(): int
34 | {
35 | return self::SRID;
36 | }
37 |
38 | public function getLongitude(): float
39 | {
40 | return $this->getX();
41 | }
42 |
43 | public function getLatitude(): float
44 | {
45 | return $this->getY();
46 | }
47 |
48 | public function getHeight(): float
49 | {
50 | return $this->getZ();
51 | }
52 |
53 | public function getCrs(): string
54 | {
55 | return self::CRS;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Types/WGS84Point.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\Types;
15 |
16 | use Laudis\Neo4j\Contracts\BoltConvertibleInterface;
17 | use Laudis\Neo4j\Contracts\PointInterface;
18 |
19 | /**
20 | * A WGS84 Point in two dimensional space.
21 | *
22 | * @psalm-immutable
23 | *
24 | * @see https://neo4j.com/docs/cypher-manual/current/functions/spatial/#functions-point-wgs84-2d
25 | *
26 | * @psalm-import-type Crs from \Laudis\Neo4j\Contracts\PointInterface
27 | */
28 | final class WGS84Point extends AbstractPoint implements PointInterface, BoltConvertibleInterface
29 | {
30 | public const SRID = 4326;
31 | public const CRS = 'wgs-84';
32 |
33 | public function getSrid(): int
34 | {
35 | return self::SRID;
36 | }
37 |
38 | public function getCrs(): string
39 | {
40 | return self::CRS;
41 | }
42 |
43 | /**
44 | * A numeric expression that represents the longitude/x value in decimal degrees.
45 | */
46 | public function getLongitude(): float
47 | {
48 | return $this->getX();
49 | }
50 |
51 | /**
52 | * A numeric expression that represents the latitude/y value in decimal degrees.
53 | */
54 | public function getLatitude(): float
55 | {
56 | return $this->getY();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/testkit-backend/blacklist.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | return [
15 | 'neo4j' => [
16 | 'datatypes' => [
17 | 'TestDataTypes' => [
18 | 'test_should_echo_very_long_map' => 'Work in progress on testkit frontend',
19 | ],
20 | ],
21 | 'sessionrun' => [
22 | 'TestSessionRun' => [
23 | 'test_autocommit_transactions_should_support_metadata' => 'Meta data isn\'t supported yet',
24 | 'test_autocommit_transactions_should_support_timeout' => 'Waiting on bookmarks isn\'t supported yet',
25 | ],
26 | ],
27 | 'test_direct_driver' => [
28 | 'TestDirectDriver' => [
29 | 'test_custom_resolver' => 'No custom resolver implemented',
30 | 'test_fail_nicely_when_using_http_port' => 'Not implemented yet',
31 | ],
32 | ],
33 | 'test_summary' => [
34 | 'TestDirectDriver' => [
35 | 'test_agent_string' => 'This is not an official driver yet',
36 | ],
37 | ],
38 | 'txrun' => [
39 | 'TestTxRun' => [
40 | 'test_should_fail_to_run_query_for_invalid_bookmark' => 'Waiting on bookmarks isn\'t supported yet',
41 | ],
42 | ],
43 | 'txfuncrun' => [
44 | 'TestTxFuncRun' => [
45 | 'test_iteration_nested' => 'Buffers not supported yet',
46 | 'test_updates_last_bookmark_on_commit' => 'Waiting on bookmarks isn\'t supported yet',
47 | ],
48 | ],
49 | ],
50 | ];
51 |
--------------------------------------------------------------------------------
/testkit-backend/index.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | require_once __DIR__.'/../vendor/autoload.php';
15 |
16 | use Laudis\Neo4j\TestkitBackend\Backend;
17 |
18 | $backend = Backend::boot();
19 | while (true) {
20 | $backend->handle();
21 | }
22 |
--------------------------------------------------------------------------------
/testkit-backend/register.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | use Laudis\Neo4j\TestkitBackend\Handlers\GetFeatures;
15 | use Laudis\Neo4j\TestkitBackend\Handlers\StartTest;
16 | use Laudis\Neo4j\TestkitBackend\MainRepository;
17 | use Monolog\Handler\StreamHandler;
18 | use Monolog\Logger;
19 | use Psr\Log\LoggerInterface;
20 |
21 | return [
22 | LoggerInterface::class => static function () {
23 | $logger = new Logger('testkit-backend');
24 | $logger->pushHandler(new StreamHandler('php://stdout', Logger::DEBUG));
25 |
26 | return $logger;
27 | },
28 |
29 | GetFeatures::class => static function () {
30 | $featuresConfig = require __DIR__.'/features.php';
31 |
32 | return new GetFeatures($featuresConfig);
33 | },
34 |
35 | StartTest::class => static function () {
36 | $acceptedTests = require __DIR__.'/blacklist.php';
37 |
38 | return new StartTest($acceptedTests);
39 | },
40 |
41 | MainRepository::class => static function () {
42 | return new MainRepository(
43 | [],
44 | [],
45 | [],
46 | [],
47 | );
48 | },
49 | ];
50 |
--------------------------------------------------------------------------------
/testkit-backend/src/Contracts/RequestHandlerInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Contracts;
15 |
16 | /**
17 | * @template T
18 | */
19 | interface RequestHandlerInterface
20 | {
21 | /**
22 | * @param T $request
23 | */
24 | public function handle($request): TestkitResponseInterface;
25 | }
26 |
--------------------------------------------------------------------------------
/testkit-backend/src/Contracts/TestkitResponseInterface.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Contracts;
15 |
16 | use JsonSerializable;
17 |
18 | interface TestkitResponseInterface extends JsonSerializable
19 | {
20 | /**
21 | * @return array{name:string, data?:iterable}
22 | */
23 | public function jsonSerialize(): array;
24 | }
25 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/CheckMultiDBSupport.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Exception;
17 | use Laudis\Neo4j\Databags\SessionConfiguration;
18 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
20 | use Laudis\Neo4j\TestkitBackend\MainRepository;
21 | use Laudis\Neo4j\TestkitBackend\Requests\CheckMultiDBSupportRequest;
22 | use Laudis\Neo4j\TestkitBackend\Responses\MultiDBSupportResponse;
23 |
24 | /**
25 | * @implements RequestHandlerInterface
26 | */
27 | final class CheckMultiDBSupport implements RequestHandlerInterface
28 | {
29 | private MainRepository $repository;
30 |
31 | public function __construct(MainRepository $repository)
32 | {
33 | $this->repository = $repository;
34 | }
35 |
36 | /**
37 | * @param CheckMultiDBSupportRequest $request
38 | */
39 | public function handle($request): TestkitResponseInterface
40 | {
41 | $driver = $this->repository->getDriver($request->getDriverId());
42 |
43 | try {
44 | $session = $driver->createSession(SessionConfiguration::default()->withDatabase('system'));
45 | $session->run('SHOW databases');
46 | } catch (Exception $e) {
47 | return new MultiDBSupportResponse($request->getDriverId(), false);
48 | }
49 |
50 | return new MultiDBSupportResponse($request->getDriverId(), true);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/DomainNameResolutionCompleted.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\Requests\DomainNameResolutionCompletedRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class DomainNameResolutionCompleted implements RequestHandlerInterface
25 | {
26 | /**
27 | * @param DomainNameResolutionCompletedRequest $request
28 | */
29 | public function handle($request): TestkitResponseInterface
30 | {
31 | return new BackendErrorResponse('Domain name resolution not implemented yet'); // TODO
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/DriverClose.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\MainRepository;
18 | use Laudis\Neo4j\TestkitBackend\Requests\DriverCloseRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\DriverResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class DriverClose implements RequestHandlerInterface
25 | {
26 | private MainRepository $repository;
27 |
28 | public function __construct(MainRepository $repository)
29 | {
30 | $this->repository = $repository;
31 | }
32 |
33 | /**
34 | * @param DriverCloseRequest $request
35 | */
36 | public function handle($request): DriverResponse
37 | {
38 | $this->repository->removeDriver($request->getDriverId());
39 |
40 | return new DriverResponse($request->getDriverId());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/ForcedRoutingTableUpdate.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Exception;
17 | use Laudis\Neo4j\Contracts\ConnectionPoolInterface;
18 | use Laudis\Neo4j\Neo4j\Neo4jConnectionPool;
19 | use Laudis\Neo4j\Neo4j\Neo4jDriver;
20 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
21 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
22 | use Laudis\Neo4j\TestkitBackend\MainRepository;
23 | use Laudis\Neo4j\TestkitBackend\Requests\ForcedRoutingTableUpdateRequest;
24 | use Laudis\Neo4j\TestkitBackend\Responses\DriverResponse;
25 | use ReflectionClass;
26 | use ReflectionException;
27 |
28 | /**
29 | * @implements RequestHandlerInterface
30 | */
31 | final class ForcedRoutingTableUpdate implements RequestHandlerInterface
32 | {
33 | private MainRepository $repository;
34 |
35 | public function __construct(MainRepository $repository)
36 | {
37 | $this->repository = $repository;
38 | }
39 |
40 | /**
41 | * @param ForcedRoutingTableUpdateRequest $request
42 | *
43 | * @throws ReflectionException
44 | * @throws Exception
45 | */
46 | public function handle($request): TestkitResponseInterface
47 | {
48 | $driver = $this->repository->getDriver($request->getDriverId());
49 |
50 | if ($driver instanceof Neo4jDriver) {
51 | $poolProperty = (new ReflectionClass(Neo4jDriver::class))->getProperty('pool');
52 | $poolProperty->setAccessible(true);
53 | /** @var ConnectionPoolInterface $pool */
54 | $pool = $poolProperty->getValue($driver);
55 |
56 | $tableProperty = (new ReflectionClass(Neo4jConnectionPool::class))->getProperty('table');
57 | $tableProperty->setAccessible(true);
58 | $tableProperty->setValue($pool, null);
59 | }
60 |
61 | $driver->createSession()->run('RETURN 1 AS x');
62 |
63 | return new DriverResponse($request->getDriverId());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/GetFeatures.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Requests\GetFeaturesRequest;
18 | use Laudis\Neo4j\TestkitBackend\Responses\FeatureListResponse;
19 |
20 | /**
21 | * @implements RequestHandlerInterface
22 | */
23 | final class GetFeatures implements RequestHandlerInterface
24 | {
25 | /** @var iterable */
26 | private iterable $featuresConfig;
27 |
28 | /**
29 | * @param iterable $featuresConfig
30 | */
31 | public function __construct(iterable $featuresConfig)
32 | {
33 | $this->featuresConfig = $featuresConfig;
34 | }
35 |
36 | /**
37 | * @param GetFeaturesRequest $request
38 | */
39 | public function handle($request): FeatureListResponse
40 | {
41 | $features = [];
42 | foreach ($this->featuresConfig as $feature => $available) {
43 | if ($available) {
44 | $features[] = $feature;
45 | }
46 | }
47 |
48 | return new FeatureListResponse($features);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/NewDriver.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Authentication\Authenticate;
17 | use Laudis\Neo4j\Databags\DriverConfiguration;
18 | use Laudis\Neo4j\DriverFactory;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
20 | use Laudis\Neo4j\TestkitBackend\MainRepository;
21 | use Laudis\Neo4j\TestkitBackend\Requests\NewDriverRequest;
22 | use Laudis\Neo4j\TestkitBackend\Responses\DriverResponse;
23 | use Symfony\Component\Uid\Uuid;
24 |
25 | /**
26 | * @implements RequestHandlerInterface
27 | */
28 | final class NewDriver implements RequestHandlerInterface
29 | {
30 | private MainRepository $repository;
31 |
32 | public function __construct(MainRepository $repository)
33 | {
34 | $this->repository = $repository;
35 | }
36 |
37 | /**
38 | * @param NewDriverRequest $request
39 | */
40 | public function handle($request): DriverResponse
41 | {
42 | $user = $request->authToken->principal;
43 | $pass = $request->authToken->credentials;
44 |
45 | $ua = $request->userAgent;
46 | $timeout = $request->connectionTimeoutMs;
47 | $config = DriverConfiguration::default()
48 | ->withAcquireConnectionTimeout($timeout);
49 |
50 | if ($ua) {
51 | $config = $config->withUserAgent($ua);
52 | }
53 |
54 | $authenticate = Authenticate::basic($user, $pass);
55 | $driver = DriverFactory::create($request->uri, $config, $authenticate);
56 |
57 | $id = Uuid::v4();
58 | $this->repository->addDriver($id, $driver);
59 |
60 | return new DriverResponse($id);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/NewSession.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Databags\Bookmark;
17 | use Laudis\Neo4j\Databags\SessionConfiguration;
18 | use Laudis\Neo4j\Enum\AccessMode;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
20 | use Laudis\Neo4j\TestkitBackend\MainRepository;
21 | use Laudis\Neo4j\TestkitBackend\Requests\NewSessionRequest;
22 | use Laudis\Neo4j\TestkitBackend\Responses\SessionResponse;
23 | use Symfony\Component\Uid\Uuid;
24 |
25 | /**
26 | * @implements RequestHandlerInterface
27 | */
28 | final class NewSession implements RequestHandlerInterface
29 | {
30 | private MainRepository $repository;
31 |
32 | public function __construct(MainRepository $repository)
33 | {
34 | $this->repository = $repository;
35 | }
36 |
37 | /**
38 | * @param NewSessionRequest $request
39 | */
40 | public function handle($request): SessionResponse
41 | {
42 | $driver = $this->repository->getDriver($request->driverId);
43 |
44 | $config = SessionConfiguration::default()
45 | ->withAccessMode($request->accessMode === 'r' ? AccessMode::READ() : AccessMode::WRITE());
46 |
47 | if ($request->bookmarks !== null) {
48 | $config = $config->withBookmarks([new Bookmark($request->bookmarks)]);
49 | }
50 |
51 | if ($request->database !== null) {
52 | $config = $config->withDatabase($request->database);
53 | }
54 |
55 | $config = $config->withFetchSize($request->fetchSize ?? 1);
56 |
57 | $session = $driver->createSession($config);
58 | $id = Uuid::v4();
59 | $this->repository->addSession($id, $session);
60 |
61 | return new SessionResponse($id);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/ResolverResolutionCompleted.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\Requests\ResolverResolutionCompletedRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class ResolverResolutionCompleted implements RequestHandlerInterface
25 | {
26 | /**
27 | * @param ResolverResolutionCompletedRequest $request
28 | */
29 | public function handle($request): TestkitResponseInterface
30 | {
31 | return new BackendErrorResponse('Resolver resolution not implemented yet'); // TODO
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/ResultConsume.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\MainRepository;
19 | use Laudis\Neo4j\TestkitBackend\Requests\ResultConsumeRequest;
20 | use Laudis\Neo4j\TestkitBackend\Responses\SummaryResponse;
21 |
22 | /**
23 | * @implements RequestHandlerInterface
24 | */
25 | final class ResultConsume implements RequestHandlerInterface
26 | {
27 | private MainRepository $repository;
28 |
29 | public function __construct(MainRepository $repository)
30 | {
31 | $this->repository = $repository;
32 | }
33 |
34 | /**
35 | * @param ResultConsumeRequest $request
36 | */
37 | public function handle($request): TestkitResponseInterface
38 | {
39 | $result = $this->repository->getRecords($request->getResultId());
40 |
41 | if ($result instanceof TestkitResponseInterface) {
42 | return $result;
43 | }
44 |
45 | return new SummaryResponse($result);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/ResultSingle.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\MainRepository;
19 | use Laudis\Neo4j\TestkitBackend\Requests\ResultSingleRequest;
20 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
21 | use Laudis\Neo4j\TestkitBackend\Responses\RecordResponse;
22 |
23 | /**
24 | * Request to expect and return exactly one record in the result stream.
25 | *
26 | * Backend should respond with a Record if exactly one record was found.
27 | * If more or fewer records are left in the result stream, or if any other
28 | * error occurs while retrieving the records, an Error response should be
29 | * returned.
30 | *
31 | * @implements RequestHandlerInterface
32 | */
33 | final class ResultSingle implements RequestHandlerInterface
34 | {
35 | private function __construct(
36 | private readonly MainRepository $repository,
37 | ) {
38 | }
39 |
40 | public function handle($request): TestkitResponseInterface
41 | {
42 | $record = $this->repository->getRecords($request->getResultId());
43 | if ($record instanceof TestkitResponseInterface) {
44 | return new BackendErrorResponse('Something went wrong with the result handling');
45 | }
46 |
47 | $count = $record->count();
48 | if ($count !== 1) {
49 | return new BackendErrorResponse(sprintf('Found exactly %s result rows, but expected just one.', $count));
50 | }
51 |
52 | $values = [];
53 | foreach ($record->getAsCypherMap(0) as $value) {
54 | $values[] = $value;
55 | }
56 |
57 | return new RecordResponse($values);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/RetryableNegative.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\Requests\RetryableNegativeRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class RetryableNegative implements RequestHandlerInterface
25 | {
26 | /**
27 | * @param RetryableNegativeRequest $request
28 | */
29 | public function handle($request): TestkitResponseInterface
30 | {
31 | return new BackendErrorResponse('Retryable negative not implemented yet'); // TODO
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/RetryablePositive.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\Requests\RetryablePositiveRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\RetryableDoneResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class RetryablePositive implements RequestHandlerInterface
25 | {
26 | /**
27 | * @param RetryablePositiveRequest $request
28 | */
29 | public function handle($request): TestkitResponseInterface
30 | {
31 | return new RetryableDoneResponse();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/SessionClose.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\MainRepository;
18 | use Laudis\Neo4j\TestkitBackend\Requests\SessionCloseRequest;
19 | use Laudis\Neo4j\TestkitBackend\Responses\SessionResponse;
20 |
21 | /**
22 | * @implements RequestHandlerInterface
23 | */
24 | final class SessionClose implements RequestHandlerInterface
25 | {
26 | private MainRepository $repository;
27 |
28 | public function __construct(MainRepository $repository)
29 | {
30 | $this->repository = $repository;
31 | }
32 |
33 | /**
34 | * @param SessionCloseRequest $request
35 | */
36 | public function handle($request): SessionResponse
37 | {
38 | $this->repository->removeSession($request->getSessionId());
39 |
40 | return new SessionResponse($request->getSessionId());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/SessionLastBookmarks.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\MainRepository;
19 | use Laudis\Neo4j\TestkitBackend\Requests\SessionLastBookmarksRequest;
20 | use Laudis\Neo4j\TestkitBackend\Responses\BookmarksResponse;
21 | use Symfony\Component\Uid\Uuid;
22 |
23 | /**
24 | * @implements AbstractRunner
25 | */
26 | final class SessionLastBookmarks implements RequestHandlerInterface
27 | {
28 | public function __construct(
29 | private readonly MainRepository $repository,
30 | ) {
31 | }
32 |
33 | /**
34 | * @param SessionLastBookmarksRequest $request
35 | *
36 | * @return TestkitResponseInterface
37 | */
38 | public function handle($request): TestkitResponseInterface
39 | {
40 | $session = $this->repository->getSession($request->getSessionId());
41 |
42 | $bookmarks = $session->getLastBookmark()->values();
43 |
44 | return new BookmarksResponse($bookmarks);
45 | }
46 |
47 | protected function getId($request): Uuid
48 | {
49 | return $request->getSessionId();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/SessionRun.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Contracts\SessionInterface;
17 | use Laudis\Neo4j\TestkitBackend\Requests\SessionRunRequest;
18 | use Symfony\Component\Uid\Uuid;
19 |
20 | /**
21 | * @extends AbstractRunner
22 | */
23 | final class SessionRun extends AbstractRunner
24 | {
25 | protected function getRunner($request): SessionInterface
26 | {
27 | return $this->repository->getSession($request->getSessionId());
28 | }
29 |
30 | protected function getId($request): Uuid
31 | {
32 | return $request->getSessionId();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/SessionWriteTransaction.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\MainRepository;
19 | use Laudis\Neo4j\TestkitBackend\Requests\SessionWriteTransactionRequest;
20 | use Laudis\Neo4j\TestkitBackend\Responses\RetryableTryResponse;
21 | use Symfony\Component\Uid\Uuid;
22 |
23 | /**
24 | * @implements RequestHandlerInterface
25 | */
26 | final class SessionWriteTransaction implements RequestHandlerInterface
27 | {
28 | private MainRepository $repository;
29 |
30 | public function __construct(MainRepository $repository)
31 | {
32 | $this->repository = $repository;
33 | }
34 |
35 | /**
36 | * @param SessionWriteTransactionRequest $request
37 | */
38 | public function handle($request): TestkitResponseInterface
39 | {
40 | $session = $this->repository->getSession($request->getSessionId());
41 |
42 | $id = Uuid::v4();
43 |
44 | $this->repository->addTransaction($id, $session);
45 | $this->repository->bindTransactionToSession($request->getSessionId(), $id);
46 |
47 | return new RetryableTryResponse($id);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/StartTest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use function is_string;
17 |
18 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
20 | use Laudis\Neo4j\TestkitBackend\Requests\StartTestRequest;
21 | use Laudis\Neo4j\TestkitBackend\Responses\RunTestResponse;
22 | use Laudis\Neo4j\TestkitBackend\Responses\SkipTestResponse;
23 |
24 | /**
25 | * @implements RequestHandlerInterface
26 | */
27 | final class StartTest implements RequestHandlerInterface
28 | {
29 | /** @var array */
30 | private array $acceptedTests;
31 |
32 | /**
33 | * @param array $acceptedTests
34 | */
35 | public function __construct(array $acceptedTests)
36 | {
37 | $this->acceptedTests = $acceptedTests;
38 | }
39 |
40 | /**
41 | * @param StartTestRequest $request
42 | */
43 | public function handle($request): TestkitResponseInterface
44 | {
45 | $section = $this->acceptedTests;
46 | foreach (explode('.', $request->getTestName()) as $key) {
47 | if (array_key_exists($key, $section)) {
48 | if ($section[$key] === false) {
49 | return new SkipTestResponse('Test disabled in backend');
50 | }
51 | if (is_string($section[$key])) {
52 | return new SkipTestResponse($section[$key]);
53 | }
54 | /** @var array $section */
55 | $section = $section[$key];
56 | } else {
57 | break;
58 | }
59 | }
60 |
61 | return new RunTestResponse();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/TransactionCommit.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface;
17 | use Laudis\Neo4j\Exception\Neo4jException;
18 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
20 | use Laudis\Neo4j\TestkitBackend\MainRepository;
21 | use Laudis\Neo4j\TestkitBackend\Requests\TransactionCommitRequest;
22 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
23 | use Laudis\Neo4j\TestkitBackend\Responses\DriverErrorResponse;
24 | use Laudis\Neo4j\TestkitBackend\Responses\TransactionResponse;
25 |
26 | /**
27 | * @implements RequestHandlerInterface
28 | */
29 | final class TransactionCommit implements RequestHandlerInterface
30 | {
31 | private MainRepository $repository;
32 |
33 | public function __construct(MainRepository $repository)
34 | {
35 | $this->repository = $repository;
36 | }
37 |
38 | /**
39 | * @param TransactionCommitRequest $request
40 | */
41 | public function handle($request): TestkitResponseInterface
42 | {
43 | $tsx = $this->repository->getTransaction($request->getTxId());
44 |
45 | if (!$tsx instanceof UnmanagedTransactionInterface) {
46 | return new BackendErrorResponse('Transaction not found');
47 | }
48 |
49 | try {
50 | $tsx->commit();
51 | } catch (Neo4jException $e) {
52 | return new DriverErrorResponse($request->getTxId(), $e);
53 | }
54 |
55 | return new TransactionResponse($request->getTxId());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/TransactionRollback.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Contracts\TransactionInterface;
17 | use Laudis\Neo4j\Exception\Neo4jException;
18 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
19 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
20 | use Laudis\Neo4j\TestkitBackend\MainRepository;
21 | use Laudis\Neo4j\TestkitBackend\Requests\TransactionRollbackRequest;
22 | use Laudis\Neo4j\TestkitBackend\Responses\BackendErrorResponse;
23 | use Laudis\Neo4j\TestkitBackend\Responses\DriverErrorResponse;
24 | use Laudis\Neo4j\TestkitBackend\Responses\TransactionResponse;
25 |
26 | /**
27 | * @implements RequestHandlerInterface
28 | */
29 | final class TransactionRollback implements RequestHandlerInterface
30 | {
31 | private MainRepository $repository;
32 |
33 | public function __construct(MainRepository $repository)
34 | {
35 | $this->repository = $repository;
36 | }
37 |
38 | /**
39 | * @param TransactionRollbackRequest $request
40 | */
41 | public function handle($request): TestkitResponseInterface
42 | {
43 | $tsx = $this->repository->getTransaction($request->getTxId());
44 |
45 | if ($tsx === null || !$tsx instanceof TransactionInterface) {
46 | return new BackendErrorResponse('Transaction not found');
47 | }
48 |
49 | try {
50 | $tsx->rollback();
51 | } catch (Neo4jException $e) {
52 | return new DriverErrorResponse($request->getTxId(), $e);
53 | }
54 |
55 | return new TransactionResponse($request->getTxId());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/TransactionRun.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\Contracts\TransactionInterface;
17 | use Laudis\Neo4j\TestkitBackend\Requests\TransactionRunRequest;
18 | use Symfony\Component\Uid\Uuid;
19 |
20 | /**
21 | * @extends AbstractRunner
22 | */
23 | final class TransactionRun extends AbstractRunner
24 | {
25 | /**
26 | * @param TransactionRunRequest $request
27 | */
28 | protected function getRunner($request): TransactionInterface
29 | {
30 | return $this->repository->getTransaction($request->getTxId());
31 | }
32 |
33 | protected function getId($request): Uuid
34 | {
35 | return $request->getTxId();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/testkit-backend/src/Handlers/VerifyConnectivity.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Handlers;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\RequestHandlerInterface;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Laudis\Neo4j\TestkitBackend\MainRepository;
19 | use Laudis\Neo4j\TestkitBackend\Requests\VerifyConnectivityRequest;
20 | use Laudis\Neo4j\TestkitBackend\Responses\DriverResponse;
21 |
22 | /**
23 | * @implements RequestHandlerInterface
24 | */
25 | final class VerifyConnectivity implements RequestHandlerInterface
26 | {
27 | private MainRepository $repository;
28 |
29 | public function __construct(MainRepository $repository)
30 | {
31 | $this->repository = $repository;
32 | }
33 |
34 | /**
35 | * @param VerifyConnectivityRequest $request
36 | */
37 | public function handle($request): TestkitResponseInterface
38 | {
39 | $driver = $this->repository->getDriver($request->getDriverId());
40 |
41 | $driver->createSession()->run('RETURN 2 as x');
42 |
43 | return new DriverResponse($request->getDriverId());
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Request.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend;
15 |
16 | final class Request
17 | {
18 | public function __construct(string $name, array $data)
19 | {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/AuthorizationTokenRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | final class AuthorizationTokenRequest
17 | {
18 | public function __construct(
19 | public readonly string $scheme,
20 | public readonly string $realm,
21 | public readonly string $principal,
22 | public readonly string $credentials,
23 | ) {
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/CheckMultiDBSupportRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class CheckMultiDBSupportRequest
19 | {
20 | private Uuid $driverId;
21 |
22 | public function __construct(Uuid $driverId)
23 | {
24 | $this->driverId = $driverId;
25 | }
26 |
27 | public function getDriverId(): Uuid
28 | {
29 | return $this->driverId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/DomainNameResolutionCompletedRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class DomainNameResolutionCompletedRequest
19 | {
20 | private Uuid $requestId;
21 | /** @var iterable */
22 | private iterable $addresses;
23 |
24 | /**
25 | * @param iterable $addresses
26 | */
27 | public function __construct(Uuid $requestId, iterable $addresses)
28 | {
29 | $this->requestId = $requestId;
30 | $this->addresses = $addresses;
31 | }
32 |
33 | public function getRequestId(): Uuid
34 | {
35 | return $this->requestId;
36 | }
37 |
38 | /**
39 | * @return iterable
40 | */
41 | public function getAddresses(): iterable
42 | {
43 | return $this->addresses;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/DriverCloseRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class DriverCloseRequest
19 | {
20 | private Uuid $driverId;
21 |
22 | public function __construct(Uuid $driverId)
23 | {
24 | $this->driverId = $driverId;
25 | }
26 |
27 | public function getDriverId(): Uuid
28 | {
29 | return $this->driverId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/ForcedRoutingTableUpdateRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class ForcedRoutingTableUpdateRequest
19 | {
20 | private Uuid $driverId;
21 | private ?string $database;
22 | /** @var iterable */
23 | private ?iterable $bookmarks;
24 |
25 | /**
26 | * @param iterable $bookmarks
27 | */
28 | public function __construct(Uuid $driverId, ?string $database, ?iterable $bookmarks)
29 | {
30 | $this->driverId = $driverId;
31 | $this->database = $database;
32 | $this->bookmarks = $bookmarks;
33 | }
34 |
35 | public function getDriverId(): Uuid
36 | {
37 | return $this->driverId;
38 | }
39 |
40 | public function getDatabase(): ?string
41 | {
42 | return $this->database;
43 | }
44 |
45 | /**
46 | * @return iterable
47 | */
48 | public function getBookmarks(): ?iterable
49 | {
50 | return $this->bookmarks;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/GetFeaturesRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | final class GetFeaturesRequest
17 | {
18 | }
19 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/GetRoutingTableRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class GetRoutingTableRequest
19 | {
20 | private Uuid $driverId;
21 | private ?string $database;
22 |
23 | public function __construct(Uuid $driverId, ?string $database)
24 | {
25 | $this->driverId = $driverId;
26 | $this->database = $database;
27 | }
28 |
29 | public function getDriverId(): Uuid
30 | {
31 | return $this->driverId;
32 | }
33 |
34 | public function getDatabase(): ?string
35 | {
36 | return $this->database;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/NewDriverRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | /*
17 | * This file is part of the Laudis Neo4j package.
18 | *
19 | * (c) Laudis technologies
20 | *
21 | * For the full copyright and license information, please view the LICENSE
22 | * file that was distributed with this source code.
23 | */
24 |
25 | namespace Laudis\Neo4j\TestkitBackend\Requests;
26 |
27 | final class NewDriverRequest
28 | {
29 | public function __construct(
30 | public readonly string $uri,
31 | public readonly AuthorizationTokenRequest $authToken,
32 | public readonly ?string $authTokenManagerId = null,
33 | public readonly ?string $userAgent = null,
34 | public readonly ?bool $resolverRegistered = null,
35 | public readonly ?bool $domainNameResolverRegistered = null,
36 | public readonly ?int $connectionTimeoutMs = null,
37 | public readonly ?int $fetchSize = null,
38 | public readonly ?int $maxTxRetryTimeMs = null,
39 | public readonly ?int $livenessCheckTimeoutMs = null,
40 | public readonly ?int $maxConnectionPoolSize = null,
41 | public readonly ?int $connectionAcquisitionTimeoutMs = null,
42 | public readonly mixed $clientCertificate = null,
43 | public readonly ?string $clientCertificateProviderId = null,
44 | ) {
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/NewSessionRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class NewSessionRequest
19 | {
20 | /**
21 | * @param list|null $bookmarks
22 | */
23 | public function __construct(
24 | public Uuid $driverId,
25 | public string $accessMode,
26 | public ?array $bookmarks,
27 | public ?string $database,
28 | public ?int $fetchSize,
29 | public ?string $impersonatedUser,
30 | ) {
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/ResolverResolutionCompletedRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class ResolverResolutionCompletedRequest
19 | {
20 | private Uuid $requestId;
21 | /** @var iterable */
22 | private iterable $addresses;
23 |
24 | /**
25 | * @param iterable $addresses
26 | */
27 | public function __construct(Uuid $requestId, iterable $addresses)
28 | {
29 | $this->requestId = $requestId;
30 | $this->addresses = $addresses;
31 | }
32 |
33 | public function getRequestId(): Uuid
34 | {
35 | return $this->requestId;
36 | }
37 |
38 | /**
39 | * @return iterable
40 | */
41 | public function getAddresses(): iterable
42 | {
43 | return $this->addresses;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/ResultConsumeRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class ResultConsumeRequest
19 | {
20 | private Uuid $resultId;
21 |
22 | public function __construct(Uuid $resultId)
23 | {
24 | $this->resultId = $resultId;
25 | }
26 |
27 | public function getResultId(): Uuid
28 | {
29 | return $this->resultId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/ResultNextRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class ResultNextRequest
19 | {
20 | private Uuid $resultId;
21 |
22 | public function __construct(Uuid $resultId)
23 | {
24 | $this->resultId = $resultId;
25 | }
26 |
27 | public function getResultId(): Uuid
28 | {
29 | return $this->resultId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/ResultSingleRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class ResultSingleRequest
19 | {
20 | private Uuid $resultId;
21 |
22 | public function __construct(Uuid $resultId)
23 | {
24 | $this->resultId = $resultId;
25 | }
26 |
27 | public function getResultId(): Uuid
28 | {
29 | return $this->resultId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/RetryableNegativeRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class RetryableNegativeRequest
19 | {
20 | private Uuid $sessionId;
21 | /** @var Uuid|string */
22 | private $errorId;
23 |
24 | /**
25 | * @param Uuid|string $errorId
26 | */
27 | public function __construct(Uuid $sessionId, $errorId)
28 | {
29 | $this->sessionId = $sessionId;
30 | $this->errorId = $errorId;
31 | }
32 |
33 | public function getSessionId(): Uuid
34 | {
35 | return $this->sessionId;
36 | }
37 |
38 | /**
39 | * @return Uuid|string
40 | */
41 | public function getErrorId()
42 | {
43 | return $this->errorId;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/RetryablePositiveRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class RetryablePositiveRequest
19 | {
20 | private Uuid $sessionId;
21 |
22 | public function __construct(Uuid $sessionId)
23 | {
24 | $this->sessionId = $sessionId;
25 | }
26 |
27 | public function getSessionId(): Uuid
28 | {
29 | return $this->sessionId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionBeginTransactionRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Laudis\Neo4j\Databags\TransactionConfiguration;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | final class SessionBeginTransactionRequest
20 | {
21 | private Uuid $sessionId;
22 | /** @var iterable|null */
23 | private ?iterable $txMeta;
24 | private ?int $timeout;
25 |
26 | /**
27 | * @param iterable|null $txMeta
28 | */
29 | public function __construct(
30 | Uuid $sessionId,
31 | ?iterable $txMeta = null,
32 | ?int $timeout = null,
33 | ) {
34 | $this->sessionId = $sessionId;
35 | $this->txMeta = $txMeta;
36 | $this->timeout = $timeout;
37 | }
38 |
39 | public function getSessionId(): Uuid
40 | {
41 | return $this->sessionId;
42 | }
43 |
44 | /**
45 | * @return iterable
46 | */
47 | public function getTxMeta(): iterable
48 | {
49 | return $this->txMeta ?? [];
50 | }
51 |
52 | public function getTimeout(): int
53 | {
54 | return (int) ($this->timeout ?? TransactionConfiguration::DEFAULT_TIMEOUT);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionCloseRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class SessionCloseRequest
19 | {
20 | private Uuid $sessionId;
21 |
22 | public function __construct(Uuid $sessionId)
23 | {
24 | $this->sessionId = $sessionId;
25 | }
26 |
27 | public function getSessionId(): Uuid
28 | {
29 | return $this->sessionId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionLastBookmarksRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class SessionLastBookmarksRequest
19 | {
20 | private Uuid $sessionId;
21 |
22 | public function __construct(Uuid $sessionId)
23 | {
24 | $this->sessionId = $sessionId;
25 | }
26 |
27 | public function getSessionId(): Uuid
28 | {
29 | return $this->sessionId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionReadTransactionRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class SessionReadTransactionRequest
19 | {
20 | private Uuid $sessionId;
21 | /** @var iterable */
22 | private iterable $txMeta;
23 | private ?int $timeout;
24 |
25 | /**
26 | * @param iterable|null $txMeta
27 | */
28 | public function __construct(
29 | Uuid $sessionId,
30 | ?iterable $txMeta = null,
31 | ?int $timeout = null,
32 | ) {
33 | $this->sessionId = $sessionId;
34 | $this->txMeta = $txMeta ?? [];
35 | $this->timeout = $timeout;
36 | }
37 |
38 | public function getSessionId(): Uuid
39 | {
40 | return $this->sessionId;
41 | }
42 |
43 | /**
44 | * @return iterable
45 | */
46 | public function getTxMeta(): iterable
47 | {
48 | return $this->txMeta;
49 | }
50 |
51 | public function getTimeout(): ?int
52 | {
53 | return $this->timeout;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionRunRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class SessionRunRequest
19 | {
20 | /**
21 | * @param iterable|null $params
22 | * @param iterable|null $txMeta
23 | */
24 | public function __construct(
25 | private Uuid $sessionId,
26 | private string $cypher,
27 | private ?iterable $params = null,
28 | private ?iterable $txMeta = null,
29 | private ?float $timeout = null,
30 | ) {
31 | }
32 |
33 | public function getSessionId(): Uuid
34 | {
35 | return $this->sessionId;
36 | }
37 |
38 | public function getCypher(): string
39 | {
40 | return $this->cypher;
41 | }
42 |
43 | /**
44 | * @return iterable
45 | */
46 | public function getParams(): iterable
47 | {
48 | return $this->params ?? [];
49 | }
50 |
51 | /**
52 | * @return iterable|null
53 | */
54 | public function getTxMeta(): ?iterable
55 | {
56 | return $this->txMeta;
57 | }
58 |
59 | public function getTimeout(): ?float
60 | {
61 | return $this->timeout;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/SessionWriteTransactionRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class SessionWriteTransactionRequest
19 | {
20 | private Uuid $sessionId;
21 | /** @var iterable */
22 | private iterable $txMeta;
23 | private ?int $timeout;
24 |
25 | /**
26 | * @param iterable|null $txMeta
27 | */
28 | public function __construct(
29 | Uuid $sessionId,
30 | ?iterable $txMeta = null,
31 | ?int $timeout = null,
32 | ) {
33 | $this->sessionId = $sessionId;
34 | $this->txMeta = $txMeta ?? [];
35 | $this->timeout = $timeout;
36 | }
37 |
38 | public function getSessionId(): Uuid
39 | {
40 | return $this->sessionId;
41 | }
42 |
43 | /**
44 | * @return iterable
45 | */
46 | public function getTxMeta(): iterable
47 | {
48 | return $this->txMeta;
49 | }
50 |
51 | public function getTimeout(): ?int
52 | {
53 | return $this->timeout;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/StartTestRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | final class StartTestRequest
17 | {
18 | private string $testName;
19 |
20 | public function __construct(string $testName)
21 | {
22 | $this->testName = $testName;
23 | }
24 |
25 | public function getTestName(): string
26 | {
27 | return $this->testName;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/TransactionCommitRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class TransactionCommitRequest
19 | {
20 | private Uuid $txId;
21 |
22 | public function __construct(Uuid $txId)
23 | {
24 | $this->txId = $txId;
25 | }
26 |
27 | public function getTxId(): Uuid
28 | {
29 | return $this->txId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/TransactionRollbackRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class TransactionRollbackRequest
19 | {
20 | private Uuid $txId;
21 |
22 | public function __construct(Uuid $txId)
23 | {
24 | $this->txId = $txId;
25 | }
26 |
27 | public function getTxId(): Uuid
28 | {
29 | return $this->txId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/TransactionRunRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class TransactionRunRequest
19 | {
20 | /**
21 | * @param iterable|null $params
22 | */
23 | public function __construct(
24 | private Uuid $txId,
25 | private string $cypher,
26 | private ?iterable $params = null,
27 | private ?float $timeout = null,
28 | ) {
29 | }
30 |
31 | public function getTxId(): Uuid
32 | {
33 | return $this->txId;
34 | }
35 |
36 | public function getCypher(): string
37 | {
38 | return $this->cypher;
39 | }
40 |
41 | /**
42 | * @return iterable
43 | */
44 | public function getParams(): iterable
45 | {
46 | return $this->params ?? [];
47 | }
48 |
49 | public function getTimeout(): ?float
50 | {
51 | return $this->timeout;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/testkit-backend/src/Requests/VerifyConnectivityRequest.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Requests;
15 |
16 | use Symfony\Component\Uid\Uuid;
17 |
18 | final class VerifyConnectivityRequest
19 | {
20 | private Uuid $driverId;
21 |
22 | public function __construct(Uuid $driverId)
23 | {
24 | $this->driverId = $driverId;
25 | }
26 |
27 | public function getDriverId(): Uuid
28 | {
29 | return $this->driverId;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/BackendErrorResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Indicates an internal error has occurred.
20 | */
21 | final class BackendErrorResponse implements TestkitResponseInterface
22 | {
23 | private string $message;
24 |
25 | public function __construct(string $message)
26 | {
27 | $this->message = $message;
28 | }
29 |
30 | public function jsonSerialize(): array
31 | {
32 | return [
33 | 'name' => 'BackendError',
34 | 'data' => [
35 | 'msg' => $this->message,
36 | ],
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/BookmarksResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Represents an array of bookmarks.
20 | */
21 | final class BookmarksResponse implements TestkitResponseInterface
22 | {
23 | /**
24 | * @var iterable
25 | */
26 | private iterable $bookmarks;
27 |
28 | /**
29 | * @param iterable $bookmarks
30 | */
31 | public function __construct(iterable $bookmarks)
32 | {
33 | $this->bookmarks = $bookmarks;
34 | }
35 |
36 | public function jsonSerialize(): array
37 | {
38 | return [
39 | 'name' => 'Bookmarks',
40 | 'data' => [
41 | 'bookmarks' => $this->bookmarks,
42 | ],
43 | ];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/DomainNameResolutionRequiredResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a need for new address resolution.
21 | *
22 | * This means that the backend expects the frontend to call the resolver function and submit a new request
23 | * with the results of it.
24 | */
25 | final class DomainNameResolutionRequiredResponse implements TestkitResponseInterface
26 | {
27 | private Uuid $id;
28 | private string $name;
29 |
30 | public function __construct(Uuid $id, string $name)
31 | {
32 | $this->id = $id;
33 | $this->name = $name;
34 | }
35 |
36 | public function jsonSerialize(): array
37 | {
38 | return [
39 | 'name' => 'DomainNameResolutionRequired',
40 | 'data' => [
41 | 'id' => $this->id->toRfc4122(),
42 | 'name' => $this->name,
43 | ],
44 | ];
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/DriverErrorResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\Exception\Neo4jException;
17 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
18 | use Symfony\Component\Uid\Uuid;
19 |
20 | /**
21 | * Base class for all kind of driver errors that is NOT a backend specific error.
22 | */
23 | final class DriverErrorResponse implements TestkitResponseInterface
24 | {
25 | private Uuid $id;
26 | private Neo4jException $exception;
27 |
28 | public function __construct(Uuid $id, Neo4jException $exception)
29 | {
30 | $this->id = $id;
31 | $this->exception = $exception;
32 | }
33 |
34 | public function jsonSerialize(): array
35 | {
36 | return [
37 | 'name' => 'DriverError',
38 | 'data' => [
39 | 'id' => $this->id->toRfc4122(),
40 | 'code' => $this->exception->getNeo4jCode(),
41 | 'msg' => $this->exception->getNeo4jMessage(),
42 | ],
43 | ];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/DriverResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents the driver instance in the backend.
21 | */
22 | final class DriverResponse implements TestkitResponseInterface
23 | {
24 | private Uuid $id;
25 |
26 | public function __construct(Uuid $id)
27 | {
28 | $this->id = $id;
29 | }
30 |
31 | public function jsonSerialize(): array
32 | {
33 | return [
34 | 'name' => 'Driver',
35 | 'data' => [
36 | 'id' => $this->id->toRfc4122(),
37 | ],
38 | ];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/FeatureListResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Indicates the features the driver supports.
20 | */
21 | final class FeatureListResponse implements TestkitResponseInterface
22 | {
23 | private array $features;
24 |
25 | public function __construct(array $features)
26 | {
27 | $this->features = $features;
28 | }
29 |
30 | public function jsonSerialize(): array
31 | {
32 | return [
33 | 'name' => 'FeatureList',
34 | 'data' => [
35 | 'features' => $this->features,
36 | ],
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/FrontendErrorResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Represents an error originating from client code.
20 | */
21 | final class FrontendErrorResponse implements TestkitResponseInterface
22 | {
23 | private string $message;
24 |
25 | public function __construct(string $message)
26 | {
27 | $this->message = $message;
28 | }
29 |
30 | public function jsonSerialize(): array
31 | {
32 | return [
33 | 'name' => 'FrontendError',
34 | 'data' => [
35 | 'msg' => $this->message,
36 | ],
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/MultiDBSupportResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Specifies whether the server or cluster the driver connects to supports multi-databases.
21 | */
22 | final class MultiDBSupportResponse implements TestkitResponseInterface
23 | {
24 | private Uuid $id;
25 | private bool $available;
26 |
27 | public function __construct(Uuid $id, bool $available)
28 | {
29 | $this->id = $id;
30 | $this->available = $available;
31 | }
32 |
33 | public function jsonSerialize(): array
34 | {
35 | return [
36 | 'name' => 'MultiDBSupport',
37 | 'data' => [
38 | 'id' => $this->id,
39 | 'available' => $this->available,
40 | ],
41 | ];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/NullRecordResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Represents the record end when iterating through it.
20 | */
21 | final class NullRecordResponse implements TestkitResponseInterface
22 | {
23 | public function jsonSerialize(): array
24 | {
25 | return [
26 | 'name' => 'NullRecord',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/RecordResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Represents a record from a result.
20 | */
21 | final class RecordResponse implements TestkitResponseInterface
22 | {
23 | /**
24 | * @var iterable
25 | */
26 | private iterable $values;
27 |
28 | /**
29 | * @param iterable $values
30 | */
31 | public function __construct(iterable $values)
32 | {
33 | $this->values = $values;
34 | }
35 |
36 | public function jsonSerialize(): array
37 | {
38 | return [
39 | 'name' => 'Record',
40 | 'data' => [
41 | 'values' => $this->values,
42 | ],
43 | ];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/ResolverResolutionRequiredResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a need for new address resolution.
21 | *
22 | * This means that the backend is expecting the frontend to call the resolver function and submit a new request
23 | * with the results of it.
24 | */
25 | final class ResolverResolutionRequiredResponse implements TestkitResponseInterface
26 | {
27 | private Uuid $id;
28 | private string $address;
29 |
30 | public function __construct(Uuid $id, string $address)
31 | {
32 | $this->id = $id;
33 | $this->address = $address;
34 | }
35 |
36 | public function jsonSerialize(): array
37 | {
38 | return [
39 | 'name' => 'ResolverResolutionRequired',
40 | 'data' => [
41 | 'id' => $this->id->toRfc4122(),
42 | 'address' => $this->address,
43 | ],
44 | ];
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/ResultResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a result instance on the backend.
21 | */
22 | final class ResultResponse implements TestkitResponseInterface
23 | {
24 | private Uuid $id;
25 | private iterable $keys;
26 |
27 | /**
28 | * @param iterable $keys
29 | */
30 | public function __construct(Uuid $id, iterable $keys)
31 | {
32 | $this->id = $id;
33 | $this->keys = $keys;
34 | }
35 |
36 | public function jsonSerialize(): array
37 | {
38 | return [
39 | 'name' => 'Result',
40 | 'data' => [
41 | 'id' => $this->id->toRfc4122(),
42 | 'keys' => $this->keys,
43 | ],
44 | ];
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/RetryableDoneResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Indicates a retryable transaction is successfully committed.
20 | */
21 | final class RetryableDoneResponse implements TestkitResponseInterface
22 | {
23 | public function jsonSerialize(): array
24 | {
25 | return [
26 | 'name' => 'RetryableDone',
27 | 'data' => [],
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/RetryableTryResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a retryable transaction. The backend created a transaction and will use a retryable function.
21 | * All further requests will be applied through that retryable function.
22 | */
23 | final class RetryableTryResponse implements TestkitResponseInterface
24 | {
25 | private Uuid $id;
26 |
27 | public function __construct(Uuid $id)
28 | {
29 | $this->id = $id;
30 | }
31 |
32 | public function jsonSerialize(): array
33 | {
34 | return [
35 | 'name' => 'RetryableTry',
36 | 'data' => [
37 | 'id' => $this->id->toRfc4122(),
38 | ],
39 | ];
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/RoutingTableResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Represents the full routing table.
20 | */
21 | final class RoutingTableResponse implements TestkitResponseInterface
22 | {
23 | private ?string $database;
24 | private int $ttl;
25 | /** @var iterable */
26 | private iterable $routers;
27 | /** @var iterable */
28 | private iterable $readers;
29 | /** @var iterable */
30 | private iterable $writers;
31 |
32 | /**
33 | * @param iterable $routers
34 | * @param iterable $readers
35 | * @param iterable $writers
36 | */
37 | public function __construct(?string $database, int $ttl, iterable $routers, iterable $readers, iterable $writers)
38 | {
39 | $this->database = $database;
40 | $this->ttl = $ttl;
41 | $this->routers = $routers;
42 | $this->readers = $readers;
43 | $this->writers = $writers;
44 | }
45 |
46 | public function jsonSerialize(): array
47 | {
48 | return [
49 | 'name' => 'RoutingTable',
50 | 'data' => [
51 | 'database' => $this->database,
52 | 'ttl' => $this->ttl,
53 | 'routers' => $this->routers,
54 | 'readers' => $this->readers,
55 | 'writers' => $this->writers,
56 | ],
57 | ];
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/RunTestResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Indicates the test can start.
20 | */
21 | final class RunTestResponse implements TestkitResponseInterface
22 | {
23 | public function jsonSerialize(): array
24 | {
25 | return [
26 | 'name' => 'RunTest',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/SessionResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a session instance on the backend.
21 | */
22 | final class SessionResponse implements TestkitResponseInterface
23 | {
24 | private Uuid $id;
25 |
26 | public function __construct(Uuid $id)
27 | {
28 | $this->id = $id;
29 | }
30 |
31 | public function jsonSerialize(): array
32 | {
33 | return [
34 | 'name' => 'Session',
35 | 'data' => [
36 | 'id' => $this->id->toRfc4122(),
37 | ],
38 | ];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/SkipTestResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | /**
19 | * Indicates the test should be skipped.
20 | */
21 | final class SkipTestResponse implements TestkitResponseInterface
22 | {
23 | private string $reason;
24 |
25 | public function __construct(string $reason)
26 | {
27 | $this->reason = $reason;
28 | }
29 |
30 | public function jsonSerialize(): array
31 | {
32 | return [
33 | 'name' => 'SkipTest',
34 | 'data' => [
35 | 'reason' => $this->reason,
36 | ],
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/TransactionResponse.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 | use Symfony\Component\Uid\Uuid;
18 |
19 | /**
20 | * Represents a transaction instance on the backend.
21 | */
22 | final class TransactionResponse implements TestkitResponseInterface
23 | {
24 | private Uuid $id;
25 |
26 | public function __construct(Uuid $id)
27 | {
28 | $this->id = $id;
29 | }
30 |
31 | public function jsonSerialize(): array
32 | {
33 | return [
34 | 'name' => 'Transaction',
35 | 'data' => [
36 | 'id' => $this->id->toRfc4122(),
37 | ],
38 | ];
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/Types/CypherNode.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses\Types;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | final class CypherNode implements TestkitResponseInterface
19 | {
20 | private CypherObject $id;
21 | private CypherObject $labels;
22 | private CypherObject $props;
23 | private CypherObject $elementId;
24 |
25 | public function __construct(CypherObject $id, CypherObject $labels, CypherObject $props, CypherObject $elementId)
26 | {
27 | $this->id = $id;
28 | $this->labels = $labels;
29 | $this->props = $props;
30 | $this->elementId = $elementId;
31 | }
32 |
33 | public function jsonSerialize(): array
34 | {
35 | return [
36 | 'name' => 'CypherNode',
37 | 'data' => [
38 | 'id' => $this->id,
39 | 'labels' => $this->labels,
40 | 'props' => $this->props,
41 | 'elementId' => $this->elementId,
42 | ],
43 | ];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/Types/CypherPath.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses\Types;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | final class CypherPath implements TestkitResponseInterface
19 | {
20 | private CypherObject $nodes;
21 | private CypherObject $relationships;
22 |
23 | public function __construct(CypherObject $nodes, CypherObject $relationships)
24 | {
25 | $this->nodes = $nodes;
26 | $this->relationships = $relationships;
27 | }
28 |
29 | public function jsonSerialize(): array
30 | {
31 | return [
32 | 'name' => 'CypherPath',
33 | 'data' => [
34 | 'nodes' => $this->nodes,
35 | 'relationships' => $this->relationships,
36 | ],
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/testkit-backend/src/Responses/Types/CypherRelationship.php:
--------------------------------------------------------------------------------
1 |
9 | *
10 | * For the full copyright and license information, please view the LICENSE
11 | * file that was distributed with this source code.
12 | */
13 |
14 | namespace Laudis\Neo4j\TestkitBackend\Responses\Types;
15 |
16 | use Laudis\Neo4j\TestkitBackend\Contracts\TestkitResponseInterface;
17 |
18 | final class CypherRelationship implements TestkitResponseInterface
19 | {
20 | private CypherObject $id;
21 | private CypherObject $startNodeId;
22 | private CypherObject $endNodeId;
23 | private CypherObject $type;
24 | private CypherObject $props;
25 | private CypherObject $elementId;
26 |
27 | public function __construct(CypherObject $id, CypherObject $startNodeId, CypherObject $endNodeId, CypherObject $type, CypherObject $props, CypherObject $elementId)
28 | {
29 | $this->id = $id;
30 | $this->startNodeId = $startNodeId;
31 | $this->endNodeId = $endNodeId;
32 | $this->type = $type;
33 | $this->props = $props;
34 | $this->elementId = $elementId;
35 | }
36 |
37 | public function jsonSerialize(): array
38 | {
39 | return [
40 | 'name' => 'CypherRelationship',
41 | 'data' => [
42 | 'id' => $this->id,
43 | 'startNodeId' => $this->startNodeId,
44 | 'endNodeId' => $this->endNodeId,
45 | 'type' => $this->type,
46 | 'props' => $this->props,
47 | 'elementId' => $this->elementId,
48 | ],
49 | ];
50 | }
51 | }
52 |
--------------------------------------------------------------------------------