Skip to content

Commit

Permalink
Improve methods reusability
Browse files Browse the repository at this point in the history
cerbero90 committed Feb 11, 2024
1 parent ed81c94 commit 45a55b1
Showing 8 changed files with 89 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -10,16 +10,21 @@
use Psr\Http\Message\ResponseInterface;

/**
* The trait to yield paginated items.
* The trait to parse pages.
*/
trait YieldsPaginatedItems
trait ParsesPages
{
/**
* The number of items per page.
*/
protected readonly int $itemsPerPage;

/**
* Yield paginated items and the given key from the provided response.
*
* @return Generator<int, mixed>
*/
protected function yieldItemsAndReturnKey(ResponseInterface $response, string $key): Generator
protected function yieldItemsAndGetKey(ResponseInterface $response, string $key): Generator
{
$itemsPerPage = 0;
$pointers = [$this->config->itemsPointer];
36 changes: 36 additions & 0 deletions src/Concerns/YieldsItemsByCursor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Cerbero\LazyJsonPages\Concerns;

use Cerbero\LazyJsonPages\Services\Client;
use Closure;
use Generator;
use Psr\Http\Message\ResponseInterface;

/**
* The trait to yield items from cursor-aware paginations.
*/
trait YieldsItemsByCursor
{
/**
* Yield the paginated items by following the cursor of each page.
*
* @param (Closure(ResponseInterface): Generator<int, mixed>) $callback
* @return Generator<int, mixed>
*/
protected function yieldItemsByCursor(Closure $callback): Generator
{
yield from $generator = $callback($this->source->pullResponse());

$request = clone $this->source->request();

while ($cursor = $this->toPage($generator->getReturn(), onlyNumerics: false)) {
$uri = $this->uriForPage($request->getUri(), (string) $cursor);
$response = Client::instance()->send($request->withUri($uri));

yield from $generator = $callback($response);
}
}
}
Original file line number Diff line number Diff line change
@@ -2,51 +2,52 @@

declare(strict_types=1);

namespace Cerbero\LazyJsonPages\Paginations;
namespace Cerbero\LazyJsonPages\Concerns;

use Cerbero\LazyJsonPages\Concerns\SendsAsyncRequests;
use Cerbero\LazyJsonPages\Exceptions\InvalidKeyException;
use Closure;
use Generator;
use Illuminate\Support\LazyCollection;
use Psr\Http\Message\ResponseInterface;

/**
* The abstract implementation of a pagination that is aware of its length.
* The trait to yield items from length-aware paginations.
*/
abstract class LengthAwarePagination extends Pagination
trait YieldsItemsByLength
{
use SendsAsyncRequests;

/**
* Yield paginated items until the page resolved from the given key is reached.
*
* @param (Closure(int): int)|null $callback
* @param (Closure(int): int) $callback
* @return Generator<int, mixed>
*/
protected function yieldItemsUntilKey(string $key, ?Closure $callback = null): Generator
protected function yieldItemsUntilKey(string $key, Closure $callback = null): Generator
{
yield from $generator = $this->yieldItemsAndReturnKey($this->source->response(), $key);
yield from $this->yieldItemsUntilPage(function(ResponseInterface $response) use ($key, $callback) {
yield from $generator = $this->yieldItemsAndGetKey($response, $key);

$page = $this->toPage($generator->getReturn());
if (!is_int($page = $this->toPage($generator->getReturn()))) {
throw new InvalidKeyException($key);
}

if (!is_int($page)) {
throw new InvalidKeyException($key);
}

$page = $callback ? $callback($page) : $page;

yield from $this->yieldItemsUntilPage($page);
return $callback ? $callback($page) : $page;
});
}

/**
* Yield paginated items until the given page is reached.
* Yield paginated items until the resolved page is reached.
*
* @param (Closure(ResponseInterface): Generator<int, mixed>) $callback
* @return Generator<int, mixed>
*/
protected function yieldItemsUntilPage(int $page): Generator
protected function yieldItemsUntilPage(Closure $callback): Generator
{
yield from $generator = $callback($this->source->pullResponse());

$uri = $this->source->request()->getUri();
$chunkedPages = $this->chunkPages($page);
$chunkedPages = $this->chunkPages($generator->getReturn());

foreach ($this->fetchPagesAsynchronously($chunkedPages, $uri) as $page) {
yield from $this->yieldItemsFrom($page);
Original file line number Diff line number Diff line change
@@ -4,14 +4,17 @@

namespace Cerbero\LazyJsonPages\Paginations;

use Cerbero\LazyJsonPages\Services\Client;
use Cerbero\LazyJsonPages\Concerns\YieldsItemsByCursor;
use Psr\Http\Message\ResponseInterface;
use Traversable;

/**
* The pagination aware of the cursor of the next page.
*/
class CursorPagination extends Pagination
class CursorAwarePagination extends Pagination
{
use YieldsItemsByCursor;

/**
* Determine whether the configuration matches this pagination.
*/
@@ -30,15 +33,10 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
yield from $generator = $this->yieldItemsAndReturnKey($this->source->response(), $this->config->cursorKey);

$request = clone $this->source->request();

while ($cursor = $this->toPage($generator->getReturn(), onlyNumerics: false)) {
$uri = $this->uriForPage($request->getUri(), (string) $cursor);
$response = Client::instance()->send($request->withUri($uri));
yield from $this->yieldItemsByCursor(function(ResponseInterface $response) {
yield from $generator = $this->yieldItemsAndGetKey($response, $this->config->cursorKey);

yield from $generator = $this->yieldItemsAndReturnKey($response, $this->config->cursorKey);
}
return $generator->getReturn();
});
}
}
2 changes: 1 addition & 1 deletion src/Paginations/CustomPagination.php
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
/**
* The user-defined pagination.
*/
class CustomPagination extends LengthAwarePagination
class CustomPagination extends Pagination
{
/**
* Determine whether the configuration matches this pagination.
7 changes: 5 additions & 2 deletions src/Paginations/LastPageAwarePagination.php
Original file line number Diff line number Diff line change
@@ -4,13 +4,16 @@

namespace Cerbero\LazyJsonPages\Paginations;

use Cerbero\LazyJsonPages\Concerns\YieldsItemsByLength;
use Traversable;

/**
* The pagination aware of the number of the last page.
*/
class LastPageAwarePagination extends LengthAwarePagination
class LastPageAwarePagination extends Pagination
{
use YieldsItemsByLength;

/**
* Determine whether the configuration matches this pagination.
*/
@@ -26,7 +29,7 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
yield from $this->yieldItemsUntilKey($this->config->lastPageKey, function (int $page) {
yield from $this->yieldItemsUntilKey($this->config->lastPageKey, function(int $page) {
return $this->config->firstPage === 0 ? $page + 1 : $page;
});
}
18 changes: 7 additions & 11 deletions src/Paginations/TotalItemsAwarePagination.php
Original file line number Diff line number Diff line change
@@ -4,14 +4,16 @@

namespace Cerbero\LazyJsonPages\Paginations;

use Cerbero\LazyJsonPages\Exceptions\InvalidKeyException;
use Cerbero\LazyJsonPages\Concerns\YieldsItemsByLength;
use Traversable;

/**
* The pagination aware of the total number of items.
*/
class TotalItemsAwarePagination extends LengthAwarePagination
class TotalItemsAwarePagination extends Pagination
{
use YieldsItemsByLength;

/**
* Determine whether the configuration matches this pagination.
*/
@@ -29,14 +31,8 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
yield from $generator = $this->yieldItemsAndReturnKey($this->source->response(), $this->config->totalItemsKey);

if (!is_numeric($totalItems = $generator->getReturn())) {
throw new InvalidKeyException($this->config->totalItemsKey);
}

$totalPages = $this->itemsPerPage > 0 ? (int) ceil(intval($totalItems) / $this->itemsPerPage) : 0;

yield from $this->yieldItemsUntilPage($totalPages);
yield from $this->yieldItemsUntilKey($this->config->totalItemsKey, function(int $totalItems) {
return $this->itemsPerPage > 0 ? (int) ceil($totalItems / $this->itemsPerPage) : 0;
});
}
}
5 changes: 4 additions & 1 deletion src/Paginations/TotalPagesAwarePagination.php
Original file line number Diff line number Diff line change
@@ -4,13 +4,16 @@

namespace Cerbero\LazyJsonPages\Paginations;

use Cerbero\LazyJsonPages\Concerns\YieldsItemsByLength;
use Traversable;

/**
* The pagination aware of the total number of pages.
*/
class TotalPagesAwarePagination extends LengthAwarePagination
class TotalPagesAwarePagination extends Pagination
{
use YieldsItemsByLength;

/**
* Determine whether the configuration matches this pagination.
*/

0 comments on commit 45a55b1

Please sign in to comment.