diff --git a/Classes/Client.php b/Classes/Client.php index 9ee193a..44fe0d3 100644 --- a/Classes/Client.php +++ b/Classes/Client.php @@ -24,6 +24,8 @@ class Client const AUTH_TOKEN = 'token'; const AUTH_BASIC_AUTH = 'basic_auth'; + const BASE_URI = '/api/v1'; + /** * @var \GuzzleHttp\Client */ @@ -75,12 +77,27 @@ class Client */ public function request(string $uri = '', string $method = 'GET', array $options = []): ResponseInterface { - if (!empty($this->config['query']) && !empty($options['query'])) { + $uri = self::BASE_URI . $uri; + + if (!empty($this->config['query']) && isset($options['query'])) { $options['query'] = array_merge($this->config['query'], $options['query']); + } else if (!empty($this->config['query'])) { + $options['query'] = $this->config['query']; } + return $this->httpClient->request($method, $uri, $options); } + /** + * @param string $username + * @return $this + */ + public function sudo(string $username): self + { + $this->config['query']['sudo'] = $username; + return $this; + } + /** * @param array $authentication * @throws Exception diff --git a/Classes/Endpoint/AbstractEndpoint.php b/Classes/Endpoint/AbstractEndpoint.php index d69b432..916fe91 100644 --- a/Classes/Endpoint/AbstractEndpoint.php +++ b/Classes/Endpoint/AbstractEndpoint.php @@ -17,11 +17,12 @@ abstract class AbstractEndpoint implements EndpointInterface */ protected function removeNullValues(array $array): array { - return array_filter( - $array, - function($value) { - return !is_null($value); - } - ); + $array = array_map(function($value) { + return is_array($value) ? $this->removeNullValues($value) : $value; + }, $array); + + return array_filter($array, function($value) { + return !is_null($value) && !(is_array($value) && empty($value)); + }); } } diff --git a/Classes/Endpoint/Admin.php b/Classes/Endpoint/Admin.php index bef190e..cd758c6 100644 --- a/Classes/Endpoint/Admin.php +++ b/Classes/Endpoint/Admin.php @@ -11,7 +11,7 @@ use Avency\Gitea\Client; */ class Admin extends AbstractEndpoint implements EndpointInterface { - const BASE_URI = 'api/v1/admin'; + const BASE_URI = '/admin'; /** * @var Client diff --git a/Classes/Endpoint/Miscellaneous.php b/Classes/Endpoint/Miscellaneous.php index 237c1a3..685c0d3 100644 --- a/Classes/Endpoint/Miscellaneous.php +++ b/Classes/Endpoint/Miscellaneous.php @@ -11,7 +11,7 @@ use Avency\Gitea\Client; */ class Miscellaneous extends AbstractEndpoint implements EndpointInterface { - const BASE_URI = 'api/v1'; + const BASE_URI = ''; /** * @var Client diff --git a/Classes/Endpoint/Repositories.php b/Classes/Endpoint/Repositories.php index cf52e67..91a8845 100644 --- a/Classes/Endpoint/Repositories.php +++ b/Classes/Endpoint/Repositories.php @@ -5,13 +5,42 @@ declare(strict_types=1); namespace Avency\Gitea\Endpoint; use Avency\Gitea\Client; +use Avency\Gitea\Endpoint\Repositories\BranchesTrait; +use Avency\Gitea\Endpoint\Repositories\CollaboratorsTrait; +use Avency\Gitea\Endpoint\Repositories\CommitsTrait; +use Avency\Gitea\Endpoint\Repositories\ContentsTrait; +use Avency\Gitea\Endpoint\Repositories\ForksTrait; +use Avency\Gitea\Endpoint\Repositories\GitTrait; +use Avency\Gitea\Endpoint\Repositories\HooksTrait; +use Avency\Gitea\Endpoint\Repositories\KeysTrait; +use Avency\Gitea\Endpoint\Repositories\PullsTrait; +use Avency\Gitea\Endpoint\Repositories\ReleasesTrait; +use Avency\Gitea\Endpoint\Repositories\RepositoryTrait; +use Avency\Gitea\Endpoint\Repositories\StatusesTrait; +use Avency\Gitea\Endpoint\Repositories\SubscriptionTrait; +use Avency\Gitea\Endpoint\Repositories\TopicsTrait; /** * Repositories endpoint */ class Repositories extends AbstractEndpoint implements EndpointInterface { - const BASE_URI = 'api/v1/repos'; + use BranchesTrait; + use CollaboratorsTrait; + use CommitsTrait; + use ContentsTrait; + use ForksTrait; + use GitTrait; + use HooksTrait; + use KeysTrait; + use PullsTrait; + use ReleasesTrait; + use RepositoryTrait; + use StatusesTrait; + use SubscriptionTrait; + use TopicsTrait; + + const BASE_URI = '/repos'; /** * @var Client @@ -25,152 +54,4 @@ class Repositories extends AbstractEndpoint implements EndpointInterface { $this->client = $client; } - - /** - * @param string $cloneAddr - * @param string $repoName - * @param int $uid - * @param string|null $authPassword - * @param string|null $authUsername - * @param string $description - * @param bool $issues - * @param bool $labels - * @param bool $milestones - * @param bool $mirror - * @param bool $private - * @param bool $pullRequests - * @param bool $releases - * @param bool $wiki - * @return array - */ - public function migrate( - string $cloneAddr, - string $repoName, - int $uid, - ?string $authPassword = null, - ?string $authUsername = null, - string $description = '', - bool $issues = true, - bool $labels = true, - bool $milestones = true, - bool $mirror = true, - bool $private = true, - bool $pullRequests = true, - bool $releases = true, - bool $wiki = true - ): array - { - $options = [ - 'json' => [ - 'clone_addr' => $cloneAddr, - 'repo_name' => $repoName, - 'uid' => $uid, - 'auth_password' => $authPassword, - 'auth_username' => $authUsername, - 'description' => $description, - 'issues' => $issues, - 'labels' => $labels, - 'milestones' => $milestones, - 'mirror' => $mirror, - 'private' => $private, - 'pull_requests' => $pullRequests, - 'releases' => $releases, - 'wiki' => $wiki, - ] - ]; - - $options['json'] = $this->removeNullValues($options['json']); - $response = $this->client->request(self::BASE_URI . '/migrate', 'POST', $options); - return \GuzzleHttp\json_decode($response->getBody(), true); - } - - /** - * @param string $query - * @param bool|null $topic - * @param bool|null $includeDesc - * @param int|null $uid - * @param int|null $priorityOwnerId - * @param int|null $starredBy - * @param bool|null $private - * @param bool|null $template - * @param int|null $page - * @param int|null $limit - * @param string|null $mode - * @param bool|null $exclusive - * @param string|null $sort - * @param string|null $order - * @return array - */ - public function search( - string $query, - ?bool $topic = null, - ?bool $includeDesc = null, - ?int $uid = null, - ?int $priorityOwnerId = null, - ?int $starredBy = null, - ?bool $private = null, - ?bool $template = null, - ?int $page = null, - ?int $limit = null, - ?string $mode = null, - ?bool $exclusive = null, - ?string $sort = null, - ?string $order = null - ): array - { - $options['query'] = [ - 'query' => $query, - 'topic' => $topic, - 'includeDesc' => $includeDesc, - 'uid' => $uid, - 'priorityOwnerId' => $priorityOwnerId, - 'starredBy' => $starredBy, - 'private' => $private, - 'template' => $template, - 'page' => $page, - 'limit' => $limit, - 'mode' => $mode, - 'exclusive' => $exclusive, - 'sort' => $sort, - 'order' => $order, - ]; - $options['query'] = $this->removeNullValues($options['query']); - $response = $this->client->request(self::BASE_URI . '/search', 'GET', $options); - return \GuzzleHttp\json_decode($response->getBody(), true); - } - - /** - * @param string $owner - * @param string $repositoryName - * @return array - */ - public function get(string $owner, string $repositoryName): array - { - $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName); - return \GuzzleHttp\json_decode($response->getBody(), true); - } - - /** - * @param string $owner - * @param string $repositoryName - * @return bool - */ - public function delete(string $owner, string $repositoryName): array - { - $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName, 'DELETE'); - return true; - } - - /** - * @param string $owner - * @param string $repositoryName - * @return array - */ - public function patch(string $owner, string $repositoryName, array $properties): array - { - $options['json'] = $properties; - - $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName, 'PATCH', $options); - return \GuzzleHttp\json_decode($response->getBody(), true); - } } diff --git a/Classes/Endpoint/Repositories/BranchesTrait.php b/Classes/Endpoint/Repositories/BranchesTrait.php new file mode 100644 index 0000000..aebe13b --- /dev/null +++ b/Classes/Endpoint/Repositories/BranchesTrait.php @@ -0,0 +1,38 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/branches'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param $branch + * @return array + */ + public function getBranche(string $owner, string $repositoryName, string $branch): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/branches/' . $branch); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/CollaboratorsTrait.php b/Classes/Endpoint/Repositories/CollaboratorsTrait.php new file mode 100644 index 0000000..075c70c --- /dev/null +++ b/Classes/Endpoint/Repositories/CollaboratorsTrait.php @@ -0,0 +1,69 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/collaborators'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $collaborator + * @return bool + */ + public function checkCollaborator(string $owner, string $repositoryName, string $collaborator): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/collaborators/' . $collaborator); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $collaborator + * @param string $permission + * @return bool + */ + public function addCollaborator(string $owner, string $repositoryName, string $collaborator, string $permission = 'write'): bool + { + $options['json'] = [ + 'permission' => $permission + ]; + + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/collaborators/' . $collaborator, 'PUT', $options); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $collaborator + * @return bool + */ + public function deleteCollaborator(string $owner, string $repositoryName, string $collaborator): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/collaborators/' . $collaborator, 'DELETE'); + + return true; + } +} diff --git a/Classes/Endpoint/Repositories/CommitsTrait.php b/Classes/Endpoint/Repositories/CommitsTrait.php new file mode 100644 index 0000000..d74527a --- /dev/null +++ b/Classes/Endpoint/Repositories/CommitsTrait.php @@ -0,0 +1,52 @@ + $sha, + 'page' => $page + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/commits', 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $ref + * @param int|null $page + * @return array + */ + public function getCommitStatuses(string $owner, string $repositoryName, string $ref, int $page = null): array + { + $options['query'] = [ + 'page' => $page + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/commits/' . $ref . '/statuses', 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/ContentsTrait.php b/Classes/Endpoint/Repositories/ContentsTrait.php new file mode 100644 index 0000000..d8260b6 --- /dev/null +++ b/Classes/Endpoint/Repositories/ContentsTrait.php @@ -0,0 +1,250 @@ + $ref + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/contents'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $filepath + * @param string|null $ref + * @return array + */ + public function getContent(string $owner, string $repositoryName, string $filepath, string $ref = null): array + { + $options['query'] = [ + 'ref' => $ref + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/contents/' . $filepath); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $filepath + * @param string $sha + * @param string $content + * @param string|null $authorEmail + * @param string|null $authorName + * @param string|null $branch + * @param string|null $committerEmail + * @param string|null $committerName + * @param \DateTime|null $authorDate + * @param \DateTime|null $committerDate + * @param string|null $message + * @param string|null $newBranch + * @return array + */ + public function updateContent( + string $owner, + string $repositoryName, + string $filepath, + string $sha, + string $content, + string $authorEmail = null, + string $authorName = null, + string $branch = null, + string $committerEmail = null, + string $committerName = null, + \DateTime $authorDate = null, + \DateTime $committerDate = null, + string $message = null, + string $newBranch = null + ): array + { + $options['json'] = [ + 'sha' => $sha, + 'content' => base64_encode($content), + 'author' => [ + 'email' => $authorEmail, + 'name' => $authorName, + ], + 'branch' => $branch, + 'committer' => [ + 'email' => $committerEmail, + 'name' => $committerName, + ], + 'dates' => [ + 'author' => $authorDate ? $authorDate->format(\DateTime::ATOM) : null, + 'committer' => $committerDate ? $committerDate->format(\DateTime::ATOM) : null, + ], + 'message' => $message, + 'new_branch' => $newBranch, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/contents/' . $filepath, 'PUT', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $filepath + * @param string $content + * @param string|null $authorEmail + * @param string|null $authorName + * @param string|null $branch + * @param string|null $committerEmail + * @param string|null $committerName + * @param \DateTime|null $authorDate + * @param \DateTime|null $committerDate + * @param string|null $message + * @param string|null $newBranch + * @return array + */ + public function addContent( + string $owner, + string $repositoryName, + string $filepath, + string $content, + string $authorEmail = null, + string $authorName = null, + string $branch = null, + string $committerEmail = null, + string $committerName = null, + \DateTime $authorDate = null, + \DateTime $committerDate = null, + string $message = null, + string $newBranch = null + ): array + { + $options['json'] = [ + 'content' => base64_encode($content), + 'author' => [ + 'email' => $authorEmail, + 'name' => $authorName, + ], + 'branch' => $branch, + 'committer' => [ + 'email' => $committerEmail, + 'name' => $committerName, + ], + 'dates' => [ + 'author' => $authorDate ? $authorDate->format(\DateTime::ATOM) : null, + 'committer' => $committerDate ? $committerDate->format(\DateTime::ATOM) : null, + ], + 'message' => $message, + 'new_branch' => $newBranch, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/contents/' . $filepath, 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $filepath + * @param string $sha + * @param string $content + * @param string|null $authorEmail + * @param string|null $authorName + * @param string|null $branch + * @param string|null $committerEmail + * @param string|null $committerName + * @param \DateTime|null $authorDate + * @param \DateTime|null $committerDate + * @param string|null $message + * @param string|null $newBranch + * @return array + */ + public function deleteContent( + string $owner, + string $repositoryName, + string $filepath, + string $sha, + string $authorEmail = null, + string $authorName = null, + string $branch = null, + string $committerEmail = null, + string $committerName = null, + \DateTime $authorDate = null, + \DateTime $committerDate = null, + string $message = null, + string $newBranch = null + ): array + { + $options['json'] = [ + 'sha' => $sha, + 'author' => [ + 'email' => $authorEmail, + 'name' => $authorName, + ], + 'branch' => $branch, + 'committer' => [ + 'email' => $committerEmail, + 'name' => $committerName, + ], + 'dates' => [ + 'author' => $authorDate ? $authorDate->format(\DateTime::ATOM) : null, + 'committer' => $committerDate ? $committerDate->format(\DateTime::ATOM) : null, + ], + 'message' => $message, + 'new_branch' => $newBranch, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/contents/' . $filepath, 'DELETE', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $filepath + * @return array + */ + public function getEditorConfig(string $owner, string $repositoryName, string $filepath): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/editorconfig/' . $filepath); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return string + */ + public function getRawContent(string $owner, string $repositoryName, string $filepath): string + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/raw/' . $filepath); + + return (string)$response->getBody(); + } +} diff --git a/Classes/Endpoint/Repositories/ForksTrait.php b/Classes/Endpoint/Repositories/ForksTrait.php new file mode 100644 index 0000000..a4069d0 --- /dev/null +++ b/Classes/Endpoint/Repositories/ForksTrait.php @@ -0,0 +1,43 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/forks'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string|null $organisation + * @return array + */ + public function createFork(string $owner, string $repositoryName, string $organisation = null): array + { + $options['json'] = [ + 'organization' => $organisation + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/forks', 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/GitTrait.php b/Classes/Endpoint/Repositories/GitTrait.php new file mode 100644 index 0000000..0ef0fcd --- /dev/null +++ b/Classes/Endpoint/Repositories/GitTrait.php @@ -0,0 +1,107 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/blobs/' . $sha); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $sha + * @return array + */ + public function getCommit(string $owner, string $repositoryName, string $sha): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/commits/' . $sha); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function getRefs(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/refs'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $ref + * @return array + */ + public function getRef(string $owner, string $repositoryName, string $ref): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/refs/' . $ref); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $sha + * @return array + */ + public function getTag(string $owner, string $repositoryName, string $sha): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/tags/' . $sha); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $sha + * @param bool|null $recursive + * @param int|null $page + * @param int|null $perPage + * @return array + */ + public function getTree( + string $owner, + string $repositoryName, + string $sha, + bool $recursive = null, + int $page = null, + int $perPage = null + ): array + { + $options['query'] = [ + 'recursive' => $recursive, + 'page' => $page, + 'per_page' => $perPage, + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/git/trees/' . $sha, 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/HooksTrait.php b/Classes/Endpoint/Repositories/HooksTrait.php new file mode 100644 index 0000000..8ad415e --- /dev/null +++ b/Classes/Endpoint/Repositories/HooksTrait.php @@ -0,0 +1,191 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $type + * @param array $config + * @param bool|null $active + * @param string|null $branchFilter + * @param array|null $events + * @return array + */ + public function addHook( + string $owner, + string $repositoryName, + string $type, + array $config, + bool $active = null, + string $branchFilter = null, + array $events = null + ): array + { + $options['json'] = [ + 'type' => $type, + 'config' => $config, + 'active' => $active, + 'branch_filter' => $branchFilter, + 'events' => $events, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks', 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function getGitHooks(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/git'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function getGitHook(string $owner, string $repositoryName, int $id): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/git/' . $id); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return bool + */ + public function deleteGitHook(string $owner, string $repositoryName, int $id): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/git/' . $id, 'DELETE'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @param string $content + * @return array + */ + public function updateGitHook(string $owner, string $repositoryName, int $id, string $content): array + { + $options['json'] = [ + 'content' => $content + ]; + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/git/' . $id, 'PATCH', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function getHook(string $owner, string $repositoryName, int $id): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/' . $id); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return bool + */ + public function deleteHook(string $owner, string $repositoryName, int $id): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/' . $id, 'DELETE'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @param array|null $config + * @param bool|null $active + * @param string|null $branchFilter + * @param array|null $events + * @return array + */ + public function updateHook( + string $owner, + string $repositoryName, + int $id, + array $config = null, + bool $active = null, + string $branchFilter = null, + array $events = null + ): array + { + $options['json'] = [ + 'config' => $config, + 'active' => $active, + 'branch_filter' => $branchFilter, + 'events' => $events, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/' . $id, 'PATCH', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function testHook( + string $owner, + string $repositoryName, + int $id + ): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/hooks/' . $id . '/tests', 'POST'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/KeysTrait.php b/Classes/Endpoint/Repositories/KeysTrait.php new file mode 100644 index 0000000..2cba946 --- /dev/null +++ b/Classes/Endpoint/Repositories/KeysTrait.php @@ -0,0 +1,86 @@ + $keyId, + 'fingerprint' => $fingerprint + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/keys', 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $title + * @param string $key + * @param bool|null $readOnly + * @return array + */ + public function addKey( + string $owner, + string $repositoryName, + string $title, + string $key, + bool $readOnly = null + ): array + { + $options['json'] = [ + 'title' => $title, + 'key' => $key, + 'read_only' => $readOnly, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/keys', 'POST', $options); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $keyId + * @return array + */ + public function getKey(string $owner, string $repositoryName, int $keyId): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/keys/' . $keyId); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $keyId + * @return bool + */ + public function deleteKey(string $owner, string $repositoryName, int $keyId): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/keys/' . $keyId, 'DELETE'); + + return true; + } +} diff --git a/Classes/Endpoint/Repositories/PullsTrait.php b/Classes/Endpoint/Repositories/PullsTrait.php new file mode 100644 index 0000000..13efbfd --- /dev/null +++ b/Classes/Endpoint/Repositories/PullsTrait.php @@ -0,0 +1,205 @@ + $page, + 'state' => $state, + 'sort' => $sort, + 'milestone' => $milestone, + 'lables' => $lables, + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls', 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $assignee + * @param string $base + * @param string $head + * @param array|null $assignees + * @param string|null $title + * @param string|null $body + * @param \DateTime|null $dueDate + * @param array|null $labels + * @param int|null $milestone + * @return array + */ + public function createPull( + string $owner, + string $repositoryName, + string $assignee, + string $base, + string $head, + string $title, + array $assignees = null, + string $body = null, + \DateTime $dueDate = null, + array $labels = null, + int $milestone = null + ): array + { + $options['json'] = [ + 'assignee' => $assignee, + 'base' => $base, + 'head' => $head, + 'assignees' => $assignees, + 'title' => $title, + 'body' => $body, + 'due_date' => $dueDate ? $dueDate->format(\DateTime::ATOM) : null, + 'labels' => $labels, + 'milestone' => $milestone, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls', 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $index + * @return array + */ + public function getPull( + string $owner, + string $repositoryName, + int $index + ): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls/' . $index, 'GET'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $index + * @param string|null $assignee + * @param string|null $title + * @param string|null $state + * @param array|null $assignees + * @param string|null $body + * @param \DateTime|null $dueDate + * @param bool|null $unsetDueDate + * @param array|null $labels + * @param int|null $milestone + * @return array + */ + public function updatePull( + string $owner, + string $repositoryName, + int $index, + string $assignee = null, + string $title = null, + string $state = null, + array $assignees = null, + string $body = null, + \DateTime $dueDate = null, + bool $unsetDueDate = null, + array $labels = null, + int $milestone = null + ): array + { + $options['json'] = [ + 'assignee' => $assignee, + 'assignees' => $assignees, + 'title' => $title, + 'state' => $state, + 'body' => $body, + 'due_date' => $dueDate ? $dueDate->format(\DateTime::ATOM) : null, + 'unsetDueDate' => $unsetDueDate, + 'labels' => $labels, + 'milestone' => $milestone, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls/' . $index, 'PATCH', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $index + * @return bool + */ + public function checkMerged( + string $owner, + string $repositoryName, + int $index + ): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls/' . $index . '/merge', 'GET'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $index + * @param string $do + * @param string|null $mergeMessage + * @param string|null $mergeTitle + * @return bool + */ + public function mergePull( + string $owner, + string $repositoryName, + int $index, + string $do, + string $mergeMessage = null, + string $mergeTitle = null + ): bool + { + $options['json'] = [ + 'Do' => $do, + 'MergeMessageField' => $mergeMessage, + 'MergeTitleField' => $mergeTitle, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/pulls/' . $index . '/merge', 'POST', $options); + + return true; + } +} diff --git a/Classes/Endpoint/Repositories/ReleasesTrait.php b/Classes/Endpoint/Repositories/ReleasesTrait.php new file mode 100644 index 0000000..353f7fb --- /dev/null +++ b/Classes/Endpoint/Repositories/ReleasesTrait.php @@ -0,0 +1,184 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $tagName + * @param string|null $body + * @param bool|null $draft + * @param string|null $name + * @param bool|null $prerelease + * @param string|null $targetCommitish + * @return array + */ + public function createRelease( + string $owner, + string $repositoryName, + string $tagName, + string $body = null, + bool $draft = null, + string $name = null, + bool $prerelease = null, + string $targetCommitish = null + ): array + { + $options['json'] = [ + 'tag_name' => $tagName, + 'body' => $body, + 'draft' => $draft, + 'name' => $name, + 'prerelease' => $prerelease, + 'target_commitish' => $targetCommitish, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases', 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function getRelease(string $owner, string $repositoryName, int $id): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return bool + */ + public function deleteRelease(string $owner, string $repositoryName, int $id): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id, 'DELETE'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @param string|null $tagName + * @param string|null $body + * @param bool|null $draft + * @param string|null $name + * @param bool|null $prerelease + * @param string|null $targetCommitish + * @return array + */ + public function updateRelease( + string $owner, + string $repositoryName, + int $id, + string $tagName = null, + string $body = null, + bool $draft = null, + string $name = null, + bool $prerelease = null, + string $targetCommitish = null + ): array + { + $options['json'] = [ + 'tag_name' => $tagName, + 'body' => $body, + 'draft' => $draft, + 'name' => $name, + 'prerelease' => $prerelease, + 'target_commitish' => $targetCommitish, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id, 'PATCH', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function getReleaseAssets(string $owner, string $repositoryName, int $id): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id . '/assets'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return array + */ + public function getReleaseAsset(string $owner, string $repositoryName, int $id, int $assetId): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id . '/assets/' . $assetId); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @return bool + */ + public function deleteReleaseAsset(string $owner, string $repositoryName, int $id, int $assetId): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id . '/assets/' . $assetId, 'DELETE'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param int $id + * @param string $name + * @return array + */ + public function updateReleaseAsset(string $owner, string $repositoryName, int $id, int $assetId, string $name): array + { + $options['json'] = [ + 'name' => $name + ]; + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/releases/' . $id . '/assets/' . $assetId, 'PATCH', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/RepositoryTrait.php b/Classes/Endpoint/Repositories/RepositoryTrait.php new file mode 100644 index 0000000..3097da7 --- /dev/null +++ b/Classes/Endpoint/Repositories/RepositoryTrait.php @@ -0,0 +1,363 @@ + [ + 'clone_addr' => $cloneAddr, + 'repo_name' => $repoName, + 'uid' => $uid, + 'auth_password' => $authPassword, + 'auth_username' => $authUsername, + 'description' => $description, + 'issues' => $issues, + 'labels' => $labels, + 'milestones' => $milestones, + 'mirror' => $mirror, + 'private' => $private, + 'pull_requests' => $pullRequests, + 'releases' => $releases, + 'wiki' => $wiki, + ] + ]; + + $options['json'] = $this->removeNullValues($options['json']); + $response = $this->client->request(self::BASE_URI . '/migrate', 'POST', $options); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $query + * @param bool|null $topic + * @param bool|null $includeDesc + * @param int|null $uid + * @param int|null $priorityOwnerId + * @param int|null $starredBy + * @param bool|null $private + * @param bool|null $template + * @param int|null $page + * @param int|null $limit + * @param string|null $mode + * @param bool|null $exclusive + * @param string|null $sort + * @param string|null $order + * @return array + */ + public function search( + string $query, + ?bool $topic = null, + ?bool $includeDesc = null, + ?int $uid = null, + ?int $priorityOwnerId = null, + ?int $starredBy = null, + ?bool $private = null, + ?bool $template = null, + ?int $page = null, + ?int $limit = null, + ?string $mode = null, + ?bool $exclusive = null, + ?string $sort = null, + ?string $order = null + ): array + { + $options['query'] = [ + 'query' => $query, + 'topic' => $topic, + 'includeDesc' => $includeDesc, + 'uid' => $uid, + 'priorityOwnerId' => $priorityOwnerId, + 'starredBy' => $starredBy, + 'private' => $private, + 'template' => $template, + 'page' => $page, + 'limit' => $limit, + 'mode' => $mode, + 'exclusive' => $exclusive, + 'sort' => $sort, + 'order' => $order, + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/search', 'GET', $options); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function get(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return bool + */ + public function delete(string $owner, string $repositoryName): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName, 'DELETE'); + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param bool|null $allow_merge_commits + * @param bool|null $allow_rebase + * @param bool|null $allow_rebase_explicit + * @param bool|null $allow_squash_merge + * @param bool|null $archived + * @param string|null $default_branch + * @param string|null $description + * @param string|null $external_tracker_format + * @param string|null $external_tracker_style + * @param string|null $external_tracker_url + * @param string|null $external_wiki_url + * @param bool|null $has_issues + * @param bool|null $has_pull_requests + * @param bool|null $has_wiki + * @param bool|null $ignore_whitespace_conflicts + * @param bool|null $allow_only_contributors_to_track_time + * @param bool|null $enable_issue_dependencies + * @param bool|null $enable_time_tracker + * @param string|null $name + * @param bool|null $private + * @param bool|null $template + * @param string|null $website + * @return array + */ + public function update( + string $owner, + string $repositoryName, + bool $allow_merge_commits = null, + bool $allow_rebase = null, + bool $allow_rebase_explicit = null, + bool $allow_squash_merge = null, + bool $archived = null, + string $default_branch = null, + string $description = null, + string $external_tracker_format = null, + string $external_tracker_style = null, + string $external_tracker_url = null, + string $external_wiki_url = null, + bool $has_issues = null, + bool $has_pull_requests = null, + bool $has_wiki = null, + bool $ignore_whitespace_conflicts = null, + bool $allow_only_contributors_to_track_time = null, + bool $enable_issue_dependencies = null, + bool $enable_time_tracker = null, + string $name = null, + bool $private = null, + bool $template = null, + string $website = null + ): array + { + $options['json'] = [ + 'allow_merge_commits' => $allow_merge_commits, + 'allow_rebase' => $allow_rebase, + 'allow_rebase_explicit' => $allow_rebase_explicit, + 'allow_squash_merge' => $allow_squash_merge, + 'archived' => $archived, + 'default_branch' => $default_branch, + 'description' => $description, + 'external_tracker' => [ + 'external_tracker_format' => $external_tracker_format, + 'external_tracker_style' => $external_tracker_style, + 'external_tracker_url' => $external_tracker_url, + ], + 'external_wiki' => [ + 'external_wiki_url' => $external_wiki_url, + ], + 'has_issues' => $has_issues, + 'has_pull_requests' => $has_pull_requests, + 'has_wiki' => $has_wiki, + 'ignore_whitespace_conflicts' => $ignore_whitespace_conflicts, + 'internal_tracker' => [ + 'allow_only_contributors_to_track_time' => $allow_only_contributors_to_track_time, + 'enable_issue_dependencies' => $enable_issue_dependencies, + 'enable_time_tracker' => $enable_time_tracker, + ], + 'name' => $name, + 'private' => $private, + 'template' => $template, + 'website' => $website, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName, 'PATCH', $options); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return bool + */ + public function mirrorSync(string $owner, string $repositoryName): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/mirror-sync', 'POST'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @return string + */ + public function getSigningKeyGPG(string $owner, string $repositoryName): string + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/signing-key.gpg'); + + return (string)$response->getBody(); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function getStargazers(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/stargazers'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function getTags(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/tags'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function getTimes(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/times'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param int $id + * @return array + */ + public function getById(int $id): array + { + $response = $this->client->request('/repositories/' . $id); + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $searchTerm + * @return array + */ + public function topicsSearch(string $searchTerm): array + { + $options['query'] = [ + 'q' => $searchTerm + ]; + + $response = $this->client->request('/topics/search', 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $name + * @param bool $autoInit + * @param string $description + * @param string $gitignores + * @param string $issueLabels + * @param string $license + * @param bool $private + * @param string $readme + * @return array + */ + public function create( + string $name, + bool $autoInit = null, + string $description = null, + string $gitignores = null, + string $issueLabels = null, + string $license = null, + bool $private = null, + string $readme = null + ): array + { + $options['json'] = [ + 'name' => $name, + 'auto_init' => $autoInit, + 'description' => $description, + 'gitignores' => $gitignores, + 'issue_labels' => $issueLabels, + 'license' => $license, + 'private' => $private, + 'readme' => $readme, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request('/user/repos', 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/StatusesTrait.php b/Classes/Endpoint/Repositories/StatusesTrait.php new file mode 100644 index 0000000..6b6d7a1 --- /dev/null +++ b/Classes/Endpoint/Repositories/StatusesTrait.php @@ -0,0 +1,76 @@ + $page, + 'sort' => $sort, + 'state' => $state, + ]; + $options['query'] = $this->removeNullValues($options['query']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/statuses/' . $sha, 'GET', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $sha + * @param string $state // pending, success, error, failure, warning + * @param string|null $description + * @param string|null $context + * @param string|null $targetUrl + * @return array + */ + public function createStatus( + string $owner, + string $repositoryName, + string $sha, + string $state, + string $description = null, + string $context = null, + string $targetUrl = null + ): array + { + $options['json'] = [ + 'state' => $state, + 'description' => $description, + 'context' => $context, + 'target_url' => $targetUrl, + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/statuses/' . $sha, 'POST', $options); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } +} diff --git a/Classes/Endpoint/Repositories/SubscriptionTrait.php b/Classes/Endpoint/Repositories/SubscriptionTrait.php new file mode 100644 index 0000000..5c3e507 --- /dev/null +++ b/Classes/Endpoint/Repositories/SubscriptionTrait.php @@ -0,0 +1,61 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/subscribers'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function checkSubscription(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/subscription'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return array + */ + public function addSubscription(string $owner, string $repositoryName): array + { + $response = $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/subscription', 'PUT'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @return bool + */ + public function deleteSubscription(string $owner, string $repositoryName): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/subscription', 'DELETE'); + + return true; + } +} diff --git a/Classes/Endpoint/Repositories/TopicsTrait.php b/Classes/Endpoint/Repositories/TopicsTrait.php new file mode 100644 index 0000000..c237327 --- /dev/null +++ b/Classes/Endpoint/Repositories/TopicsTrait.php @@ -0,0 +1,69 @@ +client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/topics'); + + return \GuzzleHttp\json_decode($response->getBody(), true); + } + + /** + * @param string $owner + * @param string $repositoryName + * @param array $topics + * @return bool + */ + public function replaceTopics(string $owner, string $repositoryName, array $topics): bool + { + $options['json'] = [ + 'topics' => $topics + ]; + $options['json'] = $this->removeNullValues($options['json']); + + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/topics', 'PUT', $options); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $topic + * @return bool + */ + public function addTopic(string $owner, string $repositoryName, string $topic): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/topics/' . $topic, 'PUT'); + + return true; + } + + /** + * @param string $owner + * @param string $repositoryName + * @param string $topic + * @return bool + */ + public function deleteTopic(string $owner, string $repositoryName, string $topic): bool + { + $this->client->request(self::BASE_URI . '/' . $owner . '/' . $repositoryName . '/topics/' . $topic, 'DELETE'); + + return true; + } +} diff --git a/README.md b/README.md index 2385b78..06704fd 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,13 @@ $repository = $giteaClient->repositories()->get('owner', 'repoName'); $repository = $giteaClient->miscellaneous()->version(); ``` +Run an API call as another user: + +``` +// e.g. check subscription status as a user +$status = $giteaClient->sudo('username')->repositories()->checkSubscription(); +``` + ## Versioning We use [SemVer](http://semver.org/) for versioning. For the versions available, @@ -80,236 +87,236 @@ This project is licensed under the MIT License - see the #### Admin -Status | Method | Endpoint ---- | --- | --- -✅ | GET | /admin/orgs -✅ | POST | /admin/users -✅ | DELETE | /admin/users/{username} -✅ | PATCH | /admin/users/{username} -✅ | POST | /admin/users/{username}/keys -✅ | DELETE | /admin/users/{username}/keys/{id} -✅ | POST | /admin/users/{username}/orgs -✅ | POST | /admin/users/{username}/repos +Status | Method | Endpoint | Comment +--- | --- | --- | --- +✅ | GET | /admin/orgs | +✅ | POST | /admin/users | +✅ | DELETE | /admin/users/{username} | +✅ | PATCH | /admin/users/{username} | +✅ | POST | /admin/users/{username}/keys | +✅ | DELETE | /admin/users/{username}/keys/{id} | +✅ | POST | /admin/users/{username}/orgs | +✅ | POST | /admin/users/{username}/repos | #### Miscellaneous -Status | Method | Endpoint ---- | --- | --- -✅ | POST | /markdown -✅ | POST | /markdown/raw -✅ | GET | /signing-key.gpg -✅ | GET | /version +Status | Method | Endpoint | Comment +--- | --- | --- | --- +✅ | POST | /markdown | +✅ | POST | /markdown/raw | +✅ | GET | /signing-key.gpg | +✅ | GET | /version | #### Organization -Status | Method | Endpoint ---- | --- | --- -❌ | POST | /org/{org}/repos -❌ | POST | /orgs -❌ | GET | /orgs/{org} -❌ | DELETE | /orgs/{org} -❌ | PATCH | /orgs/{org} -❌ | GET | /orgs/{org}/hooks -❌ | POST | /orgs/{org}/hooks/ -❌ | GET | /orgs/{org}/hooks/{id} -❌ | DELETE | /orgs/{org}/hooks/{id} -❌ | PATCH | /orgs/{org}/hooks/{id} -❌ | GET | /orgs/{org}/members -❌ | GET | /orgs/{org}/members/{username} -❌ | DELETE | /orgs/{org}/members/{username} -❌ | GET | /orgs/{org}/public_members -❌ | GET | /orgs/{org}/public_members/{username} -❌ | PUT | /orgs/{org}/public_members/{username} -❌ | DELETE | /orgs/{org}/public_members/{username} -❌ | GET | /orgs/{org}/repos -❌ | GET | /orgs/{org}/teams -❌ | POST | /orgs/{org}/teams -❌ | GET | /orgs/{org}/teams/search -❌ | GET | /teams/{id} -❌ | DELETE | /teams/{id} -❌ | PATCH | /teams/{id} -❌ | GET | /teams/{id}/members -❌ | GET | /teams/{id}/members/{username} -❌ | PUT | /teams/{id}/members/{username} -❌ | DELETE | /teams/{id}/members/{username} -❌ | GET | /teams/{id}/repos -❌ | PUT | /teams/{id}/repos/{org}/{repo} -❌ | DELETE | /teams/{id}/repos/{org}/{repo} -❌ | GET | /user/orgs -❌ | GET | /users/{username}/orgs +Status | Method | Endpoint | Comment +--- | --- | --- | --- +❌ | POST | /org/{org}/repos | +❌ | POST | /orgs | +❌ | GET | /orgs/{org} | +❌ | DELETE | /orgs/{org} | +❌ | PATCH | /orgs/{org} | +❌ | GET | /orgs/{org}/hooks | +❌ | POST | /orgs/{org}/hooks/ | +❌ | GET | /orgs/{org}/hooks/{id} | +❌ | DELETE | /orgs/{org}/hooks/{id} | +❌ | PATCH | /orgs/{org}/hooks/{id} | +❌ | GET | /orgs/{org}/members | +❌ | GET | /orgs/{org}/members/{username} | +❌ | DELETE | /orgs/{org}/members/{username} | +❌ | GET | /orgs/{org}/public_members | +❌ | GET | /orgs/{org}/public_members/{username} | +❌ | PUT | /orgs/{org}/public_members/{username} | +❌ | DELETE | /orgs/{org}/public_members/{username} | +❌ | GET | /orgs/{org}/repos | +❌ | GET | /orgs/{org}/teams | +❌ | POST | /orgs/{org}/teams | +❌ | GET | /orgs/{org}/teams/search | +❌ | GET | /teams/{id} | +❌ | DELETE | /teams/{id} | +❌ | PATCH | /teams/{id} | +❌ | GET | /teams/{id}/members | +❌ | GET | /teams/{id}/members/{username} | +❌ | PUT | /teams/{id}/members/{username} | +❌ | DELETE | /teams/{id}/members/{username} | +❌ | GET | /teams/{id}/repos | +❌ | PUT | /teams/{id}/repos/{org}/{repo} | +❌ | DELETE | /teams/{id}/repos/{org}/{repo} | +❌ | GET | /user/orgs | +❌ | GET | /users/{username}/orgs | #### Issue -Status | Method | Endpoint ---- | --- | --- -❌ | GET | /repos/issues/search -❌ | GET | /repos/{owner}/{repo}/issues -❌ | POST | /repos/{owner}/{repo}/issues -❌ | GET | /repos/{owner}/{repo}/issues/comments -❌ | DELETE | /repos/{owner}/{repo}/issues/comments/{id} -❌ | PATCH | /repos/{owner}/{repo}/issues/comments/{id} -❌ | GET | /repos/{owner}/{repo}/issues/comments/{id}/reactions -❌ | POST | /repos/{owner}/{repo}/issues/comments/{id}/reactions -❌ | DELETE | /repos/{owner}/{repo}/issues/comments/{id}/reactions -❌ | GET | /repos/{owner}/{repo}/issues/{index} -❌ | PATCH | /repos/{owner}/{repo}/issues/{index} -❌ | GET | /repos/{owner}/{repo}/issues/{index}/comments -❌ | POST | /repos/{owner}/{repo}/issues/{index}/comments -❌ | POST | /repos/{owner}/{repo}/issues/{index}/deadline -❌ | GET | /repos/{owner}/{repo}/issues/{index}/labels -❌ | PUT | /repos/{owner}/{repo}/issues/{index}/labels -❌ | POST | /repos/{owner}/{repo}/issues/{index}/labels -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/labels -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/labels/{id} -❌ | GET | /repos/{owner}/{repo}/issues/{index}/reactions -❌ | POST | /repos/{owner}/{repo}/issues/{index}/reactions -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/reactions -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/stopwatch/delete -❌ | POST | /repos/{owner}/{repo}/issues/{index}/stopwatch/start -❌ | POST | /repos/{owner}/{repo}/issues/{index}/stopwatch/stop -❌ | GET | /repos/{owner}/{repo}/issues/{index}/subscriptions -❌ | PUT | /repos/{owner}/{repo}/issues/{index}/subscriptions/{user} -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/subscriptions/{user} -❌ | GET | /repos/{owner}/{repo}/issues/{index}/times -❌ | POST | /repos/{owner}/{repo}/issues/{index}/times -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/times -❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/times/{id} -❌ | GET | /repos/{owner}/{repo}/labels -❌ | POST | /repos/{owner}/{repo}/labels -❌ | GET | /repos/{owner}/{repo}/labels/{id} -❌ | DELETE | /repos/{owner}/{repo}/labels/{id} -❌ | PATCH | /repos/{owner}/{repo}/labels/{id} -❌ | GET | /repos/{owner}/{repo}/milestones -❌ | POST | /repos/{owner}/{repo}/milestones -❌ | GET | /repos/{owner}/{repo}/milestones/{id} -❌ | DELETE | /repos/{owner}/{repo}/milestones/{id} -❌ | PATCH | /repos/{owner}/{repo}/milestones/{id} +Status | Method | Endpoint | Comment +--- | --- | --- | --- +❌ | GET | /repos/issues/search | +❌ | GET | /repos/{owner}/{repo}/issues | +❌ | POST | /repos/{owner}/{repo}/issues | +❌ | GET | /repos/{owner}/{repo}/issues/comments | +❌ | DELETE | /repos/{owner}/{repo}/issues/comments/{id} | +❌ | PATCH | /repos/{owner}/{repo}/issues/comments/{id} | +❌ | GET | /repos/{owner}/{repo}/issues/comments/{id}/reactions | +❌ | POST | /repos/{owner}/{repo}/issues/comments/{id}/reactions | +❌ | DELETE | /repos/{owner}/{repo}/issues/comments/{id}/reactions | +❌ | GET | /repos/{owner}/{repo}/issues/{index} | +❌ | PATCH | /repos/{owner}/{repo}/issues/{index} | +❌ | GET | /repos/{owner}/{repo}/issues/{index}/comments | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/comments | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/deadline | +❌ | GET | /repos/{owner}/{repo}/issues/{index}/labels | +❌ | PUT | /repos/{owner}/{repo}/issues/{index}/labels | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/labels | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/labels | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/labels/{id} | +❌ | GET | /repos/{owner}/{repo}/issues/{index}/reactions | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/reactions | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/reactions | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/stopwatch/delete | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/stopwatch/start | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/stopwatch/stop | +❌ | GET | /repos/{owner}/{repo}/issues/{index}/subscriptions | +❌ | PUT | /repos/{owner}/{repo}/issues/{index}/subscriptions/{user} | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/subscriptions/{user} | +❌ | GET | /repos/{owner}/{repo}/issues/{index}/times | +❌ | POST | /repos/{owner}/{repo}/issues/{index}/times | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/times | +❌ | DELETE | /repos/{owner}/{repo}/issues/{index}/times/{id} | +❌ | GET | /repos/{owner}/{repo}/labels | +❌ | POST | /repos/{owner}/{repo}/labels | +❌ | GET | /repos/{owner}/{repo}/labels/{id} | +❌ | DELETE | /repos/{owner}/{repo}/labels/{id} | +❌ | PATCH | /repos/{owner}/{repo}/labels/{id} | +❌ | GET | /repos/{owner}/{repo}/milestones | +❌ | POST | /repos/{owner}/{repo}/milestones | +❌ | GET | /repos/{owner}/{repo}/milestones/{id} | +❌ | DELETE | /repos/{owner}/{repo}/milestones/{id} | +❌ | PATCH | /repos/{owner}/{repo}/milestones/{id} | #### Repository -Status | Method | Endpoint ---- | --- | --- -✅ | POST | /repos/migrate -✅ | GET | /repos/search -✅ | GET | /repos/{owner}/{repo} -✅ | DELETE | /repos/{owner}/{repo} -✅ | PATCH | /repos/{owner}/{repo} -❌ | GET | /repos/{owner}/{repo}/archive/{archive} -❌ | GET | /repos/{owner}/{repo}/branches -❌ | GET | /repos/{owner}/{repo}/branches/{branch} -❌ | GET | /repos/{owner}/{repo}/collaborators -❌ | GET | /repos/{owner}/{repo}/collaborators/{collaborator} -❌ | PUT | /repos/{owner}/{repo}/collaborators/{collaborator} -❌ | DELETE | /repos/{owner}/{repo}/collaborators/{collaborator} -❌ | GET | /repos/{owner}/{repo}/commits -❌ | GET | /repos/{owner}/{repo}/commits/{ref}/statuses -❌ | GET | /repos/{owner}/{repo}/contents -❌ | GET | /repos/{owner}/{repo}/contents/{filepath} -❌ | PUT | /repos/{owner}/{repo}/contents/{filepath} -❌ | POST | /repos/{owner}/{repo}/contents/{filepath} -❌ | DELETE | /repos/{owner}/{repo}/contents/{filepath} -❌ | GET | /repos/{owner}/{repo}/editorconfig/{filepath} -❌ | GET | /repos/{owner}/{repo}/forks -❌ | POST | /repos/{owner}/{repo}/forks -❌ | GET | /repos/{owner}/{repo}/git/blobs/{sha} -❌ | GET | /repos/{owner}/{repo}/git/commits/{sha} -❌ | GET | /repos/{owner}/{repo}/git/refs -❌ | GET | /repos/{owner}/{repo}/git/refs/{ref} -❌ | GET | /repos/{owner}/{repo}/git/tags/{sha} -❌ | GET | /repos/{owner}/{repo}/git/trees/{sha} -❌ | GET | /repos/{owner}/{repo}/hooks -❌ | POST | /repos/{owner}/{repo}/hooks -❌ | GET | /repos/{owner}/{repo}/hooks/git -❌ | GET | /repos/{owner}/{repo}/hooks/git/{id} -❌ | DELETE | /repos/{owner}/{repo}/hooks/git/{id} -❌ | PATCH | /repos/{owner}/{repo}/hooks/git/{id} -❌ | GET | /repos/{owner}/{repo}/hooks/{id} -❌ | DELETE | /repos/{owner}/{repo}/hooks/{id} -❌ | PATCH | /repos/{owner}/{repo}/hooks/{id} -❌ | POST | /repos/{owner}/{repo}/hooks/{id}/tests -❌ | GET | /repos/{owner}/{repo}/keys -❌ | POST | /repos/{owner}/{repo}/keys -❌ | GET | /repos/{owner}/{repo}/keys/{id} -❌ | DELETE | /repos/{owner}/{repo}/keys/{id} -❌ | POST | /repos/{owner}/{repo}/mirror-sync -❌ | GET | /repos/{owner}/{repo}/pulls -❌ | POST | /repos/{owner}/{repo}/pulls -❌ | GET | /repos/{owner}/{repo}/pulls/{index} -❌ | PATCH | /repos/{owner}/{repo}/pulls/{index} -❌ | GET | /repos/{owner}/{repo}/pulls/{index}/merge -❌ | POST | /repos/{owner}/{repo}/pulls/{index}/merge -❌ | GET | /repos/{owner}/{repo}/raw/{filepath} -❌ | GET | /repos/{owner}/{repo}/releases -❌ | POST | /repos/{owner}/{repo}/releases -❌ | GET | /repos/{owner}/{repo}/releases/{id} -❌ | DELETE | /repos/{owner}/{repo}/releases/{id} -❌ | PATCH | /repos/{owner}/{repo}/releases/{id} -❌ | GET | /repos/{owner}/{repo}/releases/{id}/assets -❌ | POST | /repos/{owner}/{repo}/releases/{id}/assets -❌ | GET | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} -❌ | DELETE | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} -❌ | PATCH | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} -❌ | GET | /repos/{owner}/{repo}/signing-key.gpg -❌ | GET | /repos/{owner}/{repo}/stargazers -❌ | GET | /repos/{owner}/{repo}/statuses/{sha} -❌ | POST | /repos/{owner}/{repo}/statuses/{sha} -❌ | GET | /repos/{owner}/{repo}/subscribers -❌ | GET | /repos/{owner}/{repo}/subscription -❌ | PUT | /repos/{owner}/{repo}/subscription -❌ | DELETE | /repos/{owner}/{repo}/subscription -❌ | GET | /repos/{owner}/{repo}/tags -❌ | GET | /repos/{owner}/{repo}/times -❌ | GET | /repos/{owner}/{repo}/topics -❌ | PUT | /repos/{owner}/{repo}/topics -❌ | PUT | /repos/{owner}/{repo}/topics/{topic} -❌ | DELETE | /repos/{owner}/{repo}/topics/{topic} -❌ | GET | /repositories/{id} -❌ | GET | /topics/search -❌ | POST | /user/repos +Status | Method | Endpoint | Comment +--- | --- | --- | --- +✅ | POST | /repos/migrate | +✅ | GET | /repos/search | +✅ | GET | /repos/{owner}/{repo} | +✅ | DELETE | /repos/{owner}/{repo} | +✅ | PATCH | /repos/{owner}/{repo} | +⛔️ | GET | /repos/{owner}/{repo}/archive/{archive} | Not supported +✅ | GET | /repos/{owner}/{repo}/branches | +✅ | GET | /repos/{owner}/{repo}/branches/{branch} | +✅ | GET | /repos/{owner}/{repo}/collaborators | +✅ | GET | /repos/{owner}/{repo}/collaborators/{collaborator} | +✅ | PUT | /repos/{owner}/{repo}/collaborators/{collaborator} | +✅ | DELETE | /repos/{owner}/{repo}/collaborators/{collaborator} | +✅ | GET | /repos/{owner}/{repo}/commits | +✅ | GET | /repos/{owner}/{repo}/commits/{ref}/statuses | +✅ | GET | /repos/{owner}/{repo}/contents | +✅ | GET | /repos/{owner}/{repo}/contents/{filepath} | +✅ | PUT | /repos/{owner}/{repo}/contents/{filepath} | +✅ | POST | /repos/{owner}/{repo}/contents/{filepath} | +✅ | DELETE | /repos/{owner}/{repo}/contents/{filepath} | +✅ | GET | /repos/{owner}/{repo}/editorconfig/{filepath} | +✅ | GET | /repos/{owner}/{repo}/forks | +✅ | POST | /repos/{owner}/{repo}/forks | +✅ | GET | /repos/{owner}/{repo}/git/blobs/{sha} | +✅ | GET | /repos/{owner}/{repo}/git/commits/{sha} | +✅ | GET | /repos/{owner}/{repo}/git/refs | +✅ | GET | /repos/{owner}/{repo}/git/refs/{ref} | +✅ | GET | /repos/{owner}/{repo}/git/tags/{sha} | +✅ | GET | /repos/{owner}/{repo}/git/trees/{sha} | +✅ | GET | /repos/{owner}/{repo}/hooks | +✅ | POST | /repos/{owner}/{repo}/hooks | +✅ | GET | /repos/{owner}/{repo}/hooks/git | +✅ | GET | /repos/{owner}/{repo}/hooks/git/{id} | +✅ | DELETE | /repos/{owner}/{repo}/hooks/git/{id} | +✅ | PATCH | /repos/{owner}/{repo}/hooks/git/{id} | +✅ | GET | /repos/{owner}/{repo}/hooks/{id} | +✅ | DELETE | /repos/{owner}/{repo}/hooks/{id} | +✅ | PATCH | /repos/{owner}/{repo}/hooks/{id} | +✅ | POST | /repos/{owner}/{repo}/hooks/{id}/tests | +✅ | GET | /repos/{owner}/{repo}/keys | +✅ | POST | /repos/{owner}/{repo}/keys | +✅ | GET | /repos/{owner}/{repo}/keys/{id} | +✅ | DELETE | /repos/{owner}/{repo}/keys/{id} | +✅ | POST | /repos/{owner}/{repo}/mirror-sync | +✅ | GET | /repos/{owner}/{repo}/pulls | +✅ | POST | /repos/{owner}/{repo}/pulls | +✅ | GET | /repos/{owner}/{repo}/pulls/{index} | +✅ | PATCH | /repos/{owner}/{repo}/pulls/{index} | +✅ | GET | /repos/{owner}/{repo}/pulls/{index}/merge | +✅ | POST | /repos/{owner}/{repo}/pulls/{index}/merge | +✅ | GET | /repos/{owner}/{repo}/raw/{filepath} | +✅ | GET | /repos/{owner}/{repo}/releases | +✅ | POST | /repos/{owner}/{repo}/releases | +✅ | GET | /repos/{owner}/{repo}/releases/{id} | +✅ | DELETE | /repos/{owner}/{repo}/releases/{id} | +✅ | PATCH | /repos/{owner}/{repo}/releases/{id} | +✅ | GET | /repos/{owner}/{repo}/releases/{id}/assets | +⛔️ | POST | /repos/{owner}/{repo}/releases/{id}/assets | Not supported +✅ | GET | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} | +✅ | DELETE | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} | +✅ | PATCH | /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} | +✅ | GET | /repos/{owner}/{repo}/signing-key.gpg | +✅ | GET | /repos/{owner}/{repo}/stargazers | +✅ | GET | /repos/{owner}/{repo}/statuses/{sha} | +✅ | POST | /repos/{owner}/{repo}/statuses/{sha} | +✅ | GET | /repos/{owner}/{repo}/subscribers | +✅ | GET | /repos/{owner}/{repo}/subscription | +✅ | PUT | /repos/{owner}/{repo}/subscription | +✅ | DELETE | /repos/{owner}/{repo}/subscription | +✅ | GET | /repos/{owner}/{repo}/tags | +✅ | GET | /repos/{owner}/{repo}/times | +✅ | GET | /repos/{owner}/{repo}/topics | +✅ | PUT | /repos/{owner}/{repo}/topics | +✅ | PUT | /repos/{owner}/{repo}/topics/{topic} | +✅ | DELETE | /repos/{owner}/{repo}/topics/{topic} | +✅ | GET | /repositories/{id} | +✅ | GET | /topics/search | +✅ | POST | /user/repos | #### User -Status | Method | Endpoint ---- | --- | --- -❌ | GET | /repos/{owner}/{repo}/times/{user} -❌ | GET | /user -❌ | GET | /user/emails -❌ | POST | /user/emails -❌ | DELETE | /user/emails -❌ | GET | /user/followers -❌ | GET | /user/following -❌ | GET | /user/following/{username} -❌ | PUT | /user/following/{username} -❌ | DELETE | /user/following/{username} -❌ | GET | /user/gpg_keys -❌ | POST | /user/gpg_keys -❌ | GET | /user/gpg_keys/{id} -❌ | DELETE | /user/gpg_keys/{id} -❌ | GET | /user/keys -❌ | POST | /user/keys -❌ | GET | /user/keys/{id} -❌ | DELETE | /user/keys/{id} -❌ | GET | /user/repos -❌ | POST | /user/repos -❌ | GET | /user/starred -❌ | GET | /user/starred/{owner}/{repo} -❌ | PUT | /user/starred/{owner}/{repo} -❌ | DELETE | /user/starred/{owner}/{repo} -❌ | GET | /user/stopwatches -❌ | GET | /user/subscriptions -❌ | GET | /user/teams -❌ | GET | /user/times -❌ | GET | /users/search -❌ | GET | /users/{follower}/following/{followee} -❌ | GET | /users/{username} -❌ | GET | /users/{username}/followers -❌ | GET | /users/{username}/following -❌ | GET | /users/{username}/gpg_keys -❌ | GET | /users/{username}/heatmap -❌ | GET | /users/{username}/keys -❌ | GET | /users/{username}/repos -❌ | GET | /users/{username}/starred -❌ | GET | /users/{username}/subscriptions -❌ | GET | /users/{username}/tokens -❌ | POST | /users/{username}/tokens -❌ | DELETE | /users/{username}/tokens/{token} +Status | Method | Endpoint | Comment +--- | --- | --- | --- +❌ | GET | /repos/{owner}/{repo}/times/{user} | +❌ | GET | /user | +❌ | GET | /user/emails | +❌ | POST | /user/emails | +❌ | DELETE | /user/emails | +❌ | GET | /user/followers | +❌ | GET | /user/following | +❌ | GET | /user/following/{username} | +❌ | PUT | /user/following/{username} | +❌ | DELETE | /user/following/{username} | +❌ | GET | /user/gpg_keys | +❌ | POST | /user/gpg_keys | +❌ | GET | /user/gpg_keys/{id} | +❌ | DELETE | /user/gpg_keys/{id} | +❌ | GET | /user/keys | +❌ | POST | /user/keys | +❌ | GET | /user/keys/{id} | +❌ | DELETE | /user/keys/{id} | +❌ | GET | /user/repos | +❌ | POST | /user/repos | +❌ | GET | /user/starred | +❌ | GET | /user/starred/{owner}/{repo} | +❌ | PUT | /user/starred/{owner}/{repo} | +❌ | DELETE | /user/starred/{owner}/{repo} | +❌ | GET | /user/stopwatches | +❌ | GET | /user/subscriptions | +❌ | GET | /user/teams | +❌ | GET | /user/times | +❌ | GET | /users/search | +❌ | GET | /users/{follower}/following/{followee} | +❌ | GET | /users/{username} | +❌ | GET | /users/{username}/followers | +❌ | GET | /users/{username}/following | +❌ | GET | /users/{username}/gpg_keys | +❌ | GET | /users/{username}/heatmap | +❌ | GET | /users/{username}/keys | +❌ | GET | /users/{username}/repos | +❌ | GET | /users/{username}/starred | +❌ | GET | /users/{username}/subscriptions | +❌ | GET | /users/{username}/tokens | +❌ | POST | /users/{username}/tokens | +❌ | DELETE | /users/{username}/tokens/{token} |