From dd2c90a4a136c8b3924cb12097756382341a33f7 Mon Sep 17 00:00:00 2001 From: Justin Doyle Date: Wed, 24 Feb 2016 23:27:35 -0500 Subject: [PATCH] Finish adding models off Project --- .gitignore | 1 + src/Sifter/JsonObjectHelpers.php | 147 +++++++++++++++++++ src/Sifter/Sifter.php | 36 +---- src/Sifter/SifterCurl.php | 16 ++ src/Sifter/model/Category.php | 49 +++++++ src/Sifter/model/Milestone.php | 61 ++++++++ src/Sifter/model/Person.php | 80 ++++++++++ src/Sifter/model/Project.php | 36 ++++- src/Sifter/resource/IssuesResource.php | 23 +-- tests/Sifter/SifterTest.php | 98 ++++++++++++- tests/json/{project.json => projects_1.json} | 0 tests/json/projects_1_categories.json | 14 ++ tests/json/projects_1_milestones.json | 16 ++ tests/json/projects_1_people.json | 20 +++ 14 files changed, 539 insertions(+), 58 deletions(-) create mode 100644 src/Sifter/JsonObjectHelpers.php create mode 100644 src/Sifter/model/Category.php create mode 100644 src/Sifter/model/Milestone.php create mode 100644 src/Sifter/model/Person.php rename tests/json/{project.json => projects_1.json} (100%) create mode 100644 tests/json/projects_1_categories.json create mode 100644 tests/json/projects_1_milestones.json create mode 100644 tests/json/projects_1_people.json diff --git a/.gitignore b/.gitignore index 639a1b5..4ccc291 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /composer.lock /vendor /.env +/index.php /.idea \ No newline at end of file diff --git a/src/Sifter/JsonObjectHelpers.php b/src/Sifter/JsonObjectHelpers.php new file mode 100644 index 0000000..e717d82 --- /dev/null +++ b/src/Sifter/JsonObjectHelpers.php @@ -0,0 +1,147 @@ +name, + $json->primary_company_name, + $json->archived, + $json->url, + $json->issues_url, + $json->milestones_url, + $json->api_url, + $json->api_issues_url, + $json->api_milestones_url, + $json->api_categories_url, + $json->api_people_url + ); + } + + static public function toProjectsArray($json) + { + if(is_string($json)) { + $json = json_decode($json); + } + + $projects = []; + if ( ! isset($json->projects) || ! is_array($json->projects)) { + throw new \Exception('Projects were not returned'); + } else { + foreach ($json->projects as $project) { + $projects[] = self::toProject($project); + } + return $projects; + } + } + + static public function toIssuesResource($json) { + if(is_string($json)) { + $json = json_decode($json); + } + return new IssuesResource( + $json->issues, + $json->page, + $json->per_page, + $json->total_pages, + $json->next_page_url, + $json->previous_page_url + ); + } + + static public function toMilestone($json) { + if(is_string($json)) { + $json = json_decode($json); + } + return new Milestone( + $json->name, + $json->due_date, + $json->issues_url, + $json->api_issues_url + ); + } + + static public function toMilestonesArray($json) { + if(is_string($json)) { + $json = json_decode($json); + } + $milestones = []; + + if ( ! isset($json->milestones) || ! is_array($json->milestones)) { + throw new \Exception('Milestones were not returned'); + } else { + foreach($json->milestones as $milestone) { + $milestones[] = self::toMilestone($milestone); + } + return $milestones; + } + } + + static public function toCategory($json) { + if(is_string($json)) { + $json = json_decode($json); + } + return new Category( + $json->name, + $json->issues_url, + $json->api_issues_url + ); + } + + static public function toCategoriesArray($json) { + if(is_string($json)) { + $json = json_decode($json); + } + $categories = []; + + if ( ! isset($json->categories) || ! is_array($json->categories)) { + throw new \Exception('Categories were not returned'); + } else { + foreach($json->categories as $category) { + $categories[] = self::toCategory($category); + } + return $categories; + } + } + + static public function toPerson($json) { + if(is_string($json)) { + $json = json_decode($json); + } + return new Person( + $json->username, + $json->first_name, + $json->last_name, + $json->email, + $json->issues_url, + $json->api_issues_url + ); + } + + static public function toPeopleArray($json) { + if(is_string($json)) { + $json = json_decode($json); + } + $people = []; + + if ( ! isset($json->people) || ! is_array($json->people)) { + throw new \Exception('People were not returned'); + } else { + foreach($json->people as $person) { + $people[] = self::toPerson($person); + } + return $people; + } + } + +} \ No newline at end of file diff --git a/src/Sifter/Sifter.php b/src/Sifter/Sifter.php index 86b986a..c04032a 100644 --- a/src/Sifter/Sifter.php +++ b/src/Sifter/Sifter.php @@ -28,45 +28,13 @@ public function allProjects($all = false) { $url = Sifter::curl()->getBaseUrl().self::PROJECTS_URL; if($all) { $url.'?all=true'; } - Sifter::curl()->get(Sifter::curl()->getBaseUrl().self::PROJECTS_URL); + Sifter::curl()->get($url); if (Sifter::curl()->error) { throw new \Exception('cURL GET failed with code ' . Sifter::curl()->error_code); } else { - $projects = $this->jsonToProjects(json_decode(Sifter::curl()->response)); + $projects = JsonObjectHelpers::toProjectsArray(Sifter::curl()->response); return $projects; } } - - - /* - * HELPER FUNCTIONS - */ - - private function jsonToProjects($json) - { - $projects = []; - if ( ! isset($json->projects) || ! is_array($json->projects)) { - throw new \Exception('Projects were not returned'); - } else { - foreach ($json->projects as $project) { - $projects[] = new Project( - $project->name, - $project->primary_company_name, - $project->archived, - $project->url, - $project->issues_url, - $project->milestones_url, - $project->api_url, - $project->api_issues_url, - $project->api_milestones_url, - $project->api_categories_url, - $project->api_people_url - ); - } - return $projects; - } - } - - } \ No newline at end of file diff --git a/src/Sifter/SifterCurl.php b/src/Sifter/SifterCurl.php index 9c795da..93a3082 100644 --- a/src/Sifter/SifterCurl.php +++ b/src/Sifter/SifterCurl.php @@ -2,10 +2,22 @@ use Curl\Curl; +/** + * Class SifterCurl + * @package Sifter + */ class SifterCurl extends Curl { + /** + * @var string + */ private $baseUrl = ''; + /** + * SifterCurl constructor. + * @param $apiKey + * @param $apiSubdomain + */ public function __construct($apiKey, $apiSubdomain) { parent::__construct(); @@ -14,7 +26,11 @@ public function __construct($apiKey, $apiSubdomain) $this->setHeader('Accept', 'application/json'); } + /** + * @return string + */ public function getBaseUrl() { return $this->baseUrl; } + } \ No newline at end of file diff --git a/src/Sifter/model/Category.php b/src/Sifter/model/Category.php new file mode 100644 index 0000000..7fff65a --- /dev/null +++ b/src/Sifter/model/Category.php @@ -0,0 +1,49 @@ +name = $name; + $this->issuesUrl = $issuesUrl; + $this->apiIssuesUrl = $apiIssuesUrl; + } + + /** + * @return mixed + */ + public function getName() + { + return $this->name; + } + + /** + * @return mixed + */ + public function getIssuesUrl() + { + return $this->issuesUrl; + } + + /** + * @return mixed + */ + public function getApiIssuesUrl() + { + return $this->apiIssuesUrl; + } + + + + +} \ No newline at end of file diff --git a/src/Sifter/model/Milestone.php b/src/Sifter/model/Milestone.php new file mode 100644 index 0000000..cbf7b10 --- /dev/null +++ b/src/Sifter/model/Milestone.php @@ -0,0 +1,61 @@ +name = $name; + $this->dueDate = new Carbon($dueDate); + $this->issuesUrl = $issuesUrl; + $this->apiIssuesUrl = $apiIssuesUrl; + } + + /** + * @return mixed + */ + public function getName() + { + return $this->name; + } + + /** + * @return mixed + */ + public function getDueDate() + { + return $this->dueDate->copy(); + } + + /** + * @return mixed + */ + public function getIssuesUrl() + { + return $this->issuesUrl; + } + + /** + * @return mixed + */ + public function getApiIssuesUrl() + { + return $this->apiIssuesUrl; + } + + + + +} \ No newline at end of file diff --git a/src/Sifter/model/Person.php b/src/Sifter/model/Person.php new file mode 100644 index 0000000..b80ccf0 --- /dev/null +++ b/src/Sifter/model/Person.php @@ -0,0 +1,80 @@ +username = $username; + $this->firstName = $firstName; + $this->lastName = $lastName; + $this->email = $email; + $this->issuesUrl = $issuesUrl; + $this->apiIssuesUrl = $apiIssuesUrl; + } + + /** + * @return mixed + */ + public function getUsername() + { + return $this->username; + } + + /** + * @return mixed + */ + public function getFirstName() + { + return $this->firstName; + } + + /** + * @return mixed + */ + public function getLastName() + { + return $this->lastName; + } + + /** + * @return mixed + */ + public function getEmail() + { + return $this->email; + } + + /** + * @return mixed + */ + public function getIssuesUrl() + { + return $this->issuesUrl; + } + + /** + * @return mixed + */ + public function getApiIssuesUrl() + { + return $this->apiIssuesUrl; + } + + + +} \ No newline at end of file diff --git a/src/Sifter/model/Project.php b/src/Sifter/model/Project.php index 003a434..583916d 100644 --- a/src/Sifter/model/Project.php +++ b/src/Sifter/model/Project.php @@ -1,5 +1,6 @@ get($this->apiMilestonesUrl); + + if($curl->error) { + throw new \Exception('cURL GET failed with code '.$curl->error_code); + } else { + return JsonObjectHelpers::toMilestonesArray($curl->response); + } + } + + public function categories() { + $curl = Sifter::curl(); + $curl->get($this->apiCategoriesUrl); + + if($curl->error) { + throw new \Exception('cURL GET failed with code '.$curl->error_code); + } else { + return JsonObjectHelpers::toCategoriesArray($curl->response); + } + } + + public function people() { + $curl = Sifter::curl(); + $curl->get($this->apiPeopleUrl); + + if($curl->error) { + throw new \Exception('cURL GET failed with code '.$curl->error_code); + } else { + return JsonObjectHelpers::toPeopleArray($curl->response); + } + } + } \ No newline at end of file diff --git a/src/Sifter/resource/IssuesResource.php b/src/Sifter/resource/IssuesResource.php index efeba59..b420a72 100644 --- a/src/Sifter/resource/IssuesResource.php +++ b/src/Sifter/resource/IssuesResource.php @@ -1,5 +1,6 @@ issues, - $json->page, - $json->per_page, - $json->total_pages, - $json->next_page_url, - $json->previous_page_url - ); + return JsonObjectHelpers::toIssuesResource($json); } /** @@ -117,15 +108,7 @@ private function changePage($pageUrl) { if($curl->error) { throw new \Exception('cURL GET failed with code '.$curl->error_code); } else { - $json = json_decode($curl->response); - return new IssuesResource( - $json->issues, - $json->page, - $json->per_page, - $json->total_pages, - $json->next_page_url, - $json->previous_page_url - ); + return JsonObjectHelpers::toIssuesResource($curl->response); } } diff --git a/tests/Sifter/SifterTest.php b/tests/Sifter/SifterTest.php index 5c74d41..a4d37bd 100644 --- a/tests/Sifter/SifterTest.php +++ b/tests/Sifter/SifterTest.php @@ -3,6 +3,7 @@ use Curl\Curl; use josegonzalez\Dotenv\Loader; +use Sifter\Resource\IssuesResource; use Sifter\Sifter; class SifterTest extends \PHPUnit_Framework_TestCase @@ -60,6 +61,24 @@ public function testIssuesThroughProject() $this->assertTrue(is_array($projects)); $this->assertNotEmpty($projects); + /* @var $issues IssuesResource */ + $issues = $projects[0]->issues(); + + $this->assertInstanceOf('Sifter\Resource\IssuesResource', $issues); + $this->assertEquals(1, $issues->getPage()); + $this->assertEquals(100, $issues->getPerPage()); + $this->assertEquals(2, $issues->getTotalPages()); + $this->assertEquals('https://example.sifterapp.com/api/projects/1/issues?per_page=10&page=1', $issues->getNextPageUrl()); + $this->assertNull($issues->getPreviousPageUrl()); + } + + public function testIssueThroughProject() { + $sifter = new Sifter($this->sifterCurlMock); + $projects = $sifter->allProjects(); + + $this->assertTrue(is_array($projects)); + $this->assertNotEmpty($projects); + $issues = $projects[0]->issues(); /* @var $issue \Sifter\Model\Issue */ @@ -84,7 +103,65 @@ public function testIssuesThroughProject() $this->assertEquals('https://example.sifterapp.com/projects/1/issues/5', $issue->getUrl()); } - private function createSifterCallbackClosure() { + public function testMilestoneThroughProject() { + $sifter = new Sifter($this->sifterCurlMock); + $projects = $sifter->allProjects(); + + $this->assertTrue(is_array($projects)); + $this->assertNotEmpty($projects); + + $milestones = $projects[0]->milestones(); + + /* @var $milestone \Sifter\Model\Milestone */ + $milestone = $milestones[0]; + + $this->assertEquals('Private Release', $milestone->getName()); + $this->assertEquals('2010-04-15', $milestone->getDueDate()->format('Y-m-d')); + $this->assertEquals('https://example.sifterapp.com/projects/1/issues?m=1', $milestone->getIssuesUrl()); + $this->assertEquals('https://example.sifterapp.com/api/projects/1/issues?m=1', $milestone->getApiIssuesUrl()); + + } + + public function testCategoryThroughProject() { + $sifter = new Sifter($this->sifterCurlMock); + $projects = $sifter->allProjects(); + + $this->assertTrue(is_array($projects)); + $this->assertNotEmpty($projects); + + $categories = $projects[0]->categories(); + + /* @var $category \Sifter\Model\Category */ + $category = $categories[0]; + + $this->assertEquals('Bugs', $category->getName()); + $this->assertEquals('https://example.sifterapp.com/projects/1/issues?c=1', $category->getIssuesUrl()); + $this->assertEquals('https://example.sifterapp.com/api/projects/1/issues?c=1', $category->getApiIssuesUrl()); + + } + + public function testPersonThroughProject() { + $sifter = new Sifter($this->sifterCurlMock); + $projects = $sifter->allProjects(); + + $this->assertTrue(is_array($projects)); + $this->assertNotEmpty($projects); + + $people = $projects[0]->people(); + + /* @var $person \Sifter\Model\Person */ + $person = $people[0]; + + $this->assertEquals('gdimon', $person->getUsername()); + $this->assertEquals('Garrett', $person->getFirstName()); + $this->assertEquals('Dimon', $person->getLastName()); + $this->assertEquals('garrett@nextupdate.com', $person->getEmail()); + $this->assertEquals('https://example.sifterapp.com/projects/1/issues?a=1', $person->getIssuesUrl()); + $this->assertEquals('https://example.sifterapp.com/api/projects/1/issues?a=1', $person->getApiIssuesUrl()); + + } + + private function createSifterCurlCallbackClosure() { return function() { $args = func_get_args(); $url = $args[0]; @@ -101,6 +178,23 @@ private function createSifterCallbackClosure() { break; case self::$baseUrl . 'projects/1'; + $this->sifterCurlMock->response = $this->jsonTestString('projects_1.json'); + $this->sifterCurlMock->error = 0; + break; + + case self::$baseUrl . 'projects/1/milestones': + $this->sifterCurlMock->response = $this->jsonTestString('projects_1_milestones.json'); + $this->sifterCurlMock->error = 0; + break; + + case self::$baseUrl . 'projects/1/categories': + $this->sifterCurlMock->response = $this->jsonTestString('projects_1_categories.json'); + $this->sifterCurlMock->error = 0; + break; + + case self::$baseUrl . 'projects/1/people': + $this->sifterCurlMock->response = $this->jsonTestString('projects_1_people.json'); + $this->sifterCurlMock->error = 0; break; default: @@ -119,7 +213,7 @@ private function setUpSifterCurlMock() ->willReturn(self::$baseUrl); // Set up the routes that are going to be called - $sifterCurlCallback = $this->createSifterCallbackClosure(); + $sifterCurlCallback = $this->createSifterCurlCallbackClosure(); $this->sifterCurlMock ->expects($this->any()) diff --git a/tests/json/project.json b/tests/json/projects_1.json similarity index 100% rename from tests/json/project.json rename to tests/json/projects_1.json diff --git a/tests/json/projects_1_categories.json b/tests/json/projects_1_categories.json new file mode 100644 index 0000000..9209cb9 --- /dev/null +++ b/tests/json/projects_1_categories.json @@ -0,0 +1,14 @@ +{ + "categories": [ + { + "name": "Bugs", + "issues_url": "https://example.sifterapp.com/projects/1/issues?c=1", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?c=1" + }, + { + "name": "Issues", + "issues_url": "https://example.sifterapp.com/projects/1/issues?c=2", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?c=2" + } + ] +} \ No newline at end of file diff --git a/tests/json/projects_1_milestones.json b/tests/json/projects_1_milestones.json new file mode 100644 index 0000000..4fc860d --- /dev/null +++ b/tests/json/projects_1_milestones.json @@ -0,0 +1,16 @@ +{ + "milestones": [ + { + "name": "Private Release", + "due_date": "2010/04/15", + "issues_url": "https://example.sifterapp.com/projects/1/issues?m=1", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?m=1" + }, + { + "name": "Public Release", + "due_date": "2010/05/15", + "issues_url": "https://example.sifterapp.com/projects/1/issues?m=2", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?m=2" + } + ] +} \ No newline at end of file diff --git a/tests/json/projects_1_people.json b/tests/json/projects_1_people.json new file mode 100644 index 0000000..e0d9e33 --- /dev/null +++ b/tests/json/projects_1_people.json @@ -0,0 +1,20 @@ +{ + "people": [ + { + "username": "gdimon", + "first_name": "Garrett", + "last_name": "Dimon", + "email": "garrett@nextupdate.com", + "issues_url": "https://example.sifterapp.com/projects/1/issues?a=1", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?a=1" + }, + { + "username": "akeys", + "first_name": "Adam", + "last_name": "Keys", + "email": "adam@nextupdate.com", + "issues_url": "https://example.sifterapp.com/projects/1/issues?a=2", + "api_issues_url": "https://example.sifterapp.com/api/projects/1/issues?a=2" + } + ] +} \ No newline at end of file