2
2
3
3
namespace Redmine \Api ;
4
4
5
+ use Closure ;
6
+ use InvalidArgumentException ;
5
7
use Redmine \Api ;
6
8
use Redmine \Client \Client ;
7
9
use Redmine \Exception ;
8
10
use Redmine \Exception \SerializerException ;
11
+ use Redmine \Http \HttpClient ;
12
+ use Redmine \Http \Response ;
9
13
use Redmine \Serializer \JsonSerializer ;
10
14
use Redmine \Serializer \PathSerializer ;
11
15
use Redmine \Serializer \XmlSerializer ;
@@ -23,9 +27,52 @@ abstract class AbstractApi implements Api
23
27
*/
24
28
protected $ client ;
25
29
26
- public function __construct (Client $ client )
30
+ /**
31
+ * @var HttpClient
32
+ */
33
+ private $ httpClient ;
34
+
35
+ /**
36
+ * @var Response
37
+ */
38
+ private $ lastResponse ;
39
+
40
+ /**
41
+ * @param Client|HttpClient $client
42
+ */
43
+ public function __construct ($ client )
27
44
{
28
- $ this ->client = $ client ;
45
+ if (! is_object ($ client ) || (! $ client instanceof Client && ! $ client instanceof HttpClient)) {
46
+ throw new InvalidArgumentException (sprintf (
47
+ '%s(): Argument #1 ($client) must be of type %s or %s, `%s` given ' ,
48
+ __METHOD__ ,
49
+ Client::class,
50
+ HttpClient::class,
51
+ (is_object ($ client )) ? get_class ($ client ) : gettype ($ client )
52
+ ));
53
+ }
54
+
55
+ if ($ client instanceof Client) {
56
+ $ this ->client = $ client ;
57
+ }
58
+
59
+ $ httpClient = $ client ;
60
+
61
+ if (! $ httpClient instanceof HttpClient) {
62
+ $ httpClient = $ this ->handleClient ($ client );
63
+ }
64
+
65
+ $ this ->httpClient = $ httpClient ;
66
+ }
67
+
68
+ final protected function getHttpClient (): HttpClient
69
+ {
70
+ return $ this ->httpClient ;
71
+ }
72
+
73
+ final protected function getLastResponse (): Response
74
+ {
75
+ return $ this ->lastResponse !== null ? $ this ->lastResponse : $ this ->createResponse (0 , '' , '' );
29
76
}
30
77
31
78
/**
@@ -40,7 +87,13 @@ public function lastCallFailed()
40
87
{
41
88
@trigger_error ('` ' . __METHOD__ . '()` is deprecated since v2.1.0, use \Redmine\Client\Client::getLastResponseStatusCode() instead. ' , E_USER_DEPRECATED );
42
89
43
- $ code = $ this ->client ->getLastResponseStatusCode ();
90
+ if ($ this ->lastResponse !== null ) {
91
+ $ code = $ this ->lastResponse ->getStatusCode ();
92
+ } elseif ($ this ->client !== null ) {
93
+ $ code = $ this ->client ->getLastResponseStatusCode ();
94
+ } else {
95
+ $ code = 0 ;
96
+ }
44
97
45
98
return 200 !== $ code && 201 !== $ code ;
46
99
}
@@ -55,10 +108,10 @@ public function lastCallFailed()
55
108
*/
56
109
protected function get ($ path , $ decodeIfJson = true )
57
110
{
58
- $ this ->client -> requestGet ( strval ($ path ));
111
+ $ this ->lastResponse = $ this -> getHttpClient ()-> request ( ' GET ' , strval ($ path ));
59
112
60
- $ body = $ this ->client -> getLastResponseBody ();
61
- $ contentType = $ this ->client -> getLastResponseContentType ();
113
+ $ body = $ this ->lastResponse -> getBody ();
114
+ $ contentType = $ this ->lastResponse -> getContentType ();
62
115
63
116
// if response is XML, return a SimpleXMLElement object
64
117
if ('' !== $ body && 0 === strpos ($ contentType , 'application/xml ' )) {
@@ -82,16 +135,17 @@ protected function get($path, $decodeIfJson = true)
82
135
* @param string $path
83
136
* @param string $data
84
137
*
85
- * @return string|false
138
+ * @return string|SimpleXMLElement| false
86
139
*/
87
140
protected function post ($ path , $ data )
88
141
{
89
- $ this ->client -> requestPost ( $ path , $ data );
142
+ $ this ->lastResponse = $ this -> getHttpClient ()-> request ( ' POST ' , strval ( $ path) , $ data );
90
143
91
- $ body = $ this ->client ->getLastResponseBody ();
144
+ $ body = $ this ->lastResponse ->getBody ();
145
+ $ contentType = $ this ->lastResponse ->getContentType ();
92
146
93
147
// if response is XML, return a SimpleXMLElement object
94
- if ('' !== $ body && 0 === strpos ($ this -> client -> getLastResponseContentType () , 'application/xml ' )) {
148
+ if ('' !== $ body && 0 === strpos ($ contentType , 'application/xml ' )) {
95
149
return new SimpleXMLElement ($ body );
96
150
}
97
151
@@ -104,16 +158,17 @@ protected function post($path, $data)
104
158
* @param string $path
105
159
* @param string $data
106
160
*
107
- * @return string|false
161
+ * @return string|SimpleXMLElement
108
162
*/
109
163
protected function put ($ path , $ data )
110
164
{
111
- $ this ->client -> requestPut ( $ path , $ data );
165
+ $ this ->lastResponse = $ this -> getHttpClient ()-> request ( ' PUT ' , strval ( $ path) , $ data );
112
166
113
- $ body = $ this ->client ->getLastResponseBody ();
167
+ $ body = $ this ->lastResponse ->getBody ();
168
+ $ contentType = $ this ->lastResponse ->getContentType ();
114
169
115
170
// if response is XML, return a SimpleXMLElement object
116
- if ('' !== $ body && 0 === strpos ($ this -> client -> getLastResponseContentType () , 'application/xml ' )) {
171
+ if ('' !== $ body && 0 === strpos ($ contentType , 'application/xml ' )) {
117
172
return new SimpleXMLElement ($ body );
118
173
}
119
174
@@ -125,13 +180,13 @@ protected function put($path, $data)
125
180
*
126
181
* @param string $path
127
182
*
128
- * @return false|SimpleXMLElement| string
183
+ * @return string
129
184
*/
130
185
protected function delete ($ path )
131
186
{
132
- $ this ->client -> requestDelete ( $ path );
187
+ $ this ->lastResponse = $ this -> getHttpClient ()-> request ( ' DELETE ' , strval ( $ path) );
133
188
134
- return $ this ->client -> getLastResponseBody ();
189
+ return $ this ->lastResponse -> getBody ();
135
190
}
136
191
137
192
/**
@@ -179,7 +234,7 @@ protected function retrieveAll($endpoint, array $params = [])
179
234
try {
180
235
$ data = $ this ->retrieveData (strval ($ endpoint ), $ params );
181
236
} catch (Exception $ e ) {
182
- if ($ this ->client -> getLastResponseBody () === '' ) {
237
+ if ($ this ->getLastResponse ()-> getBody () === '' ) {
183
238
return false ;
184
239
}
185
240
@@ -203,9 +258,9 @@ protected function retrieveAll($endpoint, array $params = [])
203
258
protected function retrieveData (string $ endpoint , array $ params = []): array
204
259
{
205
260
if (empty ($ params )) {
206
- $ this ->client -> requestGet ( $ endpoint );
261
+ $ this ->lastResponse = $ this -> getHttpClient ()-> request ( ' GET ' , strval ( $ endpoint) );
207
262
208
- return $ this ->getLastResponseBodyAsArray ( );
263
+ return $ this ->getResponseAsArray ( $ this -> lastResponse );
209
264
}
210
265
211
266
$ params = $ this ->sanitizeParams (
@@ -232,11 +287,12 @@ protected function retrieveData(string $endpoint, array $params = []): array
232
287
$ params ['limit ' ] = $ _limit ;
233
288
$ params ['offset ' ] = $ offset ;
234
289
235
- $ this ->client ->requestGet (
290
+ $ this ->lastResponse = $ this ->getHttpClient ()->request (
291
+ 'GET ' ,
236
292
PathSerializer::create ($ endpoint , $ params )->getPath ()
237
293
);
238
294
239
- $ newDataSet = $ this ->getLastResponseBodyAsArray ( );
295
+ $ newDataSet = $ this ->getResponseAsArray ( $ this -> lastResponse );
240
296
241
297
$ returnData = array_merge_recursive ($ returnData , $ newDataSet );
242
298
@@ -310,11 +366,10 @@ protected function attachCustomFieldXML(SimpleXMLElement $xml, array $fields)
310
366
*
311
367
* @throws SerializerException if response body could not be converted into array
312
368
*/
313
- private function getLastResponseBodyAsArray ( ): array
369
+ private function getResponseAsArray ( Response $ response ): array
314
370
{
315
- $ body = $ this ->client ->getLastResponseBody ();
316
-
317
- $ contentType = $ this ->client ->getLastResponseContentType ();
371
+ $ body = $ response ->getBody ();
372
+ $ contentType = $ response ->getContentType ();
318
373
$ returnData = null ;
319
374
320
375
// parse XML
@@ -330,4 +385,70 @@ private function getLastResponseBodyAsArray(): array
330
385
331
386
return $ returnData ;
332
387
}
388
+
389
+ private function handleClient (Client $ client ): HttpClient
390
+ {
391
+ $ responseFactory = Closure::fromCallable ([$ this , 'createResponse ' ]);
392
+
393
+ return new class ($ client , $ responseFactory ) implements HttpClient {
394
+ private $ client ;
395
+ private $ responseFactory ;
396
+
397
+ public function __construct (Client $ client , Closure $ responseFactory )
398
+ {
399
+ $ this ->client = $ client ;
400
+ $ this ->responseFactory = $ responseFactory ;
401
+ }
402
+
403
+ public function request (string $ method , string $ path , string $ body = '' ): Response
404
+ {
405
+ if ($ method === 'POST ' ) {
406
+ $ this ->client ->requestPost ($ path , $ body );
407
+ } elseif ($ method === 'PUT ' ) {
408
+ $ this ->client ->requestPut ($ path , $ body );
409
+ } elseif ($ method === 'DELETE ' ) {
410
+ $ this ->client ->requestDelete ($ path );
411
+ } else {
412
+ $ this ->client ->requestGet ($ path );
413
+ }
414
+
415
+ return ($ this ->responseFactory )(
416
+ $ this ->client ->getLastResponseStatusCode (),
417
+ $ this ->client ->getLastResponseContentType (),
418
+ $ this ->client ->getLastResponseBody ()
419
+ );
420
+ }
421
+ };
422
+ }
423
+
424
+ private function createResponse (int $ statusCode , string $ contentType , string $ body ): Response
425
+ {
426
+ return new class ($ statusCode , $ contentType , $ body ) implements Response {
427
+ private $ statusCode ;
428
+ private $ contentType ;
429
+ private $ body ;
430
+
431
+ public function __construct (int $ statusCode , string $ contentType , string $ body )
432
+ {
433
+ $ this ->statusCode = $ statusCode ;
434
+ $ this ->contentType = $ contentType ;
435
+ $ this ->body = $ body ;
436
+ }
437
+
438
+ public function getStatusCode (): int
439
+ {
440
+ return $ this ->statusCode ;
441
+ }
442
+
443
+ public function getContentType (): string
444
+ {
445
+ return $ this ->contentType ;
446
+ }
447
+
448
+ public function getBody (): string
449
+ {
450
+ return $ this ->body ;
451
+ }
452
+ };
453
+ }
333
454
}
0 commit comments