Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 16 additions & 21 deletions libs/php-api-client-base/src/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,22 @@ static function (callable $handler) use ($authenticator): callable {
]);
}

public function sendRequest(RequestInterface $request): void
/**
* @param array<string, mixed> $options
*/
public function sendRequest(RequestInterface $request, array $options = []): ResponseInterface
{
$this->doSendRequest($request);
try {
return $this->httpClient->send($request, $options);
} catch (RequestException $e) {
throw $this->processRequestException($e);
} catch (GuzzleException $e) {
throw new $this->exceptionClass($e->getMessage(), 0, $e, null, null);
} catch (Throwable $e) {
// Non-Guzzle failure bubbling out of the handler stack — e.g. an authenticator
// that could not produce credentials (after retries are exhausted).
throw new $this->exceptionClass(trim($e->getMessage()), 0, $e, null, null);
}
}

/**
Expand All @@ -130,7 +143,7 @@ public function sendRequestAndMapResponse(
array $options = [],
bool $isList = false,
) {
$response = $this->doSendRequest($request, $options);
$response = $this->sendRequest($request, $options);
$body = $response->getBody()->getContents();

try {
Expand Down Expand Up @@ -165,24 +178,6 @@ public function sendRequestAndMapResponse(
}
}

/**
* @param array<string, mixed> $options
*/
private function doSendRequest(RequestInterface $request, array $options = []): ResponseInterface
{
try {
return $this->httpClient->send($request, $options);
} catch (RequestException $e) {
throw $this->processRequestException($e);
} catch (GuzzleException $e) {
throw new $this->exceptionClass($e->getMessage(), 0, $e, null, null);
} catch (Throwable $e) {
// Non-Guzzle failure bubbling out of the handler stack — e.g. an authenticator
// that could not produce credentials (after retries are exhausted).
throw new $this->exceptionClass(trim($e->getMessage()), 0, $e, null, null);
}
}

private function processRequestException(RequestException $e): ClientException
{
$response = $e->getResponse();
Expand Down
13 changes: 13 additions & 0 deletions libs/php-api-client-base/tests/ApiClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ public function testAddsAuthHeaderPerRequest(): void
self::assertSame('secret-token', $last->getHeaderLine('X-KBC-ManageApiToken'));
}

public function testSendRequestReturnsResponse(): void
{
$mock = new MockHandler([new Response(201, [], '{"hello":"world"}')]);
$client = new ApiClient('https://example.test', new NoAuthAuthenticator(), new ApiClientOptions(
requestHandler: HandlerStack::create($mock),
));

$response = $client->sendRequest(new Request('GET', 'foo'));

self::assertSame(201, $response->getStatusCode());
self::assertSame('{"hello":"world"}', (string) $response->getBody());
}

public function testMapsResponseToModel(): void
{
$mock = new MockHandler([new Response(200, [], '{"name":"foo"}')]);
Expand Down
36 changes: 22 additions & 14 deletions libs/sync-actions-api-php-client/README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
# Sync Actions PHP Client

PHP client for the Job Queue API ([API docs](https://app.swaggerhub.com/apis-docs/keboola/job-queue-api/1.0.0)).
PHP client for the Keboola sync actions API, built on top of
[`keboola/php-api-client-base`](../php-api-client-base).

## Usage
```bash
composer require keboola/sync-actions-api-php-client
composer require keboola/sync-actions-client
```

```php
use Keboola\SyncActionsClient\Client;
use Keboola\SyncActionsClient\JobData;
use Psr\Log\NullLogger;
use Keboola\SyncActionsClient\ActionData;
use Keboola\SyncActionsClient\SyncActionsApiClient;

$client = new Client(
'http://sync-actions.keboola.com/',
'xxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
$client = new SyncActionsApiClient(
'https://sync-actions.keboola.com/',
'xxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
);
$result = $client->createJob(new JobData(

// Invoke a component action; $response->data is a stdClass with the raw action payload.
$response = $client->callAction(new ActionData(
'keboola.ex-db-snowflake',
'getTables'
'getTables',
));
var_dump($result);
var_dump($response->data);

// List the actions a component exposes.
$actions = $client->getActions('keboola.ex-db-snowflake');
var_dump($actions->actions);
```

Failures throw `Keboola\SyncActionsClient\Exception\SyncActionsClientException`.

## Development

Clone this repository and init the workspace with following command:

```
Expand All @@ -46,7 +54,7 @@ Run the test suite using this command:
```
docker-compose run --rm dev composer tests
```

# Integration

For information about deployment and integration with KBC, please refer to the [deployment section of developers documentation](https://developers.keboola.com/extend/component/deployment/)
For information about deployment and integration with KBC, please refer to the [deployment section of developers documentation](https://developers.keboola.com/extend/component/deployment/)
14 changes: 10 additions & 4 deletions libs/sync-actions-api-php-client/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,27 @@
],
"type": "library",
"license": "MIT",
"repositories": {
"libs": {
"type": "path",
"url": "../../libs/*"
}
},
"require": {
"php": "^8.4",
"guzzlehttp/guzzle": "^7.8",
"keboola/php-api-client-base": "*@dev",
"psr/log": "^3.0",
"symfony/config": "^7.3",
"symfony/validator": "^7.3"
"webmozart/assert": "^1.11"
},
"require-dev": {
"keboola/coding-standard": ">=16.0",
"keboola/php-temp": "^2.0",
"monolog/monolog": "^3.9",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^12.3",
"symfony/process": "^7.3",
"symfony/dotenv": "^7.3",
"monolog/monolog": "^3.9"
"symfony/process": "^7.3"
},
"autoload": {
"psr-4": {
Expand Down
10 changes: 9 additions & 1 deletion libs/sync-actions-api-php-client/phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
parameters:
level: max
# The client validates non-empty-string params at runtime (Assert::stringNotEmpty) for
# callers who bypass the type hints, so don't treat those PHPDoc types as certain.
treatPhpDocTypesAsCertain: false
paths:
- src
- tests
ignoreErrors:
- identifier: missingType.iterableValue
- identifier: missingType.iterableValue
# Guzzle's Middleware::history() types its by-ref container as array|ArrayAccess,
# so PHPStan cannot verify the (correct) @param-out type of the test request handler.
-
identifier: paramOut.type
path: tests/ApiClientTestTrait.php
25 changes: 0 additions & 25 deletions libs/sync-actions-api-php-client/src/ApiClientConfiguration.php

This file was deleted.

Loading
Loading