Completed
Push — master ( 2b1385...7c6a84 )
by Thomas
07:21
created

RingBridge::completeRingResponse()   D

Complexity

Conditions 10
Paths 40

Size

Total Lines 36
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 36
rs 4.8197
cc 10
eloc 25
nc 40
nop 3

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace GuzzleHttp;
3
4
use GuzzleHttp\Message\MessageFactoryInterface;
5
use GuzzleHttp\Message\RequestInterface;
6
use GuzzleHttp\Event\ProgressEvent;
7
use GuzzleHttp\Message\Request;
8
use GuzzleHttp\Ring\Core;
9
use GuzzleHttp\Stream\Stream;
10
use GuzzleHttp\Exception\RequestException;
11
12
/**
13
 * Provides the bridge between Guzzle requests and responses and Guzzle Ring.
14
 */
15
class RingBridge
16
{
17
    /**
18
     * Creates a Ring request from a request object.
19
     *
20
     * This function does not hook up the "then" and "progress" events that
21
     * would be required for actually sending a Guzzle request through a
22
     * RingPHP handler.
23
     *
24
     * @param RequestInterface $request Request to convert.
25
     *
26
     * @return array Converted Guzzle Ring request.
27
     */
28
    public static function createRingRequest(RequestInterface $request)
29
    {
30
        $options = $request->getConfig()->toArray();
31
        $url = $request->getUrl();
32
        // No need to calculate the query string twice (in URL and query).
33
        $qs = ($pos = strpos($url, '?')) ? substr($url, $pos + 1) : null;
34
35
        return [
36
            'scheme'       => $request->getScheme(),
37
            'http_method'  => $request->getMethod(),
38
            'url'          => $url,
39
            'uri'          => $request->getPath(),
40
            'headers'      => $request->getHeaders(),
41
            'body'         => $request->getBody(),
42
            'version'      => $request->getProtocolVersion(),
43
            'client'       => $options,
44
            'query_string' => $qs,
45
            'future'       => isset($options['future']) ? $options['future'] : false
46
        ];
47
    }
48
49
    /**
50
     * Creates a Ring request from a request object AND prepares the callbacks.
51
     *
52
     * @param Transaction $trans Transaction to update.
53
     *
54
     * @return array Converted Guzzle Ring request.
55
     */
56
    public static function prepareRingRequest(Transaction $trans)
57
    {
58
        // Clear out the transaction state when initiating.
59
        $trans->exception = null;
60
        $request = self::createRingRequest($trans->request);
61
62
        // Emit progress events if any progress listeners are registered.
63
        if ($trans->request->getEmitter()->hasListeners('progress')) {
64
            $emitter = $trans->request->getEmitter();
65
            $request['client']['progress'] = function ($a, $b, $c, $d) use ($trans, $emitter) {
66
                $emitter->emit('progress', new ProgressEvent($trans, $a, $b, $c, $d));
67
            };
68
        }
69
70
        return $request;
71
    }
72
73
    /**
74
     * Handles the process of processing a response received from a ring
75
     * handler. The created response is added to the transaction, and the
76
     * transaction stat is set appropriately.
77
     *
78
     * @param Transaction             $trans          Owns request and response.
79
     * @param array                   $response       Ring response array
80
     * @param MessageFactoryInterface $messageFactory Creates response objects.
81
     */
82
    public static function completeRingResponse(
83
        Transaction $trans,
84
        array $response,
85
        MessageFactoryInterface $messageFactory
86
    ) {
87
        $trans->state = 'complete';
88
        $trans->transferInfo = isset($response['transfer_stats'])
89
            ? $response['transfer_stats'] : [];
90
91
        if (!empty($response['status'])) {
92
            $options = [];
93
            if (isset($response['version'])) {
94
                $options['protocol_version'] = $response['version'];
95
            }
96
            if (isset($response['reason'])) {
97
                $options['reason_phrase'] = $response['reason'];
98
            }
99
            $trans->response = $messageFactory->createResponse(
100
                $response['status'],
101
                isset($response['headers']) ? $response['headers'] : [],
102
                isset($response['body']) ? $response['body'] : null,
103
                $options
104
            );
105
            if (isset($response['effective_url'])) {
106
                $trans->response->setEffectiveUrl($response['effective_url']);
107
            }
108
        } elseif (empty($response['error'])) {
109
            // When nothing was returned, then we need to add an error.
110
            $response['error'] = self::getNoRingResponseException($trans->request);
111
        }
112
113
        if (isset($response['error'])) {
114
            $trans->state = 'error';
115
            $trans->exception = $response['error'];
116
        }
117
    }
118
119
    /**
120
     * Creates a Guzzle request object using a ring request array.
121
     *
122
     * @param array $request Ring request
123
     *
124
     * @return Request
125
     * @throws \InvalidArgumentException for incomplete requests.
126
     */
127
    public static function fromRingRequest(array $request)
128
    {
129
        $options = [];
130
        if (isset($request['version'])) {
131
            $options['protocol_version'] = $request['version'];
132
        }
133
134
        if (!isset($request['http_method'])) {
135
            throw new \InvalidArgumentException('No http_method');
136
        }
137
138
        return new Request(
139
            $request['http_method'],
140
            Core::url($request),
141
            isset($request['headers']) ? $request['headers'] : [],
142
            isset($request['body']) ? Stream::factory($request['body']) : null,
143
            $options
144
        );
145
    }
146
147
    /**
148
     * Get an exception that can be used when a RingPHP handler does not
149
     * populate a response.
150
     *
151
     * @param RequestInterface $request
152
     *
153
     * @return RequestException
154
     */
155
    public static function getNoRingResponseException(RequestInterface $request)
156
    {
157
        $message = <<<EOT
158
Sending the request did not return a response, exception, or populate the
159
transaction with a response. This is most likely due to an incorrectly
160
implemented RingPHP handler. If you are simply trying to mock responses,
161
then it is recommended to use the GuzzleHttp\Ring\Client\MockHandler.
162
EOT;
163
        return new RequestException($message, $request);
164
    }
165
}
166