-
Notifications
You must be signed in to change notification settings - Fork 259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CBP tickets #511
CBP tickets #511
Changes from all commits
f2c3aa9
ec0d08c
6fe01de
aed494a
362515b
b3b232e
a33faf0
6427d28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php | ||
|
||
namespace Zendesk\API\Traits\Utility; | ||
|
||
use Iterator; | ||
|
||
/** | ||
* An iterator for fetching tickets from the Zendesk API using cursor-based pagination. | ||
*/ | ||
class TicketsIterator implements Iterator | ||
{ | ||
/** | ||
* The default number of items per page for pagination. | ||
*/ | ||
public const DEFAULT_PAGE_SIZE = 100; | ||
|
||
/** | ||
* @var Zendesk\API\HttpClient The Zendesk API client. | ||
*/ | ||
private $resources; | ||
|
||
/** | ||
* @var int The current position in the tickets array. | ||
*/ | ||
private $position = 0; | ||
|
||
/** | ||
* @var array The fetched tickets. | ||
*/ | ||
private $tickets = []; | ||
|
||
/** | ||
* @var string|null The cursor for the next page of tickets. | ||
*/ | ||
private $afterCursor = null; | ||
|
||
/** | ||
* @var int The number of tickets to fetch per page. | ||
*/ | ||
private $pageSize; | ||
|
||
/** | ||
* @var bool A flag indicating whether the iterator has started fetching tickets. | ||
*/ | ||
private $started = false; | ||
|
||
/** | ||
* TicketsIterator constructor. | ||
* | ||
* @param \stdClass $resources implementing the iterator ($this), with findAll() | ||
* @param int $pageSize The number of tickets to fetch per page. | ||
*/ | ||
public function __construct($resources, $pageSize = self::DEFAULT_PAGE_SIZE) | ||
{ | ||
$this->resources = $resources; | ||
$this->pageSize = $pageSize; | ||
} | ||
|
||
/** | ||
* @return Ticket The current ticket, possibly fetching a new page. | ||
*/ | ||
public function current() | ||
{ | ||
if (!isset($this->tickets[$this->position]) && (!$this->started || $this->afterCursor)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just noted this can be abstracted. I'll do that in my next PR. |
||
$this->getPage(); | ||
} | ||
return $this->tickets[$this->position]; | ||
} | ||
|
||
/** | ||
* @return int The current position. | ||
*/ | ||
public function key() | ||
{ | ||
return $this->position; | ||
} | ||
|
||
/** | ||
* Moves to the next ticket. | ||
*/ | ||
public function next() | ||
{ | ||
++$this->position; | ||
} | ||
|
||
/** | ||
* Rewinds to the first ticket. | ||
*/ | ||
public function rewind() | ||
{ | ||
$this->position = 0; | ||
} | ||
|
||
/** | ||
* @return bool True there is a current element after calls to `rewind` or `next`, possibly fetching a new page. | ||
*/ | ||
public function valid() | ||
{ | ||
if (!isset($this->tickets[$this->position]) && (!$this->started || $this->afterCursor)) { | ||
$this->getPage(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note we only fetch the next page if we're done with the current one. we don't want to fetch all pages and then do all the processing. This is also in the readme. |
||
} | ||
return isset($this->tickets[$this->position]); | ||
} | ||
|
||
/** | ||
* Fetches the next page of tickets from the API. | ||
*/ | ||
private function getPage() | ||
{ | ||
$this->started = true; | ||
$params = ['page[size]' => $this->pageSize]; | ||
if ($this->afterCursor) { | ||
$params['page[after]'] = $this->afterCursor; | ||
} | ||
$response = $this->resources->findAll($params); | ||
$this->tickets = array_merge($this->tickets, $response->tickets); | ||
$this->afterCursor = $response->meta->has_more ? $response->meta->after_cursor : null; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
namespace Zendesk\API\UnitTests\Core; | ||
|
||
use Zendesk\API\UnitTests\BasicTest; | ||
use Zendesk\API\Traits\Utility\TicketsIterator; | ||
|
||
class MockTickets { | ||
public function findAll($params) | ||
{ | ||
static $callCount = 0; | ||
|
||
// Simulate two pages of tickets | ||
$tickets = $callCount === 0 | ||
? [['id' => 1], ['id' => 2]] | ||
: [['id' => 3], ['id' => 4]]; | ||
|
||
// Simulate a cursor for the next page on the first call | ||
$afterCursor = $callCount === 0 ? 'cursor_for_next_page' : null; | ||
|
||
$callCount++; | ||
|
||
return (object) [ | ||
'tickets' => $tickets, | ||
'meta' => (object) [ | ||
'has_more' => $afterCursor !== null, | ||
'after_cursor' => $afterCursor, | ||
], | ||
]; | ||
} | ||
} | ||
|
||
class TicketsIteratorTest extends BasicTest | ||
{ | ||
public function testFetchesTickets() | ||
{ | ||
$mockTickets = new MockTickets; | ||
$iterator = new TicketsIterator($mockTickets, 2); | ||
|
||
$tickets = iterator_to_array($iterator); | ||
|
||
$this->assertEquals([['id' => 1], ['id' => 2], ['id' => 3], ['id' => 4]], $tickets); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this,
valid
,key
and other methods are part of the PHP Iterator pattern.