Skip to content

Commit cbfd43e

Browse files
committed
issue #36
1 parent 2b7ea8e commit cbfd43e

File tree

6 files changed

+119
-21
lines changed

6 files changed

+119
-21
lines changed

lib/collection.inc

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ class Collection extends Base {
3030
$itemclass,
3131
$itemlist=array(),
3232
$pointer=0,
33-
$sortkey;
33+
$sortkey,
34+
$next_page_class,
35+
$next_page_callback,
36+
$next_page_url;
3437

3538
/**
3639
* A Collection is an array of objects
@@ -44,6 +47,7 @@ class Collection extends Base {
4447
$this->service = $service;
4548
$this->debug('Collection:service=%s, class=%s, array=%s',
4649
get_class($service), $itemclass, print_r($arr,TRUE));
50+
$this->next_page_class = $itemclass;
4751
$p = strrpos($itemclass, '\\');
4852
if ($p !== FALSE)
4953
$this->itemclass = substr($itemclass, $p+1);
@@ -171,6 +175,51 @@ class Collection extends Base {
171175
unset($this->itemlist[$index]);
172176
}
173177
}
178+
179+
/**
180+
* returns the Collection object for the next page of results, or
181+
* FALSE if there are no more pages
182+
*
183+
* Generally, the structure for a multi-page collection will look like
184+
* this:
185+
*
186+
* $coll = $obj->Collection();
187+
* do {
188+
* while($item = $coll->Next()) {
189+
* // do something with the item
190+
* |
191+
* } while ($coll = $coll->NextPage());
192+
*
193+
* @api
194+
* @return Collection if there are more pages of results, otherwise FALSE
195+
*/
196+
public function NextPage() {
197+
if (isset($this->next_page_url)) {
198+
return call_user_func(
199+
$this->next_page_callback,
200+
$this->next_page_class,
201+
$this->next_page_url);
202+
}
203+
return FALSE;
204+
}
205+
206+
/**
207+
* for paginated collection, sets the callback function and URL for
208+
* the next page
209+
*
210+
* The callback function should have the signature:
211+
* function Whatever($class, $url, $parent)
212+
* and the `$url` should be the URL of the next page of results
213+
*
214+
* @param callable $callback the name of the function (or array of
215+
* object, function name)
216+
* @param string $url the URL of the next page of results
217+
* @return void
218+
*/
219+
public function SetNextPageCallback($callback, $url) {
220+
$this->next_page_callback = $callback;
221+
$this->next_page_url = $url;
222+
}
174223

175224
/********** PRIVATE METHODS **********/
176225

lib/dbservice.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class DbService extends Nova {
8181
* @return Collection
8282
*/
8383
public function InstanceList($params=array()) {
84-
return $this->Collection('\OpenCloud\DbService\Instance');
84+
return $this->Collection(
85+
'\OpenCloud\DbService\Instance', NULL, NULL, $params);
8586
}
8687
}

lib/service.inc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,22 +174,47 @@ abstract class Service extends Base {
174174
$obj = json_decode($response->HttpBody());
175175
if ($this->CheckJsonError())
176176
return FALSE;
177+
178+
// see if there is a "next" link
179+
if (isset($obj->links)) {
180+
if (is_array($obj->links)) {
181+
foreach($obj->links as $link) {
182+
if (isset($link->rel) && ($link->rel=='next')) {
183+
if (isset($link->href))
184+
$next_page_url = $link->href;
185+
else
186+
throw new \OpenCloud\DomainError(
187+
_('unexpected [links] found with no [href]'));
188+
}
189+
}
190+
}
191+
}
177192

178193
// and say goodbye
179194
if (!$collection)
180-
return new Collection($parent, $class, $obj);
195+
$coll_obj = new Collection($parent, $class, $obj);
181196
elseif (isset($obj->$collection)) {
182197
if (!$element)
183-
return new Collection($parent, $class, $obj->$collection);
198+
$coll_obj = new Collection($parent, $class, $obj->$collection);
184199
else { // handle element levels
185200
$arr = array();
186201
foreach($obj->$collection as $index => $item)
187202
$arr[] = $item->$element;
188-
return new Collection($parent, $class, $arr);
203+
$coll_obj = new Collection($parent, $class, $arr);
189204
}
190205
}
191206
else
192-
return new Collection($parent, $class, array());
207+
$coll_obj = new Collection($parent, $class, array());
208+
209+
// if there's a $next_page_url, then we need to establish a
210+
// callback method
211+
if (isset($next_page_url)) {
212+
$coll_obj->SetNextPageCallback(
213+
array($this, 'Collection'),
214+
$next_page_url);
215+
}
216+
217+
return $coll_obj;
193218
}
194219

195220
/**

samples/database/create.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
$instance = $dbservice->Instance();
2525
$instance->flavor = $dbservice->Flavor(1);
2626
$instance->volume->size = 3;
27-
$instance->Create(array('name'=>'MySQL'));
27+
$instance->Create(array('name'=>'TestInstance'.time()));
2828
$instance->WaitFor('ACTIVE', 300, 'showstatus');
2929

3030
// create a database

samples/database/list.php

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,22 @@
2020
$dbservice = $connection->DbService('cloudDatabases', 'DFW');
2121

2222
// delete all the instances created by the create.php script
23-
$inlist = $dbservice->InstanceList();
24-
while($instance = $inlist->Next()) {
25-
printf("Instance: %s (%s)\n", $instance->id, $instance->Name());
26-
$dblist = $instance->DatabaseList();
27-
while($db = $dblist->Next()) {
28-
printf(" Database: %s\n", $db->name);
29-
}
30-
$userlist = $instance->UserList();
31-
while($user = $userlist->Next()) {
32-
printf(" User: %s\n", $user->name);
33-
foreach($user->databases as $db)
34-
printf(" Database for user; %s\n", $db->name);
35-
}
36-
}
23+
$inlist = $dbservice->InstanceList(array('limit'=>2));
24+
$pageno = 0;
25+
do {
26+
printf("Page #%d of results...\n", ++$pageno);
27+
while($instance = $inlist->Next()) {
28+
printf("Instance: %s (%s)\n", $instance->id, $instance->Name());
29+
$dblist = $instance->DatabaseList();
30+
while($db = $dblist->Next()) {
31+
printf(" Database: %s\n", $db->name);
32+
}
33+
$userlist = $instance->UserList();
34+
while($user = $userlist->Next()) {
35+
printf(" User: %s\n", $user->name);
36+
foreach($user->databases as $db)
37+
printf(" Database for user; %s\n", $db->name);
38+
}
39+
}
40+
$inlist = $inlist->NextPage();
41+
} while ($inlist);

tests/CollectionTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,22 @@ public function testSelect() {
102102
// this should cause an error
103103
$coll->Select(function(){ return 5;});
104104
}
105+
public function testNextPage() {
106+
$coll = $this->my;
107+
$coll->SetNextPageCallback(
108+
array($this,'_callback'),
109+
'http://something');
110+
$this->assertEquals(
111+
'CollectionTest',
112+
get_class($coll->NextPage()));
113+
$this->assertEquals(
114+
FALSE,
115+
$coll->NextPage());
116+
}
117+
public function _callback($class, $url) {
118+
// stub function used by SetNextPageCallback
119+
}
120+
public function testSetNextPageCallback() {
121+
// not needed; exercised by testNextPage(), above
122+
}
105123
}

0 commit comments

Comments
 (0)