From 3283de824c7d8c8c943d8fefaf37d00d853c5450 Mon Sep 17 00:00:00 2001 From: robertfausk Date: Wed, 9 Dec 2020 10:12:53 +0100 Subject: [PATCH] Initial commit :tada: --- .gitignore | 3 + CHANGELOG.md | 4 + Dockerfile | 29 +++++ README.md | 60 ++++++++++ composer.json | 47 ++++++++ docker-compose.yml | 11 ++ phpunit.xml.dist | 18 +++ src/Exception/BadRequestException.php | 8 ++ src/Exception/Exception.php | 11 ++ src/Exception/ForbiddenException.php | 8 ++ src/Exception/LockedException.php | 8 ++ src/Exception/NoResponseException.php | 8 ++ src/Exception/TooManyRequestsException.php | 8 ++ src/Exception/UnexpectedResponseException.php | 13 ++ src/KurzlinkClient.php | 111 ++++++++++++++++++ tests/Integration/KurzlinkClientTest.php | 57 +++++++++ 16 files changed, 404 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 composer.json create mode 100755 docker-compose.yml create mode 100644 phpunit.xml.dist create mode 100644 src/Exception/BadRequestException.php create mode 100644 src/Exception/Exception.php create mode 100644 src/Exception/ForbiddenException.php create mode 100644 src/Exception/LockedException.php create mode 100644 src/Exception/NoResponseException.php create mode 100644 src/Exception/TooManyRequestsException.php create mode 100644 src/Exception/UnexpectedResponseException.php create mode 100644 src/KurzlinkClient.php create mode 100644 tests/Integration/KurzlinkClientTest.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c39e479 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +composer.lock +/vendor/ +/phpunit.xml diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..85f712f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +0.0.1 / 2020-12-09 +================== + +Initial Release :tada: diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3313aed --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +ARG PHP_VERSION=7.2 + +FROM composer:latest as composer +FROM php:${PHP_VERSION} + +# replace shell with bash so we can source files +RUN rm /bin/sh && ln -s /bin/bash /bin/sh + +RUN apt-get update && apt-get install -y \ + libzip-dev \ + zlib1g-dev \ + unzip \ + git-core \ + && docker-php-ext-install zip + +RUN apt-get update && apt-get install -y libzip-dev zlib1g-dev unzip chromium && docker-php-ext-install zip + +COPY --from=composer /usr/bin/composer /usr/bin/composer + +# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser +ENV COMPOSER_ALLOW_SUPERUSER 1 +ENV COMPOSER_HOME /home/docker/.composer +# contains dev-mode packages +RUN composer global require "sllh/composer-versions-check:^2.0" "pyrech/composer-changelogs:^1.7" --prefer-dist --no-progress --no-suggest --classmap-authoritative + +WORKDIR /var/www/html +COPY . /var/www/html + +RUN ls -l diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2805e2 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# KurzlinkApiClient +[![Latest Stable Version](https://poser.pugx.org/robertfausk/kurzlink-api-client/v/stable.svg)](https://packagist.org/packages/robertfausk/kurzlink-api-client) +[![Latest Unstable Version](https://poser.pugx.org/robertfausk/kurzlink-api-client/v/unstable.svg)](https://packagist.org/packages/robertfausk/kurzlink-api-client) +[![Total Downloads](https://poser.pugx.org/robertfausk/kurzlink-api-client/downloads.svg)](https://packagist.org/packages/robertfausk/kurzlink-api-client) +[![Build Status](https://travis-ci.com/robertfausk/kurzlink-api-client.svg?branch=master)](https://travis-ci.com/robertfausk/kurzlink-api-client) +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/robertfausk/kurzlink-api-client/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/robertfausk/kurzlink-api-client/) +[![Code Coverage](https://scrutinizer-ci.com/g/robertfausk/kurzlink-api-client/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/robertfausk/kurzlink-api-client/) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +![PHP7 Compatible](https://img.shields.io/travis/php-v/robertfausk/kurzlink-api-client/master?style=flat-square) +[![Open Issues](https://img.shields.io/github/issues-raw/robertfausk/kurzlink-api-client?style=flat-square)](https://github.com/robertfausk/kurzlink-api-client/issues) +[![Closed Issues](https://img.shields.io/github/issues-closed-raw/robertfausk/kurzlink-api-client?style=flat-square)](https://github.com/robertfausk/kurzlink-api-client/issues?q=is%3Aissue+is%3Aclosed) +[![Contributors](https://img.shields.io/github/contributors/robertfausk/kurzlink-api-client?style=flat-square)](https://github.com/robertfausk/kurzlink-api-client/graphs/contributors) +![Contributors](https://img.shields.io/maintenance/yes/2020?style=flat-square) + +Very simple api client written in PHP for url shortener kurzelinks.de which supports ogy.de, t1p.de, +0cn.de, kurzelinks.de and also own domains. + +## Install + + composer require --dev robertfausk/kurzlink-api-client + +Usage Example +------------- + +```PHP + '', +]; +$shortUrl = $client->request($urlToShorten, $requestParams); +``` + +### How to upgrade? + + Have a look at [CHANGELOG](CHANGELOG.md) for detailed information. + +## How to contribute? + +Copy phpunit.xml.dist and insert your api key to be able to run the integration tests. + +Start docker-compose with php web driver + + docker-compose up php7.2 + +Run phpunit tests + + docker-compose exec php7.2 vendor/bin/phpunit + + +## Credits + +Created by Robert Freigang [robertfausk](https://github.com/robertfausk). diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..1db6b6a --- /dev/null +++ b/composer.json @@ -0,0 +1,47 @@ +{ + "name": "robertfausk/kurzlink-api-client", + "description": "api client for url shortener kurzelinks.de", + "keywords": [ + "kurzelinks.de", + "url shortener", + "t1p.de", + "ogy.de", + "ogy.de", + "api-client" + ], + "type": "api-client", + "license": "MIT", + "authors": [ + { + "name": "Robert Freigang", + "email": "robertfreigang@gmx.de" + } + ], + "require": { + "php": ">=7.2", + "symfony/http-client": "~3.4|~4.0|~5.0" + }, + "require-dev": { + "phpunit/phpunit": "~8.0" + }, + "config": { + "sort-packages": true + }, + "suggest": { + }, + "autoload": { + "psr-4": { + "Robertfausk\\KurzlinkApiClient\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Robertfausk\\KurzlinkApiClient\\Tests\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100755 index 0000000..669cdd2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3" +services: + + php7.2: + tty: true + build: + context: . + args: + - PHP_VERSION=7.2 + volumes: + - .:/var/www/html diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..fc53eaa --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,18 @@ + + + + + + + + + ./tests + + + + + + ./src + + + diff --git a/src/Exception/BadRequestException.php b/src/Exception/BadRequestException.php new file mode 100644 index 0000000..66fa169 --- /dev/null +++ b/src/Exception/BadRequestException.php @@ -0,0 +1,8 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace Robertfausk\KurzlinkApiClient; + +use Robertfausk\KurzlinkApiClient\Exception\BadRequestException; +use Robertfausk\KurzlinkApiClient\Exception\Exception; +use Robertfausk\KurzlinkApiClient\Exception\ForbiddenException; +use Robertfausk\KurzlinkApiClient\Exception\LockedException; +use Robertfausk\KurzlinkApiClient\Exception\NoResponseException; +use Robertfausk\KurzlinkApiClient\Exception\TooManyRequestsException; +use Robertfausk\KurzlinkApiClient\Exception\UnexpectedResponseException; +use Symfony\Component\HttpClient\HttpClient; + +final class KurzlinkClient +{ + /** @var array */ + private $config = [ + 'json' => true, + ]; + /** @var string */ + private $kurzlinkAddress; + /** @var bool */ + private $useSandbox; + /** @var int */ + private $apiVersion; + /** @var string */ + private $apiKey; + + private function __construct(string $apiKey, string $kurzlinkAddress, bool $useSandbox) + { + $this->kurzlinkAddress = $kurzlinkAddress; + $this->useSandbox = $useSandbox; + $this->apiVersion = 21; + if ($this->useSandbox) { + $this->kurzlinkAddress .= '/sandbox'; + } else { + $this->kurzlinkAddress .= '/api'; + } + $this->apiKey = $apiKey; + } + + public static function create(string $apiKey, string $kurzlinkAddress, bool $useSandbox = true): self + { + return new self($apiKey, $kurzlinkAddress, $useSandbox); + } + + public function request(string $urlToShorten, ?array $requestParams = null): string + { + $client = HttpClient::create(); + + $url = \sprintf( + 'https://%s', + $this->kurzlinkAddress + ); + + $headers = [ + 'Content-Type' => 'application/x-www-form-urlencoded', + 'Connection' => 'keep-alive' + ]; + + $options = ['headers' => $headers]; + $options['body'] = $this->config; + $options['body']['url'] = urldecode($urlToShorten); + $options['body']['key'] = $this->apiKey; + $options['body']['apiversion'] = $this->apiVersion; + if ($requestParams) { + $options['body'] = \array_merge($options['body'], $requestParams); + } + + $response = $client->request('POST', $url, $options); + $statusCode = $response->getStatusCode(); + $content = $response->toArray(false); + + switch ($statusCode) { + case 200: + break; + case 400: + throw new BadRequestException($content); + case 403: + throw new ForbiddenException($content); + case 423: + throw new LockedException($content); + case 429: + throw new TooManyRequestsException($content); + case 444: + throw new NoResponseException($content); + default: + throw new Exception($content); + } + + $shortUrl = $content['shorturl']['url'] ?? false; + if (false === $shortUrl || !\is_string($shortUrl)) { + throw new UnexpectedResponseException($content); + } + + return $shortUrl; + } + + public function getApiVersion(): int + { + return $this->apiVersion; + } +} diff --git a/tests/Integration/KurzlinkClientTest.php b/tests/Integration/KurzlinkClientTest.php new file mode 100644 index 0000000..722fd12 --- /dev/null +++ b/tests/Integration/KurzlinkClientTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class KurzlinkClientTest extends TestCase +{ + /** @var string $kurzlinkAddress */ + private $kurzlinkAddress = 't1p.de'; + /** @var string $apiKey */ + private $apiKey; + + public function setUp(): void + { + $this->apiKey = $_ENV['apiKey']; + parent::setUp(); + } + + public function test_simple_request(): void + { + $client = KurzlinkClient::create($this->apiKey, $this->kurzlinkAddress, true); + $urlToShorten = 'https://google.de/'; + $shortUrl = $client->request($urlToShorten); + Assert::assertIsString($shortUrl); + Assert::stringStartsWith('https://t1p.de/'); + } + + public function test_request_with_desired_parameter(): void + { + $client = KurzlinkClient::create($this->apiKey, $this->kurzlinkAddress, true); + $urlToShorten = 'https://google.de/'; + $requestParams = ['requesturl' => 'testen123']; + $shortUrl = $client->request($urlToShorten, $requestParams); + Assert::assertIsString($shortUrl); + Assert::assertIsString('https://t1p.de/testen123'); + } + + public function test_request_with_another_domain(): void + { + $client = KurzlinkClient::create($this->apiKey, 'ogy.de', true); + $urlToShorten = 'https://google.de/'; + $shortUrl = $client->request($urlToShorten); + Assert::assertIsString($shortUrl); + Assert::stringStartsWith('https://ogy.de/'); + } +}