Skip to content

Commit 0c17a38

Browse files
committed
Replace PHP-HTTP usage with PSR-17
1 parent cc8f9dc commit 0c17a38

12 files changed

+137
-70
lines changed

CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5-
## 2.2.0 / Unreleased
6-
### Added:
5+
## 2.2.0 / 2021-11-15
76
### Changed:
7+
- Uses PSR-17 internally instead of the deprecated PHP-HTTP `MessageFactory`
88
### Deprecated:
99
- Usage of `Api:api` with not fully qualified class name
1010
- Usage of `Api::HTTP_RESPONSE_*` constants
1111
- Usage of response format other than `json`
1212
- Passing a string as `$params` to the methods `create` and `update` of the `PullRequests`, `BranchRestrictions`, `Pipelines`, and `Repository` API
1313
- `ClientInterface`, use `Client` instead
1414
- Passing a string as `$params` to the `request` method of `Client`
15+
- Usage of `Client::getMessageFactory` use `Client::getRequestFactory` instead
16+
- Passing `Http\Message\MessageFactory` to `HttpPluginClientBuilder`
1517

1618
## 2.1.0 / 2021-07-23
1719

composer.json

+10-3
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@
2323
"php-http/discovery": "^1.0",
2424
"php-http/client-implementation": "^1.0",
2525
"php-http/client-common": "^2.0",
26-
"symfony/deprecation-contracts": "^2.2 || ^3.0"
26+
"symfony/deprecation-contracts": "^2.2 || ^3.0",
27+
"psr/http-factory-implementation": "^1.0"
2728
},
2829
"require-dev": {
2930
"phpunit/phpunit":"^7.5|^8|^9",
3031
"php-http/mock-client": " ^1.2",
3132
"squizlabs/php_codesniffer": "^3.5",
32-
"php-http/guzzle6-adapter": "^2.0",
33-
"phpstan/phpstan": "^0.12.90|^1"
33+
"phpstan/phpstan": "^0.12.90|^1",
34+
"nyholm/psr7": "^1.6.1",
35+
"php-http/message-factory": "^1.0"
3436
},
3537
"replace": {
3638
"gentle/bitbucket-api": "*"
@@ -53,5 +55,10 @@
5355
"scripts": {
5456
"style": "php vendor/bin/phpcs --standard=psr2 lib/ test --ignore=*/HistoryVersionBridge.php",
5557
"test": "php vendor/bin/phpunit"
58+
},
59+
"config": {
60+
"allow-plugins": {
61+
"php-http/discovery": true
62+
}
5663
}
5764
}

lib/Bitbucket/API/Http/Client.php

+18-8
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
use Bitbucket\API\Http\Plugin\HistoryPlugin;
1515
use Http\Client\Common\HttpMethodsClient;
1616
use Http\Client\Common\Plugin;
17-
use Http\Discovery\UriFactoryDiscovery;
18-
use Http\Message\MessageFactory;
17+
use Http\Discovery\Psr17FactoryDiscovery;
18+
use Psr\Http\Message\RequestFactoryInterface;
1919
use Psr\Http\Message\RequestInterface;
2020
use Psr\Http\Message\ResponseInterface;
21+
use Psr\Http\Message\StreamFactoryInterface;
2122

2223
/**
2324
* @author Alexandru G. <[email protected]>
@@ -40,8 +41,10 @@ class Client implements ClientInterface
4041

4142
/** @var HttpPluginClientBuilder */
4243
private $httpClientBuilder;
43-
/** @var MessageFactory */
44-
private $messageFactory;
44+
/** @var RequestFactoryInterface */
45+
private $requestFactory;
46+
/** @var StreamFactoryInterface */
47+
private $streamFactory;
4548
/** @var HistoryPlugin */
4649
private $responseHistory;
4750

@@ -55,7 +58,7 @@ public function __construct(array $options = array(), HttpPluginClientBuilder $h
5558
$this->httpClientBuilder = $httpClientBuilder ?: new HttpPluginClientBuilder();
5659

5760
$this->httpClientBuilder->addPlugin(
58-
new Plugin\AddHostPlugin(UriFactoryDiscovery::find()->createUri($this->options['base_url']))
61+
new Plugin\AddHostPlugin(Psr17FactoryDiscovery::findUriFactory()->createUri($this->options['base_url']))
5962
);
6063
$this->httpClientBuilder->addPlugin(new Plugin\RedirectPlugin());
6164
$this->httpClientBuilder->addPlugin(new Plugin\HeaderDefaultsPlugin([
@@ -65,7 +68,8 @@ public function __construct(array $options = array(), HttpPluginClientBuilder $h
6568

6669
$this->setApiVersion($this->options['api_version']);
6770

68-
$this->messageFactory = $this->httpClientBuilder->getMessageFactory();
71+
$this->requestFactory = $this->httpClientBuilder->getRequestFactory();
72+
$this->streamFactory = Psr17FactoryDiscovery::findStreamFactory();
6973
}
7074

7175
/**
@@ -124,7 +128,7 @@ public function request($endpoint, $params = array(), $method = 'GET', array $he
124128
}
125129
}
126130

127-
$body = null;
131+
$body = '';
128132
if (is_string($paramsString) && $paramsString !== null) {
129133
$body = $paramsString;
130134
}
@@ -140,7 +144,13 @@ public function request($endpoint, $params = array(), $method = 'GET', array $he
140144
$endpoint .= (strpos($endpoint, '?') === false ? '?' : '&').'format='.$this->getResponseFormat();
141145
}
142146

143-
$request = $this->messageFactory->createRequest($method, $endpoint, $headers, $body);
147+
$request = $this->requestFactory
148+
->createRequest($method, $endpoint)
149+
->withBody($this->streamFactory->createStream($body));
150+
151+
foreach ($headers as $name => $value) {
152+
$request = $request->withHeader($name, $value);
153+
}
144154

145155
return $this->getClient()->sendRequest($request);
146156
}

lib/Bitbucket/API/Http/HttpPluginClientBuilder.php

+52-10
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,56 @@
66
use Http\Client\Common\HttpMethodsClient;
77
use Http\Client\Common\Plugin;
88
use Http\Client\Common\PluginClient;
9-
use Http\Client\HttpClient;
10-
use Http\Discovery\HttpClientDiscovery;
119
use Http\Discovery\MessageFactoryDiscovery;
10+
use Http\Discovery\Psr17FactoryDiscovery;
11+
use Http\Discovery\Psr18ClientDiscovery;
1212
use Http\Message\MessageFactory;
13+
use Psr\Http\Client\ClientInterface;
14+
use Psr\Http\Message\RequestFactoryInterface;
15+
use Psr\Http\Message\StreamFactoryInterface;
1316

1417
class HttpPluginClientBuilder
1518
{
16-
/** @var HttpClient */
19+
/** @var ClientInterface */
1720
private $httpClient;
1821
/** @var HttpMethodsClient|null */
1922
private $pluginClient;
20-
/** @var MessageFactory */
21-
private $messageFactory;
23+
/** @var MessageFactory|RequestFactoryInterface */
24+
private $requestFactory;
25+
/** @var StreamFactoryInterface */
26+
private $streamFactory;
2227
/** @var Plugin[] */
2328
private $plugins = [];
2429

25-
public function __construct(HttpClient $httpClient = null, MessageFactory $messageFactory = null)
30+
/**
31+
* @param MessageFactory|RequestFactoryInterface|null $requestFactory
32+
*/
33+
public function __construct(ClientInterface $httpClient = null, $requestFactory = null, StreamFactoryInterface $streamFactory = null)
2634
{
27-
$this->httpClient = $httpClient ?: HttpClientDiscovery::find();
28-
$this->messageFactory = $messageFactory ?: MessageFactoryDiscovery::find();
35+
$requestFactory = $requestFactory ?? Psr17FactoryDiscovery::findRequestFactory();
36+
if ($requestFactory instanceof MessageFactory) {
37+
// Use same format as symfony/deprecation-contracts.
38+
@trigger_error(sprintf(
39+
'Since %s %s: %s is deprecated, use %s instead.',
40+
'private-packagist/bitbucket-api',
41+
'2.2.0',
42+
'\Http\Message\MessageFactory',
43+
RequestFactoryInterface::class
44+
), \E_USER_DEPRECATED);
45+
} elseif (!$requestFactory instanceof RequestFactoryInterface) {
46+
/** @var mixed $requestFactory value unknown; set to mixed, prevent PHPStan complaining about guard clauses */
47+
throw new \TypeError(sprintf(
48+
'%s::__construct(): Argument #2 ($requestFactory) must be of type %s|%s, %s given',
49+
self::class,
50+
'\Http\Message\MessageFactory',
51+
RequestFactoryInterface::class,
52+
is_object($requestFactory) ? get_class($requestFactory) : gettype($requestFactory)
53+
));
54+
}
55+
56+
$this->httpClient = $httpClient ?: Psr18ClientDiscovery::find();
57+
$this->requestFactory = $requestFactory;
58+
$this->streamFactory = $streamFactory ?? Psr17FactoryDiscovery::findStreamFactory();
2959
}
3060

3161
/**
@@ -79,7 +109,8 @@ public function getHttpClient()
79109
if (!$this->pluginClient) {
80110
$this->pluginClient = new HttpMethodsClient(
81111
new PluginClient($this->httpClient, $this->plugins),
82-
$this->messageFactory
112+
$this->requestFactory,
113+
$this->streamFactory
83114
);
84115
}
85116

@@ -88,9 +119,20 @@ public function getHttpClient()
88119

89120
/**
90121
* @return MessageFactory
122+
* @deprecated Use getRequestFactory instead. message will be removed with 3.0
91123
*/
92124
public function getMessageFactory()
93125
{
94-
return $this->messageFactory;
126+
return $this->requestFactory instanceof MessageFactory
127+
? $this->requestFactory
128+
: MessageFactoryDiscovery::find();
129+
}
130+
131+
/**
132+
* @return RequestFactoryInterface
133+
*/
134+
public function getRequestFactory()
135+
{
136+
return $this->requestFactory;
95137
}
96138
}

lib/Bitbucket/API/Http/Plugin/ApiOneCollectionPlugin.php

+12-13
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
namespace Bitbucket\API\Http\Plugin;
1111

1212
use Http\Client\Common\Plugin;
13-
use Http\Discovery\MessageFactoryDiscovery;
14-
use Http\Message\ResponseFactory;
13+
use Http\Discovery\Psr17FactoryDiscovery;
1514
use Psr\Http\Message\RequestInterface;
1615
use Psr\Http\Message\ResponseInterface;
16+
use Psr\Http\Message\StreamFactoryInterface;
1717

1818
/**
1919
* Helper for `Pager`
@@ -28,8 +28,8 @@ class ApiOneCollectionPlugin implements Plugin
2828
{
2929
use Plugin\VersionBridgePlugin;
3030

31-
/** @var ResponseFactory */
32-
private $responseFactory;
31+
/** @var StreamFactoryInterface */
32+
private $streamFactory;
3333

3434
/** @var array */
3535
private $urlQueryComponents;
@@ -40,9 +40,13 @@ class ApiOneCollectionPlugin implements Plugin
4040
/** @var array */
4141
private $content;
4242

43-
public function __construct(ResponseFactory $responseFactory = null)
43+
/**
44+
* @param object|null $responseFactory This argument is deprecated and will be removed in 3.0
45+
*/
46+
public function __construct($responseFactory = null)
4447
{
45-
$this->responseFactory = $responseFactory ?: MessageFactoryDiscovery::find();
48+
$this->streamFactory = Psr17FactoryDiscovery::findStreamFactory();
49+
unset($responseFactory);
4650
}
4751

4852
/**
@@ -61,13 +65,8 @@ protected function doHandleRequest(RequestInterface $request, callable $next, ca
6165
$request
6266
);
6367

64-
return $this->responseFactory->createResponse(
65-
$response->getStatusCode(),
66-
$response->getReasonPhrase(),
67-
$response->getHeaders(),
68-
json_encode($content),
69-
$response->getProtocolVersion()
70-
);
68+
return $response
69+
->withBody($this->streamFactory->createStream(json_encode($content)));
7170
}
7271
}
7372

lib/Bitbucket/API/Http/Plugin/ApiVersionPlugin.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Http\Client\Common\Plugin;
66
use Http\Promise\Promise;
77
use Psr\Http\Message\RequestInterface;
8+
use Psr\Http\Message\ResponseInterface;
89

910
class ApiVersionPlugin implements Plugin
1011
{
@@ -26,7 +27,7 @@ public function __construct($version)
2627
* @param callable $next Next middleware in the chain, the request is passed as the first argument
2728
* @param callable $first First middleware in the chain, used to to restart a request
2829
*
29-
* @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient).
30+
* @return Promise<ResponseInterface> Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient).
3031
*/
3132
protected function doHandleRequest(RequestInterface $request, callable $next, callable $first)
3233
{

lib/Bitbucket/API/Http/Response/Pager.php

+14-14
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
namespace Bitbucket\API\Http\Response;
1111

1212
use Bitbucket\API\Http\HttpPluginClientBuilder;
13-
use Http\Discovery\MessageFactoryDiscovery;
14-
use Http\Message\MessageFactory;
13+
use Http\Discovery\Psr17FactoryDiscovery;
1514
use Psr\Http\Message\ResponseInterface;
15+
use Psr\Http\Message\StreamFactoryInterface;
1616

1717
/**
1818
* @author Alexandru Guzinschi <[email protected]>
@@ -21,22 +21,24 @@ class Pager implements PagerInterface
2121
{
2222
/** @var HttpPluginClientBuilder */
2323
private $httpPluginClientBuilder;
24-
/** @var MessageFactory */
25-
private $messageFactory;
24+
/** @var StreamFactoryInterface */
25+
private $streamFactory;
2626
/** @var ResponseInterface */
2727
private $response;
2828

2929
/**
3030
* @param HttpPluginClientBuilder $httpPluginClientBuilder
3131
* @param ResponseInterface $response
32-
* @param MessageFactory $messageFactory
32+
* @param object|null $messageFactory This argument is deprecated and will be removed in 3.0.0
33+
* @param StreamFactoryInterface|null $streamFactory
3334
*
3435
* @throws \UnexpectedValueException
3536
*/
3637
public function __construct(
3738
HttpPluginClientBuilder $httpPluginClientBuilder,
3839
ResponseInterface $response,
39-
MessageFactory $messageFactory = null
40+
$messageFactory = null,
41+
StreamFactoryInterface $streamFactory = null
4042
) {
4143
/** @var ResponseInterface $response */
4244
if ($response->getStatusCode() >= 400) {
@@ -45,7 +47,9 @@ public function __construct(
4547

4648
$this->httpPluginClientBuilder = $httpPluginClientBuilder;
4749
$this->response = $response;
48-
$this->messageFactory = $messageFactory ? : MessageFactoryDiscovery::find();
50+
$this->streamFactory = $streamFactory ?: Psr17FactoryDiscovery::findStreamFactory();
51+
52+
unset($messageFactory);
4953
}
5054

5155
/**
@@ -117,13 +121,9 @@ public function fetchAll()
117121
}
118122

119123
$content['values'] = $values;
120-
$this->response = $this->messageFactory->createResponse(
121-
$this->response->getStatusCode(),
122-
$this->response->getReasonPhrase(),
123-
$this->response->getHeaders(),
124-
json_encode($content),
125-
$this->response->getProtocolVersion()
126-
);
124+
125+
$this->response = $this->response
126+
->withBody($this->streamFactory->createStream(json_encode($content)));
127127

128128
return $this->response;
129129
}

0 commit comments

Comments
 (0)