Completed
Push — master ( 5a9d51...0920dd )
by Joel
36:06 queued 19s
created

Client   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 120
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 14

Test Coverage

Coverage 97.78%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 14
c 3
b 1
f 0
lcom 1
cbo 14
dl 0
loc 120
ccs 44
cts 45
cp 0.9778
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 9 5
A sendRequest() 0 12 2
A createRequest() 0 17 1
A createResponse() 0 12 2
B handleException() 0 24 4
1
<?php
2
3
namespace Http\Adapter\Guzzle5;
4
5
use GuzzleHttp\Client as GuzzleClient;
6
use GuzzleHttp\ClientInterface;
7
use GuzzleHttp\Message\RequestInterface as GuzzleRequest;
8
use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
9
use Http\Client\HttpClient;
10
use Http\Discovery\MessageFactoryDiscovery;
11
use Http\Message\MessageFactory;
12
use Psr\Http\Message\RequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use Http\Client\Exception as HttplugException;
15
use GuzzleHttp\Exception as GuzzleExceptions;
16
17
/**
18
 * @author GeLo <[email protected]>
19
 * @author Tobias Nyholm <[email protected]>
20
 */
21
class Client implements HttpClient
22
{
23
    /**
24
     * @var ClientInterface
25
     */
26
    private $client;
27
28
    /**
29
     * @var MessageFactory
30
     */
31
    private $messageFactory;
32
33
    /**
34
     * @param ClientInterface|null $client
35
     * @param MessageFactory|null  $messageFactory
36
     */
37 118
    public function __construct(ClientInterface $client = null, MessageFactory $messageFactory = null)
38
    {
39 118
        if (null === $messageFactory and false === class_exists('Http\Discovery\MessageFactoryDiscovery')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
40
            throw new \LogicException('No message factory provided and no discovery service is present to guess it, maybe you need to install php-http/discovery package?');
41
        }
42
43 118
        $this->client = $client ?: new GuzzleClient();
44 118
        $this->messageFactory = $messageFactory ?: MessageFactoryDiscovery::find();
45 118
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 118
    public function sendRequest(RequestInterface $request)
51
    {
52 118
        $guzzleRequest = $this->createRequest($request);
53
54
        try {
55 118
            $response = $this->client->send($guzzleRequest);
56 118
        } catch (GuzzleExceptions\TransferException $e) {
57 14
            throw $this->handleException($e, $request);
58
        }
59
60 104
        return $this->createResponse($response);
61
    }
62
63
    /**
64
     * Converts a PSR request into a Guzzle request.
65
     *
66
     * @param RequestInterface $request
67
     *
68
     * @return GuzzleRequest
69
     */
70 118
    private function createRequest(RequestInterface $request)
71
    {
72
        $options = [
73 118
            'exceptions' => false,
74 118
            'allow_redirects' => false,
75 118
        ];
76
77 118
        $options['version'] = $request->getProtocolVersion();
78 118
        $options['headers'] = $request->getHeaders();
79 118
        $options['body'] = (string) $request->getBody();
80
81 118
        return $this->client->createRequest(
82 118
            $request->getMethod(),
83 118
            (string) $request->getUri(),
84
            $options
85 118
        );
86
    }
87
88
    /**
89
     * Converts a Guzzle response into a PSR response.
90
     *
91
     * @param GuzzleResponse $response
92
     *
93
     * @return ResponseInterface
94
     */
95 108
    private function createResponse(GuzzleResponse $response)
96
    {
97 108
        $body = $response->getBody();
98
99 108
        return $this->messageFactory->createResponse(
100 108
            $response->getStatusCode(),
101 108
            null,
102 108
            $response->getHeaders(),
103 108
            isset($body) ? $body->detach() : null,
104 108
            $response->getProtocolVersion()
105 108
        );
106
    }
107
108
    /**
109
     * Converts a Guzzle exception into an Httplug exception.
110
     *
111
     * @param GuzzleExceptions\TransferException $exception
112
     * @param RequestInterface                   $request
113
     *
114
     * @return HttplugException
115
     */
116 14
    private function handleException(GuzzleExceptions\TransferException $exception, RequestInterface $request)
117
    {
118 14
        if ($exception instanceof GuzzleExceptions\ConnectException) {
119 3
            return new HttplugException\NetworkException($exception->getMessage(), $request, $exception);
120
        }
121
122 11
        if ($exception instanceof GuzzleExceptions\RequestException) {
123
            // Make sure we have a response for the HttpException
124 9
            if ($exception->hasResponse()) {
125 4
                $psr7Response = $this->createResponse($exception->getResponse());
126
127 4
                return new HttplugException\HttpException(
128 4
                    $exception->getMessage(),
129 4
                    $request,
130 4
                    $psr7Response,
131
                    $exception
132 4
                );
133
            }
134
135 5
            return new HttplugException\RequestException($exception->getMessage(), $request, $exception);
136
        }
137
138 2
        return new HttplugException\TransferException($exception->getMessage(), 0, $exception);
139
    }
140
}
141