Completed
Push — master ( b8226b...2dacf7 )
by Chad
20s
created

GuzzleAdapter::fulfillPromises()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 2
eloc 12
nc 2
nop 2
1
<?php
2
3
namespace DominionEnterprises\Api;
4
5
use ArrayObject;
6
use DominionEnterprises\Util;
7
use GuzzleHttp\Client as GuzzleClient;
8
use GuzzleHttp\Exception\RequestException;
9
use GuzzleHttp\Promise;
10
use Psr\Http\Message\ResponseInterface;
11
12
/**
13
 * Concrete implentation of Adapter interface
14
 */
15
final class GuzzleAdapter implements Adapter
16
{
17
    /**
18
     * Collection of Promise\PromiseInterface instances with keys matching what was given from start().
19
     *
20
     * @var array
21
     */
22
    private $_promises = [];
23
24
    /**
25
     * Collection of Api\Response with keys matching what was given from start().
26
     *
27
     * @var array
28
     */
29
    private $_responses = [];
30
31
    /**
32
     * Collection of \Exception with keys matching what was given from start().
33
     *
34
     * @var array
35
     */
36
    private $_exceptions = [];
37
38
    /**
39
     * @var \Guzzle\Http\Client
40
     */
41
    private $_client;
42
43
    public function __construct()
44
    {
45
        $this->_client = new GuzzleClient(
0 ignored issues
show
Documentation Bug introduced by
It seems like new \GuzzleHttp\Client(a...http_errors' => false)) of type object<GuzzleHttp\Client> is incompatible with the declared type object<Guzzle\Http\Client> of property $_client.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
46
            [
47
                'allow_redirects' => false, //stop guzzle from following redirects
48
                'http_errors' => false, //only for 400/500 error codes, actual exceptions can still happen
49
            ]
50
        );
51
    }
52
53
    /**
54
     * @see Adapter::start()
55
     */
56
    public function start(Request $request)
57
    {
58
        $this->_promises[] = $this->_client->requestAsync(
0 ignored issues
show
Bug introduced by
The method requestAsync() does not seem to exist on object<Guzzle\Http\Client>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
59
            $request->getMethod(),
60
            $request->getUrl(),
61
            [
62
                'headers' => $request->getHeaders(),
63
                'body' => $request->getBody(),
64
            ]
65
        );
66
67
        end($this->_promises);
68
        return key($this->_promises);
69
    }
70
71
    /**
72
     * @see Adapter::end()
73
     *
74
     * @throws \InvalidArgumentException
75
     */
76
    public function end($endHandle)
77
    {
78
        Util::throwIfNotType(['int' => [$endHandle]]);
79
80
        $results = $this->fulfillPromises($this->_promises, $this->_exceptions);
81
        foreach ($results as $handle => $response) {
82
            try {
83
                $body = []; //default to empty body
84
                $contents = (string)$response->getBody();
85
                if (trim($contents) !== '') {
86
                    $body = json_decode($contents, true);
87
                    Util::ensure(
88
                        JSON_ERROR_NONE,
89
                        json_last_error(),
90
                        '\UnexpectedValueException',
91
                        [json_last_error_msg()]
92
                    );
93
                }
94
95
                $this->_responses[$handle] = new Response($response->getStatusCode(), $response->getHeaders(), $body);
96
            } catch (\Exception $e) {
97
                $this->_exceptions[$handle] = $e;
98
            }
99
        }
100
101
        $this->_promises = [];
102
103
        if (array_key_exists($endHandle, $this->_exceptions)) {
104
            $exception = $this->_exceptions[$endHandle];
105
            unset($this->_exceptions[$endHandle]);
106
            throw $exception;
107
        }
108
109
        if (array_key_exists($endHandle, $this->_responses)) {
110
            $response = $this->_responses[$endHandle];
111
            unset($this->_responses[$endHandle]);
112
            return $response;
113
        }
114
115
        throw new \InvalidArgumentException('$endHandle not found');
116
    }
117
118
    /**
119
     * Helper method to execute all guzzle promises.
120
     *
121
     * @param array $promises
122
     * @param array $exceptions
123
     *
124
     * @return array Array of fulfilled PSR7 responses.
125
     */
126
    private function fulfillPromises(array $promises, array &$exceptions)
127
    {
128
        if (empty($promises)) {
129
            return [];
130
        }
131
132
        $results = [];
133
        Promise\each(
134
            $this->_promises,
135
            function (ResponseInterface $response, $index) use (&$results) {
136
                $results[$index] = $response;
137
            },
138
            function (RequestException $e, $index) use (&$exceptions) {
139
                $exceptions[$index] = $e;
140
            }
141
        )->wait();
142
143
        return $results;
144
    }
145
}
146