diff --git a/.gitignore b/.gitignore index 7021d1d..0983d73 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .php_cs .php_cs.cache .phpunit.result.cache +.phpunit.cache .vscode clover.xml composer.lock diff --git a/docs/arangodb-client.md b/docs/arangodb-client.md index 12cafe6..c547619 100644 --- a/docs/arangodb-client.md +++ b/docs/arangodb-client.md @@ -66,8 +66,28 @@ Send a request to ArangoDB's HTTP REST API. This is mostly for internal use but $arangoClient->request( 'get', '/_api/version', - 'query' => [ - 'details' => $details + [ + 'query' => [ + 'details' => $details + ] + ] +]); +``` + +### rawRequest(string $method, string $uri, array|HttpRequestOptions $options = []): ResponseInterface|null +Returns the raw response of the request. +*Note* that the request itself is made against the configured endpoint but the databasename is _not_ automatically +prepended to the uri as opposed to a regular request. + + +``` +$arangoClient->rawRequest( + 'get', + '/_api/version', + [ + 'query' => [ + 'details' => $details + ] ] ]); ``` @@ -106,4 +126,27 @@ $arangoClient->schema()->createCollection('users'); Pass chained method to the admin manager. ``` $arangoClient->admin()->getVersion(); +``` + +### connect(array $config = [], ?GuzzleClient $httpClient = null): void +You can update the config by calling the connect method. This replaces the underlying connection +and prepares the connection for any requests that follow. + +``` +$config = [ + 'host' => 'http://localhost', + 'port' => '8529', + 'username' => 'your-other-database-username', + 'password' => 'your-other-database-password', + 'database'=> 'your-other-database' +]; + +$arangoClient->connect($config): void +``` + +### disconnect(): bool +Disconnect from the current keep-alive connection, if any. + +``` +$arangoClient->disconnect(); ``` \ No newline at end of file diff --git a/src/ArangoClient.php b/src/ArangoClient.php index e5d42e7..c8336ba 100644 --- a/src/ArangoClient.php +++ b/src/ArangoClient.php @@ -43,13 +43,41 @@ class ArangoClient * @throws UnknownProperties */ public function __construct(array $config = [], ?GuzzleClient $httpClient = null) + { + $this->connect($config, $httpClient); + } + + /** + * ArangoClient constructor. + * + * @param array $config + * @param GuzzleClient|null $httpClient + * + * @throws UnknownProperties + */ + public function connect(array $config = [], ?GuzzleClient $httpClient = null): bool { $config['endpoint'] = $this->generateEndpoint($config); $this->config = new HttpClientConfig($config); $this->httpClient = $httpClient ?? new GuzzleClient($this->config->mapGuzzleHttpClientConfig()); + + return true; } + /** + * We disconnect by creating a new guzzle client. The old client will remove the current connection upon destruction. + * + * @return bool + */ + public function disconnect(): bool + { + $this->httpClient = new GuzzleClient($this->config->mapGuzzleHttpClientConfig()); + + return true; + } + + /** * @param array $config */ @@ -58,10 +86,12 @@ public function generateEndpoint(array $config): string if (isset($config['endpoint'])) { return (string) $config['endpoint']; } + $endpoint = 'http://localhost:8529'; if (isset($config['host'])) { $endpoint = (string) $config['host']; } + if (isset($config['port'])) { $endpoint .= ':' . (string) $config['port']; } @@ -96,6 +126,28 @@ public function request(string $method, string $uri, array|HttpRequestOptions $o return new stdClass(); } + /** + * @param array|HttpRequestOptions $options + * + * @throws ArangoException + */ + public function rawRequest(string $method, string $uri, array|HttpRequestOptions $options = []): ResponseInterface|null + { + if (is_array($options)) { + $options = $this->prepareRequestOptions($options); + } + + $response = null; + try { + $response = $this->httpClient->request($method, $uri, $options->all()); + } catch (Throwable $e) { + $this->handleGuzzleException($e); + } + + return $response; + } + + /** * @param array $options * diff --git a/tests/ArangoClientTest.php b/tests/ArangoClientTest.php index 0187280..05aee95 100644 --- a/tests/ArangoClientTest.php +++ b/tests/ArangoClientTest.php @@ -4,14 +4,18 @@ use ArangoClient\Admin\AdminManager; use ArangoClient\ArangoClient; +use ArangoClient\Http\HttpClientConfig; use ArangoClient\Schema\SchemaManager; use ArangoClient\Statement\Statement; use GuzzleHttp\Client; +use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Middleware; use GuzzleHttp\Psr7\Response; +use function PHPUnit\Framework\assertTrue; + uses(Tests\TestCase::class); test('get config', function () { @@ -46,13 +50,13 @@ test('client with host port config', function () { $config = [ 'host' => 'http://127.0.0.1', - 'port' => '1234', + 'port' => '8529', 'username' => 'root', ]; $client = new ArangoClient($config); $retrievedConfig = $client->getConfig(); - expect($retrievedConfig['endpoint'])->toEqual('http://127.0.0.1:1234'); + expect($retrievedConfig['endpoint'])->toEqual('http://127.0.0.1:8529'); }); test('config with alien properties', function () { @@ -60,7 +64,7 @@ 'name' => 'arangodb', 'driver' => 'arangodb', 'host' => 'http://127.0.0.1', - 'port' => '1234', + 'port' => '8529', 'username' => 'root', ]; $client = new ArangoClient($config); @@ -73,8 +77,26 @@ test('set and get http client', function () { $oldClient = $this->arangoClient->getHttpClient(); - $newClient = Mockery::mock(Client::class); + $defaultConfig = [ + 'endpoint' => 'http://localhost:8529', + 'host' => null, + 'port' => null, + 'version' => 1.1, + 'connection' => 'Keep-Alive', + 'allow_redirects' => false, + 'connect_timeout' => 0.0, + 'username' => 'root', + 'password' => null, + 'database' => $this->testDatabaseName, + 'jsonStreamDecoderThreshold' => 1048576, + ]; + + $config = new HttpClientConfig($defaultConfig); + + $newClient = new GuzzleClient($config->mapGuzzleHttpClientConfig()); + $this->arangoClient->setHttpClient($newClient); + $retrievedClient = $this->arangoClient->getHttpClient(); expect($oldClient)->toBeInstanceOf(Client::class); @@ -89,6 +111,14 @@ expect($result->version)->toBeString(); }); + +test('rawRequest', function () { + $response = $this->arangoClient->rawRequest('get', '/_api/version', []); + + expect($response->getStatusCode())->toBe(200); + expect($response->getHeader('Connection')[0])->toBe('Keep-Alive'); +}); + test('get user', function () { $user = $this->arangoClient->getUser(); expect($user)->toBe('root'); @@ -103,10 +133,13 @@ $database = $this->arangoClient->getDatabase(); expect($database)->toBe($newDatabaseName); + + // Reset DB name + $this->arangoClient->setDatabase($this->testDatabaseName); }); test('database name is used in requests', function () { - $database = 'some_database'; + $database = 'arangodb_php_client__test'; if (!$this->arangoClient->schema()->hasDatabase($database)) { $this->arangoClient->schema()->createDatabase($database); } @@ -234,3 +267,37 @@ $this->schemaManager->deleteCollection($collection); }); + + +test('connect', function () { + $oldHttpClient = $this->arangoClient->getHttpClient(); + $oldHttpClientObjectId = spl_object_id($oldHttpClient); + + $newConfig = [ + 'endpoint' => 'http://localhost:8529', + 'version' => 2, + 'connection' => 'Close', + 'username' => 'root', + 'password' => null, + 'database' => $this->testDatabaseName, + 'jsonStreamDecoderThreshold' => 1048576, + ]; + + $response = $this->arangoClient->connect($newConfig); + + $newHttpClient = $this->arangoClient->getHttpClient(); + $newHttpClientObjectId = spl_object_id($newHttpClient); + + expect($oldHttpClientObjectId)->not()->toBe($newHttpClientObjectId); + expect($response)->toBeTrue(); + + $this->arangoClient->setHttpClient($oldHttpClient); +}); + + + +test('disconnect', function () { + $disconnected = $this->arangoClient->disconnect(); + + assertTrue($disconnected); +}); diff --git a/tests/ExceptionsTest.php b/tests/ExceptionsTest.php index 668aca1..980e2c6 100644 --- a/tests/ExceptionsTest.php +++ b/tests/ExceptionsTest.php @@ -2,6 +2,8 @@ declare(strict_types=1); +use ArangoClient\Exceptions\ArangoException; + uses(Tests\TestCase::class); test('test409 conflict exception', function () { @@ -18,6 +20,7 @@ test('calls to none existing db throw', function () { $this->arangoClient->setDatabase('NoneExistingDb'); - $this->expectExceptionCode(404); $this->schemaManager->hasCollection('dummy'); -}); + + $this->arangoClient->setDatabase($this->testDatabaseName); +})->throws(ArangoException::class); diff --git a/tests/SchemaManagerGraphsTest.php b/tests/SchemaManagerGraphsTest.php index 0559eab..faa8f7d 100644 --- a/tests/SchemaManagerGraphsTest.php +++ b/tests/SchemaManagerGraphsTest.php @@ -345,4 +345,4 @@ expect($result)->toBeTrue(); expect(count($createdGraphs))->toBe(2); expect(count($finalGraphs))->toBe(0); -})->only(); +});