Skip to content

Commit 107f672

Browse files
committed
Update to use HTTP discovery with PSR-17 and PSR-18
1 parent 7a44ae7 commit 107f672

File tree

8 files changed

+158
-104
lines changed

8 files changed

+158
-104
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1212

1313
### Changed
1414

15-
- Updated [scriptotek/marc](https://github.com/scriptotek/php-marc/) to version 2.0.
15+
- Update [scriptotek/marc](https://github.com/scriptotek/php-marc/) to version 2.0.
1616
Please see [the corresponding CHANGELOG](https://github.com/scriptotek/php-marc/blob/master/CHANGELOG.md#200---2018-10-23) for information about changes that might break your app if you work with MARC records.
17+
- Update from HTTPlug to PSR-17/PSR-18 HTTP discovery.
18+
Note that a HTTP factory implementation is now required.
19+
Run `composer require http-interop/http-factory-guzzle` to add a HTTP Factory for Guzzle
1720

1821
### Fixed
1922

README.md

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,21 +46,17 @@ Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)
4646

4747
## Install using Composer
4848

49-
Make sure you have [Composer](https://getcomposer.org) installed, then run
49+
Use [Composer](https://getcomposer.org) to install sru-client with a HTTP library such as Guzzle:
5050

5151
```bash
52-
composer require scriptotek/alma-client
52+
composer require scriptotek/alma-client php-http/guzzle6-adapter http-interop/http-factory-guzzle
5353
```
5454

55-
in your project directory to get the latest stable version of the package. You
56-
also need a HTTP library. Php-alma-client uses
57-
[HTTPlug discovery](http://php-http.readthedocs.io/en/latest/discovery.html) in
58-
order to not depend on one specific library. If you don't already have a HTTP
59-
library installed, try Guzzle:
60-
61-
```bash
62-
composer require php-http/guzzle6-adapter
63-
```
55+
We use [HTTP discovery](https://github.com/http-interop/http-factory-discovery) to discover
56+
[HTTP client](https://packagist.org/providers/psr/http-client-implementation) and
57+
[HTTP factory](https://packagist.org/providers/psr/http-factory-implementation) implementations,
58+
so Guzzle can be swapped with any other
59+
[PSR-17](https://www.php-fig.org/psr/psr-17/)/[PSR-18](https://www.php-fig.org/psr/psr-18/)-compatible library.
6460

6561
## Initializing a client
6662

composer.json

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,24 @@
77
"minimum-stability": "dev",
88
"prefer-stable": true,
99
"require": {
10-
"php" : ">=5.6",
10+
"php" : ">=7.0",
1111
"ext-json": "*",
1212
"scriptotek/marc": "^2.0 || dev-master",
1313
"danmichaelo/quitesimplexmlelement": "^1.0",
14-
"scriptotek/sru-client": "^0.6",
14+
"scriptotek/sru-client": "^0.7",
1515
"psr/http-message": "^1.0",
16-
"php-http/client-implementation": "^1.0",
17-
"php-http/httplug": "^1.1 || ^2.0",
18-
"php-http/message-factory": "^1.0",
19-
"php-http/discovery": "^1.0",
20-
"php-http/client-common": "^1.5"
16+
"psr/http-client-implementation": "^1.0",
17+
"psr/http-factory-implementation": "^1.0",
18+
"http-interop/http-factory-discovery": "^1.4",
19+
"php-http/client-common": "^1.9 || ^2.0"
2120
},
2221
"require-dev": {
2322
"phpspec/phpspec": "^3.4 || ^4.0 || ^5.0",
2423
"bossa/phpspec2-expect": "^2.1 || ^3.0",
2524
"wp-cli/php-cli-tools": "^0.11.1",
2625
"php-http/mock-client": "^1.0",
27-
"php-http/message": "^1.0",
28-
"guzzlehttp/psr7": "^1.0",
2926
"php-http/guzzle6-adapter": "^1.1 || ^2.0",
27+
"http-interop/http-factory-guzzle": "^1.0",
3028
"squizlabs/php_codesniffer": "^3.3"
3129
},
3230
"license": "MIT",

spec/ClientSpec.php

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace spec\Scriptotek\Alma;
44

55
use GuzzleHttp\Psr7\Response;
6-
use Http\Client\Common\Exception\ClientErrorException;
76
use Http\Client\Common\Exception\ServerErrorException;
87
use Http\Mock\Client as MockHttp;
98
use PhpSpec\ObjectBehavior;
@@ -124,16 +123,14 @@ public function it_can_get_redirect_locations()
124123
$this->getRedirectLocation('/')->shouldBe('http://test.test');
125124
}
126125

127-
public function it_processes_json_error_responses(ClientErrorException $exception)
126+
public function it_processes_json_error_responses()
128127
{
129-
$exception->getResponse()->willReturn(new Response(
130-
400,
131-
['Content-Type' => 'application/json;charset=utf-8'],
132-
SpecHelper::getDummyData('error_response.json', false)
133-
));
134-
135128
$http = $this->let();
136-
$http->addException($exception->getWrappedObject());
129+
130+
$exception = SpecHelper::makeExceptionResponse(
131+
SpecHelper::getDummyData('error_response.json', false)
132+
);
133+
$http->addException($exception);
137134

138135
$this->shouldThrow(new RequestFailed(
139136
'Mandatory field is missing: library',
@@ -143,16 +140,16 @@ public function it_processes_json_error_responses(ClientErrorException $exceptio
143140
expect($http->getRequests())->toHaveCount(1);
144141
}
145142

146-
public function it_processes_xml_error_responses(ClientErrorException $exception)
143+
public function it_processes_xml_error_responses()
147144
{
148-
$exception->getResponse()->willReturn(new Response(
149-
400,
150-
['Content-Type' => 'application/xml;charset=utf-8'],
151-
SpecHelper::getDummyData('error_response.xml', false)
152-
));
153-
154145
$http = $this->let();
155-
$http->addException($exception->getWrappedObject());
146+
147+
$exception = SpecHelper::makeExceptionResponse(
148+
SpecHelper::getDummyData('error_response.xml', false),
149+
400,
150+
'application/xml;charset=utf-8'
151+
);
152+
$http->addException($exception);
156153

157154
$this->shouldThrow(new RequestFailed(
158155
'Mandatory field is missing: library',
@@ -162,68 +159,67 @@ public function it_processes_xml_error_responses(ClientErrorException $exception
162159
expect($http->getRequests())->toHaveCount(1);
163160
}
164161

165-
public function it_can_throw_resource_not_found(ClientErrorException $exception)
162+
public function it_can_throw_resource_not_found()
166163
{
167-
$exception->getResponse()->willReturn(new Response(
168-
400,
169-
['Content-Type' => 'application/json;charset=utf-8'],
170-
SpecHelper::getDummyData('item_barcode_error_response.json', false)
171-
));
172-
173164
$http = $this->let();
174-
$http->addException($exception->getWrappedObject());
165+
166+
$exception = SpecHelper::makeExceptionResponse(
167+
SpecHelper::getDummyData('item_barcode_error_response.json', false)
168+
);
169+
$http->addException($exception);
175170

176171
$this->shouldThrow(new ResourceNotFound('No items found for barcode 123.', '401689'))
177172
->during('getJSON', ['/items/123']);
178173

179174
expect($http->getRequests())->toHaveCount(1);
180175
}
181176

182-
public function it_can_throw_resource_not_found_for_500_errors_too(ServerErrorException $exception)
177+
public function it_can_throw_resource_not_found_for_500_errors_too()
183178
{
179+
$http = $this->let();
180+
184181
// For Analytics reports, Alma will return 500, not 4xx
185-
$exception->getResponse()->willReturn(new Response(
182+
$exception = SpecHelper::makeExceptionResponse(
183+
SpecHelper::getDummyData('report_not_found_response.xml', false),
186184
500,
187-
['Content-Type' => 'application/xml;charset=utf-8'],
188-
SpecHelper::getDummyData('report_not_found_response.xml', false)
189-
));
190-
191-
$http = $this->let();
192-
$http->addException($exception->getWrappedObject());
185+
'application/xml;charset=utf-8',
186+
ServerErrorException::class
187+
);
188+
$http->addException($exception);
193189

194190
$this->shouldThrow(new ResourceNotFound('Path not found (/test/path)', 'INTERNAL_SERVER_ERROR'))
195191
->during('getXML', ['/analytics/reports', ['path' => '/test/path']]);
196192

197193
expect($http->getRequests())->toHaveCount(1);
198194
}
199195

200-
public function it_can_throw_invalid_api_key(ClientErrorException $exception)
196+
public function it_can_throw_invalid_api_key()
201197
{
202-
$exception->getResponse()->willReturn(new Response(
203-
400,
204-
['Content-Type' => 'text/plain;charset=UTF-8'],
205-
'Invalid API Key'
206-
));
207-
208198
$http = $this->let();
209-
$http->addException($exception->getWrappedObject());
199+
200+
$exception = SpecHelper::makeExceptionResponse(
201+
'Invalid API Key',
202+
400,
203+
'text/plain;charset=UTF-8'
204+
);
205+
$http->addException($exception);
210206

211207
$this->shouldThrow(new InvalidApiKey('Invalid API Key', 0))
212208
->during('getJSON', ['/items/123']);
213209

214210
expect($http->getRequests())->toHaveCount(1);
215211
}
216212

217-
public function it_will_retry_when_reaching_rate_limit(ClientErrorException $exception)
213+
public function it_will_retry_when_reaching_rate_limit()
218214
{
219-
$exception->getResponse()->willReturn(new Response(
220-
400,
221-
['Content-Type' => 'application/json;charset=utf-8'],
222-
SpecHelper::getDummyData('per_second_threshold_error_response.json', false)
223-
));
224-
225215
$http = $this->let();
226-
$http->addException($exception->getWrappedObject());
216+
217+
$exception = SpecHelper::makeExceptionResponse(
218+
SpecHelper::getDummyData('per_second_threshold_error_response.json', false),
219+
400,
220+
'application/json;charset=utf-8'
221+
);
222+
$http->addException($exception);
227223

228224
$this->getJSON('/items/123');
229225

spec/Electronic/CollectionSpec.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace spec\Scriptotek\Alma\Electronic;
4+
5+
use PhpSpec\ObjectBehavior;
6+
use Scriptotek\Alma\Electronic\Collection;
7+
use Scriptotek\Alma\Client as AlmaClient;
8+
use spec\Scriptotek\Alma\SpecHelper;
9+
10+
class CollectionSpec extends ObjectBehavior
11+
{
12+
public function let(AlmaClient $client)
13+
{
14+
$collection_id = '123';
15+
$this->beConstructedWith($client, $collection_id);
16+
}
17+
18+
protected function expectRequest($client)
19+
{
20+
$client->getJSON('/electronic/e-collections/123')
21+
->shouldBeCalled()
22+
->willReturn(SpecHelper::getDummyData('e-collection_response.json'));
23+
}
24+
25+
public function it_is_initializable()
26+
{
27+
$this->shouldHaveType(Collection::class);
28+
}
29+
}

spec/SpecHelper.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
namespace spec\Scriptotek\Alma;
44

55
use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement;
6+
use function GuzzleHttp\Psr7\stream_for;
7+
use Http\Client\Common\Exception\ClientErrorException;
8+
use Http\Factory\Guzzle\RequestFactory;
9+
use Http\Factory\Guzzle\ResponseFactory;
610
use Prophecy\Argument;
711

812
class SpecHelper
@@ -30,4 +34,25 @@ public static function expectNoRequests($client)
3034
$client->getXML(Argument::any(), Argument::any())
3135
->shouldNotBeCalled();
3236
}
37+
38+
public static function makeExceptionResponse(
39+
$body,
40+
$code = 400,
41+
$contentType = 'application/json;charset=utf-8',
42+
$cls = ClientErrorException::class
43+
)
44+
{
45+
$requestFactory = new RequestFactory();
46+
$responseFactory = new ResponseFactory();
47+
48+
return new $cls(
49+
'Error 400',
50+
$requestFactory->createRequest('GET', ''),
51+
$responseFactory->createResponse($code, 'Bad Request')
52+
->withHeader('Content-Type', $contentType)
53+
->withBody(stream_for($body))
54+
);
55+
56+
57+
}
3358
}

spec/Users/UsersSpec.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
namespace spec\Scriptotek\Alma\Users;
44

5+
use Http\Mock\Client as MockHttp;
56
use PhpSpec\ObjectBehavior;
67
use Prophecy\Argument;
78
use Scriptotek\Alma\Client as AlmaClient;
9+
use Scriptotek\Alma\Exception\RequestFailed;
810
use Scriptotek\Alma\Users\User;
911
use Scriptotek\Alma\Users\Users;
12+
use Scriptotek\Alma\Zones;
1013
use spec\Scriptotek\Alma\SpecHelper;
1114

1215
class UsersSpec extends ObjectBehavior

0 commit comments

Comments
 (0)