try to follow to HATEOAS.

This commit is contained in:
abdulmohsen
2024-03-05 19:17:52 +03:00
parent e30819a950
commit d7d62b622f
9 changed files with 183 additions and 55 deletions

View File

@@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace App\API\Backends;
use App\Libs\Attributes\Route\Post;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Post(self::URL, name: 'backends.create')]
final class Create
{
public const URL = '%{api.prefix}/backends';
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
return api_error('Not yet implemented', HTTP_STATUS::HTTP_SERVICE_UNAVAILABLE);
}
}

View File

@@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
namespace App\API\Backends;
use App\Libs\Attributes\Route\Get;
use App\Libs\Config;
use App\Libs\HTTP_STATUS;
use App\Libs\Options;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Get(self::URL . '[/]', name: 'backends.index')]
final class Index
{
public const URL = '%{api.prefix}/backends';
public const BLACK_LIST = [
'token',
'webhook.token',
'options.' . Options::ADMIN_TOKEN
];
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$urlPath = $request->getUri()->getPath();
$response = [
'data' => [],
'links' => [
'self' => (string)$apiUrl,
],
];
foreach (self::getBackends(blacklist: true) as $backend) {
$backend = array_filter(
$backend,
fn($key) => false === in_array($key, ['options', 'webhook'], true),
ARRAY_FILTER_USE_KEY
);
$backend['links'] = [
'self' => (string)$apiUrl->withPath($urlPath . '/' . $backend['name']),
];
$response['data'][] = $backend;
}
return api_response($response, HTTP_STATUS::HTTP_OK, []);
}
public static function getBackends(string|null $name = null, bool $blacklist = false): array
{
$backends = [];
foreach (Config::get('servers', []) as $backendName => $backend) {
$backend = ['name' => $backendName, ...$backend];
if (true === $blacklist) {
foreach (self::BLACK_LIST as $hideValue) {
if (true === ag_exists($backend, $hideValue)) {
$backend = ag_set($backend, $hideValue, '__hidden__');
}
}
}
if (null !== ag($backend, 'import.lastSync')) {
$backend = ag_set($backend, 'import.lastSync', makeDate(ag($backend, 'import.lastSync')));
}
if (null !== ag($backend, 'export.lastSync')) {
$backend = ag_set($backend, 'export.lastSync', makeDate(ag($backend, 'export.lastSync')));
}
$backends[] = $backend;
}
if (null !== $name) {
return array_filter($backends, fn($backend) => $backend['name'] === $name);
}
return $backends;
}
}

42
src/API/Backends/View.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace App\API\Backends;
use App\Libs\Attributes\Route\Get;
use App\Libs\HTTP_STATUS;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
#[Get(self::URL . '/{id:[a-zA-Z0-9_-]+}[/]', name: 'backends.view')]
final class View
{
public const URL = '%{api.prefix}/backends';
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
if (null === ($id = ag($args, 'id'))) {
return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$data = Index::getBackends(name: $id, blacklist: true);
if (empty($data)) {
return api_error('Backend not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$data = array_pop($data);
$response = [
...$data,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(self::URL)),
],
];
return api_response($response, HTTP_STATUS::HTTP_OK, []);
}
}

View File

@@ -267,7 +267,6 @@ final class Index
);
$response = [
'@self' => (string)$getUri,
'paging' => [
'total' => (int)$total,
'perpage' => $perpage,
@@ -276,15 +275,16 @@ final class Index
'next_page' => $page < @ceil($total / $perpage) ? $page + 1 : null,
'prev_page' => !empty($total) && $page > 1 ? $page - 1 : null,
'last_page' => @ceil($total / $perpage),
'urls' => [
'first_url' => $firstUrl,
'next_url' => $nextUrl,
'prev_url' => $prevUrl,
'last_url' => $lastUrl,
],
],
'filters' => $filters,
'data' => [],
'links' => [
'self' => (string)$getUri,
'first_url' => $firstUrl,
'next_url' => $nextUrl,
'prev_url' => $prevUrl,
'last_url' => $lastUrl,
],
];
while ($row = $stmt->fetch()) {
@@ -302,11 +302,16 @@ final class Index
unset($item[iState::COLUMN_EXTRA]);
}
$response['data'][] = [
'@self' => (string)(new Uri())->withPath(
$item = [
...$item,
'links' => [
'self' => (string)(new Uri())->withPath(
rtrim($request->getUri()->getPath(), '/') . '/' . $entity->id
)->withQuery(http_build_query($currentQuery)),
] + $item;
],
];
$response['data'][] = $item;
}
return api_response($response, HTTP_STATUS::HTTP_OK, []);

View File

@@ -31,11 +31,21 @@ final readonly class View
return api_error('Not found', HTTP_STATUS::HTTP_NOT_FOUND);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$item = array_pop($item)->getAll();
$item[iState::COLUMN_WATCHED] = $entity->isWatched();
$item[iState::COLUMN_UPDATED] = makeDate($entity->updated);
$item = [
...$item,
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response($item, HTTP_STATUS::HTTP_OK, []);
}
}

View File

@@ -27,8 +27,10 @@ final class Env
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
$response = [
'@self' => (string)$request->getUri()->withHost('')->withPort(0)->withScheme(''),
'data' => [],
'links' => [
'self' => (string)$request->getUri()->withHost('')->withPort(0)->withScheme(''),
],
];
foreach ($_ENV as $key => $val) {

View File

@@ -17,22 +17,28 @@ final class Index
public function __invoke(ServerRequestInterface $request, array $args = []): ResponseInterface
{
$response = [
'data' => [],
];
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$urlPath = rtrim($request->getUri()->getPath(), '/');
$response = [
'data' => [],
'links' => [
'self' => (string)$apiUrl,
],
];
foreach (TasksCommand::getTasks() as $task) {
$response['data'][] = [
'@self' => (string)$apiUrl->withPath($urlPath . '/' . ag($task, 'name')),
...array_filter(
self::formatTask($task),
fn($k) => false === in_array($k, ['command', 'args']),
ARRAY_FILTER_USE_KEY
)
$task = array_filter(
self::formatTask($task),
fn($k) => false === in_array($k, ['command', 'args']),
ARRAY_FILTER_USE_KEY
);
$task['links'] = [
'self' => (string)$apiUrl->withPath($urlPath . '/' . ag($task, 'name')),
];
$response['data'][] = $task;
}
return api_response($response, HTTP_STATUS::HTTP_OK, []);

View File

@@ -19,12 +19,22 @@ final class View
return api_error('No id was given.', HTTP_STATUS::HTTP_BAD_REQUEST);
}
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$task = TasksCommand::getTasks($id);
if (empty($task)) {
return api_error('Task not found.', HTTP_STATUS::HTTP_NOT_FOUND);
}
return api_response(Index::formatTask($task), HTTP_STATUS::HTTP_OK);
$response = [
...Index::formatTask($task),
'links' => [
'self' => (string)$apiUrl,
'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
],
];
return api_response($response, HTTP_STATUS::HTTP_OK);
}
}