From 7aa8efc9a8a8d0b119b3704c69d174c0aaf282cb Mon Sep 17 00:00:00 2001 From: michaelbausor Date: Tue, 11 Dec 2018 12:59:33 -0800 Subject: [PATCH] Make PagedListResponse iterable (#221) * Make PagedListResponse iterable * Update method doc * Added examples * Indent code examples --- src/PagedListResponse.php | 59 ++++++++++++++++++++-- tests/Tests/Unit/PagedListResponseTest.php | 45 +++++++++++++++-- 2 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/PagedListResponse.php b/src/PagedListResponse.php index 224cf7ca9..7679cb727 100644 --- a/src/PagedListResponse.php +++ b/src/PagedListResponse.php @@ -32,6 +32,7 @@ namespace Google\ApiCore; use Generator; +use IteratorAggregate; /** * Response object for paged results from a list API method @@ -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; @@ -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) { diff --git a/tests/Tests/Unit/PagedListResponseTest.php b/tests/Tests/Unit/PagedListResponseTest.php index ea4df03ac..ec3ec8111 100644 --- a/tests/Tests/Unit/PagedListResponseTest.php +++ b/tests/Tests/Unit/PagedListResponseTest.php @@ -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', @@ -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; } }