diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..08e2f8c --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,17 @@ +engines: + duplication: + enabled: true + config: + languages: + - "php" + phpcodesniffer: + enabled: true + config: + file_extensions: "php" +ratings: + paths: + - "**.php" +exclude_paths: + - "examples/**/*" + - "test/**/*" + - "vendor/**/*" \ No newline at end of file diff --git a/lib/Client.php b/lib/Client.php index 37da48f..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 */ @@ -30,32 +36,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 = ['get', 'post', 'patch', 'put', 'delete']; /** * 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 = '/v3', $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; } /** @@ -91,28 +98,39 @@ public function getPath() } /** - * @return array + * Set extra options to set during curl initialization + * + * @param array $options + * + * @return Client */ - public function getCurlOptions() + public function setCurlOptions(array $options) { - return $this->curlOptions; + $this->curlOptions = $options; + + return $this; } /** - * Make a new Client object - * - * @param string $name name of the url segment - * - * @return Client object - */ - private function buildClient($name = null) + * Set default retry on limit flag + * + * @param bool $retry + * + * @return Client + */ + public function setRetryOnLimit($retry) { - if (isset($name)) { - $this->path[] = $name; - } - $client = new Client($this->host, $this->headers, $this->version, $this->path, $this->curlOptions); - $this->path = []; - return $client; + $this->retryOnLimit = $retry; + + return $this; + } + + /** + * @return array + */ + public function getCurlOptions() + { + return $this->curlOptions; } /** @@ -135,10 +153,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 @@ -147,13 +165,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); @@ -179,7 +202,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); @@ -201,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); + } }