diff --git a/.env-example b/.env-example new file mode 100644 index 00000000000..4f6da72cb4a --- /dev/null +++ b/.env-example @@ -0,0 +1,14 @@ +# token, login +GITHUB_AUTH_METHOD= + +GITHUB_REPO_1= +GITHUB_USER_1= +GITHUB_USERNAME_1= +GITHUB_PASSWORD_1= +GITHUB_TOKEN_1= + +GITHUB_REPO_2= +GITHUB_USER_2= +GITHUB_USERNAME_2= +GITHUB_PASSWORD_2= +GITHUB_TOKEN_2= diff --git a/.gitignore b/.gitignore index 2c9d04ccd11..37d239ef1fc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ phpunit.xml composer.lock composer.phar vendor/* +# +.idea +.DS_STORE +.env diff --git a/composer.json b/composer.json index 9c96c716a3f..5ee0d93afcb 100644 --- a/composer.json +++ b/composer.json @@ -1,9 +1,14 @@ { - "name": "knplabs/github-api", + "name": "teamdevsquad/github-api", "type": "library", "description": "GitHub API v3 client", "homepage": "https://github.com/KnpLabs/php-github-api", - "keywords": ["github", "gh", "api", "gist"], + "keywords": [ + "github", + "gh", + "api", + "gist" + ], "license": "MIT", "authors": [ { @@ -32,13 +37,18 @@ "php-http/mock-client": "^1.0", "guzzlehttp/psr7": "^1.2", "sllh/php-cs-fixer-styleci-bridge": "^1.3", - "cache/array-adapter": "^0.4" + "cache/array-adapter": "^0.4", + "vlucas/phpdotenv": "^2.4" }, "autoload": { - "psr-4": { "Github\\": "lib/Github/" } + "psr-4": { + "Github\\": "lib/Github/" + } }, "autoload-dev": { - "psr-4": { "Github\\Tests\\": "test/Github/Tests/"} + "psr-4": { + "Github\\Tests\\": "test/Github/Tests/" + } }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/lib/Github/Api/Repo.php b/lib/Github/Api/Repo.php index c0c54a95f15..497c733ea27 100644 --- a/lib/Github/Api/Repo.php +++ b/lib/Github/Api/Repo.php @@ -10,6 +10,7 @@ use Github\Api\Repository\Downloads; use Github\Api\Repository\Forks; use Github\Api\Repository\Hooks; +use Github\Api\Repository\Invitations; use Github\Api\Repository\Labels; use Github\Api\Repository\Projects; use Github\Api\Repository\Protection; @@ -283,6 +284,18 @@ public function collaborators() return new Collaborators($this->client); } + /** + * Manage the invitations of a repository. + * + * @link http://developer.github.com/v3/repos/invitations/ + * + * @return Invitations + */ + public function invitations() + { + return new Invitations($this->client); + } + /** * Manage the comments of a repository. * diff --git a/lib/Github/Api/Repository/Invitations.php b/lib/Github/Api/Repository/Invitations.php new file mode 100644 index 00000000000..bc4c966da3a --- /dev/null +++ b/lib/Github/Api/Repository/Invitations.php @@ -0,0 +1,33 @@ +get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/invitations', array_merge(['page' => 1], $params)); + } + + public function update($username, $repository, $invitation, array $params) + { + return $this->patch('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/invitations/'.rawurlencode($invitation), $params); + } + + public function accept($invitation) + { + return $this->patch('/user/repository_invitations/'.rawurlencode($invitation)); + } + + public function decline($invitation) + { + return $this->delete('/user/repository_invitations/'.rawurlencode($invitation)); + } + + public function remove($username, $repository, $invitation) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/invitations/'.rawurlencode($invitation)); + } +} diff --git a/test/Github/Tests/Integration/InvitationsTest.php b/test/Github/Tests/Integration/InvitationsTest.php new file mode 100644 index 00000000000..9321e337622 --- /dev/null +++ b/test/Github/Tests/Integration/InvitationsTest.php @@ -0,0 +1,100 @@ +username = getenv('GITHUB_USER_1'); + $this->repo = getenv('GITHUB_REPO_1'); + + $this->invitedClient = new Client(); + $this->auth($this->invitedClient, 2); + } + + /** + * @test + */ + public function test() + { + $invitations = $this->listInvitations(); + $originalSize = count($invitations); + + $this->client->repo()->collaborators()->add($this->username, $this->repo, getenv('GITHUB_USER_2')); + $invitations = $this->listInvitations(); + $this->assertEquals($originalSize + 1, count($invitations)); + $invitation = $invitations[$originalSize]; + + $collaborators = $this->client->repo()->collaborators()->all($this->username, $this->repo); + $collaboratorsCount = count($collaborators); + + $this->accept($invitation['id']); + $collaborators = $this->client->repo()->collaborators()->all($this->username, $this->repo); + $this->assertEquals($collaboratorsCount + 1, count($collaborators)); + + $this->client->repo()->collaborators()->remove($this->username, $this->repo, getenv('GITHUB_USER_2')); + + $this->client->repo()->collaborators()->add($this->username, $this->repo, getenv('GITHUB_USER_2')); + $invitations = $this->listInvitations(); + $this->assertEquals($originalSize + 1, count($invitations)); + $invitation = $invitations[$originalSize]; + + $this->decline($invitation['id']); + $invitations = $this->listInvitations(); + $this->assertEquals($originalSize, count($invitations)); + + $this->client->repo()->collaborators()->add($this->username, $this->repo, getenv('GITHUB_USER_2')); + $invitations = $this->listInvitations(); + $this->assertEquals($originalSize + 1, count($invitations)); + $invitation = $invitations[$originalSize]; + + $this->updateInvitation($invitation['id']); + $invitations = $this->listInvitations(); + $invitation = $invitations[$originalSize]; + $this->assertEquals('read', $invitation['permissions']); + + $this->removeInvitation($invitation['id']); + $invitations = $this->listInvitations(); + $this->assertEquals($originalSize, count($invitations)); + } + + public function decline($id) + { + return $this->invitedClient->repo()->invitations()->decline($id); + } + + public function accept($id) + { + return $this->invitedClient->repo()->invitations()->accept($id); + } + + public function updateInvitation($id) + { + return $this->client->repo()->invitations()->update($this->username, $this->repo, $id, [ + 'permissions' => 'read', + ]); + } + + public function listInvitations() + { + return $this->client->repo()->invitations()->all($this->username, $this->repo); + } + + public function removeInvitation($id) + { + return $this->client->repo()->invitations()->remove($this->username, $this->repo, $id); + } +} diff --git a/test/Github/Tests/Integration/TestCase.php b/test/Github/Tests/Integration/TestCase.php index 6f8e5815719..f6206c9c31f 100644 --- a/test/Github/Tests/Integration/TestCase.php +++ b/test/Github/Tests/Integration/TestCase.php @@ -2,6 +2,7 @@ namespace Github\Tests\Integration; +use Dotenv\Dotenv; use Github\Client; use Github\Exception\ApiLimitExceedException; use Github\Exception\RuntimeException; @@ -20,6 +21,7 @@ public function setUp() { // You have to specify authentication here to run full suite $client = new Client(); + $this->auth($client); try { $client->api('current_user')->show(); @@ -33,4 +35,26 @@ public function setUp() $this->client = $client; } + + protected function auth(Client &$client, $accountNumber = 1) + { + try { + (new Dotenv(__DIR__.'/../../../../'))->load(); + $method = getenv('GITHUB_AUTH_METHOD'); + if (!getenv('GITHUB_AUTH_METHOD')) { + return; + } + switch ($method) { + case 'token': + $client->authenticate($method, getenv('GITHUB_TOKEN_'.$accountNumber)); + break; + case 'login': + $client->authenticate($method, getenv('GITHUB_USERNAME_'.$accountNumber), + getenv('GITHUB_PASSWORD_{$accountNumber}')); + break; + } + } catch (\Exception $e) { + error_log('Unable to authenticated', 0); + } + } }