diff --git a/src/Configuration.php b/src/Configuration.php index 9ba968f..2faa24c 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -2,11 +2,23 @@ namespace Neo4j\QueryAPI; +use InvalidArgumentException; use Neo4j\QueryAPI\Objects\Bookmarks; use Neo4j\QueryAPI\Enums\AccessMode; final class Configuration { + /** + * Constructor for Configuration class. + * + * @param string $baseUri The base URI for the Neo4j instance. + * @param string $database The name of the database to connect to. + * @param bool $includeCounters Whether to include counters in the response. + * @param Bookmarks $bookmarks Bookmarks for tracking queries. + * @param AccessMode $accessMode The access mode for the connection (read/write). + * + * @throws InvalidArgumentException if $baseUri is empty. + */ public function __construct( public readonly string $baseUri, public readonly string $database = 'neo4j', @@ -14,5 +26,6 @@ public function __construct( public readonly Bookmarks $bookmarks = new Bookmarks([]), public readonly AccessMode $accessMode = AccessMode::WRITE, ) { + } } diff --git a/src/Neo4jQueryAPI.php b/src/Neo4jQueryAPI.php index 1df9868..332ac78 100644 --- a/src/Neo4jQueryAPI.php +++ b/src/Neo4jQueryAPI.php @@ -5,6 +5,7 @@ use Http\Discovery\Psr17FactoryDiscovery; use Http\Discovery\Psr18ClientDiscovery; use http\Exception\RuntimeException; +use InvalidArgumentException; use Neo4j\QueryAPI\Exception\Neo4jException; use Psr\Http\Client\ClientInterface; use Neo4j\QueryAPI\Authentication\AuthenticateInterface; @@ -15,36 +16,63 @@ final class Neo4jQueryAPI { + private Configuration $config; + public function __construct( - private ClientInterface $client, - private ResponseParser $responseParser, - private Neo4jRequestFactory $requestFactory + private ClientInterface $client, + private ResponseParser $responseParser, + private Neo4jRequestFactory $requestFactory, + ?Configuration $config = null ) { + $this->config = $config ?? new Configuration(baseUri: 'http://myaddress'); // Default configuration if not provided } /** * @api */ - public static function login(string $address, AuthenticateInterface $auth = null): self + public static function login(string $address = null, ?AuthenticateInterface $auth = null, ?Configuration $config = null): self { + $config = $config ?? new Configuration(baseUri: $address ?? ''); + if ( + trim($config->baseUri) !== '' && + $address !== null && + trim($address) !== '' && + $config->baseUri !== $address + ) { + throw new InvalidArgumentException(sprintf('Address (%s) as argument is different from address in configuration (%s)', $config->baseUri, $address)); + } + $client = Psr18ClientDiscovery::find(); return new self( client: $client, - responseParser: new ResponseParser( - ogm: new OGM() - ), + responseParser: new ResponseParser(new OGM()), requestFactory: new Neo4jRequestFactory( psr17Factory: Psr17FactoryDiscovery::findRequestFactory(), streamFactory: Psr17FactoryDiscovery::findStreamFactory(), - configuration: new Configuration( - baseUri: $address - ), + configuration: $config, auth: $auth ?? Authentication::fromEnvironment() - ) + ), + config: $config ); } + /** + * @api + */ + public function create(Configuration $configuration, AuthenticateInterface $auth = null): self + { + return self::login(auth: $auth, config: $configuration); + } + + public function getConfig(): Configuration + { + return $this->config; + } + + /** + * Executes a Cypher query. + */ public function run(string $cypher, array $parameters = []): ResultSet { $request = $this->requestFactory->buildRunQueryRequest($cypher, $parameters); @@ -54,13 +82,13 @@ public function run(string $cypher, array $parameters = []): ResultSet } catch (RequestExceptionInterface $e) { $this->handleRequestException($e); } + return $this->responseParser->parseRunQueryResponse($response); } public function beginTransaction(): Transaction { $request = $this->requestFactory->buildBeginTransactionRequest(); - $response = $this->client->sendRequest($request); try { $response = $this->client->sendRequest($request); @@ -82,8 +110,6 @@ public function beginTransaction(): Transaction ); } - - /** * Handles request exceptions by parsing error details and throwing a Neo4jException. * @@ -96,7 +122,7 @@ private function handleRequestException(RequestExceptionInterface $e): void $response = method_exists($e, 'getResponse') ? $e->getResponse() : null; if ($response instanceof ResponseInterface) { - $errorResponse = json_decode((string)$response->getBody(), true); + $errorResponse = json_decode((string) $response->getBody(), true); throw Neo4jException::fromNeo4jResponse($errorResponse, $e); } diff --git a/tests/Integration/Neo4jQueryAPITest.php b/tests/Integration/Neo4jQueryAPITest.php new file mode 100644 index 0000000..bd9bc8a --- /dev/null +++ b/tests/Integration/Neo4jQueryAPITest.php @@ -0,0 +1,42 @@ +expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Address (http://valid.address) as argument is different from address in configuration (http://myaddress)'); + + Neo4jQueryAPI::login('http://myaddress', Authentication::fromEnvironment(), $config); + } + + public function testLoginWithNullConfiguration(): void + { + $config = null; + + $api = Neo4jQueryAPI::login('http://myaddress', Authentication::fromEnvironment(), $config); + + $this->assertInstanceOf(Neo4jQueryAPI::class, $api); + $this->assertEquals('http://myaddress', $api->getConfig()->baseUri); + } + + public function testConfigOnly(): void + { + $config = new Configuration(baseUri: 'http://valid.address'); + + $api = Neo4jQueryAPI::login(auth: Authentication::fromEnvironment(), config: $config); + + $this->assertInstanceOf(Neo4jQueryAPI::class, $api); + $this->assertEquals('http://valid.address', $api->getConfig()->baseUri); + } +}