250 lines
7.8 KiB
PHP
250 lines
7.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
// src/Utils/TimeTrackingServices/YoutrackService.php
|
|
|
|
namespace RprtCli\Utils\TimeTrackingServices;
|
|
|
|
use Exception;
|
|
use GuzzleHttp\ClientInterface;
|
|
use GuzzleHttp\Exception\ClientException;
|
|
use RprtCli\Utils\Configuration\ConfigurationInterface;
|
|
use Throwable;
|
|
|
|
use function array_combine;
|
|
use function array_filter;
|
|
use function array_map;
|
|
use function file_put_contents;
|
|
use function floor;
|
|
use function json_decode;
|
|
use function microtime;
|
|
use function readline;
|
|
use function sleep;
|
|
use function sys_get_temp_dir;
|
|
use function tempnam;
|
|
use function trim;
|
|
use function var_dump;
|
|
|
|
class YoutrackService implements YoutrackInterface
|
|
{
|
|
protected string $ytToken;
|
|
protected string $ytBaseUrl;
|
|
|
|
protected ConfigurationInterface $config;
|
|
|
|
protected ClientInterface $httpClient;
|
|
|
|
protected string $report_id;
|
|
protected ?string $reportName = null;
|
|
|
|
public function __construct(ConfigurationInterface $config, ClientInterface $http_client)
|
|
{
|
|
$this->config = $config;
|
|
$this->httpClient = $http_client;
|
|
}
|
|
|
|
public function testYoutrackapi(): ?string
|
|
{
|
|
// Get base url from config or add input.
|
|
// Get token or add input.
|
|
$path = 'youtrack/api/admin/users/me';
|
|
$yt_url = $this->getYtUrl($path);
|
|
$yt_token = $this->getYtToken();
|
|
$query = ['fields' => 'id,email,fullName'];
|
|
$headers = [
|
|
"Authorization" => "Bearer $yt_token",
|
|
'Cache-Control' => 'no-cache',
|
|
];
|
|
$me_response = $this->httpClient->request('GET', $yt_url, [
|
|
'query' => $query,
|
|
'headers' => $headers,
|
|
]);
|
|
$test = (string) $me_response->getBody()->getContents();
|
|
$me_json = (array) json_decode($test);
|
|
if ($me_json && isset($me_json['fullName'])) {
|
|
return $me_json['fullName'];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function requestYoutrackPath(string $path, array $query)
|
|
{
|
|
$yt_url = $this->getYtUrl($path);
|
|
$headers = $this->getHeaders();
|
|
return $this->httpClient->request('GET', $yt_url, [
|
|
'query' => $query,
|
|
'headers' => $headers,
|
|
]);
|
|
}
|
|
|
|
protected function getHeaders()
|
|
{
|
|
$yt_token = $this->getYtToken();
|
|
return [
|
|
"Authorization" => "Bearer $yt_token",
|
|
'Cache-Control' => 'no-cache',
|
|
];
|
|
}
|
|
|
|
public function getReportId(): ?string
|
|
{
|
|
// --report option value should take precedence.
|
|
// @TODO error handling.
|
|
if (isset($this->report_id)) {
|
|
return $this->report_id;
|
|
}
|
|
$yt_report_id = $this->config->get('tracking_service.youtrack.report_id');
|
|
if (! $yt_report_id) {
|
|
$yt_report_id = readline('Enter the report id: ');
|
|
}
|
|
return $yt_report_id;
|
|
}
|
|
|
|
public function setReportId(string $report_id): void
|
|
{
|
|
$this->report_id = $report_id;
|
|
}
|
|
|
|
public function setReportName(?string $report_name = null): void
|
|
{
|
|
if (! $report_name) {
|
|
$reports = $this->listReports();
|
|
if ($report_id = $this->getReportId()) {
|
|
$report_name = $reports[$report_id] ?? null;
|
|
} else {
|
|
$report_name = null;
|
|
}
|
|
}
|
|
$this->reportName = $report_name;
|
|
}
|
|
|
|
public function getReportName(): ?string
|
|
{
|
|
return $this->reportName;
|
|
}
|
|
|
|
public function downloadReport(string $report_id): ?string
|
|
{
|
|
$path = "youtrack/api/reports/$report_id/export/csv";
|
|
$query = ['$top' => -1];
|
|
$yt_token = $this->getYtToken();
|
|
$headers = [
|
|
'Accept' => 'application/json, text/plain, */*',
|
|
// 'Accept-Encoding' => 'gzip, deflate, br',
|
|
// 'Connection' => 'keep-alive',
|
|
'Accept-Language' => 'en-US,en;q=0.5',
|
|
"Authorization" => "Bearer $yt_token",
|
|
];
|
|
try {
|
|
$csv_response = $this->httpClient->request('GET', $this->getYtUrl($path), [
|
|
'headers' => $headers,
|
|
'query' => $query,
|
|
]);
|
|
// Write csv response test into temporary file.
|
|
$csv_file = tempnam(sys_get_temp_dir(), "rprt-csv-{$report_id}");
|
|
file_put_contents($csv_file, $csv_response->getBody());
|
|
return $csv_file;
|
|
} catch (ClientException $e) {
|
|
$status = $e->getResponse()->getStatusCode();
|
|
if ($status === 409) {
|
|
sleep(3);
|
|
// @TODO Find a way to break of of loop if necessary!
|
|
var_dump("409 response status during download of report {$report_id}. Sleep 3 and try again.");
|
|
return $this->downloadReport($report_id);
|
|
}
|
|
} catch (Throwable $t) {
|
|
$status = $t->getMessage();
|
|
var_dump($status);
|
|
}
|
|
throw new Exception("Unable to download report {$report_id}!");
|
|
}
|
|
|
|
protected function getYtToken(): string
|
|
{
|
|
if (isset($this->ytToken)) {
|
|
return $this->ytToken;
|
|
}
|
|
$yt_token = $this->config->get('tracking_service.youtrack.auth_token', false);
|
|
if (! $yt_token) {
|
|
$yt_token = readline('Enter your youtrack authentication token: ');
|
|
}
|
|
return $yt_token;
|
|
}
|
|
|
|
public function setYtToken(string $token): void
|
|
{
|
|
$this->ytToken = $token;
|
|
}
|
|
|
|
protected function getYtUrl(string $path = ''): ?string
|
|
{
|
|
if (isset($this->ytBaseUrl)) {
|
|
$yt_base_url = $this->ytBaseUrl;
|
|
} else {
|
|
$yt_base_url = $this->config->get('tracking_service.youtrack.base_url', false);
|
|
}
|
|
if (empty($yt_base_url)) {
|
|
$yt_base_url = readline('Enter base url for of the youtrack service: ');
|
|
}
|
|
if (! empty($path)) {
|
|
$yt_base_url .= '/' . trim($path, '/');
|
|
}
|
|
return $yt_base_url;
|
|
}
|
|
|
|
public function setYtUrl(string $base_url)
|
|
{
|
|
$this->ytBaseUrl = $base_url;
|
|
}
|
|
|
|
public function listReports(): array
|
|
{
|
|
// Now filter results by own = true;
|
|
$url = '/youtrack/api/reports';
|
|
$query = [
|
|
'$top' => -1,
|
|
'fields' => 'id,name,own,owner(login,name)',
|
|
];
|
|
$response = $this->requestYoutrackPath($url, $query);
|
|
$body = (string) $response->getBody()->getContents();
|
|
$body_json = (array) json_decode($body);
|
|
$my_reports = array_filter($body_json, fn($report) => $report->own);
|
|
$reports = array_combine(
|
|
array_map(fn($r) => $r->id, $my_reports),
|
|
array_map(fn ($r) => $r->name, $my_reports)
|
|
);
|
|
return $reports;
|
|
}
|
|
|
|
public function clearReportCache(string $report_id): int
|
|
{
|
|
$path = "/youtrack/api/reports/${report_id}/status";
|
|
$query = [
|
|
'$top' => -1,
|
|
// phpcs:ignore
|
|
'fields' => 'calculationInProgress,error(id),errorMessage,isOutdated,lastCalculated,progress,wikifiedErrorMessage',
|
|
];
|
|
$post = [
|
|
'lastCalculated' => floor(microtime(true) * 1000),
|
|
'calculationInProgress' => true,
|
|
'wikifiedErrorMessage' => '',
|
|
'isOutdated' => false,
|
|
'progress' => -1,
|
|
'error' => null,
|
|
'errorMessage' => null,
|
|
'$type' => 'ReportStatus',
|
|
];
|
|
$yt_url = $this->getYtUrl($path);
|
|
$response = $this->httpClient->request('POST', $yt_url, [
|
|
'query' => $query,
|
|
'headers' => $this->getHeaders(),
|
|
'json' => $post,
|
|
]);
|
|
// $body = (string) $response->getBody()->getContents();
|
|
// var_dump($body);
|
|
return $response->getStatusCode();
|
|
}
|
|
}
|