Skip to content

Commit e8c17f5

Browse files
committed
use HTTPlug to handle API HTTP requests
1 parent 0f87973 commit e8c17f5

16 files changed

+287
-167
lines changed

.travis.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ env:
1111
- deps=""
1212

1313
php:
14-
- 5.4
1514
- 5.5
1615
- 5.6
1716
- hhvm
1817

1918
matrix:
2019
fast_finish: true
2120
include:
22-
- php: 5.3
21+
- php: 5.4
2322
env: deps="low"
2423
- php: 7.0
2524
env: xdebug="yes"
@@ -29,7 +28,7 @@ before_install:
2928
- composer self-update
3029

3130
install:
32-
- if [ "$deps" = "low" ]; then composer update --prefer-lowest --prefer-stable; fi
31+
- if [ "$deps" = "low" ]; then composer update --prefer-lowest --prefer-stable --ignore-platform-reqs; fi
3332
- if [ "$deps" = "" ]; then composer install; fi
3433

3534
script:

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,42 @@ CHANGELOG
44
0.5.0
55
-----
66

7+
* **CAUTION**: This release drops support for PHP 5.3 due to the introduced
8+
dependency on `php-http/httplug` (see below).
9+
10+
* The client now depends on the [HTTPlug library](http://httplug.io/) to
11+
perform HTTP requests. This means that the package now depends the virtual
12+
`php-http/client-implementation`. To satisfy this dependency you have to
13+
pick [an implementation](https://packagist.org/providers/php-http/client-implementation)
14+
and install it together with `php-xapi/client`.
15+
16+
For example, if you prefer to use [Guzzle 6](http://docs.guzzlephp.org/en/latest/)
17+
you would do the following:
18+
19+
```bash
20+
$ composer require --no-update php-http/guzzle6-adapter
21+
$ composer require php-xapi/client
22+
```
23+
24+
* The `setHttpClient()` and `setRequestFactory()` method have been added
25+
to the `XApiClientBuilderInterface` and must be used to configure the
26+
`HttpClient` and `RequestFactory` instances you intend to use.
27+
28+
To use [Guzzle 6](http://docs.guzzlephp.org/en/latest/), for example,
29+
this will look like this:
30+
31+
```php
32+
use Http\Adapter\Guzzle6\Client;
33+
use Http\Message\MessageFactory\GuzzleMessageFactory;
34+
use Xabbuh\XApi\Client\XApiClientBuilder;
35+
36+
$builder = new XApiClientBuilder();
37+
$client = $builder->setHttpClient(new Client())
38+
->setRequestFactory(new GuzzleMessageFactory())
39+
->setBaseUrl('http://example.com/xapi/')
40+
->build();
41+
```
42+
743
* Bumped the required versions of all `php-xapi` packages to the `1.x` release
844
series.
945

UPGRADE.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,45 @@
11
UPGRADE
22
=======
33

4+
Upgrading from 0.4 to 0.5
5+
-------------------------
6+
7+
* **CAUTION**: This release drops support for PHP 5.3 due to the introduced
8+
dependency on `php-http/httplug` (see below).
9+
10+
* The client now depends on the [HTTPlug library](http://httplug.io/) to
11+
perform HTTP requests. This means that the package now depends the virtual
12+
`php-http/client-implementation`. To satisfy this dependency you have to
13+
pick [an implementation](https://packagist.org/providers/php-http/client-implementation)
14+
and install it together with `php-xapi/client`.
15+
16+
For example, if you prefer to use [Guzzle 6](http://docs.guzzlephp.org/en/latest/)
17+
you would do the following:
18+
19+
```bash
20+
$ composer require --no-update php-http/guzzle6-adapter
21+
$ composer require php-xapi/client
22+
```
23+
24+
* The `setHttpClient()` and `setRequestFactory()` method have been added
25+
to the `XApiClientBuilderInterface` and must be used to configure the
26+
`HttpClient` and `RequestFactory` instances you intend to use.
27+
28+
To use [Guzzle 6](http://docs.guzzlephp.org/en/latest/), for example,
29+
this will look like this:
30+
31+
```php
32+
use Http\Adapter\Guzzle6\Client;
33+
use Http\Message\MessageFactory\GuzzleMessageFactory;
34+
use Xabbuh\XApi\Client\XApiClientBuilder;
35+
36+
$builder = new XApiClientBuilder();
37+
$client = $builder->setHttpClient(new Client())
38+
->setRequestFactory(new GuzzleMessageFactory())
39+
->setBaseUrl('http://example.com/xapi/')
40+
->build();
41+
```
42+
443
Upgrading from 0.2 to 0.3
544
-------------------------
645

composer.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,22 @@
1212
}
1313
],
1414
"require": {
15-
"php": ">=5.3.0",
16-
"guzzle/guzzle": "~3.7",
15+
"php": ">=5.4.0",
16+
"php-http/client-common": "^1.0",
17+
"php-http/client-implementation": "^1.0",
18+
"php-http/httplug": "^1.0",
19+
"php-http/message": "^1.0",
20+
"php-http/message-factory": "^1.0",
1721
"php-xapi/exception": "^0.1.0",
1822
"php-xapi/model": "^1.0",
1923
"php-xapi/serializer": "^1.0",
2024
"php-xapi/serializer-implementation": "^1.0",
21-
"php-xapi/symfony-serializer": "^1.0"
25+
"php-xapi/symfony-serializer": "^1.0",
26+
"psr/http-message": "^1.0"
2227
},
2328
"require-dev": {
2429
"phpspec/phpspec": "^2.3",
30+
"php-http/mock-client": "^0.3",
2531
"php-xapi/test-fixtures": "^1.0"
2632
},
2733
"conflict": {

spec/Request/HandlerSpec.php

Lines changed: 52 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,126 +2,118 @@
22

33
namespace spec\Xabbuh\XApi\Client\Request;
44

5-
use Guzzle\Http\Message\RequestInterface;
6-
use Guzzle\Http\Message\Response;
7-
use Guzzle\Service\ClientInterface;
5+
use Http\Client\HttpClient;
6+
use Http\Message\RequestFactory;
87
use PhpSpec\ObjectBehavior;
8+
use Psr\Http\Message\RequestInterface;
9+
use Psr\Http\Message\ResponseInterface;
910

1011
class HandlerSpec extends ObjectBehavior
1112
{
12-
function let(ClientInterface $client)
13+
function let(HttpClient $client, RequestFactory $requestFactory)
1314
{
14-
$this->beConstructedWith($client, '1.0.1');
15+
$this->beConstructedWith($client, $requestFactory, 'http://example.com/xapi/', '1.0.1');
1516
}
1617

1718
function it_throws_an_exception_if_a_request_is_created_with_an_invalid_method()
1819
{
1920
$this->shouldThrow('\InvalidArgumentException')->during('createRequest', array('options', '/xapi/statements'));
2021
}
2122

22-
function it_sets_the_experience_api_version_header_and_the_content_type_header_when_creating_a_request(ClientInterface $client, RequestInterface $request)
23+
function it_returns_get_request_created_by_the_http_client(RequestFactory $requestFactory, RequestInterface $request)
2324
{
24-
$client->get('/xapi/statements')->willReturn($request);
25-
$request->addHeader('X-Experience-API-Version', '1.0.1')->shouldBeCalled();
26-
$request->addHeader('Content-Type', 'application/json')->shouldBeCalled();
25+
$requestFactory->createRequest('GET', 'http://example.com/xapi/statements', array(
26+
'X-Experience-API-Version' => '1.0.1',
27+
'Content-Type' => 'application/json',
28+
))->willReturn($request);
2729

28-
$this->createRequest('get', '/xapi/statements');
30+
$this->createRequest('get', '/statements')->shouldReturn($request);
31+
$this->createRequest('GET', '/statements')->shouldReturn($request);
2932
}
3033

31-
function it_sets_basic_auth_data_when_credentials_are_configured_when_creating_a_request(ClientInterface $client, RequestInterface $request)
34+
function it_returns_post_request_created_by_the_http_client(RequestFactory $requestFactory, RequestInterface $request)
3235
{
33-
$this->beConstructedWith($client, '1.0.1', 'username', 'password');
36+
$requestFactory->createRequest('POST', 'http://example.com/xapi/statements', array(
37+
'X-Experience-API-Version' => '1.0.1',
38+
'Content-Type' => 'application/json',
39+
))->willReturn($request);
3440

35-
$client->get('/xapi/statements')->willReturn($request);
36-
$request->addHeader('X-Experience-API-Version', '1.0.1')->shouldBeCalled();
37-
$request->addHeader('Content-Type', 'application/json')->shouldBeCalled();
38-
$request->setAuth('username', 'password')->shouldBeCalled();
39-
40-
$this->createRequest('get', '/xapi/statements');
41-
}
42-
43-
function it_returns_get_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
44-
{
45-
$client->get('/xapi/statements')->willReturn($request);
46-
47-
$this->createRequest('get', '/xapi/statements')->shouldReturn($request);
48-
$this->createRequest('GET', '/xapi/statements')->shouldReturn($request);
49-
}
50-
51-
function it_returns_post_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
52-
{
53-
$client->post('/xapi/statements', null, 'body')->willReturn($request);
54-
55-
$this->createRequest('post', '/xapi/statements', array(), 'body')->shouldReturn($request);
56-
$this->createRequest('POST', '/xapi/statements', array(), 'body')->shouldReturn($request);
41+
$this->createRequest('post', '/statements', array(), 'body')->shouldReturn($request);
42+
$this->createRequest('POST', '/statements', array(), 'body')->shouldReturn($request);
5743
}
5844

59-
function it_returns_put_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
45+
function it_returns_put_request_created_by_the_http_client(RequestFactory $requestFactory, RequestInterface $request)
6046
{
61-
$client->put('/xapi/statements', null, 'body')->willReturn($request);
47+
$requestFactory->createRequest('PUT', 'http://example.com/xapi/statements', array(
48+
'X-Experience-API-Version' => '1.0.1',
49+
'Content-Type' => 'application/json',
50+
))->willReturn($request);
6251

63-
$this->createRequest('put', '/xapi/statements', array(), 'body')->shouldReturn($request);
64-
$this->createRequest('PUT', '/xapi/statements', array(), 'body')->shouldReturn($request);
52+
$this->createRequest('put', '/statements', array(), 'body')->shouldReturn($request);
53+
$this->createRequest('PUT', '/statements', array(), 'body')->shouldReturn($request);
6554
}
6655

67-
function it_returns_delete_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
56+
function it_returns_delete_request_created_by_the_http_client(RequestFactory $requestFactory, RequestInterface $request)
6857
{
69-
$client->delete('/xapi/statements')->willReturn($request);
58+
$requestFactory->createRequest('DELETE', 'http://example.com/xapi/statements', array(
59+
'X-Experience-API-Version' => '1.0.1',
60+
'Content-Type' => 'application/json',
61+
))->willReturn($request);
7062

71-
$this->createRequest('delete', '/xapi/statements')->shouldReturn($request);
72-
$this->createRequest('DELETE', '/xapi/statements')->shouldReturn($request);
63+
$this->createRequest('delete', '/statements')->shouldReturn($request);
64+
$this->createRequest('DELETE', '/statements')->shouldReturn($request);
7365
}
7466

75-
function it_throws_an_access_denied_exception_when_a_401_status_code_is_returned(RequestInterface $request, Response $response)
67+
function it_throws_an_access_denied_exception_when_a_401_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
7668
{
77-
$request->send()->willReturn($response);
69+
$client->sendRequest($request)->willReturn($response);
7870
$response->getStatusCode()->willReturn(401);
79-
$response->getBody(true)->willReturn('body');
71+
$response->getBody()->willReturn('body');
8072

8173
$this->shouldThrow('Xabbuh\XApi\Common\Exception\AccessDeniedException')->during('executeRequest', array($request, array(200)));
8274
}
8375

84-
function it_throws_an_access_denied_exception_when_a_403_status_code_is_returned(RequestInterface $request, Response $response)
76+
function it_throws_an_access_denied_exception_when_a_403_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
8577
{
86-
$request->send()->willReturn($response);
78+
$client->sendRequest($request)->willReturn($response);
8779
$response->getStatusCode()->willReturn(403);
88-
$response->getBody(true)->willReturn('body');
80+
$response->getBody()->willReturn('body');
8981

9082
$this->shouldThrow('Xabbuh\XApi\Common\Exception\AccessDeniedException')->during('executeRequest', array($request, array(200)));
9183
}
9284

93-
function it_throws_a_not_found_exception_when_a_404_status_code_is_returned(RequestInterface $request, Response $response)
85+
function it_throws_a_not_found_exception_when_a_404_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
9486
{
95-
$request->send()->willReturn($response);
87+
$client->sendRequest($request)->willReturn($response);
9688
$response->getStatusCode()->willReturn(404);
97-
$response->getBody(true)->willReturn('body');
89+
$response->getBody()->willReturn('body');
9890

9991
$this->shouldThrow('Xabbuh\XApi\Common\Exception\NotFoundException')->during('executeRequest', array($request, array(200)));
10092
}
10193

102-
function it_throws_a_conflict_exception_when_a_409_status_code_is_returned(RequestInterface $request, Response $response)
94+
function it_throws_a_conflict_exception_when_a_409_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
10395
{
104-
$request->send()->willReturn($response);
96+
$client->sendRequest($request)->willReturn($response);
10597
$response->getStatusCode()->willReturn(409);
106-
$response->getBody(true)->willReturn('body');
98+
$response->getBody()->willReturn('body');
10799

108100
$this->shouldThrow('Xabbuh\XApi\Common\Exception\ConflictException')->during('executeRequest', array($request, array(200)));
109101
}
110102

111-
function it_throws_an_xapi_exception_when_an_unexpected_status_code_is_returned(RequestInterface $request, Response $response)
103+
function it_throws_an_xapi_exception_when_an_unexpected_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
112104
{
113-
$request->send()->willReturn($response);
105+
$client->sendRequest($request)->willReturn($response);
114106
$response->getStatusCode()->willReturn(204);
115-
$response->getBody(true)->willReturn('body');
107+
$response->getBody()->willReturn('body');
116108

117109
$this->shouldThrow('Xabbuh\XApi\Common\Exception\XApiException')->during('executeRequest', array($request, array(200)));
118110
}
119111

120-
function it_returns_the_response_on_success(RequestInterface $request, Response $response)
112+
function it_returns_the_response_on_success(HttpClient $client, RequestInterface $request, ResponseInterface $response)
121113
{
122-
$request->send()->willReturn($response);
114+
$client->sendRequest($request)->willReturn($response);
123115
$response->getStatusCode()->willReturn(200);
124-
$response->getBody(true)->willReturn('body');
116+
$response->getBody()->willReturn('body');
125117

126118
$this->executeRequest($request, array(200))->shouldReturn($response);
127119
}

spec/XApiClientBuilderSpec.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace spec\Xabbuh\XApi\Client;
44

5+
use Http\Client\HttpClient;
6+
use Http\Message\RequestFactory;
57
use PhpSpec\ObjectBehavior;
68

79
class XApiClientBuilderSpec extends ObjectBehavior
@@ -11,22 +13,45 @@ function it_is_an_xapi_client_builder()
1113
$this->shouldHaveType('Xabbuh\XApi\Client\XApiClientBuilderInterface');
1214
}
1315

14-
function it_creates_an_xapi_client()
16+
function it_creates_an_xapi_client(HttpClient $httpClient, RequestFactory $requestFactory)
1517
{
18+
$this->setHttpClient($httpClient);
19+
$this->setRequestFactory($requestFactory);
1620
$this->setBaseUrl('http://example.com/xapi/');
1721
$this->build()->shouldHaveType('Xabbuh\XApi\Client\XApiClientInterface');
1822
}
1923

20-
function its_methods_can_be_chained()
24+
function its_methods_can_be_chained(HttpClient $httpClient, RequestFactory $requestFactory)
2125
{
26+
$this->setHttpClient($httpClient)->shouldReturn($this);
27+
$this->setRequestFactory($requestFactory)->shouldReturn($this);
2228
$this->setBaseUrl('http://example.com/xapi/')->shouldReturn($this);
2329
$this->setVersion('1.0.0')->shouldReturn($this);
2430
$this->setAuth('foo', 'bar')->shouldReturn($this);
2531
$this->setOAuthCredentials('consumer key', 'consumer secret', 'token', 'token secret')->shouldReturn($this);
2632
}
2733

28-
function it_throws_an_exception_if_the_base_uri_is_not_configured()
34+
function it_throws_an_exception_if_the_http_client_is_not_configured(RequestFactory $requestFactory)
2935
{
36+
$this->setRequestFactory($requestFactory);
37+
$this->setBaseUrl('http://example.com/xapi/');
38+
39+
$this->shouldThrow('\LogicException')->during('build');
40+
}
41+
42+
function it_throws_an_exception_if_the_request_factory_is_not_configured(HttpClient $httpClient)
43+
{
44+
$this->setHttpClient($httpClient);
45+
$this->setBaseUrl('http://example.com/xapi/');
46+
47+
$this->shouldThrow('\LogicException')->during('build');
48+
}
49+
50+
function it_throws_an_exception_if_the_base_uri_is_not_configured(HttpClient $httpClient, RequestFactory $requestFactory)
51+
{
52+
$this->setHttpClient($httpClient);
53+
$this->setRequestFactory($requestFactory);
54+
3055
$this->shouldThrow('\LogicException')->during('build');
3156
}
3257
}

src/Api/DocumentApiClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected function doGetDocument($uri, array $urlParameters)
8282
{
8383
$request = $this->requestHandler->createRequest('get', $uri, $urlParameters);
8484
$response = $this->requestHandler->executeRequest($request, array(200));
85-
$document = $this->deserializeDocument($response->getBody(true));
85+
$document = $this->deserializeDocument((string) $response->getBody());
8686

8787
return $document;
8888
}

0 commit comments

Comments
 (0)