RequestBuilder   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 3
dl 0
loc 217
ccs 64
cts 64
cp 1
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A setBaseUrl() 0 8 1
A replacePath() 0 6 1
A addQuery() 0 9 2
A addQueryName() 0 8 2
A addHeader() 0 5 1
A setBody() 0 4 1
A addField() 0 9 2
A addPart() 0 9 1
B build() 0 28 7
1
<?php
2
/*
3
 * Copyright (c) Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
declare(strict_types=1);
8
9
namespace Tebru\Retrofit\Internal;
10
11
use GuzzleHttp\Psr7;
12
use GuzzleHttp\Psr7\MultipartStream;
13
use GuzzleHttp\Psr7\Request;
14
use GuzzleHttp\Psr7\Uri;
15
use LogicException;
16
use Psr\Http\Message\StreamInterface;
17
18
/**
19
 * Class RequestBuilder
20
 *
21
 * @author Nate Brunette <[email protected]>
22
 */
23
final class RequestBuilder
24
{
25
    /**
26
     * The request method
27
     *
28
     * @var string
29
     */
30
    private $method;
31
32
    /**
33
     * The request [@see Uri] object
34
     *
35
     * @var Uri
36
     */
37
    private $uri;
38
39
    /**
40
     * An array of query strings that can be appended together
41
     *
42
     * @var array
43
     */
44
    private $queries = [];
45
46
    /**
47
     * An array of headers in PSR-7 format
48
     *
49
     * @var array
50
     */
51
    private $headers;
52
53
    /**
54
     * The request body
55
     *
56
     * @var StreamInterface
57
     */
58
    private $body;
59
60
    /**
61
     * An array of request body fields that can be appended together
62
     *
63
     * @var array
64
     */
65
    private $fields = [];
66
67
    /**
68
     * An array of arrays of multipart parts, each with name, content, headers, and filename
69
     *
70
     * @var array[]
71
     */
72
    private $parts = [];
73
74
    /**
75
     * Constructor
76
     *
77
     * @param string $method
78
     * @param string $baseUrl
79
     * @param string $uri
80
     * @param array $headers
81
     */
82 65
    public function __construct(string $method, string $baseUrl, string $uri, array $headers)
83
    {
84 65
        $this->method = $method;
85 65
        $this->uri = new Uri($baseUrl.$uri);
86 65
        $this->headers = $headers;
87 65
    }
88
89
    /**
90
     * Set the uri base url
91
     *
92
     * @param string $value
93
     */
94 4
    public function setBaseUrl(string $value): void
95
    {
96 4
        $uri = new Uri($value);
97 4
        $this->uri = $this->uri
98 4
            ->withScheme($uri->getScheme())
99 4
            ->withHost($uri->getHost())
100 4
            ->withPort($uri->getPort());
101 4
    }
102
103
    /**
104
     * Replace a url path placeholder with a value
105
     *
106
     * @param string $name
107
     * @param string $value
108
     */
109 4
    public function replacePath(string $name, string $value): void
110
    {
111 4
        $path = rawurldecode($this->uri->getPath());
112 4
        $path = str_replace(sprintf('{%s}', $name), $value, $path);
113 4
        $this->uri = $this->uri->withPath($path);
114 4
    }
115
116
    /**
117
     * Add a query string; if encoded, decodes to be encoded later
118
     *
119
     * @param string $name
120
     * @param string $value
121
     * @param bool $encoded
122
     */
123 9
    public function addQuery(string $name, string $value, bool $encoded): void
124
    {
125 9
        $name = rawurlencode($name);
126 9
        if ($encoded === false) {
127 8
            $value = rawurlencode($value);
128
        }
129
130 9
        $this->queries[] = $name.'='.$value;
131 9
    }
132
133
    /**
134
     * Adds a query string without value; if encoded, decodes to be encoded later
135
     *
136
     * @param string $value
137
     * @param bool $encoded
138
     */
139 5
    public function addQueryName(string $value, bool $encoded): void
140
    {
141 5
        if ($encoded === false) {
142 4
            $value = rawurlencode($value);
143
        }
144
145 5
        $this->queries[] = $value;
146 5
    }
147
148
    /**
149
     * Add a header in PSR-7 format
150
     *
151
     * @param string $name
152
     * @param string $value
153
     */
154 8
    public function addHeader(string $name, string $value): void
155
    {
156 8
        $name = strtolower($name);
157 8
        $this->headers[$name][] = $value;
158 8
    }
159
160
    /**
161
     * Set the request body
162
     *
163
     * @param StreamInterface $body
164
     */
165 6
    public function setBody(StreamInterface $body): void
166
    {
167 6
        $this->body = $body;
168 6
    }
169
170
    /**
171
     * Add a field; if not encoded, encodes first
172
     *
173
     * @param string $name
174
     * @param string $value
175
     * @param bool $encoded
176
     */
177 8
    public function addField(string $name, string $value, bool $encoded): void
178
    {
179 8
        $name = rawurlencode($name);
180 8
        if ($encoded === false) {
181 7
            $value = rawurlencode($value);
182
        }
183
184 8
        $this->fields[] = $name.'='.$value;
185 8
    }
186
187
    /**
188
     * Add a multipart part
189
     *
190
     * @param string $name
191
     * @param StreamInterface $contents
192
     * @param array $headers
193
     * @param null|string $filename
194
     */
195 9
    public function addPart(string $name, StreamInterface $contents, array $headers = [], ?string $filename = null): void
196
    {
197 9
        $this->parts[] = [
198 9
            'name' => $name,
199 9
            'contents' => $contents,
200 9
            'headers' => $headers,
201 9
            'filename' => $filename,
202
        ];
203 9
    }
204
205
    /**
206
     * Create a PSR-7 request
207
     *
208
     * @return Request
209
     * @throws \LogicException
210
     */
211 26
    public function build(): Request
212
    {
213 26
        $uri = $this->uri;
214 26
        if ($this->queries !== []) {
215 5
            $query = implode('&', $this->queries);
216 5
            $uri = $this->uri->getQuery() === ''
217 3
                ? $this->uri->withQuery($query)
218 5
                : $this->uri->withQuery($query.'&'.$this->uri->getQuery());
219
        }
220
221 26
        if ($this->fields !== []) {
222 4
            if ($this->body !== null) {
223 1
                throw new LogicException('Retrofit: Cannot mix @Field and @Body annotations.');
224
            }
225
226 3
            $this->body = Psr7\stream_for(implode('&', $this->fields));
227
        }
228
229 25
        if ($this->parts !== []) {
230 4
            if ($this->body !== null) {
231 1
                throw new LogicException('Retrofit: Cannot mix @Part and @Body annotations.');
232
            }
233
234 3
            $this->body = new MultipartStream($this->parts);
235
        }
236
237 24
        return new Request($this->method, $uri, $this->headers, $this->body);
238
    }
239
}
240