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": {
|
||||
"php": ">=8.0",
|
||||
"composer/composer": "^2.7.1",
|
||||
"doctrine/collections": "^1.8.0",
|
||||
"guzzlehttp/guzzle": "~7.0",
|
||||
"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