RprtCli/app/src/Utils/TimeTrackingServices/YoutrackService.php

210 lines
6.7 KiB
PHP

<?php
declare(strict_types=1);
// src/Utils/TimeTrackingServices/YoutrackService.php
namespace RprtCli\Utils\TimeTrackingServices;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ClientException;
use RprtCli\Utils\Configuration\ConfigurationInterface;
class YoutrackService implements YoutrackInterface
{
protected $ytToken;
protected $ytBaseUrl;
protected $config;
protected $httpClient;
protected $report_id;
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 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 = $yt_base_url . '/' . trim($path, '/');
}
return $yt_base_url;
}
public function setYtUrl(string $base_url) {
$this->ytBaseUrl = $base_url;
}
public function listReports() {
// 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,
'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();
}
}