Skip to content
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

Red 1953 pagination #513

Merged
merged 18 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ The use of the correct pagination is encapsulated using the iterator pattern, wh
$ticketsIterator = $client->tickets()->iterator();

foreach ($ticketsIterator as $ticket) {
process($ticket) // Your implementation
process($ticket); // Your implementation
}
```

Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ services:
- .:/app
- vendor:/app/vendor
command: vendor/bin/phpunit --testsuite "Zendesk API Unit Test Suites"
# command: vendor/bin/phpunit tests/Zendesk/API/UnitTests/Traits/Utility/PaginationTest.php
# command: vendor/bin/phpunit tests/Zendesk/API/UnitTests/Core/TicketsTest.php
# command: vendor/bin/phpunit tests/Zendesk/API/UnitTests/Core/OrganizationMembershipsTest.php
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do some cleaning at the end, but these comments come useful to switch between tests.


volumes:
vendor:
5 changes: 5 additions & 0 deletions src/Zendesk/API/Resources/Core/AppInstallations.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Zendesk\API\Traits\Resource\Find;
use Zendesk\API\Traits\Resource\FindAll;
use Zendesk\API\Traits\Resource\Update;
use Zendesk\API\Traits\Utility\Pagination\SinglePageStrategy;

/**
* The AppInstallations class exposes methods seen at
Expand Down Expand Up @@ -123,4 +124,8 @@ public function update($id = null, array $updateResourceFields = [], $routeKey =
$updateResourceFields
);
}

private function paginationStrategyClass() {
return SinglePageStrategy::class;
}
Copy link
Collaborator Author

@ecoologic ecoologic Oct 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const are not available in traits in the current PHP version (7.4)

}
5 changes: 5 additions & 0 deletions src/Zendesk/API/Resources/Core/CustomRoles.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Zendesk\API\Resources\ResourceAbstract;
use Zendesk\API\Traits\Resource\FindAll;
use Zendesk\API\Traits\Utility\Pagination\SinglePageStrategy;

/**
* Class CustomRoles
Expand All @@ -12,4 +13,8 @@
class CustomRoles extends ResourceAbstract
{
use FindAll;

protected function paginationStrategyClass() {
return SinglePageStrategy::class;
}
}
6 changes: 6 additions & 0 deletions src/Zendesk/API/Resources/Core/SharingAgreements.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Zendesk\API\Resources\ResourceAbstract;
use Zendesk\API\Traits\Resource\FindAll;
use Zendesk\API\Traits\Utility\Pagination\ObpStrategy;
use Zendesk\API\Traits\Utility\Pagination\SinglePageStrategy;

/**
* The SharingAgreements class
Expand All @@ -12,4 +14,8 @@
class SharingAgreements extends ResourceAbstract
{
use FindAll;

protected function paginationStrategyClass() {
return SinglePageStrategy::class;
}
}
5 changes: 5 additions & 0 deletions src/Zendesk/API/Resources/Core/Targets.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

use Zendesk\API\Resources\ResourceAbstract;
use Zendesk\API\Traits\Resource\Defaults;
use Zendesk\API\Traits\Utility\Pagination\SinglePageStrategy;

/**
* The Tags class exposes methods as detailed on https://developer.zendesk.com/rest_api/docs/core/targets
*/
class Targets extends ResourceAbstract
{
use Defaults;

protected function paginationStrategyClass() {
return SinglePageStrategy::class;
}
}
14 changes: 0 additions & 14 deletions src/Zendesk/API/Resources/Core/Tickets.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use Zendesk\API\Traits\Resource\FindMany;
use Zendesk\API\Traits\Resource\UpdateMany;
use Zendesk\API\Traits\Utility\InstantiatorTrait;
use Zendesk\API\Traits\Utility\TicketsIterator;

/**
* The Tickets class exposes key methods for reading and updating ticket data
Expand Down Expand Up @@ -45,19 +44,6 @@ class Tickets extends ResourceAbstract
*/
protected $lastAttachments = [];

/**
* Usage:
* foreach ($ticketsIterator as $ticket) {
* process($ticket)
* }
*
* @return TicketsIterator Returns a new TicketsIterator object.
*/
public function iterator()
{
return new TicketsIterator($this);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved into trait to make it generic to all resources.

/**
* {@inheritdoc}
*/
Expand Down
5 changes: 4 additions & 1 deletion src/Zendesk/API/Traits/Resource/FindAll.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
namespace Zendesk\API\Traits\Resource;

use Zendesk\API\Exceptions\RouteException;
use Zendesk\API\Traits\Utility\Pagination\CbpStrategy;

trait FindAll
{
use Pagination;

/**
* List all of this resource
*
Expand All @@ -22,7 +25,7 @@ public function findAll(array $params = [], $routeKey = __FUNCTION__)
try {
$route = $this->getRoute($routeKey, $params);
} catch (RouteException $e) {
if (! isset($this->resourceName)) {
if (!isset($this->resourceName)) {
$this->resourceName = $this->getResourceNameFromClass();
}

Expand Down
36 changes: 36 additions & 0 deletions src/Zendesk/API/Traits/Resource/Pagination.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Zendesk\API\Traits\Resource;

use Zendesk\API\Traits\Utility\Pagination\AbstractStrategy;
use Zendesk\API\Traits\Utility\Pagination\CbpStrategy;
use Zendesk\API\Traits\Utility\Pagination\PaginationIterator;

trait Pagination {

/**
* Usage:
* foreach ($ticketsIterator as $ticket) {
* process($ticket)
* }
*
* @return PaginationIterator to fetch all pages.
*/
public function iterator()
{
$strategyClass = $this->paginationStrategyClass();
$strategy = new $strategyClass($this, $this->resourcesKey(), AbstractStrategy::DEFAULT_PAGE_SIZE);
return new PaginationIterator($strategy);
}

protected function paginationStrategyClass() {
return CbpStrategy::class;
}

/*
* @return string eg: "job_statuses"
*/
protected function resourcesKey() {
return $this->objectNamePlural;
}
}
28 changes: 28 additions & 0 deletions src/Zendesk/API/Traits/Utility/Pagination/AbstractStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
namespace Zendesk\API\Traits\Utility\Pagination;

abstract class AbstractStrategy
{
public const DEFAULT_PAGE_SIZE = 100;

/*
* @var mixed use trait FindAll. The object handling the list, Ie: `$client->{clientList}()`
*/
protected $clientList;

/*
* @var string The response key where the data is returned
*/
protected $resourcesKey;
protected $pageSize;

public function __construct($clientList, $resourcesKey, $pageSize = self::DEFAULT_PAGE_SIZE)
{
$this->clientList = $clientList;
$this->resourcesKey = $resourcesKey;
$this->pageSize = $pageSize;
}

abstract public function getPage();
abstract public function shouldGetPage($position);
}
26 changes: 26 additions & 0 deletions src/Zendesk/API/Traits/Utility/Pagination/CbpStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Zendesk\API\Traits\Utility\Pagination;

class CbpStrategy extends AbstractStrategy
{
private $afterCursor = null;
private $started = false;

public function getPage()
{
$this->started = true;
$params = ['page[size]' => $this->pageSize];
if ($this->afterCursor) {
$params['page[after]'] = $this->afterCursor;
}
$response = $this->clientList->findAll($params);

$this->afterCursor = $response->meta->has_more ? $response->meta->after_cursor : null;
return $response->{$this->resourcesKey};
}

public function shouldGetPage($position) {
return !$this->started || $this->afterCursor;
}
}
25 changes: 25 additions & 0 deletions src/Zendesk/API/Traits/Utility/Pagination/ObpStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Zendesk\API\Traits\Utility\Pagination;


/**
* Offset Based Pagination
*/
class ObpStrategy extends AbstractStrategy
{
private $pageNumber = 0;

public function getPage()
{
++$this->pageNumber;
$params = ['page' => $this->pageNumber, 'page_size' => $this->pageSize];
$response = $this->clientList->findAll($params);

return $response->{$this->resourcesKey};
}

public function shouldGetPage($position) {
return $this->pageNumber == 0 || $position >= $this->pageNumber * $this->pageSize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Zendesk\API\Traits\Utility\Pagination;

use Iterator;

class PaginationIterator implements Iterator
{
private $position = 0;
private $page = [];
private $strategy;

public function __construct(AbstractStrategy $strategy)
{
$this->strategy = $strategy;
}

public function key()
{
return $this->position;
}

public function next()
{
++$this->position;
}

public function rewind()
{
$this->position = 0;
}

public function valid()
{
$this->getPageIfNecessary();
return !!$this->current();
}

public function current()
{
if (isset($this->page[$this->position])) {
return $this->page[$this->position];
} else {
return null;
}
}

private function getPageIfNecessary()
{
if (!$this->strategy->shouldGetPage($this->position)) {
return;
}

$this->page = array_merge($this->page, $this->strategy->getPage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Zendesk\API\Traits\Utility\Pagination;


/**
* Single Page (no pagination)
*/
class SinglePageStrategy extends AbstractStrategy
{
protected $started = false;

public function getPage()
{
$this->started = true;
$response = $this->clientList->findAll();

return $response->{$this->resourcesKey};
}

public function shouldGetPage($position) {
return !$this->started;
}
}
Loading
Loading