diff --git a/.travis.yml b/.travis.yml index cf5da1d..79178e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,17 @@ language: php php: - - 5.3 - 5.4 - 5.5 - 5.6 + - 7.0 - hhvm -matrix: - allow_failures: - - php: hhvm +before_install: + - travis_retry composer self-update -before_script: - - echo 'Installing composer dependencies now!' - - composer install +install: + - travis_retry composer install + +script: + - phpunit \ No newline at end of file diff --git a/composer.json b/composer.json index 1a9baa7..61bc460 100644 --- a/composer.json +++ b/composer.json @@ -2,10 +2,11 @@ "name": "mailgun/mailgun-php", "description": "The Mailgun SDK provides methods for all API functions.", "require": { - "guzzle/guzzle": "<4.0,>=3.8" + "guzzlehttp/guzzle": "~5.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*" + "php": ">=5.4.0", + "phpunit/phpunit": "~4.6" }, "autoload": { "psr-0": { diff --git a/src/Mailgun/Connection/RestClient.php b/src/Mailgun/Connection/RestClient.php index 12b7c56..e78b39f 100644 --- a/src/Mailgun/Connection/RestClient.php +++ b/src/Mailgun/Connection/RestClient.php @@ -2,11 +2,12 @@ namespace Mailgun\Connection; -use Guzzle\Http\Client as Guzzle; - +use GuzzleHttp\Client as Guzzle; +use GuzzleHttp\Message\ResponseInterface; +use GuzzleHttp\Post\PostBodyInterface; +use GuzzleHttp\Post\PostFile; +use GuzzleHttp\Query; use Mailgun\Connection\Exceptions\GenericHTTPError; -use Guzzle\Http\QueryAggregator\DuplicateAggregator; -use Guzzle\Http\QueryAggregator\PhpAggregator; use Mailgun\Connection\Exceptions\InvalidCredentials; use Mailgun\Connection\Exceptions\MissingRequiredParameters; use Mailgun\Connection\Exceptions\MissingEndpoint; @@ -16,213 +17,219 @@ use Mailgun\Constants\ExceptionMessages; /** * This class is a wrapper for the Guzzle (HTTP Client Library). */ -class RestClient { - +class RestClient +{ /** * @var string */ - private $apiKey; + private $apiKey; /** * @var Guzzle */ - protected $mgClient; - - /** - * @var bool - */ - protected $hasFiles = False; + protected $mgClient; /** * @param string $apiKey * @param string $apiEndpoint * @param string $apiVersion - * @param bool $ssl + * @param bool $ssl */ - public function __construct($apiKey, $apiEndpoint, $apiVersion, $ssl){ - $this->apiKey = $apiKey; - $this->mgClient = new Guzzle($this->generateEndpoint($apiEndpoint, $apiVersion, $ssl)); - $this->mgClient->setDefaultOption('curl.options', array('CURLOPT_FORBID_REUSE' => true)); - $this->mgClient->setDefaultOption('auth', array (Api::API_USER, $this->apiKey)); - $this->mgClient->setDefaultOption('exceptions', false); - $this->mgClient->setUserAgent(Api::SDK_USER_AGENT . '/' . Api::SDK_VERSION); - } + public function __construct($apiKey, $apiEndpoint, $apiVersion, $ssl) + { + $this->apiKey = $apiKey; + $this->mgClient = new Guzzle([ + 'base_url'=>$this->generateEndpoint($apiEndpoint, $apiVersion, $ssl), + 'defaults'=>[ + 'auth' => array(Api::API_USER, $this->apiKey), + 'exceptions' => false, + 'config' => ['curl' => [ CURLOPT_FORBID_REUSE => true ]], + 'headers' => [ + 'User-Agent' => Api::SDK_USER_AGENT.'/'.Api::SDK_VERSION, + ], + ], + ]); + } /** * @param string $endpointUrl - * @param array $postData - * @param array $files + * @param array $postData + * @param array $files + * * @return \stdClass + * * @throws GenericHTTPError * @throws InvalidCredentials * @throws MissingEndpoint * @throws MissingRequiredParameters */ - public function post($endpointUrl, $postData = array(), $files = array()){ - $request = $this->mgClient->post($endpointUrl, array(), $postData); + public function post($endpointUrl, $postData = array(), $files = array()) + { + $request = $this->mgClient->createRequest('POST', $endpointUrl, ['body' => $postData]); + /** @var \GuzzleHttp\Post\PostBodyInterface $postBody */ + $postBody = $request->getBody(); + $postBody->setAggregator(Query::duplicateAggregator()); - if(isset($files["message"])){ - $this->hasFiles = True; - foreach($files as $message){ - $request->addPostFile("message", $message); - } - } + $fields = ['message', 'attachment', 'inline']; + foreach ($fields as $fieldName) { + if (isset($files[$fieldName])) { + if (is_array($files[$fieldName])) { + foreach ($files[$fieldName] as $file) { + $this->addFile($postBody, $fieldName, $file); + } + } else { + $this->addFile($postBody, $fieldName, $files[$fieldName]); + } + } + } - if(isset($files["attachment"])){ - $this->hasFiles = True; - foreach($files["attachment"] as $attachment){ - // Backward compatibility code - if (is_array($attachment)){ - $request->addPostFile("attachment", - $attachment['filePath'], null, - $attachment['remoteName']); - } - else{ - $request->addPostFile("attachment", $attachment); - } - } - } + $response = $this->mgClient->send($request); - if(isset($files["inline"])){ - $this->hasFiles = True; - foreach($files["inline"] as $inline){ - // Backward compatibility code - if (is_array($inline)){ - $request->addPostFile("inline", - $inline['filePath'], null, - $inline['remoteName']); - } - else{ - $request->addPostFile("inline", $inline); - } - } - } - - /* - This block of code is to accommodate for a bug in Guzzle. - See https://github.com/guzzle/guzzle/issues/545. - It can be removed when Guzzle resolves the issue. - */ - - if($this->hasFiles){ - $request->getPostFields()->setAggregator(new PhpAggregator()); - } - - else{ - $request->getPostFields()->setAggregator(new DuplicateAggregator()); - } - - $response = $request->send(); - return $this->responseHandler($response); - } + return $this->responseHandler($response); + } /** * @param string $endpointUrl - * @param array $queryString + * @param array $queryString + * * @return \stdClass + * * @throws GenericHTTPError * @throws InvalidCredentials * @throws MissingEndpoint * @throws MissingRequiredParameters */ - public function get($endpointUrl, $queryString = array()){ - $request = $this->mgClient->get($endpointUrl); - if(isset($queryString)){ - foreach($queryString as $key=>$value){ - $request->getQuery()->set($key, $value); - } - } - $response = $request->send(); - return $this->responseHandler($response); - } + public function get($endpointUrl, $queryString = array()) + { + $response = $this->mgClient->get($endpointUrl, ['query' => $queryString]); + + return $this->responseHandler($response); + } /** * @param string $endpointUrl + * * @return \stdClass + * * @throws GenericHTTPError * @throws InvalidCredentials * @throws MissingEndpoint * @throws MissingRequiredParameters */ - public function delete($endpointUrl){ - $request = $this->mgClient->delete($endpointUrl); - $response = $request->send(); - return $this->responseHandler($response); - } + public function delete($endpointUrl) + { + $response = $this->mgClient->delete($endpointUrl); + + return $this->responseHandler($response); + } /** * @param string $endpointUrl - * @param array $putData + * @param array $putData + * * @return \stdClass + * * @throws GenericHTTPError * @throws InvalidCredentials * @throws MissingEndpoint * @throws MissingRequiredParameters */ - public function put($endpointUrl, $putData){ - $request = $this->mgClient->put($endpointUrl, array(), $putData); - $request->getPostFields()->setAggregator(new DuplicateAggregator()); - $response = $request->send(); - return $this->responseHandler($response); - } - - /** - * @param \Guzzle\Http\Message\Response $responseObj - * @return \stdClass - * @throws GenericHTTPError - * @throws InvalidCredentials - * @throws MissingEndpoint - * @throws MissingRequiredParameters - */ - public function responseHandler($responseObj){ - $httpResponseCode = $responseObj->getStatusCode(); - if($httpResponseCode === 200){ - $data = (string) $responseObj->getBody(); - $jsonResponseData = json_decode($data, false); - $result = new \stdClass(); - // return response data as json if possible, raw if not - $result->http_response_body = $data && $jsonResponseData === null ? $data : $jsonResponseData; - } - elseif($httpResponseCode == 400){ - throw new MissingRequiredParameters(ExceptionMessages::EXCEPTION_MISSING_REQUIRED_PARAMETERS . $this->getResponseExceptionMessage($responseObj)); - } - elseif($httpResponseCode == 401){ - throw new InvalidCredentials(ExceptionMessages::EXCEPTION_INVALID_CREDENTIALS); - } - elseif($httpResponseCode == 404){ - throw new MissingEndpoint(ExceptionMessages::EXCEPTION_MISSING_ENDPOINT . $this->getResponseExceptionMessage($responseObj)); - } - else{ - throw new GenericHTTPError(ExceptionMessages::EXCEPTION_GENERIC_HTTP_ERROR, $httpResponseCode, $responseObj->getBody()); - } - $result->http_response_code = $httpResponseCode; - return $result; - } + public function put($endpointUrl, $putData) + { + $request = $this->mgClient->createRequest('PUT', $endpointUrl, ['body' => $putData]); + /** @var \GuzzleHttp\Post\PostBodyInterface $postBody */ + $postBody = $request->getBody(); + $postBody->setAggregator(Query::duplicateAggregator()); + + $response = $this->mgClient->send($request); + + return $this->responseHandler($response); + } + + /** + * @param ResponseInterface $responseObj + * + * @return \stdClass + * + * @throws GenericHTTPError + * @throws InvalidCredentials + * @throws MissingEndpoint + * @throws MissingRequiredParameters + */ + public function responseHandler($responseObj) + { + $httpResponseCode = $responseObj->getStatusCode(); + if ($httpResponseCode === 200) { + $data = (string) $responseObj->getBody(); + $jsonResponseData = json_decode($data, false); + $result = new \stdClass(); + // return response data as json if possible, raw if not + $result->http_response_body = $data && $jsonResponseData === null ? $data : $jsonResponseData; + } elseif ($httpResponseCode == 400) { + throw new MissingRequiredParameters(ExceptionMessages::EXCEPTION_MISSING_REQUIRED_PARAMETERS.$this->getResponseExceptionMessage($responseObj)); + } elseif ($httpResponseCode == 401) { + throw new InvalidCredentials(ExceptionMessages::EXCEPTION_INVALID_CREDENTIALS); + } elseif ($httpResponseCode == 404) { + throw new MissingEndpoint(ExceptionMessages::EXCEPTION_MISSING_ENDPOINT.$this->getResponseExceptionMessage($responseObj)); + } else { + throw new GenericHTTPError(ExceptionMessages::EXCEPTION_GENERIC_HTTP_ERROR, $httpResponseCode, $responseObj->getBody()); + } + $result->http_response_code = $httpResponseCode; + + return $result; + } /** * @param \Guzzle\Http\Message\Response $responseObj + * * @return string */ - protected function getResponseExceptionMessage(\Guzzle\Http\Message\Response $responseObj){ - $body = (string)$responseObj->getBody(); - $response = json_decode($body); - if (json_last_error() == JSON_ERROR_NONE && isset($response->message)) { - return " " . $response->message; - } - } + protected function getResponseExceptionMessage(\Guzzle\Http\Message\Response $responseObj) + { + $body = (string) $responseObj->getBody(); + $response = json_decode($body); + if (json_last_error() == JSON_ERROR_NONE && isset($response->message)) { + return " ".$response->message; + } + } /** * @param string $apiEndpoint * @param string $apiVersion - * @param bool $ssl + * @param bool $ssl + * * @return string */ - private function generateEndpoint($apiEndpoint, $apiVersion, $ssl){ - if(!$ssl){ - return "http://" . $apiEndpoint . "/" . $apiVersion . "/"; - } - else{ - return "https://" . $apiEndpoint . "/" . $apiVersion . "/"; - } - } + private function generateEndpoint($apiEndpoint, $apiVersion, $ssl) + { + if (!$ssl) { + return "http://".$apiEndpoint."/".$apiVersion."/"; + } else { + return "https://".$apiEndpoint."/".$apiVersion."/"; + } + } + + /** + * Add a file to the postBody. + * + * @param PostBodyInterface $postBody + * @param string $fieldName + * @param string|array $filePath + */ + private function addFile(PostBodyInterface $postBody, $fieldName, $filePath) + { + $filename = null; + // Backward compatibility code + if (is_array($filePath)) { + $filename = $filePath['remoteName']; + $filePath = $filePath['filePath']; + } + + // Remove leading @ symbol + if (strpos($filePath, '@') === 0) { + $filePath = substr($filePath, 1); + } + + $postBody->addFile(new PostFile($fieldName, fopen($filePath, 'r'), $filename)); + } } diff --git a/tests/Mailgun/Tests/MailgunTestCase.php b/tests/Mailgun/Tests/MailgunTestCase.php index 0f476e8..3d8f2e6 100644 --- a/tests/Mailgun/Tests/MailgunTestCase.php +++ b/tests/Mailgun/Tests/MailgunTestCase.php @@ -2,8 +2,6 @@ namespace Mailgun\Tests; -use Guzzle\Tests\GuzzleTestCase; - -abstract class MailgunTestCase extends GuzzleTestCase +abstract class MailgunTestCase extends \PHPUnit_Framework_TestCase { } diff --git a/tests/Mailgun/Tests/Mock/Connection/TestBroker.php b/tests/Mailgun/Tests/Mock/Connection/TestBroker.php index 23baeb9..a9ee3b0 100644 --- a/tests/Mailgun/Tests/Mock/Connection/TestBroker.php +++ b/tests/Mailgun/Tests/Mock/Connection/TestBroker.php @@ -1,7 +1,11 @@ responseHandler($endpointUrl, $httpResponseCode = 200); + return $this->testResponseHandler($endpointUrl, $httpResponseCode = 200); } public function get($endpointUrl, $queryString = array()) { - return $this->responseHandler($endpointUrl, $httpResponseCode = 200); + return $this->testResponseHandler($endpointUrl, $httpResponseCode = 200); } public function delete($endpointUrl) { - return $this->responseHandler($endpointUrl, $httpResponseCode = 200); + return $this->testResponseHandler($endpointUrl, $httpResponseCode = 200); } public function put($endpointUrl, $queryString) { - return $this->responseHandler($endpointUrl, $httpResponseCode = 200); + return $this->testResponseHandler($endpointUrl, $httpResponseCode = 200); } - public function responseHandler($endpointUrl, $httpResponseCode = 200) + public function testResponseHandler($endpointUrl, $httpResponseCode = 200) { if ($httpResponseCode === 200) { $result = new \stdClass(); @@ -44,13 +48,13 @@ class TestBroker extends RestClient foreach ($jsonResponseData as $key => $value) { $result->http_response_body->$key = $value; } - } elseif ($httpStatusCode == 400) { + } elseif ($httpResponseCode == 400) { throw new MissingRequiredMIMEParameters(EXCEPTION_MISSING_REQUIRED_MIME_PARAMETERS); - } elseif ($httpStatusCode == 401) { + } elseif ($httpResponseCode == 401) { throw new InvalidCredentials(EXCEPTION_INVALID_CREDENTIALS); - } elseif ($httpStatusCode == 401) { + } elseif ($httpResponseCode == 401) { throw new GenericHTTPError(EXCEPTION_INVALID_CREDENTIALS); - } elseif ($httpStatusCode == 404) { + } elseif ($httpResponseCode == 404) { throw new MissingEndpoint(EXCEPTION_MISSING_ENDPOINT); } else { throw new GenericHTTPError(EXCEPTION_GENERIC_HTTP_ERROR);