Skip to content

Commit f9122bf

Browse files
committed
Merge pull request #6 from clue-labs/deps
Update dependencies in order to properly escape URIs
2 parents dc65913 + 40d97d2 commit f9122bf

File tree

3 files changed

+59
-32
lines changed

3 files changed

+59
-32
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"require": {
1414
"php": ">=5.3",
1515
"knplabs/packagist-api": "~1.0",
16-
"clue/buzz-react": "~0.1.0|~0.2.0"
16+
"clue/buzz-react": "^0.5",
17+
"rize/uri-template": "^0.3"
1718
},
1819
"autoload": {
1920
"psr-4": { "Clue\\React\\Packagist\\Api\\": "src/" }

src/Client.php

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,47 @@
44

55
use Packagist\Api\Result\Factory;
66
use Clue\React\Buzz\Browser;
7-
use Clue\React\Buzz\Message\Response;
7+
use Psr\Http\Message\ResponseInterface;
8+
use Rize\UriTemplate;
89

910
class Client
1011
{
1112
private $http;
1213
private $resultFactory;
14+
private $uri;
1315

14-
public function __construct(Browser $http, Factory $resultFactory = null)
16+
public function __construct(Browser $http, Factory $resultFactory = null, UriTemplate $uri = null)
1517
{
16-
$this->http = $http;
18+
$this->http = $http->withBase('https://packagist.org/');
1719

1820
if (null === $resultFactory) {
1921
$resultFactory = new Factory();
2022
}
2123

24+
if (null === $uri) {
25+
$uri = new UriTemplate();
26+
}
27+
2228
$this->resultFactory = $resultFactory;
29+
$this->uri = $uri;
2330
}
2431

2532
public function search($query, array $filters = array())
2633
{
27-
$results = array();
2834
$filters['q'] = $query;
29-
$url = $this->url('/search.json?' . http_build_query($filters));
35+
36+
$url = $this->uri->expand(
37+
'/search.json{?filters*}',
38+
array(
39+
'filters' => $filters
40+
)
41+
);
42+
43+
$results = array();
3044
$that = $this;
3145

3246
$fetch = function ($url) use (&$results, $that, &$fetch) {
33-
return $that->request($url)->then(function (Response $response) use (&$results, $that, $fetch) {
47+
return $that->request($url)->then(function (ResponseInterface $response) use (&$results, $that, $fetch) {
3448
$parsed = $that->parse((string)$response->getBody());
3549
$results = array_merge($results, $that->create($parsed));
3650

@@ -47,30 +61,34 @@ public function search($query, array $filters = array())
4761

4862
public function get($package)
4963
{
50-
return $this->respond(sprintf($this->url('/packages/%s.json'), $package));
64+
return $this->respond(
65+
$this->uri->expand(
66+
'/packages/{package}.json',
67+
array(
68+
'package' => $package
69+
)
70+
)
71+
);
5172
}
5273

5374
public function all(array $filters = array())
5475
{
55-
$url = '/packages/list.json';
56-
if ($filters) {
57-
$url .= '?'.http_build_query($filters);
58-
}
59-
60-
return $this->respond($this->url($url));
61-
}
62-
63-
protected function url($url)
64-
{
65-
return 'https://packagist.org'.$url;
76+
return $this->respond(
77+
$this->uri->expand(
78+
'/packages/list.json{?filters*}',
79+
array(
80+
'filters' => $filters
81+
)
82+
)
83+
);
6684
}
6785

6886
protected function respond($url)
6987
{
7088
$response = $this->request($url);
7189
$that = $this;
7290

73-
return $response->then(function (Response $response) use ($that) {
91+
return $response->then(function (ResponseInterface $response) use ($that) {
7492
return $that->create($that->parse((string)$response->getBody()));
7593
});
7694
}

tests/ClientTest.php

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
use Clue\React\Packagist\Api\Client;
44
use React\Promise\Deferred;
5-
use Clue\React\Buzz\Message\Response;
6-
use Clue\React\Buzz\Message\Headers;
7-
use Clue\React\Buzz\Message\Body;
5+
use RingCentral\Psr7\Response;
6+
use React\Promise;
87

98
class ClientTest extends TestCase
109
{
@@ -14,38 +13,46 @@ class ClientTest extends TestCase
1413
public function setUp()
1514
{
1615
$this->browser = $this->getMockBuilder('Clue\React\Buzz\Browser')->disableOriginalConstructor()->getMock();
16+
$this->browser->expects($this->any())->method('withBase')->willReturn($this->browser);
1717

1818
$this->client = new Client($this->browser);
1919
}
2020

2121
public function testGet()
2222
{
23-
$this->setupBrowser('packages/clue/zenity-react.json', $this->createResponsePromise('{"package":{"name":"clue\/zenity-react", "versions": {}}}'));
23+
$this->setupBrowser('/packages/clue%2Fzenity-react.json', $this->createResponsePromise('{"package":{"name":"clue\/zenity-react", "versions": {}}}'));
2424

2525
$this->expectPromiseResolve($this->client->get('clue/zenity-react'));
2626
}
2727

2828
public function testAll()
2929
{
30-
$this->setupBrowser('packages/list.json', $this->createResponsePromise('{"packageNames":["a/a", "b/b"]}'));
30+
$this->setupBrowser('/packages/list.json', $this->createResponsePromise('{"packageNames":["a/a", "b/b"]}'));
3131

3232
$this->expectPromiseResolve($this->client->all());
3333
}
3434

3535
public function testAllVendor()
3636
{
37-
$this->setupBrowser('packages/list.json?vendor=a', $this->createResponsePromise('{"packageNames":["a/a"]}'));
37+
$this->setupBrowser('/packages/list.json?vendor=a', $this->createResponsePromise('{"packageNames":["a/a"]}'));
3838

3939
$this->expectPromiseResolve($this->client->all(array('vendor' => 'a')));
4040
}
4141

4242
public function testSearch()
4343
{
44-
$this->setupBrowser('search.json?q=zenity', $this->createResponsePromise('{"results":[{"name":"clue\/zenity-react","description":"Build graphical desktop (GUI) applications in PHP","url":"https:\/\/packagist.org\/packages\/clue\/zenity-react","downloads":57,"favers":0,"repository":"https:\/\/github.com\/clue\/reactphp-zenity"}],"total":1}'));
44+
$this->setupBrowser('/search.json?q=zenity', $this->createResponsePromise('{"results":[{"name":"clue\/zenity-react","description":"Build graphical desktop (GUI) applications in PHP","url":"https:\/\/packagist.org\/packages\/clue\/zenity-react","downloads":57,"favers":0,"repository":"https:\/\/github.com\/clue\/reactphp-zenity"}],"total":1}'));
4545

4646
$this->expectPromiseResolve($this->client->search('zenity'));
4747
}
4848

49+
public function testSearchSpecialWithNoResults()
50+
{
51+
$this->setupBrowser('/search.json?q=%3C%C3%A4%3E', $this->createResponsePromise('{"results":[],"total":0}'));
52+
53+
$this->expectPromiseResolve($this->client->search('<ä>'));
54+
}
55+
4956
public function testSearchPagination()
5057
{
5158
$this->browser->expects($this->exactly(2))
@@ -60,7 +67,7 @@ public function testSearchPagination()
6067

6168
public function testHttpError()
6269
{
63-
$this->setupBrowser('packages/clue/invalid.json', $this->createRejectedPromise(new RuntimeException('error')));
70+
$this->setupBrowser('/packages/clue%2Finvalid.json', $this->createRejectedPromise(new RuntimeException('error')));
6471

6572
$this->expectPromiseReject($this->client->get('clue/invalid'));
6673
}
@@ -69,15 +76,16 @@ private function setupBrowser($expectedUrl, $promise)
6976
{
7077
$this->browser->expects($this->once())
7178
->method('get')
72-
->with($this->equalTo('https://packagist.org/' . $expectedUrl), array())
79+
->with($this->equalTo($expectedUrl), array())
7380
->will($this->returnValue($promise));
7481
}
7582

7683
private function createResponsePromise($fakeResponseBody)
7784
{
78-
$d = new Deferred();
79-
$d->resolve(new Response('HTTP/1.0', 200, 'OK', new Headers(), new Body($fakeResponseBody)));
80-
return $d->promise();
85+
$response = $this->getMock('Psr\Http\Message\ResponseInterface');
86+
$response->expects($this->once())->method('getBody')->willReturn($fakeResponseBody);
87+
88+
return Promise\resolve($response);
8189
}
8290

8391
private function createRejectedPromise($reason)

0 commit comments

Comments
 (0)