RequestContext   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 20
eloc 53
c 1
b 0
f 0
dl 0
loc 151
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A add_header() 0 4 1
A add_a_parameter() 0 15 3
A set_the_body() 0 6 1
A __construct() 0 7 1
A clearCache() 0 4 1
A create_a_request() 0 9 1
A set_the_content_type() 0 4 1
A set_the_parameters() 0 6 2
A set_headers() 0 9 2
A getDefaultContentType() 0 3 1
A getRequest() 0 7 2
A send_request() 0 19 3
A send_a_request() 0 4 1
1
<?php declare(strict_types=1);
2
namespace Behapi\Http;
3
4
use RuntimeException;
5
6
use Psr\Http\Message\RequestInterface;
7
8
use Behat\Behat\Context\Context;
9
use Behat\Gherkin\Node\TableNode;
10
11
use Http\Client\HttpClient;
12
use Http\Client\HttpAsyncClient;
13
14
use Http\Message\StreamFactory;
15
use Http\Message\MessageFactory;
16
17
use Http\Discovery\HttpClientDiscovery;
18
19
use function trim;
20
use function is_array;
21
use function http_build_query;
22
23
class RequestContext implements Context
24
{
25
    use Builder;
26
27
    /** @var ?RequestInterface */
28
    private $request;
29
30
    /** @var mixed[] Query args to add */
31
    private $query;
32
33
    /** @var HttpClient|HttpAsyncClient */
34
    private $client;
35
36
    public function __construct(PluginClientBuilder $builder, StreamFactory $streamFactory, MessageFactory $messageFactory)
37
    {
38
        $this->builder = $builder;
39
        $this->streamFactory = $streamFactory;
40
        $this->messageFactory = $messageFactory;
41
42
        $this->client = HttpClientDiscovery::find();
43
    }
44
45
    /** @When /^I create a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/ */
46
    final public function create_a_request(string $method, string $url): void
47
    {
48
        $url = trim($url);
49
50
        $this->query = [];
51
        $this->request = $this->messageFactory->createRequest(strtoupper($method), $url);
52
53
        // let's set a default content-type
54
        $this->set_the_content_type($this->getDefaultContentType());
55
    }
56
57
    /**
58
     * @When /^I send a "(?P<method>GET|POST|PATCH|PUT|DELETE|OPTIONS|HEAD)" request to "(?P<url>.+?)"$/
59
     *
60
     * -------
61
     *
62
     * Shortcut for `When I create a X request to Then send the request`
63
     */
64
    final public function send_a_request($method, $url): void
65
    {
66
        $this->create_a_request($method, $url);
67
        $this->send_request();
68
    }
69
70
    /** @When I add/set the value :value to the parameter :parameter */
71
    final public function add_a_parameter(string $parameter, string $value): void
72
    {
73
        if (!isset($this->query[$parameter])) {
74
            $this->query[$parameter] = $value;
75
            return;
76
        }
77
78
        $current = &$this->query[$parameter];
79
80
        if (is_array($current)) {
81
            $current[] = $value;
82
            return;
83
        }
84
85
        $current = [$current, $value];
86
    }
87
88
    /** @When I set the following query arguments: */
89
    final public function set_the_parameters(TableNode $parameters): void
90
    {
91
        $this->query = [];
92
93
        foreach ($parameters->getRowsHash() as $parameter => $value) {
94
            $this->add_a_parameter($parameter, $value);
95
        }
96
    }
97
98
    /** @When I set the content-type to :type */
99
    final public function set_the_content_type(string $type): void
100
    {
101
        $request = $this->getRequest();
102
        $this->request = $request->withHeader('Content-Type', $type);
103
    }
104
105
    /** @When I set the following body: */
106
    final public function set_the_body(string $body): void
107
    {
108
        $stream = $this->streamFactory->createStream($body);
109
110
        $request = $this->getRequest();
111
        $this->request = $request->withBody($stream);
112
    }
113
114
    /** @When I add/set the value :value to the header :header */
115
    final public function add_header(string $header, string $value): void
116
    {
117
        $request = $this->getRequest();
118
        $this->request = $request->withAddedHeader($header, $value);
119
    }
120
121
    /** @When I set the headers: */
122
    final public function set_headers(TableNode $headers): void
123
    {
124
        $request = $this->getRequest();
125
126
        foreach ($headers->getRowsHash() as $header => $value) {
127
            $request = $request->withHeader($header, $value);
128
        }
129
130
        $this->request = $request;
131
    }
132
133
    /** @When I send the request */
134
    final public function send_request(): void
135
    {
136
        $request = $this->getRequest();
137
138
        if (!empty($this->query)) {
139
            $uri = $request->getUri();
140
            $current = $uri->getQuery();
141
            $query = http_build_query($this->query);
142
143
            if (!empty($current)) {
144
                $query = "{$current}&{$query}";
145
            }
146
147
            $uri = $uri->withQuery($query);
148
            $request = $request->withUri($uri);
149
        }
150
151
        $client = $this->builder->createClient($this->client);
152
        $client->sendRequest($request);
153
    }
154
155
    /** @AfterScenario @api */
156
    final public function clearCache(): void
157
    {
158
        $this->query = [];
159
        $this->request = null;
160
    }
161
162
    final public function getRequest(): RequestInterface
163
    {
164
        if (null === $this->request) {
165
            throw new RuntimeException('No request initiated');
166
        }
167
168
        return $this->request;
169
    }
170
171
    protected function getDefaultContentType(): string
172
    {
173
        return 'application/json';
174
    }
175
}
176