add connection
This commit is contained in:
parent
33963563ed
commit
7a157033f3
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 ProductFlow B.V.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
45
README.md
Normal file
45
README.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
  [](https://git.d3data.de/D3Private/klicktipp-php-client/raw/branch/main/LICENSE)
|
||||||
|
|
||||||
|
# klicktipp-php-client
|
||||||
|
|
||||||
|
An unofficial client for the Klicktipp API.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
This project can easily be installed through Composer.
|
||||||
|
|
||||||
|
```
|
||||||
|
composer require d3/klicktipp-php-client
|
||||||
|
```
|
||||||
|
|
||||||
|
## Set-up connection
|
||||||
|
Prepare the client for connecting to Klicktipp with your client key and secret key.
|
||||||
|
|
||||||
|
```php
|
||||||
|
$klicktipp = new \D3\KlicktippPhpClient\Klicktipp(
|
||||||
|
$clientkey,
|
||||||
|
$secretkey,
|
||||||
|
new \GuzzleHttp\Client(...) // optional
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## search a subscriber
|
||||||
|
|
||||||
|
```php
|
||||||
|
$subscriberId = $klicktipp->subscriber()->search('me@johndoe.net');
|
||||||
|
$subscriber = $klicktipp->subscriber()->search($subscriberId);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported endpoints (still being added)
|
||||||
|
|
||||||
|
[API](https://www.klicktipp.com/de/support/wissensdatenbank/rest-application-programming-interface-api/)
|
||||||
|
|
||||||
|
:white_check_mark: = Done, and tested<br />
|
||||||
|
:ballot_box_with_check: = Done, but not yet tested<br />
|
||||||
|
:x: = Not yet developed<br />
|
||||||
|
:heavy_exclamation_mark: = deprecated/not supported <br />
|
||||||
|
|
||||||
|
| Endpoint | Status |
|
||||||
|
|--------------------------------------------------------------------------------------|-------------------------|
|
||||||
|
| account | :ballot_box_with_check: |
|
||||||
|
| subscriber | :ballot_box_with_check: |
|
||||||
|
| tag | :white_check_mark: |
|
@ -17,6 +17,8 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.0",
|
"php": ">=8.0",
|
||||||
|
"composer/composer": "^2.7.1",
|
||||||
|
"doctrine/collections": "^1.8.0",
|
||||||
"guzzlehttp/guzzle": "~7.0",
|
"guzzlehttp/guzzle": "~7.0",
|
||||||
"ext-json": "*"
|
"ext-json": "*"
|
||||||
},
|
},
|
||||||
|
173
src/Connection.php
Normal file
173
src/Connection.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* https://www.d3data.de
|
||||||
|
*
|
||||||
|
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||||
|
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||||
|
* @link https://www.oxidmodule.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient;
|
||||||
|
|
||||||
|
use Composer\InstalledVersions;
|
||||||
|
use D3\KlicktippPhpClient\Exceptions\BaseException;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\ClientInterface;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use GuzzleHttp\Exception\RequestException;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
class Connection
|
||||||
|
{
|
||||||
|
public const URL = 'https://api.klicktipp.com/';
|
||||||
|
|
||||||
|
public const USERAGENT = 'Klicktipp-php-client';
|
||||||
|
|
||||||
|
protected string $client_key;
|
||||||
|
|
||||||
|
protected string $secret_key;
|
||||||
|
|
||||||
|
protected ?string $cookie = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the HTTP client (e.g. Guzzle)
|
||||||
|
*/
|
||||||
|
private ClientInterface $client;
|
||||||
|
|
||||||
|
public function __construct(string $client_key, string $secret_key)
|
||||||
|
{
|
||||||
|
$this->client_key = $client_key;
|
||||||
|
$this->secret_key = $secret_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientKey(): string
|
||||||
|
{
|
||||||
|
return $this->client_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSecretKey(): string
|
||||||
|
{
|
||||||
|
return $this->secret_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClientInterface $client
|
||||||
|
*/
|
||||||
|
public function setClient(ClientInterface $client): void
|
||||||
|
{
|
||||||
|
$this->client = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ClientInterface
|
||||||
|
*/
|
||||||
|
public function getClient(): ClientInterface
|
||||||
|
{
|
||||||
|
$this->client = $this->client ??
|
||||||
|
new Client([
|
||||||
|
'base_uri' => self::URL,
|
||||||
|
'headers' => [
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'User-Agent' => self::USERAGENT.'/'.InstalledVersions::getVersion('d3/klicktipp-php-client')
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $method
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $options
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws BaseException|GuzzleException
|
||||||
|
*/
|
||||||
|
public function request(string $method, string $uri, array $options = []): ResponseInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$options['query'] = $options['query'] ?? [];
|
||||||
|
|
||||||
|
if (! empty($options['body'])) {
|
||||||
|
$options['body'] = json_encode($options['body']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = [
|
||||||
|
'Cookie' => $this->cookie ?? ''
|
||||||
|
];
|
||||||
|
$options['headers'] = $header;
|
||||||
|
|
||||||
|
return $this->getClient()->request($method, $uri, $options);
|
||||||
|
} catch (RequestException $e) {
|
||||||
|
if ($e->hasResponse()) {
|
||||||
|
$this->parseResponse($e->getResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BaseException(
|
||||||
|
$e->getResponse()->getBody(),
|
||||||
|
$e->getResponse()->getStatusCode(),
|
||||||
|
$e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $method
|
||||||
|
* @param string $uri
|
||||||
|
* @param array $options
|
||||||
|
* @return array
|
||||||
|
* @throws BaseException
|
||||||
|
* @throws GuzzleException
|
||||||
|
*/
|
||||||
|
public function requestAndParse(string $method, string $uri, array $options = []): array
|
||||||
|
{
|
||||||
|
return $this->parseResponse($this->request($method, $uri, $options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return array Parsed JSON result
|
||||||
|
* @throws BaseException
|
||||||
|
*/
|
||||||
|
public function parseResponse(ResponseInterface $response): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Rewind the response (middlewares might have read it already)
|
||||||
|
$response->getBody()->rewind();
|
||||||
|
|
||||||
|
$response_body = $response->getBody()->getContents();
|
||||||
|
$result_array = json_decode($response_body, true);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 204) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_array($result_array)) {
|
||||||
|
throw new BaseException(
|
||||||
|
sprintf('%s: %s', $response->getStatusCode(), $response_body),
|
||||||
|
$response->getStatusCode()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result_array;
|
||||||
|
} catch (RuntimeException $e) {
|
||||||
|
throw new BaseException(
|
||||||
|
$e->getMessage(),
|
||||||
|
0,
|
||||||
|
$e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCookie(?string $cookie): void
|
||||||
|
{
|
||||||
|
$this->cookie = $cookie;
|
||||||
|
}
|
||||||
|
}
|
14
src/Exceptions/BaseException.php
Normal file
14
src/Exceptions/BaseException.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class BaseException extends Exception
|
||||||
|
{
|
||||||
|
public function __construct($message = "", $code = 0, Exception $previous = null)
|
||||||
|
{
|
||||||
|
$message = 'Klicktipp error: '.$message;
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
7
src/Exceptions/NoCredentialsException.php
Normal file
7
src/Exceptions/NoCredentialsException.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient\Exceptions;
|
||||||
|
|
||||||
|
class NoCredentialsException extends BaseException
|
||||||
|
{
|
||||||
|
}
|
74
src/Klicktipp.php
Normal file
74
src/Klicktipp.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* https://www.d3data.de
|
||||||
|
*
|
||||||
|
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
|
||||||
|
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
|
||||||
|
* @link https://www.oxidmodule.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient;
|
||||||
|
|
||||||
|
use D3\KlicktippPhpClient\Exceptions\BaseException;
|
||||||
|
use D3\KlicktippPhpClient\Resources\Account;
|
||||||
|
use D3\KlicktippPhpClient\Resources\Subscriber;
|
||||||
|
use D3\KlicktippPhpClient\Resources\Tag;
|
||||||
|
use GuzzleHttp\ClientInterface;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
|
||||||
|
class Klicktipp
|
||||||
|
{
|
||||||
|
protected string $client_key;
|
||||||
|
|
||||||
|
protected string $secret_key;
|
||||||
|
|
||||||
|
protected ?Connection $connection = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws BaseException
|
||||||
|
* @throws GuzzleException
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $client_key,
|
||||||
|
string $secret_key,
|
||||||
|
ClientInterface $client = null
|
||||||
|
){
|
||||||
|
$this->client_key = $client_key;
|
||||||
|
$this->secret_key = $secret_key;
|
||||||
|
|
||||||
|
if ($client) {
|
||||||
|
$this->getConnection()->setClient($client);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->account()->login();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getConnection(): Connection
|
||||||
|
{
|
||||||
|
if (!$this->connection) {
|
||||||
|
$this->connection = new Connection($this->client_key, $this->secret_key);
|
||||||
|
}
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function account(): Account
|
||||||
|
{
|
||||||
|
return new Account($this->getConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subscriber(): Subscriber
|
||||||
|
{
|
||||||
|
return new Subscriber($this->getConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tag(): Tag
|
||||||
|
{
|
||||||
|
return new Tag($this->getConnection());
|
||||||
|
}
|
||||||
|
}
|
51
src/Resources/Account.php
Normal file
51
src/Resources/Account.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient\Resources;
|
||||||
|
|
||||||
|
use D3\KlicktippPhpClient\Exceptions\BaseException;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
|
||||||
|
class Account extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws BaseException|GuzzleException
|
||||||
|
*/
|
||||||
|
public function login(): array
|
||||||
|
{
|
||||||
|
$response = $this->connection->request(
|
||||||
|
'POST',
|
||||||
|
'account/login',
|
||||||
|
[
|
||||||
|
'query' => $this->getQuery(),
|
||||||
|
'form_params' => [
|
||||||
|
'username' => $this->connection->getClientKey(),
|
||||||
|
'password' => $this->connection->getSecretKey()
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->connection->setCookie(
|
||||||
|
current($response->getHeader('set-cookie'))
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->connection->parseResponse($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws BaseException|GuzzleException
|
||||||
|
*/
|
||||||
|
public function logout(): bool
|
||||||
|
{
|
||||||
|
$response = $this->connection->requestAndParse(
|
||||||
|
'POST',
|
||||||
|
'account/logout',
|
||||||
|
['query' => $this->getQuery()]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (current($response)) {
|
||||||
|
$this->connection->setCookie(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bool) current($response);
|
||||||
|
}
|
||||||
|
}
|
76
src/Resources/Model.php
Normal file
76
src/Resources/Model.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace D3\KlicktippPhpClient\Resources;
|
||||||
|
|
||||||
|
use D3\KlicktippPhpClient\Connection;
|
||||||
|
|
||||||
|
abstract class Model
|
||||||
|
{
|
||||||
|
protected Connection $connection;
|
||||||
|
|
||||||
|
protected array $filters = [];
|
||||||
|
|
||||||
|
protected ?int $limit = null;
|
||||||
|
|
||||||
|
protected ?int $offset = null;
|
||||||
|
|
||||||
|
protected array $query = [];
|
||||||
|
|
||||||
|
public function __construct(Connection $connection)
|
||||||
|
{
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLimit(): ?int
|
||||||
|
{
|
||||||
|
return $this->limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLimit(int $limit): static
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOffset(): ?int
|
||||||
|
{
|
||||||
|
return $this->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOffset(int $offset): static
|
||||||
|
{
|
||||||
|
$this->offset = $offset;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFilter(string $column, $operation, $value = null): static
|
||||||
|
{
|
||||||
|
if (is_null($value)) {
|
||||||
|
$value = $operation;
|
||||||
|
$operation = 'eq';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->filters[$column][$operation] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQuery(): array
|
||||||
|
{
|
||||||
|
return array_filter(array_merge(
|
||||||
|
$this->query,
|
||||||
|
$this->filters,
|
||||||
|
[ 'limit' => $this->getLimit(), 'offset' => $this->getOffset() ]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuery(string|array $key, mixed $value = null): static
|
||||||
|
{
|
||||||
|
if (is_array($key)) {
|
||||||
|
$this->query = $key;
|
||||||
|
} else {
|
||||||
|
$this->query[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user