2026-06-19 17:23:25 +03:00
|
|
|
<?php declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
use Nechaev\Reports\Features\Reports\ReportsApi;
|
|
|
|
|
|
|
|
|
|
require_once __DIR__ . '/../init.php';
|
|
|
|
|
|
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
|
|
2026-07-07 19:03:53 +03:00
|
|
|
/**
|
|
|
|
|
* @return array<int, string>
|
|
|
|
|
*/
|
|
|
|
|
function parseRepeatedQueryParam(string $key): array {
|
|
|
|
|
$values = [];
|
|
|
|
|
|
|
|
|
|
if (isset($_GET[$key]) && is_array($_GET[$key])) {
|
|
|
|
|
foreach ($_GET[$key] as $item) {
|
|
|
|
|
if (is_string($item) && $item !== '') {
|
|
|
|
|
$values[] = $item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array_values($values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$queryString = $_SERVER['QUERY_STRING'] ?? '';
|
|
|
|
|
if ($queryString !== '') {
|
|
|
|
|
foreach (explode('&', $queryString) as $part) {
|
|
|
|
|
if ($part === '') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[$rawName, $rawValue] = array_pad(explode('=', $part, 2), 2, '');
|
|
|
|
|
$name = urldecode($rawName);
|
|
|
|
|
if ($name !== $key && $name !== $key . '[]') {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$value = urldecode($rawValue);
|
|
|
|
|
if ($value !== '') {
|
|
|
|
|
$values[] = $value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($values === [] && isset($_GET[$key]) && is_string($_GET[$key]) && $_GET[$key] !== '') {
|
|
|
|
|
return [$_GET[$key]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array_values($values);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 10:46:06 +03:00
|
|
|
/**
|
|
|
|
|
* @return array<int, string>
|
|
|
|
|
*/
|
|
|
|
|
function parseStringList(mixed $value): array {
|
|
|
|
|
if ($value === null || $value === '') {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$items = is_array($value) ? $value : [$value];
|
|
|
|
|
|
|
|
|
|
return array_values(array_filter(array_map('strval', $items), static fn (string $item): bool => $item !== ''));
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 19:03:53 +03:00
|
|
|
/**
|
|
|
|
|
* @return array<int, string>
|
|
|
|
|
*/
|
|
|
|
|
function parseStringListFromQuery(string $key): array {
|
|
|
|
|
return parseStringList(parseRepeatedQueryParam($key));
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 10:46:06 +03:00
|
|
|
/**
|
|
|
|
|
* @return array<int, int>
|
|
|
|
|
*/
|
|
|
|
|
function parseIntList(mixed $value): array {
|
|
|
|
|
$items = parseStringList($value);
|
|
|
|
|
|
|
|
|
|
return array_values(array_filter(array_map('intval', $items), static fn (int $item): bool => $item > 0));
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 19:03:53 +03:00
|
|
|
/**
|
|
|
|
|
* @return array<int, int>
|
|
|
|
|
*/
|
|
|
|
|
function parseIntListFromQuery(string $key): array {
|
|
|
|
|
return parseIntList(parseRepeatedQueryParam($key));
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 17:23:25 +03:00
|
|
|
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
|
|
|
|
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
|
|
|
|
|
|
|
|
|
|
if ($method === 'OPTIONS') {
|
|
|
|
|
http_response_code(204);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
$api = new ReportsApi();
|
|
|
|
|
|
|
|
|
|
if ($method === 'GET' && $path === '/api/teams') {
|
|
|
|
|
echo json_encode($api->getTeams(), JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 18:29:44 +03:00
|
|
|
if ($method === 'GET' && $path === '/api/config') {
|
|
|
|
|
echo json_encode($api->getPublicConfig(), JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 17:23:25 +03:00
|
|
|
if ($method === 'GET' && preg_match('#^/api/teams/(\d+)/sprints$#', $path, $matches)) {
|
|
|
|
|
echo json_encode($api->getSprintsByTeamId((int) $matches[1]), JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 10:46:06 +03:00
|
|
|
if ($method === 'GET' && preg_match('#^/api/teams/(\d+)/tasks/filters$#', $path, $matches)) {
|
|
|
|
|
$result = $api->getTeamTaskFilterOptions((int) $matches[1]);
|
|
|
|
|
if ($result === null) {
|
|
|
|
|
http_response_code(404);
|
|
|
|
|
echo json_encode(['error' => 'Team not found'], JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 21:14:10 +03:00
|
|
|
if ($method === 'GET' && preg_match('#^/api/teams/(\d+)/tasks$#', $path, $matches)) {
|
|
|
|
|
$page = max(1, (int) ($_GET['page'] ?? 1));
|
|
|
|
|
$perPage = max(1, min(100, (int) ($_GET['per_page'] ?? 50)));
|
2026-07-07 10:46:06 +03:00
|
|
|
$result = $api->getTasksByTeamId(
|
|
|
|
|
(int) $matches[1],
|
|
|
|
|
$page,
|
|
|
|
|
$perPage,
|
2026-07-07 19:03:53 +03:00
|
|
|
parseStringListFromQuery('task_type'),
|
|
|
|
|
parseStringListFromQuery('assignee'),
|
|
|
|
|
parseIntListFromQuery('sprint_id')
|
2026-07-07 10:46:06 +03:00
|
|
|
);
|
2026-06-19 21:14:10 +03:00
|
|
|
if ($result === null) {
|
|
|
|
|
http_response_code(404);
|
|
|
|
|
echo json_encode(['error' => 'Team not found'], JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
echo json_encode($result, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 18:29:44 +03:00
|
|
|
if ($method === 'GET' && preg_match('#^/api/sprints/(\d+)/tasks$#', $path, $matches)) {
|
|
|
|
|
echo json_encode($api->getTasksBySprintId((int) $matches[1]), JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($method === 'GET' && preg_match('#^/api/sprints/(\d+)$#', $path, $matches)) {
|
|
|
|
|
$sprint = $api->getSprintById((int) $matches[1]);
|
|
|
|
|
if ($sprint === null) {
|
|
|
|
|
http_response_code(404);
|
|
|
|
|
echo json_encode(['error' => 'Sprint not found'], JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
echo json_encode($sprint, JSON_UNESCAPED_UNICODE);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-19 17:23:25 +03:00
|
|
|
http_response_code(404);
|
|
|
|
|
echo json_encode(['error' => 'Not found'], JSON_UNESCAPED_UNICODE);
|
|
|
|
|
} catch (Throwable $e) {
|
|
|
|
|
http_response_code(500);
|
|
|
|
|
echo json_encode(['error' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
|
|
|
|
|
}
|