Skip to content
This repository was archived by the owner on Sep 5, 2025. It is now read-only.
Merged
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
4 changes: 4 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Minimal setup for getting Query API Client
TESTS_QUERY_API_URL=
TESTS_STORAGE_API_TOKEN=
TESTS_STORAGE_API_URL=
28 changes: 28 additions & 0 deletions .github/workflows/branch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build

on:
push:
branches-ignore:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Build development container
run: docker compose build dev

- name: Install dependencies
run: docker compose run --rm dev composer install

- name: Run tests and CI checks
run: |
docker compose run --rm \
-e TESTS_QUERY_API_URL=${{ vars.TESTS_QUERY_API_URL }} \
-e TESTS_STORAGE_API_TOKEN=${{ secrets.TESTS_STORAGE_API_TOKEN }} \
-e TESTS_STORAGE_API_URL=${{ vars.TESTS_STORAGE_API_URL }} \
dev composer ci
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Dependencies
/vendor/

# Environment files (contains sensitive information)
.env

# PHPUnit
.phpunit.result.cache
/build

# Coverage reports
/coverage/

# IDE files
.vscode/
.idea/
.claude/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM php:8.4

ENV COMPOSER_ALLOW_SUPERUSER 1
ARG COMPOSER_FLAGS="--prefer-dist --no-interaction --classmap-authoritative --no-scripts"

RUN apt-get update -q \
&& apt-get install git unzip \
-y --no-install-recommends

RUN echo "memory_limit = -1" >> /usr/local/etc/php/php.ini
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin/ --filename=composer

WORKDIR /code/

COPY composer.json .
RUN composer install $COMPOSER_FLAGS --no-scripts --no-autoloader
COPY . .
RUN composer install $COMPOSER_FLAGS
113 changes: 109 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,114 @@
# Template
# Keboola Query Service API PHP Client

[![Build](https://github.com/keboola/query-api-php-client/actions/workflows/branch.yml/badge.svg)](https://github.com/keboola/query-api-php-client/actions/workflows/branch.yml)

PHP client for Keboola Query Service API.

## Installation

Clone this repository
```shell
composer require keboola/query-api-php-client
```

## Usage

```php
<?php

use Keboola\QueryApi\Client;

$client = new Client([
'url' => 'https://query.keboola.com',
'token' => 'your-storage-api-token'
]);

// Submit a query job
$response = $client->submitQueryJob('main', 'workspace-123', [
'statements' => ['SELECT * FROM table1'],
'transactional' => true
]);

$queryJobId = $response['queryJobId'];

// Get job status
$status = $client->getJobStatus($queryJobId);

// Get job results
$results = $client->getJobResults($queryJobId, $statementId);

// Cancel job
$client->cancelJob($queryJobId, ['reason' => 'User requested cancellation']);

// Health check
$health = $client->healthCheck();
```

## Configuration Options

The client constructor accepts the following configuration options:

- `url` (required): Query Service API URL (e.g., `https://query.keboola.com`)
- `token` (required): Storage API token
- `backoffMaxTries` (optional): Number of retry attempts for failed requests (default: 3)
- `userAgent` (optional): Additional user agent string to append
- `handler` (optional): Custom Guzzle handler stack

**Note**: The `healthCheck()` endpoint does not require authentication and will work without a valid token.

## API Methods

- `submitQueryJob(string $branchId, string $workspaceId, array $requestBody): array`
- `getJobStatus(string $queryJobId): array`
- `getJobResults(string $queryJobId, string $statementId): array`
- `cancelJob(string $queryJobId, array $requestBody = []): array`
- `healthCheck(): array`

## Development

### Running Tests

#### Unit Tests
Run unit tests:
```shell
vendor/bin/phpunit tests/ClientTest.php
```

#### Functional Tests
Functional tests require environment variables to be set:

- `TESTS_STORAGE_API_TOKEN` - Storage API authentication token
- `TESTS_QUERY_API_URL` - Query Service API endpoint URL
- `TESTS_STORAGE_API_URL` - Storage API endpoint URL

Run functional tests:
```shell
vendor/bin/phpunit tests/Functional/
```

#### All Tests
Run all tests:
```shell
composer run tests
```

### Code Quality

Run code style check:
```shell
composer run phpcs
```

Fix code style issues:
```shell
composer run phpcbf
```

## License
Run static analysis:
```shell
composer run phpstan
```

MIT licensed, see [LICENSE](./LICENSE) file.
Run all CI checks. Check [Github Workflows](./.github/workflows) for more details
```shell
composer run ci
```
51 changes: 51 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "keboola/query-api-php-client",
"description": "Keboola Query Service API PHP Client",
"homepage": "https://keboola.com",
"license": "MIT",
"config": {
"lock": false,
"optimize-autoloader": true,
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"autoload": {
"psr-4": {
"Keboola\\QueryApi\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Keboola\\QueryApi\\Tests\\": "tests/"
}
},
"require": {
"php": "^8.4",
"ext-json": "*",
"guzzlehttp/guzzle": "~7.0",
"psr/log": "~1.0"
},
"require-dev": {
"keboola/coding-standard": "^16.0",
"keboola/storage-api-client": "^18.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3",
"symfony/dotenv": "^6.0"
},
"scripts": {
"phpcs": "phpcs -n src tests",
"phpcbf": "phpcbf -n src tests",
"phpstan": "phpstan analyse --no-progress --level=max src tests -c phpstan.neon",
"tests": "phpunit --coverage-clover build/logs/clover.xml --coverage-xml=build/logs/coverage-xml --log-junit=build/logs/phpunit.junit.xml",
"ci": [
"@composer validate --no-check-all --strict",
"@phpcs",
"@phpstan",
"@tests"
]
}
}
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
dev:
image: keboola/query-api-php-client
build: .
volumes:
- ./:/code
working_dir: /code
command: bash
environment:
- TESTS_QUERY_API_URL
- TESTS_STORAGE_API_TOKEN
- TESTS_STORAGE_API_URL
9 changes: 9 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<ruleset name="Keboola">
<description>The Keboola coding standard.</description>

<file>src</file>
<file>tests</file>

<rule ref="./vendor/keboola/coding-standard/src/ruleset.xml"/>
</ruleset>
9 changes: 9 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
parameters:
level: max
paths:
- src
- tests
ignoreErrors:
-
identifier: argument.type
path: tests/ClientTest.php
29 changes: 29 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="tests/bootstrap.php"
executionOrder="depends,defects"
forceCoversAnnotation="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
convertDeprecationsToExceptions="true"
failOnRisky="true"
failOnWarning="true"
verbose="true">
<testsuites>
<testsuite name="unit">
<directory>tests</directory>
<exclude>tests/Functional</exclude>
</testsuite>
<testsuite name="functional">
<directory>tests/Functional</directory>
</testsuite>
</testsuites>

<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
</phpunit>
Loading