From b07d409611f8a01c72fecb6afeedcdf92d718906 Mon Sep 17 00:00:00 2001 From: misantron Date: Sat, 28 Oct 2017 11:53:40 +0300 Subject: [PATCH 1/5] Code climate config added --- .codeclimate.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .codeclimate.yml diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..0bd0385 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,18 @@ +engines: + duplication: + enabled: true + config: + languages: + - "php" + phpcodesniffer: + enabled: true + config: + file_extensions: "php" + standard: "PSR1,PSR2" +ratings: + paths: + - "**.php" +exclude_paths: + - "examples/**/*" + - "test/**/*" + - "vendor/**/*" \ No newline at end of file From 1843976fe5f84520e45803777e145ba606d4428b Mon Sep 17 00:00:00 2001 From: misantron Date: Sat, 28 Oct 2017 11:54:08 +0300 Subject: [PATCH 2/5] Code climate config fix --- .codeclimate.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index 0bd0385..08e2f8c 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -8,7 +8,6 @@ engines: enabled: true config: file_extensions: "php" - standard: "PSR1,PSR2" ratings: paths: - "**.php" From fed617c2be6a0de36c5594788ecb95ce7cecc8d5 Mon Sep 17 00:00:00 2001 From: misantron Date: Sat, 28 Oct 2017 12:14:51 +0300 Subject: [PATCH 3/5] Code style fixes --- lib/Client.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/Client.php b/lib/Client.php index 37da48f..0732d14 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -45,8 +45,14 @@ class Client * @param array $curlOptions extra options to set during curl initialization * @param bool $retryOnLimit set default retry on limit flag */ - public function __construct($host, $headers = null, $version = null, $path = null, $curlOptions = null, $retryOnLimit = false) - { + public function __construct( + $host, + $headers = null, + $version = null, + $path = null, + $curlOptions = null, + $retryOnLimit = false + ) { $this->host = $host; $this->headers = $headers ?: []; $this->version = $version; @@ -135,10 +141,10 @@ private function buildUrl($queryParams = null) * Make the API call and return the response. This is separated into * it's own function, so we can mock it easily for testing. * - * @param string $method the HTTP verb - * @param string $url the final url to call - * @param array $body request body - * @param array $headers any additional request headers + * @param string $method the HTTP verb + * @param string $url the final url to call + * @param array $body request body + * @param array $headers any additional request headers * @param bool $retryOnLimit should retry if rate limit is reach? * * @return Response object From 9af60740929b4442c9abc616d8d683be466e2811 Mon Sep 17 00:00:00 2001 From: misantron Date: Sat, 28 Oct 2017 14:08:03 +0300 Subject: [PATCH 4/5] Object constructor refactoring --- lib/Client.php | 106 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 32 deletions(-) diff --git a/lib/Client.php b/lib/Client.php index 0732d14..8cdb694 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -30,38 +30,33 @@ class Client protected $path; /** @var array */ protected $curlOptions; - /** @var array */ - private $methods; /** @var bool */ - private $retryOnLimit; + protected $retryOnLimit; + + /** + * These are the supported HTTP verbs + * + * @var array + */ + private $methods = ['delete', 'get', 'patch', 'post', 'put']; /** * Initialize the client * - * @param string $host the base url (e.g. https://api.sendgrid.com) - * @param array $headers global request headers - * @param string $version api version (configurable) - * @param array $path holds the segments of the url path - * @param array $curlOptions extra options to set during curl initialization - * @param bool $retryOnLimit set default retry on limit flag + * @param string $host the base url (e.g. https://api.sendgrid.com) + * @param array $headers global request headers + * @param string $version api version (configurable) + * @param array $path holds the segments of the url path */ - public function __construct( - $host, - $headers = null, - $version = null, - $path = null, - $curlOptions = null, - $retryOnLimit = false - ) { + public function __construct($host, $headers = [], $version = null, $path = []) + { $this->host = $host; - $this->headers = $headers ?: []; + $this->headers = $headers; $this->version = $version; - $this->path = $path ?: []; - $this->curlOptions = $curlOptions ?: []; - // These are the supported HTTP verbs - $this->methods = ['delete', 'get', 'patch', 'post', 'put']; + $this->path = $path; - $this->retryOnLimit = $retryOnLimit; + $this->curlOptions = []; + $this->retryOnLimit = false; } /** @@ -96,6 +91,34 @@ public function getPath() return $this->path; } + /** + * Set extra options to set during curl initialization + * + * @param array $options + * + * @return Client + */ + public function setCurlOptions(array $options) + { + $this->curlOptions = $options; + + return $this; + } + + /** + * Set default retry on limit flag + * + * @param bool $retry + * + * @return Client + */ + public function setRetryOnLimit($retry) + { + $this->retryOnLimit = $retry; + + return $this; + } + /** * @return array */ @@ -116,11 +139,25 @@ private function buildClient($name = null) if (isset($name)) { $this->path[] = $name; } - $client = new Client($this->host, $this->headers, $this->version, $this->path, $this->curlOptions); + $client = $this->cloneClient(); $this->path = []; return $client; } + /** + * Clone existing Client object with all settings + * + * @return Client + */ + private function cloneClient() + { + $client = new static($this->host, $this->headers, $this->version, $this->path); + $client->setCurlOptions($this->curlOptions); + $client->setRetryOnLimit($this->retryOnLimit); + + return $client; + } + /** * Build the final URL to be passed * @@ -153,13 +190,18 @@ public function makeRequest($method, $url, $body = null, $headers = null, $retry { $curl = curl_init($url); - curl_setopt_array($curl, [ - CURLOPT_RETURNTRANSFER => true, - CURLOPT_HEADER => 1, - CURLOPT_CUSTOMREQUEST => strtoupper($method), - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_FAILONERROR => false, - ] + $this->curlOptions); + $options = array_merge( + [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HEADER => 1, + CURLOPT_CUSTOMREQUEST => strtoupper($method), + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_FAILONERROR => false, + ], + $this->curlOptions + ); + + curl_setopt_array($curl, $options); if (isset($headers)) { $this->headers = array_merge($this->headers, $headers); @@ -185,7 +227,7 @@ public function makeRequest($method, $url, $body = null, $headers = null, $retry $response = new Response($statusCode, $responseBody, $responseHeaders); - if ($statusCode == 429 && $retryOnLimit) { + if ($statusCode === 429 && $retryOnLimit) { $headers = $response->headers(true); $sleepDurations = $headers['X-Ratelimit-Reset'] - time(); sleep($sleepDurations > 0 ? $sleepDurations : 0); From bb44496e7e7db5ad853753277d90c57dd8ef6aaa Mon Sep 17 00:00:00 2001 From: misantron Date: Sat, 28 Oct 2017 23:57:35 +0300 Subject: [PATCH 5/5] Tests fixes and some refactoring --- lib/Client.php | 59 ++++++++++++++------------------------ lib/Response.php | 4 +-- test/unit/ClientTest.php | 25 +++++++++------- test/unit/ResponseTest.php | 10 +++++++ 4 files changed, 46 insertions(+), 52 deletions(-) diff --git a/lib/Client.php b/lib/Client.php index 8cdb694..cb1c03f 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -3,8 +3,6 @@ /** * HTTP Client library * - * PHP version 5.4 - * * @author Matt Bernier * @author Elmer Thomas * @copyright 2016 SendGrid @@ -16,8 +14,16 @@ namespace SendGrid; /** - * Quickly and easily access any REST or REST-like API. - */ + * Quickly and easily access any REST or REST-like API. + * + * @method Response get($body = null, $query = null, $headers = null) + * @method Response post($body = null, $query = null, $headers = null) + * @method Response patch($body = null, $query = null, $headers = null) + * @method Response put($body = null, $query = null, $headers = null) + * @method Response delete($body = null, $query = null, $headers = null) + * + * @method Client version($value) + */ class Client { /** @var string */ @@ -38,7 +44,7 @@ class Client * * @var array */ - private $methods = ['delete', 'get', 'patch', 'post', 'put']; + private $methods = ['get', 'post', 'patch', 'put', 'delete']; /** * Initialize the client @@ -48,7 +54,7 @@ class Client * @param string $version api version (configurable) * @param array $path holds the segments of the url path */ - public function __construct($host, $headers = [], $version = null, $path = []) + public function __construct($host, $headers = [], $version = '/v3', $path = []) { $this->host = $host; $this->headers = $headers; @@ -127,37 +133,6 @@ public function getCurlOptions() return $this->curlOptions; } - /** - * Make a new Client object - * - * @param string $name name of the url segment - * - * @return Client object - */ - private function buildClient($name = null) - { - if (isset($name)) { - $this->path[] = $name; - } - $client = $this->cloneClient(); - $this->path = []; - return $client; - } - - /** - * Clone existing Client object with all settings - * - * @return Client - */ - private function cloneClient() - { - $client = new static($this->host, $this->headers, $this->version, $this->path); - $client->setCurlOptions($this->curlOptions); - $client->setRetryOnLimit($this->retryOnLimit); - - return $client; - } - /** * Build the final URL to be passed * @@ -249,7 +224,15 @@ public function makeRequest($method, $url, $body = null, $headers = null, $retry */ public function _($name = null) { - return $this->buildClient($name); + if (isset($name)) { + $this->path[] = $name; + } + $client = new static($this->host, $this->headers, $this->version, $this->path); + $client->setCurlOptions($this->curlOptions); + $client->setRetryOnLimit($this->retryOnLimit); + $this->path = []; + + return $client; } /** diff --git a/lib/Response.php b/lib/Response.php index 29720f0..47be104 100644 --- a/lib/Response.php +++ b/lib/Response.php @@ -3,8 +3,6 @@ /** * HTTP Client library * - * PHP version 5.4 - * * @author Matt Bernier * @author Elmer Thomas * @copyright 2016 SendGrid @@ -89,7 +87,7 @@ public function headers($assoc = false) private function prettifyHeaders($headers) { if (!is_array($headers)) { - throw new \InvalidArgumentException('$headers should be array'); + throw new \InvalidArgumentException('Headers should be an array'); } return array_reduce( diff --git a/test/unit/ClientTest.php b/test/unit/ClientTest.php index 676f600..f052b8e 100644 --- a/test/unit/ClientTest.php +++ b/test/unit/ClientTest.php @@ -20,7 +20,7 @@ protected function setUp() 'Content-Type: application/json', 'Authorization: Bearer SG.XXXX' ]; - $this->client = new MockClient($this->host, $this->headers, '/v3', null, null); + $this->client = new MockClient($this->host, $this->headers); } public function testConstructor() @@ -30,12 +30,14 @@ public function testConstructor() $this->assertAttributeEquals('/v3', 'version', $this->client); $this->assertAttributeEquals([], 'path', $this->client); $this->assertAttributeEquals([], 'curlOptions', $this->client); - $this->assertAttributeEquals(['delete', 'get', 'patch', 'post', 'put'], 'methods', $this->client); + $this->assertAttributeEquals(false, 'retryOnLimit', $this->client); + $this->assertAttributeEquals(['get', 'post', 'patch', 'put', 'delete'], 'methods', $this->client); } public function test_() { - $client = new MockClient($this->host, $this->headers, '/v3', null, ['foo' => 'bar']); + $client = new MockClient($this->host, $this->headers, '/v3'); + $client->setCurlOptions(['foo' => 'bar']); $client = $client->_('test'); $this->assertAttributeEquals(['test'], 'path', $client); @@ -79,34 +81,35 @@ public function testGetHeaders() $client = new Client('https://localhost:4010', ['Content-Type: application/json', 'Authorization: Bearer SG.XXXX']); $this->assertSame(['Content-Type: application/json', 'Authorization: Bearer SG.XXXX'], $client->getHeaders()); - $client2 = new Client('https://localhost:4010', null); + $client2 = new Client('https://localhost:4010'); $this->assertSame([], $client2->getHeaders()); } public function testGetVersion() { - $client = new Client('https://localhost:4010', null, '/v3'); + $client = new Client('https://localhost:4010', [], '/v3'); $this->assertSame('/v3', $client->getVersion()); - $client = new Client('https://localhost:4010', null, null); - $this->assertSame(null, $client->getVersion()); + $client = new Client('https://localhost:4010'); + $this->assertSame('/v3', $client->getVersion()); } public function testGetPath() { - $client = new Client('https://localhost:4010', null, null, ['/foo/bar']); + $client = new Client('https://localhost:4010', [], null, ['/foo/bar']); $this->assertSame(['/foo/bar'], $client->getPath()); - $client = new Client('https://localhost:4010', null, null, null); + $client = new Client('https://localhost:4010'); $this->assertSame([], $client->getPath()); } public function testGetCurlOptions() { - $client = new Client('https://localhost:4010', null, null, null, [CURLOPT_PROXY => '127.0.0.1:8080']); + $client = new Client('https://localhost:4010'); + $client->setCurlOptions([CURLOPT_PROXY => '127.0.0.1:8080']); $this->assertSame([CURLOPT_PROXY => '127.0.0.1:8080'], $client->getCurlOptions()); - $client = new Client('https://localhost:4010', null, null, null, null); + $client = new Client('https://localhost:4010'); $this->assertSame([], $client->getCurlOptions()); } } diff --git a/test/unit/ResponseTest.php b/test/unit/ResponseTest.php index 45660e2..b936e28 100644 --- a/test/unit/ResponseTest.php +++ b/test/unit/ResponseTest.php @@ -48,4 +48,14 @@ public function testAssociativeHeaders() $this->assertEquals(['Content-Type' => 'text/html', 'Status' => 'HTTP/1.1 200 OK'], $response->headers(true)); } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Headers should be an array + */ + public function testHeadersWithInvalidValue() + { + $response = new Response(null, null, false); + $response->headers(true); + } }