initial commit

This commit is contained in:
2020-12-30 13:12:18 +07:00
commit f7cafcb397
10 changed files with 748 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.idea/
vendor/

15
cli.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
require_once __DIR__ . '/vendor/autoload.php';
$jokeGuzzle = new \GuzzleHttp\Client([
'base_uri' => 'https://v2.jokeapi.dev',
]);
$jokeService = new \App\Service\JokeService($jokeGuzzle);
$cache = new \Sarahman\SimpleCache\FileSystemCache(__DIR__ . '/tmp/cache');
$jokeOperation = new \App\Operation\JokeOperation($jokeService, $cache);
$app = new \Ahc\Cli\Application('Joke App', 'v0.0.1');
$app->add(new \App\Command\JokeCommand($jokeOperation));
$app->handle($_SERVER['argv']);

17
composer.json Normal file
View File

@@ -0,0 +1,17 @@
{
"name": "dannecron/test-php8",
"type": "project",
"minimum-stability": "dev",
"require": {
"php": "^8.0",
"guzzlehttp/guzzle": "7.2.0",
"adhocore/cli": "0.8.4",
"sarahman/simple-filesystem-cache": "1.0.2",
"ext-json": "*"
},
"autoload": {
"psr-4": {
"App\\": "src"
}
}
}

570
composer.lock generated Normal file
View File

@@ -0,0 +1,570 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bbca822d3f22a485ae93b527da8da2af",
"packages": [
{
"name": "adhocore/cli",
"version": "0.8.4",
"source": {
"type": "git",
"url": "https://github.com/adhocore/php-cli.git",
"reference": "c17fdec05954b3bd2df49adff56284a511dd1083"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/adhocore/php-cli/zipball/c17fdec05954b3bd2df49adff56284a511dd1083",
"reference": "c17fdec05954b3bd2df49adff56284a511dd1083",
"shasum": ""
},
"require": {
"php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Ahc\\Cli\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jitendra Adhikari",
"email": "jiten.adhikary@gmail.com"
}
],
"description": "Command line interface library for PHP",
"keywords": [
"PHP7",
"argument-parser",
"argv-parser",
"cli",
"cli-action",
"cli-app",
"cli-color",
"cli-option",
"cli-writer",
"command",
"console",
"console-app",
"php-cli",
"stream-input",
"stream-output"
],
"support": {
"issues": "https://github.com/adhocore/php-cli/issues",
"source": "https://github.com/adhocore/php-cli/tree/0.8.4"
},
"funding": [
{
"url": "https://paypal.me/ji10",
"type": "custom"
}
],
"time": "2020-10-09T00:51:05+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.2.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/0aa74dfb41ae110835923ef10a9d803a22d50e79",
"reference": "0aa74dfb41ae110835923ef10a9d803a22d50e79",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.4",
"guzzlehttp/psr7": "^1.7",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"ext-curl": "*",
"php-http/client-integration-tests": "^3.0",
"phpunit/phpunit": "^8.5.5 || ^9.3.5",
"psr/log": "^1.1"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "7.1-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.2.0"
},
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://github.com/alexeyshockov",
"type": "github"
},
{
"url": "https://github.com/gmponos",
"type": "github"
}
],
"time": "2020-10-10T11:47:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "ddfeedfff2a52661429437da0702979f708e6ac6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/ddfeedfff2a52661429437da0702979f708e6ac6",
"reference": "ddfeedfff2a52661429437da0702979f708e6ac6",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"symfony/phpunit-bridge": "^4.4 || ^5.1"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/master"
},
"time": "2020-10-19T16:50:15+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.x-dev",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f47ece9e6e8ce74e3be04bef47f46061dc18c095"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f47ece9e6e8ce74e3be04bef47f46061dc18c095",
"reference": "f47ece9e6e8ce74e3be04bef47f46061dc18c095",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.7-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/1.x"
},
"time": "2020-12-08T11:45:39+00:00"
},
{
"name": "psr/http-client",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "22b2ef5687f43679481615605d7a15c557ce85b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/22b2ef5687f43679481615605d7a15c557ce85b1",
"reference": "22b2ef5687f43679481615605d7a15c557ce85b1",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"time": "2020-09-19T09:12:31+00:00"
},
{
"name": "psr/http-message",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/efd67d1dc14a7ef4fc4e518e7dee91c271d524e4",
"reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2019-08-29T13:16:46+00:00"
},
{
"name": "psr/simple-cache",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474",
"reference": "5a7b96b1dda5d957e01bc1bfe77dcca09c5a7474",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/master"
},
"time": "2020-04-21T06:43:17+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "sarahman/simple-filesystem-cache",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/sarahman/simple-filesystem-cache.git",
"reference": "adb8f79a3890e51692db02aadeaa42999f7ff5e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sarahman/simple-filesystem-cache/zipball/adb8f79a3890e51692db02aadeaa42999f7ff5e3",
"reference": "adb8f79a3890e51692db02aadeaa42999f7ff5e3",
"shasum": ""
},
"require": {
"ext-json": "*",
"psr/simple-cache": "*"
},
"provide": {
"psr/simple-cache-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"type": "library",
"autoload": {
"psr-4": {
"Sarahman\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Syed Abidur Rahman",
"email": "aabid048@gmail.com"
}
],
"description": "Simple file system cache library for PHP built on top of PSR-16.",
"support": {
"issues": "https://github.com/sarahman/simple-filesystem-cache/issues",
"source": "https://github.com/sarahman/simple-filesystem-cache/tree/v1.0.2"
},
"time": "2020-08-09T05:14:17+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^8.0"
},
"platform-dev": [],
"plugin-api-version": "2.0.0"
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Operation\JokeOperation;
class JokeCommand extends \Ahc\Cli\Input\Command
{
private JokeOperation $jokeOperation;
public function __construct(JokeOperation $jokeOperation)
{
parent::__construct('joke', 'Get some joke');
$this->jokeOperation = $jokeOperation;
}
public function execute(): void
{
$io = $this->app()->io();
$joke = $this->jokeOperation->getRandomJoke();
$io->green($joke, true);
}
}

View File

@@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace App\Operation;
use App\Service\CachedJokes;
use App\Service\JokeInterface;
use Psr\SimpleCache\CacheInterface;
class JokeOperation
{
protected JokeInterface $jokeService;
protected CacheInterface $cache;
public function __construct(JokeInterface $jokeService, CacheInterface $cache)
{
$this->jokeService = $jokeService;
$this->cache = $cache;
}
public function getRandomJoke(): string
{
$reflection = new \ReflectionClass($this->jokeService);
$cachedJokesAttr = $reflection->getMethod('getRandomJoke')->getAttributes(CachedJokes::class);
if (count($cachedJokesAttr) > 0) {
/** @var CachedJokes $cache */
$cache = $cachedJokesAttr[0]->newInstance();
$cacheKey = $cache->getCacheKey(JokeInterface::CATEGORY_ANY);
if ($this->cache->has($cacheKey)) {
return $this->cache->get($cacheKey);
}
}
$randomJoke = $this->jokeService->getRandomJoke();
$randomJokeStr = $randomJoke['joke'];
if (isset($cacheKey)) {
$this->cache->set($cacheKey, $randomJokeStr);
}
return $randomJokeStr;
}
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\Service;
#[\Attribute]
class CachedJokes
{
public function getCacheKey(string $jokeType): string
{
return "jokes-{$jokeType}";
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\Service;
interface JokeInterface
{
public const CATEGORY_ANY = 'Any';
public const CATEGORY_MISC = 'Miscellaneous';
public const CATEGORY_PROGRAMMING = 'Programming';
public const CATEGORY_DARK = 'Dark';
public const CATEGORY_PUN = 'Pun';
public const CATEGORY_SPOOKY = 'Spooky';
public const CATEGORY_CHRISTMAS = 'Christmas';
public function getRandomJoke(): array;
}

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace App\Service;
use Psr\Http\Message\ResponseInterface;
/**
* Class JokeService
* @link https://sv443.net/jokeapi/v2
*/
class JokeService implements JokeInterface
{
protected \GuzzleHttp\Client $guzzleClient;
public function __construct(\GuzzleHttp\Client $guzzleClient)
{
$this->guzzleClient = $guzzleClient;
}
#[CachedJokes]
public function getRandomJoke(): array
{
$response = $this->sendRequest(static::CATEGORY_ANY);
$responseContent = (string) $response->getBody();
return \json_decode($responseContent, true);
}
protected function sendRequest(string ...$categories): ResponseInterface
{
$categoriesStr = implode(',', $categories);
return $this->guzzleClient->get("/joke/{$categoriesStr}", [
\GuzzleHttp\RequestOptions::QUERY => [
'format' => 'json',
'amount' => 1,
'type' => 'single',
],
]);
}
}

2
tmp/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore