Skip to content

Commit 18fc9ca

Browse files
authored
Merge pull request #111 from radutopala/paginator
added Result Paginator
2 parents 653753f + 0866fc9 commit 18fc9ca

File tree

9 files changed

+272
-3
lines changed

9 files changed

+272
-3
lines changed

lib/Gitlab/Api/AbstractApi.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
*
88
* @author Joseph Bielawski <[email protected]>
99
* @author Matt Humphrey <[email protected]>
10+
* @author Radu Topala <[email protected]>
1011
*/
11-
abstract class AbstractApi
12+
abstract class AbstractApi implements ApiInterface
1213
{
1314
/**
1415
* Default entries per page

lib/Gitlab/Api/ApiInterface.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php namespace Gitlab\Api;
2+
3+
use Gitlab\Client;
4+
5+
/**
6+
* Api interface
7+
*/
8+
interface ApiInterface
9+
{
10+
public function __construct(Client $client);
11+
}

lib/Gitlab/Api/Issues.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function all($project_id = null, $page = 1, $per_page = self::PER_PAGE, a
2929
*/
3030
public function show($project_id, $issue_id)
3131
{
32-
return $this->get($this->getProjectPath($project_id, 'issues/'.$this->encodePath($issue_id)));
32+
return $this->get($this->getProjectPath($project_id, 'issues?iid='.$this->encodePath($issue_id)));
3333
}
3434

3535
/**

lib/Gitlab/Client.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Gitlab\HttpClient\HttpClient;
99
use Gitlab\HttpClient\HttpClientInterface;
1010
use Gitlab\HttpClient\Listener\AuthListener;
11+
use Gitlab\HttpClient\Listener\PaginationListener;
1112

1213
/**
1314
* Simple API wrapper for Gitlab
@@ -81,6 +82,13 @@ public function __construct($baseUrl, ClientInterface $httpClient = null)
8182

8283
$this->baseUrl = $baseUrl;
8384
$this->httpClient = new HttpClient($this->baseUrl, $this->options, $httpClient);
85+
86+
/**
87+
* a Pagination listener on Response
88+
*/
89+
$this->httpClient->addListener(
90+
new PaginationListener()
91+
);
8492
}
8593

8694
/**
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php namespace Gitlab\HttpClient\Listener;
2+
3+
use Buzz\Listener\ListenerInterface;
4+
use Buzz\Message\MessageInterface;
5+
use Buzz\Message\RequestInterface;
6+
7+
class PaginationListener implements ListenerInterface
8+
{
9+
/**
10+
* {@inheritDoc}
11+
*/
12+
public function preSend(RequestInterface $request)
13+
{
14+
}
15+
16+
/**
17+
* {@inheritDoc}
18+
*/
19+
public function postSend(RequestInterface $request, MessageInterface $response)
20+
{
21+
$header = $response->getHeader('Link');
22+
23+
if (empty($header)) {
24+
return null;
25+
}
26+
27+
$pagination = array();
28+
foreach (explode(',', $header) as $link) {
29+
preg_match('/<(.*)>; rel="(.*)"/i', trim($link, ','), $match);
30+
31+
if (3 === count($match)) {
32+
$pagination[$match[2]] = $match[1];
33+
}
34+
}
35+
36+
$response->setPagination($pagination);
37+
}
38+
}

lib/Gitlab/HttpClient/Message/Response.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@
44

55
class Response extends BaseResponse
66
{
7+
/**
8+
* @var array pagination
9+
* See PaginationListener
10+
*/
11+
protected $pagination = array();
12+
13+
/**
14+
* @return mixed
15+
*/
16+
public function getPagination()
17+
{
18+
return $this->pagination;
19+
}
20+
21+
/**
22+
* @param array $pagination
23+
*/
24+
public function setPagination(array $pagination)
25+
{
26+
$this->pagination = $pagination;
27+
}
28+
729
/**
830
* {@inheritDoc}
931
*/

lib/Gitlab/ResultPager.php

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php namespace Gitlab;
2+
3+
use Gitlab\Api\ApiInterface;
4+
5+
/**
6+
* Pager class for supporting pagination in Gitlab classes
7+
*/
8+
class ResultPager implements ResultPagerInterface
9+
{
10+
/**
11+
* @var \Gitlab\Client client
12+
*/
13+
protected $client;
14+
15+
/**
16+
* The Gitlab client to use for pagination. This must be the same
17+
* instance that you got the Api instance from, i.e.:
18+
*
19+
* $client = new \Gitlab\Client();
20+
* $api = $client->api('someApi');
21+
* $pager = new \Gitlab\ResultPager($client);
22+
*
23+
* @param \Gitlab\Client $client
24+
*
25+
*/
26+
public function __construct(Client $client)
27+
{
28+
$this->client = $client;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function fetch(ApiInterface $api, $method, array $parameters = array())
35+
{
36+
$result = call_user_func_array(array($api, $method), $parameters);
37+
38+
return $result;
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public function fetchAll(ApiInterface $api, $method, array $parameters = array())
45+
{
46+
$result = call_user_func_array(array($api, $method), $parameters);
47+
48+
while ($this->hasNext()) {
49+
$result = array_merge($result, $this->fetchNext());
50+
}
51+
52+
return $result;
53+
}
54+
55+
/**
56+
* {@inheritdoc}
57+
*/
58+
public function hasNext()
59+
{
60+
return $this->has('next');
61+
}
62+
63+
/**
64+
* {@inheritdoc}
65+
*/
66+
public function fetchNext()
67+
{
68+
return $this->get('next');
69+
}
70+
71+
/**
72+
* {@inheritdoc}
73+
*/
74+
public function hasPrevious()
75+
{
76+
return $this->has('prev');
77+
}
78+
79+
/**
80+
* {@inheritdoc}
81+
*/
82+
public function fetchPrevious()
83+
{
84+
return $this->get('prev');
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
public function fetchFirst()
91+
{
92+
return $this->get('first');
93+
}
94+
95+
/**
96+
* {@inheritdoc}
97+
*/
98+
public function fetchLast()
99+
{
100+
return $this->get('last');
101+
}
102+
103+
/**
104+
* {@inheritdoc}
105+
*/
106+
protected function has($key)
107+
{
108+
return !empty($this->client->getHttpClient()->getLastResponse()->getPagination()) && isset($this->client->getHttpClient()->getLastResponse()->getPagination()[$key]);
109+
}
110+
111+
/**
112+
* {@inheritdoc}
113+
*/
114+
protected function get($key)
115+
{
116+
if ($this->has($key)) {
117+
$result = $this->client->getHttpClient()->get(strtr($this->client->getHttpClient()->getLastResponse()->getPagination()[$key], array($this->client->getBaseUrl() => '')))->getContent();
118+
return $result;
119+
}
120+
}
121+
}

lib/Gitlab/ResultPagerInterface.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php namespace Gitlab;
2+
3+
use Gitlab\Api\ApiInterface;
4+
5+
/**
6+
* Pager interface
7+
*/
8+
interface ResultPagerInterface
9+
{
10+
/**
11+
* Fetch a single result (page) from an api call
12+
*
13+
* @param ApiInterface $api the Api instance
14+
* @param string $method the method name to call on the Api instance
15+
* @param array $parameters the method parameters in an array
16+
*
17+
* @return array returns the result of the Api::$method() call
18+
*/
19+
public function fetch(ApiInterface $api, $method, array $parameters = array());
20+
21+
/**
22+
* Fetch all results (pages) from an api call
23+
* Use with care - there is no maximum
24+
*
25+
* @param ApiInterface $api the Api instance
26+
* @param string $method the method name to call on the Api instance
27+
* @param array $parameters the method parameters in an array
28+
*
29+
* @return array returns a merge of the results of the Api::$method() call
30+
*/
31+
public function fetchAll(ApiInterface $api, $method, array $parameters = array());
32+
33+
/**
34+
* Check to determine the availability of a next page
35+
* @return bool
36+
*/
37+
public function hasNext();
38+
39+
/**
40+
* Check to determine the availability of a previous page
41+
* @return bool
42+
*/
43+
public function hasPrevious();
44+
45+
/**
46+
* Fetch the next page
47+
* @return array
48+
*/
49+
public function fetchNext();
50+
51+
/**
52+
* Fetch the previous page
53+
* @return array
54+
*/
55+
public function fetchPrevious();
56+
57+
/**
58+
* Fetch the first page
59+
* @return array
60+
*/
61+
public function fetchFirst();
62+
63+
/**
64+
* Fetch the last page
65+
* @return array
66+
*/
67+
public function fetchLast();
68+
}

test/Gitlab/Tests/Api/IssuesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function shouldShowIssue()
7474
$api = $this->getApiMock();
7575
$api->expects($this->once())
7676
->method('get')
77-
->with('projects/1/issues/2')
77+
->with('projects/1/issues?iid=2')
7878
->will($this->returnValue($expectedArray))
7979
;
8080

0 commit comments

Comments
 (0)