Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ env:
- deps=""

php:
- 5.4
- 5.5
- 5.6
- hhvm

matrix:
fast_finish: true
include:
- php: 5.3
- php: 5.4
env: deps="low"
- php: 7.0
env: xdebug="yes"
Expand All @@ -29,7 +28,7 @@ before_install:
- composer self-update

install:
- if [ "$deps" = "low" ]; then composer update --prefer-lowest --prefer-stable; fi
- if [ "$deps" = "low" ]; then composer update --prefer-lowest --prefer-stable --ignore-platform-reqs; fi
- if [ "$deps" = "" ]; then composer install; fi

script:
Expand Down
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,42 @@ CHANGELOG
0.5.0
-----

* **CAUTION**: This release drops support for PHP 5.3 due to the introduced
dependency on `php-http/httplug` (see below).

* The client now depends on the [HTTPlug library](http://httplug.io/) to
perform HTTP requests. This means that the package now depends the virtual
`php-http/client-implementation`. To satisfy this dependency you have to
pick [an implementation](https://packagist.org/providers/php-http/client-implementation)
and install it together with `php-xapi/client`.

For example, if you prefer to use [Guzzle 6](http://docs.guzzlephp.org/en/latest/)
you would do the following:

```bash
$ composer require --no-update php-http/guzzle6-adapter
$ composer require php-xapi/client
```

* The `setHttpClient()` and `setRequestFactory()` method have been added
to the `XApiClientBuilderInterface` and must be used to configure the
`HttpClient` and `RequestFactory` instances you intend to use.

To use [Guzzle 6](http://docs.guzzlephp.org/en/latest/), for example,
this will look like this:

```php
use Http\Adapter\Guzzle6\Client;
use Http\Message\MessageFactory\GuzzleMessageFactory;
use Xabbuh\XApi\Client\XApiClientBuilder;

$builder = new XApiClientBuilder();
$client = $builder->setHttpClient(new Client())
->setRequestFactory(new GuzzleMessageFactory())
->setBaseUrl('http://example.com/xapi/')
->build();
```

* Bumped the required versions of all `php-xapi` packages to the `1.x` release
series.

Expand Down
39 changes: 39 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
UPGRADE
=======

Upgrading from 0.4 to 0.5
-------------------------

* **CAUTION**: This release drops support for PHP 5.3 due to the introduced
dependency on `php-http/httplug` (see below).

* The client now depends on the [HTTPlug library](http://httplug.io/) to
perform HTTP requests. This means that the package now depends the virtual
`php-http/client-implementation`. To satisfy this dependency you have to
pick [an implementation](https://packagist.org/providers/php-http/client-implementation)
and install it together with `php-xapi/client`.

For example, if you prefer to use [Guzzle 6](http://docs.guzzlephp.org/en/latest/)
you would do the following:

```bash
$ composer require --no-update php-http/guzzle6-adapter
$ composer require php-xapi/client
```

* The `setHttpClient()` and `setRequestFactory()` method have been added
to the `XApiClientBuilderInterface` and must be used to configure the
`HttpClient` and `RequestFactory` instances you intend to use.

To use [Guzzle 6](http://docs.guzzlephp.org/en/latest/), for example,
this will look like this:

```php
use Http\Adapter\Guzzle6\Client;
use Http\Message\MessageFactory\GuzzleMessageFactory;
use Xabbuh\XApi\Client\XApiClientBuilder;

$builder = new XApiClientBuilder();
$client = $builder->setHttpClient(new Client())
->setRequestFactory(new GuzzleMessageFactory())
->setBaseUrl('http://example.com/xapi/')
->build();
```

Upgrading from 0.2 to 0.3
-------------------------

Expand Down
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,22 @@
}
],
"require": {
"php": ">=5.3.0",
"guzzle/guzzle": "~3.7",
"php": ">=5.4.0",
"php-http/client-common": "^1.0",
"php-http/client-implementation": "^1.0",
"php-http/httplug": "^1.0",
"php-http/message": "^1.0",
"php-http/message-factory": "^1.0",
"php-xapi/exception": "^0.1.0",
"php-xapi/model": "^1.0",
"php-xapi/serializer": "^1.0",
"php-xapi/serializer-implementation": "^1.0",
"php-xapi/symfony-serializer": "^1.0"
"php-xapi/symfony-serializer": "^1.0",
"psr/http-message": "^1.0"
},
"require-dev": {
"phpspec/phpspec": "^2.3",
"php-http/mock-client": "^0.3",
"php-xapi/test-fixtures": "^1.0"
},
"conflict": {
Expand Down
112 changes: 52 additions & 60 deletions spec/Request/HandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,126 +2,118 @@

namespace spec\Xabbuh\XApi\Client\Request;

use Guzzle\Http\Message\RequestInterface;
use Guzzle\Http\Message\Response;
use Guzzle\Service\ClientInterface;
use Http\Client\HttpClient;
use Http\Message\RequestFactory;
use PhpSpec\ObjectBehavior;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

class HandlerSpec extends ObjectBehavior
{
function let(ClientInterface $client)
function let(HttpClient $client, RequestFactory $requestFactory)
{
$this->beConstructedWith($client, '1.0.1');
$this->beConstructedWith($client, $requestFactory, 'http://example.com/xapi/', '1.0.1');
}

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

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

$this->createRequest('get', '/xapi/statements');
$this->createRequest('get', '/statements')->shouldReturn($request);
$this->createRequest('GET', '/statements')->shouldReturn($request);
}

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

$client->get('/xapi/statements')->willReturn($request);
$request->addHeader('X-Experience-API-Version', '1.0.1')->shouldBeCalled();
$request->addHeader('Content-Type', 'application/json')->shouldBeCalled();
$request->setAuth('username', 'password')->shouldBeCalled();

$this->createRequest('get', '/xapi/statements');
}

function it_returns_get_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
{
$client->get('/xapi/statements')->willReturn($request);

$this->createRequest('get', '/xapi/statements')->shouldReturn($request);
$this->createRequest('GET', '/xapi/statements')->shouldReturn($request);
}

function it_returns_post_request_created_by_the_http_client(ClientInterface $client, RequestInterface $request)
{
$client->post('/xapi/statements', null, 'body')->willReturn($request);

$this->createRequest('post', '/xapi/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('POST', '/xapi/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('post', '/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('POST', '/statements', array(), 'body')->shouldReturn($request);
}

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

$this->createRequest('put', '/xapi/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('PUT', '/xapi/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('put', '/statements', array(), 'body')->shouldReturn($request);
$this->createRequest('PUT', '/statements', array(), 'body')->shouldReturn($request);
}

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

$this->createRequest('delete', '/xapi/statements')->shouldReturn($request);
$this->createRequest('DELETE', '/xapi/statements')->shouldReturn($request);
$this->createRequest('delete', '/statements')->shouldReturn($request);
$this->createRequest('DELETE', '/statements')->shouldReturn($request);
}

function it_throws_an_access_denied_exception_when_a_401_status_code_is_returned(RequestInterface $request, Response $response)
function it_throws_an_access_denied_exception_when_a_401_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(401);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

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

function it_throws_an_access_denied_exception_when_a_403_status_code_is_returned(RequestInterface $request, Response $response)
function it_throws_an_access_denied_exception_when_a_403_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(403);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

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

function it_throws_a_not_found_exception_when_a_404_status_code_is_returned(RequestInterface $request, Response $response)
function it_throws_a_not_found_exception_when_a_404_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(404);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

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

function it_throws_a_conflict_exception_when_a_409_status_code_is_returned(RequestInterface $request, Response $response)
function it_throws_a_conflict_exception_when_a_409_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(409);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

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

function it_throws_an_xapi_exception_when_an_unexpected_status_code_is_returned(RequestInterface $request, Response $response)
function it_throws_an_xapi_exception_when_an_unexpected_status_code_is_returned(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(204);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

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

function it_returns_the_response_on_success(RequestInterface $request, Response $response)
function it_returns_the_response_on_success(HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$request->send()->willReturn($response);
$client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(200);
$response->getBody(true)->willReturn('body');
$response->getBody()->willReturn('body');

$this->executeRequest($request, array(200))->shouldReturn($response);
}
Expand Down
31 changes: 28 additions & 3 deletions spec/XApiClientBuilderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace spec\Xabbuh\XApi\Client;

use Http\Client\HttpClient;
use Http\Message\RequestFactory;
use PhpSpec\ObjectBehavior;

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

function it_creates_an_xapi_client()
function it_creates_an_xapi_client(HttpClient $httpClient, RequestFactory $requestFactory)
{
$this->setHttpClient($httpClient);
$this->setRequestFactory($requestFactory);
$this->setBaseUrl('http://example.com/xapi/');
$this->build()->shouldHaveType('Xabbuh\XApi\Client\XApiClientInterface');
}

function its_methods_can_be_chained()
function its_methods_can_be_chained(HttpClient $httpClient, RequestFactory $requestFactory)
{
$this->setHttpClient($httpClient)->shouldReturn($this);
$this->setRequestFactory($requestFactory)->shouldReturn($this);
$this->setBaseUrl('http://example.com/xapi/')->shouldReturn($this);
$this->setVersion('1.0.0')->shouldReturn($this);
$this->setAuth('foo', 'bar')->shouldReturn($this);
$this->setOAuthCredentials('consumer key', 'consumer secret', 'token', 'token secret')->shouldReturn($this);
}

function it_throws_an_exception_if_the_base_uri_is_not_configured()
function it_throws_an_exception_if_the_http_client_is_not_configured(RequestFactory $requestFactory)
{
$this->setRequestFactory($requestFactory);
$this->setBaseUrl('http://example.com/xapi/');

$this->shouldThrow('\LogicException')->during('build');
}

function it_throws_an_exception_if_the_request_factory_is_not_configured(HttpClient $httpClient)
{
$this->setHttpClient($httpClient);
$this->setBaseUrl('http://example.com/xapi/');

$this->shouldThrow('\LogicException')->during('build');
}

function it_throws_an_exception_if_the_base_uri_is_not_configured(HttpClient $httpClient, RequestFactory $requestFactory)
{
$this->setHttpClient($httpClient);
$this->setRequestFactory($requestFactory);

$this->shouldThrow('\LogicException')->during('build');
}
}
2 changes: 1 addition & 1 deletion src/Api/DocumentApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected function doGetDocument($uri, array $urlParameters)
{
$request = $this->requestHandler->createRequest('get', $uri, $urlParameters);
$response = $this->requestHandler->executeRequest($request, array(200));
$document = $this->deserializeDocument($response->getBody(true));
$document = $this->deserializeDocument((string) $response->getBody());

return $document;
}
Expand Down
Loading