Skip to content

Commit

Permalink
Make PagedListResponse iterable (#221)
Browse files Browse the repository at this point in the history
* Make PagedListResponse iterable
* Update method doc
* Added examples
* Indent code examples
  • Loading branch information
michaelbausor committed Dec 11, 2018
1 parent a69d51e commit 7aa8efc
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 8 deletions.
59 changes: 55 additions & 4 deletions src/PagedListResponse.php
Expand Up @@ -32,6 +32,7 @@
namespace Google\ApiCore;

use Generator;
use IteratorAggregate;

/**
* Response object for paged results from a list API method
Expand All @@ -43,12 +44,42 @@
* are required.
*
* The list elements can be accessed in the following ways:
* - As a single iterable using the iterateAllElements method
* - As a single iterable used in a foreach loop or via the getIterator method
* - As pages of elements, using the getPage and iteratePages methods
* - As fixed size collections of elements, using the
* getFixedSizeCollection and iterateFixedSizeCollections methods
*
* Example of using PagedListResponse as an iterator:
* ```
* $pagedListResponse = $client->getList(...);
* foreach ($pagedListResponse as $element) {
* // doSomethingWith($element);
* }
* ```
*
* Example of iterating over each page of elements:
* ```
* $pagedListResponse = $client->getList(...);
* foreach ($pagedListResponse->iteratePages() as $page) {
* foreach ($page as $element) {
* // doSomethingWith($element);
* }
* }
* ```
*
* Example of accessing the current page, and manually iterating
* over pages:
* ```
* $pagedListResponse = $client->getList(...);
* $page = $pagedListResponse->getPage();
* // doSomethingWith($page);
* while ($page->hasNextPage()) {
* $page = $page->getNextPage();
* // doSomethingWith($page);
* }
* ```
*/
class PagedListResponse
class PagedListResponse implements IteratorAggregate
{
private $firstPage;

Expand All @@ -64,13 +95,33 @@ public function __construct(
}

/**
* Returns an iterator over the full list of elements. Elements
* of the list are retrieved lazily using the underlying API.
* Returns an iterator over the full list of elements. If the
* API response contains a (non-empty) next page token, then
* the PagedListResponse object will make calls to the underlying
* API to retrieve additional elements as required.
*
* NOTE: The result of this method is the same as getIterator().
* Prefer using getIterator(), or iterate directly on the
* PagedListResponse object.
*
* @return Generator
* @throws ValidationException
*/
public function iterateAllElements()
{
return $this->getIterator();
}

/**
* Returns an iterator over the full list of elements. If the
* API response contains a (non-empty) next page token, then
* the PagedListResponse object will make calls to the underlying
* API to retrieve additional elements as required.
*
* @return Generator
* @throws ValidationException
*/
public function getIterator()
{
foreach ($this->iteratePages() as $page) {
foreach ($page as $element) {
Expand Down
45 changes: 41 additions & 4 deletions tests/Tests/Unit/PagedListResponseTest.php
Expand Up @@ -45,9 +45,47 @@ class PagedListResponseTest extends TestCase
public function testNextPageToken()
{
$mockRequest = $this->createMockRequest('mockToken');

$mockResponse = $this->createMockResponse('nextPageToken1', ['resource1']);

$pageAccessor = $this->makeMockPagedCall($mockRequest, $mockResponse);

$page = $pageAccessor->getPage();
$this->assertEquals($page->getNextPageToken(), 'nextPageToken1');
$this->assertEquals(iterator_to_array($page->getIterator()), ['resource1']);
}

public function testIterateAllElements()
{
$mockRequest = $this->createMockRequest('mockToken');
$mockResponse = $this->createMockResponse('', ['resource1']);

$pageAccessor = $this->makeMockPagedCall($mockRequest, $mockResponse);

$result = iterator_to_array($pageAccessor->iterateAllElements());

$this->assertEquals(['resource1'], $result);
}

public function testIterator()
{
$mockRequest = $this->createMockRequest('mockToken');
$mockResponse = $this->createMockResponse('', ['resource1']);

$pageAccessor = $this->makeMockPagedCall($mockRequest, $mockResponse);

$result = iterator_to_array($pageAccessor);

$this->assertEquals(['resource1'], $result);
}

/**
* @param mixed $mockRequest
* @param mixed $mockResponse
* @param array $options
* @return PagedListResponse
*/
private function makeMockPagedCall($mockRequest, $mockResponse, $options = [])
{
$pageStreamingDescriptor = PageStreamingDescriptor::createFromFields([
'requestPageTokenField' => 'pageToken',
'responsePageTokenField' => 'nextPageToken',
Expand All @@ -67,8 +105,7 @@ public function testNextPageToken()

$page = new Page($call, $options, $callable, $pageStreamingDescriptor, $response);
$pageAccessor = new PagedListResponse($page);
$page = $pageAccessor->getPage();
$this->assertEquals($page->getNextPageToken(), 'nextPageToken1');
$this->assertEquals(iterator_to_array($page->getIterator()), ['resource1']);

return $pageAccessor;
}
}

0 comments on commit 7aa8efc

Please sign in to comment.