Skip to content

Commit 0a46ae1

Browse files
authored
Merge pull request #191 from fbourigault/httplug
Decouple from Buzz
2 parents eea2a84 + e49bc73 commit 0a46ae1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1012
-1022
lines changed

README.md

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,16 @@ Based on [php-github-api](https://github.com/m4tthumphrey/php-github-api) and co
77

88
Installation
99
------------
10-
1. Install Composer
1110

12-
```bash
13-
$ curl -sS https://getcomposer.org/installer | php
14-
$ sudo mv composer.phar /usr/local/bin/composer
15-
```
11+
Via [composer](https://getcomposer.org)
1612

17-
2. Add the following to your require block in composer.json config.
18-
19-
> Note: be careful when using the `dev-master` tag as this may have unexpected results depending on your version of
20-
Gitlab. See the Versioning section below for more information.
21-
22-
`php composer.phar require m4tthumphrey/php-gitlab-api:dev-master`
13+
```bash
14+
composer require m4tthumphrey/php-gitlab-api php-http/guzzle6-adapter
15+
```
2316

24-
3. Include Composer's autoloader:
17+
Why `php-http/guzzle6-adapter`? We are decoupled from any HTTP messaging client with help by [HTTPlug](http://httplug.io).
2518

26-
```php
27-
require_once dirname(__DIR__).'/vendor/autoload.php';
28-
```
19+
You can visit [HTTPlug for library users](http://docs.php-http.org/en/latest/httplug/users.html) to get more information about installing HTTPlug related packages.
2920

3021
Versioning
3122
----------
@@ -41,8 +32,9 @@ General API Usage
4132
-----------------
4233

4334
```php
44-
$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/'); // change here
45-
$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here
35+
$client = \Gitlab\Client::create('http://git.yourdomain.com')
36+
->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN)
37+
;
4638

4739
$project = $client->api('projects')->create('My Project', array(
4840
'description' => 'This is a project',
@@ -57,8 +49,9 @@ Model Usage
5749
You can also use the library in an object oriented manner:
5850

5951
```php
60-
$client = new \Gitlab\Client('http://git.yourdomain.com/api/v3/'); // change here
61-
$client->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN); // change here
52+
$client = \Gitlab\Client::create('http://git.yourdomain.com')
53+
->authenticate('your_gitlab_token_here', \Gitlab\Client::AUTH_URL_TOKEN)
54+
;
6255

6356
# Creating a new project
6457
$project = \Gitlab\Model\Project::create($client, 'My Project', array(

UPGRADE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# UPGRADE FROM 8.0 to 9.0
2+
3+
Since 9.0, lib no longer use buzz 0.7+, instead it has an HTTPlug abstraction layer.
4+
5+
## `Gitlab\Client` changes
6+
7+
* The constructor no longer allow to specify base url. Use `setUrl` or `Client::create` instead.
8+
* The default url is set to `https://gitlab.com`.
9+
* The `$options` constructor argument have been removed, the `getOption` and `setOption` methods have been removed.
10+
See [documentation](doc/customize.md) to know how to customize the client timeout and how to use a custom user agent.
11+
* The `setBaseUrl` and `getBaseUrl` methods have been removed. Use `setUrl` instead.
12+
* The `clearHeaders` and `setHeaders` methods have been removed. See [documentation](doc/customize.md) to know how use custom headers.
13+
* The `setHttpClient` method have been removed. Use a `Gitlab\HttpClient\Builder` instead.
14+
* The `getHttpClient` method return type is changed to `Http\Client\Common\HttpMethodsClient`.

composer.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@
2222
],
2323
"require": {
2424
"php": "^5.6 || ^7.0",
25-
"ext-curl": "*",
26-
"ext-xml": "*",
27-
"kriswallsmith/buzz": ">=0.7"
25+
"php-http/client-common": "^1.5",
26+
"php-http/client-implementation": "^1.0",
27+
"php-http/discovery": "^1.2",
28+
"php-http/httplug": "^1.1",
29+
"php-http/multipart-stream-builder": "^1.0"
2830
},
2931
"require-dev": {
32+
"guzzlehttp/psr7": "^1.2",
33+
"php-http/guzzle6-adapter": "^1.0",
34+
"php-http/mock-client": "^1.0",
3035
"phpunit/phpunit": "~4.5"
3136
},
3237
"autoload": {

doc/customize.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## Customize `php-gitlab-api`
2+
3+
### How to set custom headers (including `User-Agent`)?
4+
5+
By providing a `Gitlab\HttpClient\Builder` to the `Gitlab\Client` constructor, you can customize the HTTP client.
6+
7+
```php
8+
$plugin = new Http\Client\Common\Plugin\HeaderSetPlugin([
9+
'User-Agent' => 'Foobar',
10+
]);
11+
12+
$builder = new Gitlab\HttpClient\Builder();
13+
$builder->addPlugin($plugin);
14+
15+
$client = new Gitlab\Client($builder);
16+
```
17+
Read more about [HTTPlug plugins here](http://docs.php-http.org/en/latest/plugins/introduction.html#how-it-works).
18+
19+
### How to customize the HTTP client timeout?
20+
As timeout configuration is not compatible with HTTP client abstraction, you have to create the `Gitlab\Client` with
21+
an explicit HTTP client implementation.
22+
23+
```php
24+
$httpClient = Http\Adapter\Guzzle6::createWithConfig([
25+
'timeout' => 1.0
26+
]);
27+
$client = Gitlab\Client::createWithHttpClient($httpClient);
28+
```

lib/Gitlab/Api/AbstractApi.php

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
<?php namespace Gitlab\Api;
22

33
use Gitlab\Client;
4+
use Gitlab\HttpClient\Message\ResponseMediator;
5+
use Http\Discovery\StreamFactoryDiscovery;
6+
use Http\Message\MultipartStream\MultipartStreamBuilder;
7+
use Http\Message\StreamFactory;
48

59
/**
610
* Abstract class for Api classes
@@ -23,12 +27,19 @@ abstract class AbstractApi implements ApiInterface
2327
*/
2428
protected $client;
2529

30+
/**
31+
* @var StreamFactory
32+
*/
33+
private $streamFactory;
34+
2635
/**
2736
* @param Client $client
37+
* @param StreamFactory|null $streamFactory
2838
*/
29-
public function __construct(Client $client)
39+
public function __construct(Client $client, StreamFactory $streamFactory = null)
3040
{
3141
$this->client = $client;
42+
$this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
3243
}
3344

3445
/**
@@ -48,9 +59,11 @@ public function configure()
4859
*/
4960
protected function get($path, array $parameters = array(), $requestHeaders = array())
5061
{
51-
$response = $this->client->getHttpClient()->get($path, $parameters, $requestHeaders);
62+
$path = $this->preparePath($path, $parameters);
5263

53-
return $response->getContent();
64+
$response = $this->client->getHttpClient()->get($path, $requestHeaders);
65+
66+
return ResponseMediator::getContent($response);
5467
}
5568

5669
/**
@@ -62,9 +75,35 @@ protected function get($path, array $parameters = array(), $requestHeaders = arr
6275
*/
6376
protected function post($path, array $parameters = array(), $requestHeaders = array(), array $files = array())
6477
{
65-
$response = $this->client->getHttpClient()->post($path, $parameters, $requestHeaders, $files);
66-
67-
return $response->getContent();
78+
$path = $this->preparePath($path);
79+
80+
$body = null;
81+
if (empty($files) && !empty($parameters)) {
82+
$body = $this->streamFactory->createStream(http_build_query($parameters));
83+
$requestHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
84+
} elseif (!empty($files)) {
85+
$builder = new MultipartStreamBuilder($this->streamFactory);
86+
87+
foreach ($parameters as $name => $value) {
88+
$builder->addResource($name, $value);
89+
}
90+
91+
foreach ($files as $name => $file) {
92+
$builder->addResource($name, fopen($file, 'r'), [
93+
'headers' => [
94+
'Content-Type' => $this->guessContentType($file),
95+
],
96+
'filename' => basename($file),
97+
]);
98+
}
99+
100+
$body = $builder->build();
101+
$requestHeaders['Content-Type'] = 'multipart/form-data; boundary='.$builder->getBoundary();
102+
}
103+
104+
$response = $this->client->getHttpClient()->post($path, $requestHeaders, $body);
105+
106+
return ResponseMediator::getContent($response);
68107
}
69108

70109
/**
@@ -75,9 +114,13 @@ protected function post($path, array $parameters = array(), $requestHeaders = ar
75114
*/
76115
protected function patch($path, array $parameters = array(), $requestHeaders = array())
77116
{
78-
$response = $this->client->getHttpClient()->patch($path, $parameters, $requestHeaders);
117+
$path = $this->preparePath($path);
118+
119+
$body = empty($parameters) ? null : $this->streamFactory->createStream(http_build_query($parameters));
79120

80-
return $response->getContent();
121+
$response = $this->client->getHttpClient()->patch($path, $requestHeaders, $body);
122+
123+
return ResponseMediator::getContent($response);
81124
}
82125

83126
/**
@@ -88,9 +131,13 @@ protected function patch($path, array $parameters = array(), $requestHeaders = a
88131
*/
89132
protected function put($path, array $parameters = array(), $requestHeaders = array())
90133
{
91-
$response = $this->client->getHttpClient()->put($path, $parameters, $requestHeaders);
134+
$path = $this->preparePath($path);
135+
136+
$body = empty($parameters) ? null : $this->streamFactory->createStream(http_build_query($parameters));
137+
138+
$response = $this->client->getHttpClient()->put($path, $requestHeaders, $body);
92139

93-
return $response->getContent();
140+
return ResponseMediator::getContent($response);
94141
}
95142

96143
/**
@@ -101,9 +148,13 @@ protected function put($path, array $parameters = array(), $requestHeaders = arr
101148
*/
102149
protected function delete($path, array $parameters = array(), $requestHeaders = array())
103150
{
104-
$response = $this->client->getHttpClient()->delete($path, $parameters, $requestHeaders);
151+
$path = $this->preparePath($path);
105152

106-
return $response->getContent();
153+
$body = empty($parameters) ? null : $this->streamFactory->createStream(http_build_query($parameters));
154+
155+
$response = $this->client->getHttpClient()->delete($path, $requestHeaders, $body);
156+
157+
return ResponseMediator::getContent($response);
107158
}
108159

109160
/**
@@ -126,4 +177,28 @@ protected function encodePath($path)
126177

127178
return str_replace('.', '%2E', $path);
128179
}
180+
181+
private function preparePath($path, array $parameters = [])
182+
{
183+
if (count($parameters) > 0) {
184+
$path .= '?'.http_build_query($parameters);
185+
}
186+
187+
return $path;
188+
}
189+
190+
/**
191+
* @param $file
192+
*
193+
* @return string
194+
*/
195+
private function guessContentType($file)
196+
{
197+
if (!class_exists(\finfo::class, false)) {
198+
return 'application/octet-stream';
199+
}
200+
$finfo = new \finfo(FILEINFO_MIME_TYPE);
201+
202+
return $finfo->file($file);
203+
}
129204
}

0 commit comments

Comments
 (0)