Completed
Pull Request — master (#42)
by Chad
04:56
created

GuzzleAdapter::start()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
namespace TraderInteractive\Api;
4
5
use ArrayObject;
6
use TraderInteractive\Util;
7
use GuzzleHttp\Client as GuzzleClient;
8
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
9
use GuzzleHttp\Exception\RequestException;
10
use GuzzleHttp\Promise;
11
use Psr\Http\Message\RequestInterface;
12
use Psr\Http\Message\ResponseInterface;
13
14
/**
15
 * Concrete implentation of Adapter interface
16
 */
17
final class GuzzleAdapter implements AdapterInterface
18
{
19
    /**
20
     * Collection of Promise\PromiseInterface instances with keys matching what was given from start().
21
     *
22
     * @var array
23
     */
24
    private $promises = [];
25
26
    /**
27
     * Collection of Api\Response with keys matching what was given from start().
28
     *
29
     * @var array
30
     */
31
    private $responses = [];
32
33
    /**
34
     * Collection of \Exception with keys matching what was given from start().
35
     *
36
     * @var ArrayObject
37
     */
38
    private $exceptions;
39
40
    /**
41
     * @var GuzzleClientInterface
42
     */
43
    private $client;
44
45
    public function __construct(GuzzleClientInterface $client = null)
46
    {
47
        $this->exceptions = new ArrayObject();
48
        $this->client = $client ?? new GuzzleClient(
49
            [
50
                'allow_redirects' => false, //stop guzzle from following redirects
51
                'http_errors' => false, //only for 400/500 error codes, actual exceptions can still happen
52
            ]
53
        );
54
    }
55
56
    /**
57
     * @see AdapterInterface::start()
58
     */
59
    public function start(RequestInterface $request) : string
60
    {
61
        $handle = uniqid();
62
        $this->promises[$handle] = $this->client->sendAsync($request);
63
        return $handle;
64
    }
65
66
    /**
67
     * @see Adapter::end()
68
     *
69
     * @throws \InvalidArgumentException
70
     */
71
    public function end(string $endHandle) : ResponseInterface
72
    {
73
        $results = $this->fulfillPromises($this->promises, $this->exceptions);
74
        foreach ($results as $handle => $response) {
75
            try {
76
                $body = []; //default to empty body
0 ignored issues
show
Unused Code introduced by
$body is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
77
                $contents = (string)$response->getBody();
78
                if (trim($contents) !== '') {
79
                    $body = json_decode($contents, true);
0 ignored issues
show
Unused Code introduced by
$body is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
80
                    Util::ensure(
81
                        JSON_ERROR_NONE,
82
                        json_last_error(),
83
                        '\UnexpectedValueException',
84
                        [json_last_error_msg()]
85
                    );
86
                }
87
88
                $this->responses[$handle] = $response;
89
            } catch (\Exception $e) {
90
                $this->exceptions[$handle] = $e;
91
            }
92
        }
93
94
        $this->promises = [];
95
96
        if (array_key_exists($endHandle, $this->exceptions)) {
97
            $exception = $this->exceptions[$endHandle];
98
            unset($this->exceptions[$endHandle]);
99
            throw $exception;
100
        }
101
102
        if (array_key_exists($endHandle, $this->responses)) {
103
            $response = $this->responses[$endHandle];
104
            unset($this->responses[$endHandle]);
105
            return $response;
106
        }
107
108
        throw new \InvalidArgumentException('$endHandle not found');
109
    }
110
111
    /**
112
     * Helper method to execute all guzzle promises.
113
     *
114
     * @param array $promises
115
     * @param array $exceptions
116
     *
117
     * @return array Array of fulfilled PSR7 responses.
118
     */
119
    private function fulfillPromises(array $promises, ArrayObject $exceptions) : array
120
    {
121
        if (empty($promises)) {
122
            return [];
123
        }
124
125
        $results = new ArrayObject();
126
        Promise\each(
127
            $this->promises,
128
            function (ResponseInterface $response, $index) use ($results) {
129
                $results[$index] = $response;
130
            },
131
            function (RequestException $e, $index) use ($exceptions) {
132
                $exceptions[$index] = $e;
133
            }
134
        )->wait();
135
136
        return $results->getArrayCopy();
137
    }
138
}
139