From 9a8afa540e4efcee1d307e93ef1c7db5ceeab8fc Mon Sep 17 00:00:00 2001 From: l3l0 Date: Sat, 26 May 2012 12:14:41 +0200 Subject: [PATCH 1/4] Added .travis.yml file --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..33a3c723439 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: php + +php: + - 5.3 + - 5.4 + +before_script: + - curl -s http://getcomposer.org/installer | php + - php composer.phar update + +script: phpunit From 798fd9d369335b561198f765278c5cafecddb726 Mon Sep 17 00:00:00 2001 From: l3l0 Date: Sat, 26 May 2012 13:29:58 +0200 Subject: [PATCH 2/4] Fixed/improve tests. Added new composer autoload.php for test to avoid DEPRECIATED message --- lib/Github/Api/Issue.php | 29 ++-- lib/Github/Api/PullRequest.php | 29 +++- test/Github/Tests/Api/IssueTest.php | 194 +++++++++++++++++++++- test/Github/Tests/Api/PullRequestTest.php | 58 +++++-- test/Github/Tests/Api/RepoTest.php | 12 +- test/Github/Tests/ApiTestCase.php | 2 +- test/bootstrap.php | 2 +- 7 files changed, 278 insertions(+), 48 deletions(-) diff --git a/lib/Github/Api/Issue.php b/lib/Github/Api/Issue.php index 4faefc64e94..bb071671d69 100644 --- a/lib/Github/Api/Issue.php +++ b/lib/Github/Api/Issue.php @@ -18,16 +18,24 @@ class Issue extends Api * @param string $username the username * @param string $repo the repo * @param string $state the issue state, can be open or closed + * @param array $state the additional parameters like milestone, assignee, lables, sort, direction * @return array list of issues found */ - public function getList($username, $repo, $state = 'open') + public function getList($username, $repo, $state = null, $parameters = array()) { - return $this->get('repos/'.urlencode($username).'/'.urlencode($repo).'/issues?state='.urlencode($state)); + $url = 'repos/'.urlencode($username).'/'.urlencode($repo).'/issues'; + if ($state) { + $parameters['state'] = $state; + } + if ($parameters) { + $url .= '?'.http_build_query($parameters); + } + + return $this->get($url); } /** * Search issues by username, repo, state and search term - * http://develop.github.com/p/issues.html#list_a_projects_issues * * @param string $username the username * @param string $repo the repo @@ -88,7 +96,7 @@ public function open($username, $repo, $title, $body) /** * Close an existing issue by username, repo and issue number. Requires authentication. - * http://develop.github.com/p/issues.html#open_and_close_issues + * @link http://developer.github.com/v3/issues/ * * @param string $username the username * @param string $repo the repo @@ -102,7 +110,7 @@ public function close($username, $repo, $number) /** * Update issue informations by username, repo and issue number. Requires authentication. - * http://develop.github.com/p/issues.html#edit_existing_issues + * @link http://developer.github.com/v3/issues/ * * @param string $username the username * @param string $repo the repo @@ -113,12 +121,12 @@ public function close($username, $repo, $number) */ public function update($username, $repo, $number, array $data) { - return $this->post('repos/'.urlencode($username).'/'.urlencode($repo).'/issues/'.urlencode($number), $data); + return $this->patch('repos/'.urlencode($username).'/'.urlencode($repo).'/issues/'.urlencode($number), $data); } /** * Repoen an existing issue by username, repo and issue number. Requires authentication. - * http://develop.github.com/p/issues.html#open_and_close_issues + * @link http://developer.github.com/v3/issues/ * * @param string $username the username * @param string $repo the repo @@ -132,7 +140,7 @@ public function reOpen($username, $repo, $number) /** * List an issue comments by username, repo and issue number - * http://develop.github.com/p/issues.html#list_an_issues_comments + * @link http://developer.github.com/v3/issues/comments/ * * @param string $username the username * @param string $repo the repo @@ -150,13 +158,12 @@ public function getComments($username, $repo, $number) * * @param string $username the username * @param string $repo the repo - * @param string $number the issue number * @param string $id the comment id * @return array list of issue comments */ - public function getComment($username, $repo, $number, $id) + public function getComment($username, $repo, $id) { - return $this->get('repos/'.urlencode($username).'/'.urlencode($repo).'/issues/'.urlencode($number).'/comments/'.urlencode($id)); + return $this->get('repos/'.urlencode($username).'/'.urlencode($repo).'/issues/comments/'.urlencode($id)); } /** diff --git a/lib/Github/Api/PullRequest.php b/lib/Github/Api/PullRequest.php index 7a0ec042208..9c62353aa78 100644 --- a/lib/Github/Api/PullRequest.php +++ b/lib/Github/Api/PullRequest.php @@ -21,9 +21,14 @@ class PullRequest extends Api * The API seems to automatically default to 'open' * @return array array of pull requests for the project */ - public function listPullRequests($username, $repo, $state = 'open') + public function listPullRequests($username, $repo, $state = null) { - return $this->get('repos/'.urlencode($username).'/'.urlencode($repo).'/pulls?state='.urlencode($state)); + $url = 'repos/'.urlencode($username).'/'.urlencode($repo).'/pulls'; + if ($state) { + $url .= '?state='.urlencode($state); + } + + return $this->get($url); } /** @@ -43,7 +48,7 @@ public function show($username, $repo, $id) /** * Create a pull request * - * @link http://develop.github.com/p/pulls.html + * @link http://developer.github.com/v3/pulls/ * @param string $username the username * @param string $repo the repo * @param string $base A String of the branch or commit SHA that you want your changes to be pulled to. @@ -52,15 +57,23 @@ public function show($username, $repo, $id) * specify the username first: "my-user:some-branch". * @param string $title The String title of the Pull Request. Used in pair with $body. * @param string $body The String body of the Pull Request. Used in pair with $title. + * @param string $issueNumber The issue number. Used when title and body is not set. * @return array array of pull requests for the project */ - public function create($username, $repo, $base, $head, $title, $body = null) + public function create($username, $repo, $base, $head, $title, $body = null, $issueNumber = null) { - return $this->post('repos/'.urlencode($username).'/'.urlencode($repo).'/pulls', array( + $input = array( 'head' => $head, 'base' => $base, - 'title' => $title, - 'body' => $body, - )); + ); + + if ($title || $body) { + $input['title'] = $title; + $input['body'] = $body; + } else { + $input['issue'] = $issueNumber; + } + + return $this->post('repos/'.urlencode($username).'/'.urlencode($repo).'/pulls', $input); } } diff --git a/test/Github/Tests/Api/IssueTest.php b/test/Github/Tests/Api/IssueTest.php index 477f615125a..66630a4ecfb 100644 --- a/test/Github/Tests/Api/IssueTest.php +++ b/test/Github/Tests/Api/IssueTest.php @@ -6,17 +6,207 @@ class IssueTest extends ApiTestCase { - public function testGetList() + /** + * @test + */ + public function shouldBuildValidQueryForGetList() { $api = $this->getApiMock(); $api->expects($this->once()) ->method('get') - ->with('issues/list/ornicar/php-github-api/open'); + ->with('repos/ornicar/php-github-api/issues?state=open'); $api->getList('ornicar', 'php-github-api', 'open'); } + /** + * @test + */ + public function shouldBuildValidQueryForGetListWithAdditionalParameters() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/issues?milestone=%2A&assignee=l3l0&mentioned=l3l0&labels=bug%2C%40high&sort=created&direction=asc&state=open'); + + $api->getList('ornicar', 'php-github-api', 'open', array( + 'milestone' => '*', + 'assignee' => 'l3l0', + 'mentioned' => 'l3l0', + 'labels' => 'bug,@high', + 'sort' => 'created', + 'direction' => 'asc' + )); + } + + /** + * @test + */ + public function shouldBuildValidQueryForShow() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/issues/14'); + + $api->show('ornicar', 'php-github-api', 14); + } + + /** + * @test + */ + public function shouldBuildValidQueryForOpen() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('repos/ornicar/php-github-api/issues', array( + 'title' => 'some title', + 'body' => 'some body' + )); + + $api->open('ornicar', 'php-github-api', 'some title', 'some body'); + } + + /** + * @test + */ + public function shouldBuildValidQueryForClose() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('patch') + ->with('repos/ornicar/php-github-api/issues/14', array( + 'state' => 'closed', + )); + + $api->close('ornicar', 'php-github-api', 14); + } + + /** + * @test + */ + public function shouldBuildValidQueryForReOpen() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('patch') + ->with('repos/ornicar/php-github-api/issues/14', array( + 'state' => 'open', + )); + + $api->reOpen('ornicar', 'php-github-api', 14); + } + + /** + * @test + */ + public function shouldBuildValidQueryForGetComments() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/issues/14/comments'); + + $api->getComments('ornicar', 'php-github-api', 14); + } + + /** + * @test + */ + public function shouldBuildValidQueryForGetComment() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/issues/comments/666'); + + $api->getComment('ornicar', 'php-github-api', 666); + } + + /** + * @test + */ + public function shouldBuildValidQueryForAddComment() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('repos/ornicar/php-github-api/issues/14/comments', array( + 'body' => 'some body' + )); + + $api->addComment('ornicar', 'php-github-api', 14, 'some body'); + } + + /** + * @test + */ + public function shouldBuildValidQueryForGetLabels() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/labels'); + + $api->getLabels('ornicar', 'php-github-api'); + } + + /** + * @test + */ + public function shouldBuildValidQueryForGetLabel() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('repos/ornicar/php-github-api/labels/my-label'); + + $api->getLabel('ornicar', 'php-github-api', 'my-label'); + } + + /** + * @test + */ + public function shouldBuildValidQueryForAddLabel() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('repos/ornicar/php-github-api/labels', array( + 'name' => 'my-label', + 'color' => 'FFFFFF' + )); + + $api->addLabel('ornicar', 'php-github-api', 'my-label', 'FFFFFF'); + } + + /** + * @test + */ + public function shouldBuildValidQueryForRemoveLabel() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('delete') + ->with('repos/ornicar/php-github-api/labels/my-label'); + + $api->removeLabel('ornicar', 'php-github-api', 'my-label'); + } + protected function getApiClass() { return 'Github\Api\Issue'; diff --git a/test/Github/Tests/Api/PullRequestTest.php b/test/Github/Tests/Api/PullRequestTest.php index 962badb4a66..e610b3f5a05 100644 --- a/test/Github/Tests/Api/PullRequestTest.php +++ b/test/Github/Tests/Api/PullRequestTest.php @@ -6,14 +6,17 @@ class PullRequestTest extends ApiTestCase { - public function testlistPullRequests() + /** + * @test + */ + public function shouldCreateValidQueryForListPullRequests() { $api = $this->getApiMock(); // 1. Test with no last parameter $api->expects($this->once()) ->method('get') - ->with('pulls/ezsystems/ezpublish/'); + ->with('repos/ezsystems/ezpublish/pulls'); $api->listPullRequests('ezsystems', 'ezpublish' ); @@ -22,7 +25,7 @@ public function testlistPullRequests() // 2. Test with last parameter set to 'open' $api->expects($this->once()) ->method('get') - ->with('pulls/ezsystems/ezpublish/open'); + ->with('repos/ezsystems/ezpublish/pulls?state=open'); $api->listPullRequests('ezsystems', 'ezpublish', 'open' ); @@ -30,34 +33,40 @@ public function testlistPullRequests() // 2. Test with last parameter set to 'closed' $api->expects($this->once()) ->method('get') - ->with('pulls/ezsystems/ezpublish/closed'); + ->with('repos/ezsystems/ezpublish/pulls?state=closed'); $api->listPullRequests('ezsystems', 'ezpublish', 'closed' ); } - public function testshow() + /** + * @test + */ + public function shouldCreateValidQueryForShow() { $api = $this->getApiMock(); $api->expects($this->once()) ->method('get') - ->with('pulls/ezsystems/ezpublish/15'); + ->with('repos/ezsystems/ezpublish/pulls/15'); - $api->listPullRequests('ezsystems', 'ezpublish', '15' ); + $api->show('ezsystems', 'ezpublish', '15' ); } - public function testcreate() + /** + * @test + */ + public function shouldCreateValidQueryForCreate() { // 1. Testing with body & title $api = $this->getApiMock(); $api->expects($this->once()) ->method('post') - ->with('pulls/ezsystems/ezpublish', - array( 'pull[base]' => 'master', - 'pull[head]' => 'virtualtestbranch', - 'pull[title]' => 'TITLE : Testing pull-request creation from PHP Gituhub API', - 'pull[body]' => 'BODY: Testing pull-request creation from PHP Gituhub API' + ->with('repos/ezsystems/ezpublish/pulls', + array( 'base' => 'master', + 'head' => 'virtualtestbranch', + 'title' => 'TITLE : Testing pull-request creation from PHP Gituhub API', + 'body' => 'BODY: Testing pull-request creation from PHP Gituhub API' ) ); @@ -71,14 +80,29 @@ public function testcreate() $api->expects($this->once()) ->method('post') - ->with('pulls/ezsystems/ezpublish', - array( 'pull[base]' => 'master', - 'pull[head]' => 'virtualtestbranch', - 'pull[issue]' => 25 + ->with('repos/ezsystems/ezpublish/pulls', + array( 'base' => 'master', + 'head' => 'virtualtestbranch', + 'issue' => 25 ) ); $api->create('ezsystems', 'ezpublish', 'master', 'virtualtestbranch', null, null, 25 ); + + // 3. Testing with title and issue ID + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('repos/ezsystems/ezpublish/pulls', + array( 'base' => 'master', + 'head' => 'virtualtestbranch', + 'title' => 'some title', + 'body' => null + ) + ); + + $api->create('ezsystems', 'ezpublish', 'master', 'virtualtestbranch', 'some title', null, 25 ); } protected function getApiClass() diff --git a/test/Github/Tests/Api/RepoTest.php b/test/Github/Tests/Api/RepoTest.php index cb87b37864d..775de24a17d 100644 --- a/test/Github/Tests/Api/RepoTest.php +++ b/test/Github/Tests/Api/RepoTest.php @@ -6,17 +6,13 @@ class RepoTest extends ApiTestCase { - public function testSearch() + /** + * @expectedException BadMethodCallException + */ + public function testThatSearchIsNotSupported() { $api = $this->getApiMock(); - $api->expects($this->once()) - ->method('get') - ->with('repos/search/github+api', array( - 'language' => 'fr', - 'start_page' => 3 - )); - $api->search('github api', 'fr', 3); } diff --git a/test/Github/Tests/ApiTestCase.php b/test/Github/Tests/ApiTestCase.php index 063ab8e1b15..7e6317cf129 100644 --- a/test/Github/Tests/ApiTestCase.php +++ b/test/Github/Tests/ApiTestCase.php @@ -9,7 +9,7 @@ abstract protected function getApiClass(); protected function getApiMock() { return $this->getMockBuilder($this->getApiClass()) - ->setMethods(array('get', 'post')) + ->setMethods(array('get', 'post', 'patch', 'delete')) ->disableOriginalConstructor() ->getMock(); } diff --git a/test/bootstrap.php b/test/bootstrap.php index 599bc608e6d..69436c1fb1d 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -6,7 +6,7 @@ function includeIfExists($file) { } } -if ((!$loader = includeIfExists(__DIR__.'/../vendor/.composer/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) { +if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) { die('You must set up the project dependencies, run the following commands:'.PHP_EOL. 'curl -s http://getcomposer.org/installer | php'.PHP_EOL. 'php composer.phar install'.PHP_EOL); From 1ce3739ccec777f83c47d84bf116a3dde5335486 Mon Sep 17 00:00:00 2001 From: l3l0 Date: Sat, 26 May 2012 13:33:08 +0200 Subject: [PATCH 3/4] Added travis icon into README --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index 028c938a39c..eb0a577dc38 100755 --- a/README.markdown +++ b/README.markdown @@ -1,5 +1,7 @@ # PHP GitHub API +[![Build Status](https://secure.travis-ci.org/KnpLabs/php-github-api.png?branch=api_v3)](http://travis-ci.org/KnpLabs/php-github-api) + A simple Object Oriented wrapper for GitHub API, written with PHP5. ```php From 3253653a66027755e177b8a8dd62f9ce3837d663 Mon Sep 17 00:00:00 2001 From: l3l0 Date: Sat, 26 May 2012 13:54:39 +0200 Subject: [PATCH 4/4] Updated README file --- README.markdown | 50 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/README.markdown b/README.markdown index eb0a577dc38..9adf5050173 100755 --- a/README.markdown +++ b/README.markdown @@ -1,48 +1,48 @@ -# PHP GitHub API +# PHP GitHub API [WIP] [![Build Status](https://secure.travis-ci.org/KnpLabs/php-github-api.png?branch=api_v3)](http://travis-ci.org/KnpLabs/php-github-api) +[WARNING] We are converting that lib into "github api v3" so some stuff is not working yet... + A simple Object Oriented wrapper for GitHub API, written with PHP5. ```php - $github = new Github_Client(); + $github = new Github\Client(); $myRepos = $github->getRepoApi()->getUserRepos('ornicar'); ``` -Uses [GitHub API v2](http://develop.github.com/). The object API is very similar to the RESTful API. +Uses [GitHub API v3](http://developer.github.com/v3/). The object API is very similar to the RESTful API. ## Features -* Covers 100% of GitHub API with PHP methods -* Supports 3 authentication methods -* Follows PEAR conventions and coding standard: autoload friendly +* Follows PSR-0 conventions and coding standard: autoload friendly * Light and fast thanks to lazy loading of API classes * Flexible and extensible thanks to dependency injection * Extensively tested and documented ## Requirements -* PHP 5.2 or 5.3. -* [php curl](http://php.net/manual/en/book.curl.php), but it is possible to write another transport layer. +* PHP >= 5.3 * PHPUnit to run tests. ## Autoload -The first step to use php-github-api is to register its autoloader: +The new version of php-github-api using [composer](http://getcomposer.org). +The first step to use php-github-api is to download composer: `curl -s http://getcomposer.org/installer | php` +Then we have to install our dependencies using `php composer.phar install`, now we can use autoloader from composer by: ```php - require_once '/path/to/lib/Github/Autoloader.php'; - Github_Autoloader::register(); + require_once 'vendor/autoload.php'; ``` -Replace the `/path/to/lib/` path with the path you used for php-github-api installation. +TODO: More examples how to install with composer. Some example of composer.json files. Add to packagist -> php-github-api follows the PEAR convention names for its classes, which means you can easily integrate php-github-api classes loading in your own autoloader. +> php-github-api follows the PSR-0 convention names for its classes, which means you can easily integrate php-github-api classes loading in your own autoloader. ## instantiate a new github client ```php - $github = new Github_Client(); + $github = new Github\Client(); ``` From this object, you can access to all GitHub apis, listed below. @@ -57,15 +57,9 @@ From this object, you can access to all GitHub apis, listed below. Go back to the Navigation Searching users, getting user information and managing authenticated user account information. -Wrap [GitHub User API](http://develop.github.com/p/users.html). - -### Search for users by username - -```php - $users = $github->getUserApi()->search('ornicar'); -``` +Wrap [GitHub User API](http://developer.github.com/v3/users). -Returns an array of users. +### Search for users by username is depreciated cause of github api limitation. ### Get information about a user @@ -702,16 +696,16 @@ Wanna change, let's say, the http client User Agent? $github->getHttpClient()->setOption('user_agent', 'My new User Agent'); ``` -See all available options in Github/HttpClient.php +See all available options in Github/HttpClient/HttpClient.php ### Inject a new http client instance php-github-api provides a curl-based implementation of a http client. -If you want to use your own http client implementation, inject it to the Github_Client instance: +If you want to use your own http client implementation, inject it to the Github\Client instance: ```php // create a custom http client - class MyHttpClient extends Github_HttpClient + class MyHttpClient extends Github\HttpClient\HttpClient { public function doRequest($url, array $parameters = array(), $httpMethod = 'GET', array $options = array()) { @@ -722,10 +716,10 @@ If you want to use your own http client implementation, inject it to the Github_ > Your http client implementation may not extend Github_HttpClient, but only implement Github_HttpClientInterface. -You can now inject your http client through Github_Client constructor: +You can now inject your http client through Github\Client constructor: ```php - $github = new Github_Client(new MyHttpClient()); + $github = new Github\Client(new MyHttpClient()); ``` Or to an existing Github_Client instance: @@ -741,7 +735,7 @@ For example, to replace the user API: ```php // create a custom User API - class MyGithubApiUser extends Github_Api_User + class MyGithubApiUser extends Github\Api\User { // overwrite things }