Use PSR-18 (#522)

* Use PSR-18

* minor fixes

* phpstan fixes

* cs
This commit is contained in:
Tobias Nyholm 2019-02-02 08:30:04 +01:00 committed by GitHub
parent 398989de61
commit 6954b4dd2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 175 additions and 89 deletions

View File

@ -3,10 +3,10 @@
"description": "The Mailgun SDK provides methods for all API functions.",
"require": {
"php": "^7.1",
"php-http/httplug": "^1.0 || ^2.0",
"psr/http-client": "^1.0",
"php-http/multipart-stream-builder": "^1.0",
"php-http/client-common": "^1.9",
"php-http/discovery": "^1.0",
"php-http/client-common": "^1.9 || ^2.0",
"php-http/discovery": "^1.6",
"webmozart/assert": "^1.2"
},
"require-dev": {

View File

@ -3,3 +3,5 @@ parameters:
paths:
- src
excludes_analyse:
- %currentWorkingDirectory%/src/HttpClient/Plugin/HistoryTrait.php

View File

@ -11,14 +11,14 @@ declare(strict_types=1);
namespace Mailgun\Api;
use Http\Client\Exception as HttplugException;
use Http\Client\HttpClient;
use Mailgun\Exception\UnknownErrorException;
use Mailgun\Hydrator\Hydrator;
use Mailgun\Hydrator\NoopHydrator;
use Mailgun\Exception\HttpClientException;
use Mailgun\Exception\HttpServerException;
use Mailgun\HttpClient\RequestBuilder;
use Psr\Http\Client as Psr18;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
/**
@ -29,7 +29,7 @@ abstract class HttpApi
/**
* The HTTP client.
*
* @var HttpClient
* @var ClientInterface
*/
protected $httpClient;
@ -43,7 +43,7 @@ abstract class HttpApi
*/
protected $requestBuilder;
public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
public function __construct(ClientInterface $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
{
$this->httpClient = $httpClient;
$this->requestBuilder = $requestBuilder;
@ -113,7 +113,7 @@ abstract class HttpApi
$response = $this->httpClient->sendRequest(
$this->requestBuilder->create('GET', $path, $requestHeaders)
);
} catch (HttplugException\NetworkException $e) {
} catch (Psr18\NetworkExceptionInterface $e) {
throw HttpServerException::networkError($e);
}
@ -145,7 +145,7 @@ abstract class HttpApi
$response = $this->httpClient->sendRequest(
$this->requestBuilder->create('POST', $path, $requestHeaders, $body)
);
} catch (HttplugException\NetworkException $e) {
} catch (Psr18\NetworkExceptionInterface $e) {
throw HttpServerException::networkError($e);
}
@ -165,7 +165,7 @@ abstract class HttpApi
$response = $this->httpClient->sendRequest(
$this->requestBuilder->create('PUT', $path, $requestHeaders, $this->createRequestBody($parameters))
);
} catch (HttplugException\NetworkException $e) {
} catch (Psr18\NetworkExceptionInterface $e) {
throw HttpServerException::networkError($e);
}
@ -185,7 +185,7 @@ abstract class HttpApi
$response = $this->httpClient->sendRequest(
$this->requestBuilder->create('DELETE', $path, $requestHeaders, $this->createRequestBody($parameters))
);
} catch (HttplugException\NetworkException $e) {
} catch (Psr18\NetworkExceptionInterface $e) {
throw HttpServerException::networkError($e);
}

View File

@ -11,11 +11,11 @@ declare(strict_types=1);
namespace Mailgun\Api;
use Http\Client\HttpClient;
use Mailgun\Api\Suppression\Bounce;
use Mailgun\Api\Suppression\Complaint;
use Mailgun\Api\Suppression\Unsubscribe;
use Mailgun\Hydrator\Hydrator;
use Psr\Http\Client\ClientInterface;
use Mailgun\HttpClient\RequestBuilder;
/**
@ -26,7 +26,7 @@ use Mailgun\HttpClient\RequestBuilder;
class Suppression
{
/**
* @var HttpClient
* @var ClientInterface
*/
private $httpClient;
@ -40,7 +40,7 @@ class Suppression
*/
private $hydrator;
public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
public function __construct(ClientInterface $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator)
{
$this->httpClient = $httpClient;
$this->requestBuilder = $requestBuilder;

View File

@ -11,7 +11,6 @@ declare(strict_types=1);
namespace Mailgun\Api;
use Http\Client\HttpClient;
use Mailgun\Assert;
use Mailgun\Hydrator\Hydrator;
use Mailgun\Model\Webhook\CreateResponse;
@ -21,6 +20,7 @@ use Mailgun\Model\Webhook\ShowResponse;
use Mailgun\Model\Webhook\UpdateResponse;
use Mailgun\HttpClient\RequestBuilder;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Client\ClientInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
@ -32,7 +32,7 @@ class Webhook extends HttpApi
*/
private $apiKey;
public function __construct(HttpClient $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator, string $apiKey)
public function __construct(ClientInterface $httpClient, RequestBuilder $requestBuilder, Hydrator $hydrator, string $apiKey)
{
parent::__construct($httpClient, $requestBuilder, $hydrator);
$this->apiKey = $apiKey;

View File

@ -23,7 +23,7 @@ final class HttpServerException extends \RuntimeException implements Exception
return new self('An unexpected error occurred at Mailgun\'s servers. Try again later and contact support if the error still exists.', $httpStatus);
}
public static function networkError(\Exception $previous)
public static function networkError(\Throwable $previous)
{
return new self('Mailgun\'s servers are currently unreachable.', 0, $previous);
}

View File

@ -11,14 +11,14 @@ declare(strict_types=1);
namespace Mailgun\HttpClient;
use Http\Client\HttpClient;
use Http\Client\Common\PluginClient;
use Http\Discovery\HttpClientDiscovery;
use Http\Discovery\Psr18ClientDiscovery;
use Http\Discovery\UriFactoryDiscovery;
use Http\Message\UriFactory;
use Http\Client\Common\Plugin;
use Mailgun\HttpClient\Plugin\History;
use Mailgun\HttpClient\Plugin\ReplaceUriPlugin;
use Psr\Http\Client\ClientInterface;
/**
* Configure a HTTP client.
@ -50,7 +50,7 @@ final class HttpClientConfigurator
private $uriFactory;
/**
* @var HttpClient
* @var ClientInterface
*/
private $httpClient;
@ -124,16 +124,16 @@ final class HttpClientConfigurator
return $this;
}
private function getHttpClient(): HttpClient
private function getHttpClient(): ClientInterface
{
if (null === $this->httpClient) {
$this->httpClient = HttpClientDiscovery::find();
$this->httpClient = Psr18ClientDiscovery::find();
}
return $this->httpClient;
}
public function setHttpClient(HttpClient $httpClient): self
public function setHttpClient(ClientInterface $httpClient): self
{
$this->httpClient = $httpClient;

View File

@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Mailgun\HttpClient\Plugin;
use Http\Client\Common\Plugin\Journal;
use Http\Client\Exception;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
@ -23,6 +22,7 @@ use Psr\Http\Message\ResponseInterface;
*/
final class History implements Journal
{
use HistoryTrait;
/**
* @var ResponseInterface
*/
@ -40,8 +40,4 @@ final class History implements Journal
{
$this->lastResponse = $response;
}
public function addFailure(RequestInterface $request, Exception $exception)
{
}
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/*
* Copyright (C) 2013 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\HttpClient\Plugin;
use Http\Client\Exception;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\RequestInterface;
/*
* Below is a some code to make the History plugin compatible with both 1.x and 2.x of php-client/client-common
*/
if (\class_exists(\Http\Client\Common\HttpMethodsClientInterface::class)) {
/**
* @internal code for php-http/client-common:2.x
*/
trait HistoryTrait
{
public function addFailure(RequestInterface $request, ClientExceptionInterface $exception)
{
}
}
} else {
/**
* @internal code for php-http/client-common:1.x
*/
trait HistoryTrait
{
public function addFailure(RequestInterface $request, Exception $exception)
{
}
}
}

View File

@ -22,6 +22,8 @@ use Psr\Http\Message\UriInterface;
*/
final class ReplaceUriPlugin implements Plugin
{
use Plugin\VersionBridgePlugin;
/**
* @var UriInterface
*/
@ -32,10 +34,7 @@ final class ReplaceUriPlugin implements Plugin
$this->uri = $uri;
}
/**
* {@inheritdoc}
*/
public function handleRequest(RequestInterface $request, callable $next, callable $first)
public function doHandleRequest(RequestInterface $request, callable $next, callable $first)
{
$request = $request->withUri($this->uri);

View File

@ -11,10 +11,12 @@ declare(strict_types=1);
namespace Mailgun\HttpClient;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\Psr17FactoryDiscovery;
use Http\Message\MultipartStream\MultipartStreamBuilder;
use Http\Message\RequestFactory;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
@ -22,10 +24,15 @@ use Psr\Http\Message\RequestInterface;
class RequestBuilder
{
/**
* @var RequestFactory
* @var RequestFactoryInterface|null
*/
private $requestFactory;
/**
* @var StreamFactoryInterface|null
*/
private $streamFactory;
/**
* @var MultipartStreamBuilder
*/
@ -42,13 +49,13 @@ class RequestBuilder
* 'filename'=> string (optional)
* 'headers' => array (optinal) ['header-name' => 'header-value']
* )
*
* @return RequestInterface
*/
public function create(string $method, string $uri, array $headers = [], $body = null)
public function create(string $method, string $uri, array $headers = [], $body = null): RequestInterface
{
if (!is_array($body)) {
return $this->getRequestFactory()->createRequest($method, $uri, $headers, $body);
$stream = $this->getStreamFactory()->createStream($body);
return $this->createRequest($method, $uri, $headers, $stream);
}
$builder = $this->getMultipartStreamBuilder();
@ -67,37 +74,42 @@ class RequestBuilder
$headers['Content-Type'] = 'multipart/form-data; boundary="'.$boundary.'"';
return $this->getRequestFactory()->createRequest($method, $uri, $headers, $multipartStream);
return $this->createRequest($method, $uri, $headers, $multipartStream);
}
/**
* @return RequestFactory
*/
private function getRequestFactory()
private function getRequestFactory(): RequestFactoryInterface
{
if (null === $this->requestFactory) {
$this->requestFactory = MessageFactoryDiscovery::find();
$this->requestFactory = Psr17FactoryDiscovery::findRequestFactory();
}
return $this->requestFactory;
}
/**
* @param RequestFactory $requestFactory
*
* @return RequestBuilder
*/
public function setRequestFactory($requestFactory)
public function setRequestFactory(RequestFactoryInterface $requestFactory): self
{
$this->requestFactory = $requestFactory;
return $this;
}
/**
* @return MultipartStreamBuilder
*/
private function getMultipartStreamBuilder()
private function getStreamFactory(): StreamFactoryInterface
{
if (null === $this->streamFactory) {
$this->streamFactory = Psr17FactoryDiscovery::findStreamFactory();
}
return $this->streamFactory;
}
public function setStreamFactory(StreamFactoryInterface $streamFactory): self
{
$this->streamFactory = $streamFactory;
return $this;
}
private function getMultipartStreamBuilder(): MultipartStreamBuilder
{
if (null === $this->multipartStreamBuilder) {
$this->multipartStreamBuilder = new MultipartStreamBuilder();
@ -106,15 +118,21 @@ class RequestBuilder
return $this->multipartStreamBuilder;
}
/**
* @param MultipartStreamBuilder $multipartStreamBuilder
*
* @return RequestBuilder
*/
public function setMultipartStreamBuilder($multipartStreamBuilder)
public function setMultipartStreamBuilder(MultipartStreamBuilder $multipartStreamBuilder): self
{
$this->multipartStreamBuilder = $multipartStreamBuilder;
return $this;
}
private function createRequest(string $method, string $uri, array $headers, StreamInterface $stream)
{
$request = $this->getRequestFactory()->createRequest($method, $uri);
$request = $request->withBody($stream);
foreach ($headers as $name => $value) {
$request = $request->withAddedHeader($name, $value);
}
return $request;
}
}

View File

@ -11,13 +11,14 @@ declare(strict_types=1);
namespace Mailgun;
use Http\Client\HttpClient;
use Http\Client\Common\PluginClient;
use Mailgun\HttpClient\HttpClientConfigurator;
use Mailgun\HttpClient\Plugin\History;
use Mailgun\HttpClient\RequestBuilder;
use Mailgun\Hydrator\ModelHydrator;
use Mailgun\Hydrator\Hydrator;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Client\ClientInterface;
/**
* This class is the base class for the Mailgun SDK.
@ -30,7 +31,7 @@ final class Mailgun
private $apiKey;
/**
* @var HttpClient
* @var ClientInterface|PluginClient
*/
private $httpClient;

View File

@ -14,6 +14,7 @@ namespace Mailgun\Tests\Api;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Mailgun\Hydrator\ModelHydrator;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
/**
@ -49,7 +50,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
protected function getApiMock($httpClient = null, $requestClient = null, $hydrator = null)
{
if (null === $httpClient) {
$httpClient = $this->getMockBuilder('Http\Client\HttpClient')
$httpClient = $this->getMockBuilder(ClientInterface::class)
->setMethods(['sendRequest'])
->getMock();
$httpClient
@ -79,7 +80,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
*/
protected function getApiInstance($apiKey = null)
{
$httpClient = $this->getMockBuilder('Http\Client\HttpClient')
$httpClient = $this->getMockBuilder(ClientInterface::class)
->setMethods(['sendRequest'])
->getMock();
$httpClient

View File

@ -12,19 +12,25 @@ declare(strict_types=1);
namespace Mailgun\Tests\HttpClient;
use Http\Message\MultipartStream\MultipartStreamBuilder;
use Http\Message\RequestFactory;
use Mailgun\HttpClient\RequestBuilder;
use Mailgun\Tests\MailgunTestCase;
use Nyholm\Psr7\Stream;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
class RequestBuilderTest extends MailgunTestCase
{
/**
* @var MockObject|RequestFactory
* @var MockObject|RequestFactoryInterface
*/
private $requestFactory;
/**
* @var MockObject|StreamFactoryInterface
*/
private $streamFactory;
/**
* @var RequestBuilder
@ -38,13 +44,18 @@ class RequestBuilderTest extends MailgunTestCase
{
parent::setUp();
$this->requestFactory = $this->getMockBuilder(RequestFactory::class)
$this->requestFactory = $this->getMockBuilder(RequestFactoryInterface::class)
->disableOriginalConstructor()
->getMock();
$this->streamFactory = $this->getMockBuilder(StreamFactoryInterface::class)
->disableOriginalConstructor()
->getMock();
$this->requestBuilder = new RequestBuilder();
//Everything but testing class is mock. Otherwise it wouldn't be unit testing
$this->requestBuilder->setRequestFactory($this->requestFactory);
$this->requestBuilder->setStreamFactory($this->streamFactory);
}
/**
@ -60,21 +71,34 @@ class RequestBuilderTest extends MailgunTestCase
public function testCreateSimpleStream()
{
$streamContent = 'content';
$stream = Stream::create($streamContent);
$this->streamFactory
->expects($this->once())
->method('createStream')
->with($streamContent)
->willReturn($stream);
$request = $this->getMockBuilder(RequestInterface::class)->getMock();
$request->expects($this->once())
->method('withBody')
->with($this->equalTo($stream))
->willReturn($request);
$request->expects($this->once())
->method('withAddedHeader')
->with($this->equalTo('Content-Type'), $this->equalTo('application/json'))
->willReturn($request);
$this->requestFactory
->expects($this->once())
->method('createRequest')
->with(
$this->equalTo('GET'),
$this->equalTo('http://foo.bar'),
$this->callback(function (array $headers) {
$this->assertArrayHasKey('Content-Type', $headers);
$this->assertEquals('application/json', $headers['Content-Type']);
return true;
}),
$this->equalTo('content')
$this->equalTo('http://foo.bar')
)
->willReturn($request = $this->getMockBuilder(RequestInterface::class)->getMock());
->willReturn($request);
$result = $this->requestBuilder
->create('GET', 'http://foo.bar', ['Content-Type' => 'application/json'], 'content');
@ -122,21 +146,25 @@ class RequestBuilderTest extends MailgunTestCase
->method('reset')
->willReturn($multipartStreamBuilder);
$request = $this->getMockBuilder(RequestInterface::class)->getMock();
$request->expects($this->once())
->method('withBody')
->with($this->equalTo($stream))
->willReturn($request);
$request->expects($this->once())
->method('withAddedHeader')
->with($this->equalTo('Content-Type'), $this->equalTo('multipart/form-data; boundary="some boundary"'))
->willReturn($request);
$this->requestFactory
->expects($this->once())
->method('createRequest')
->with(
$this->equalTo('GET'),
$this->equalTo('http://foo.bar'),
$this->callback(function (array $headers) {
$this->assertArrayHasKey('Content-Type', $headers);
$this->assertEquals('multipart/form-data; boundary="some boundary"', $headers['Content-Type']);
return true;
}),
$this->equalTo($stream)
$this->equalTo('http://foo.bar')
)
->willReturn($request = $this->getMockBuilder(RequestInterface::class)->getMock());
->willReturn($request);
$this->requestBuilder->setMultipartStreamBuilder($multipartStreamBuilder);
$result = $this->requestBuilder