Skip to content

Commit

Permalink
✨ allow for GraphQL pageInfo to for Cursor based Pagination fetch all
Browse files Browse the repository at this point in the history
  • Loading branch information
bnomei committed Feb 25, 2025
1 parent ea822d5 commit 0903ab9
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 16 deletions.
40 changes: 31 additions & 9 deletions classes/APIRecords.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ class APIRecords

private string $cacheKey;

private ?string $recordsDataPageInfo;

public function __construct(protected ?APIRecordsPage $page = null)
{
$this->records = null;

$this->endpointUrl = $this->config('url', resolveClosures: true);
$this->endpointParams = $this->config('params', [], true);
$this->recordsDataQuery = $this->config('query', resolveClosures: true);
$this->recordsDataPageInfo = $this->config('pageInfo', resolveClosures: true);
$this->recordsDataMap = $this->config('map'); // closure resolving here would break the mapping by closure
$this->recordsCacheExpire = $this->config('expire', intval(option('bnomei.api-pages.expire')), true); // @phpstan-ignore-line
$this->recordTemplate = $this->config('template');
Expand Down Expand Up @@ -98,7 +101,7 @@ public function toArray(): array
}

$map = $this->recordsDataMap;
$data = $this->fetch();
$data = $this->fetchPaginated();

if (empty($data)) {
return [];
Expand Down Expand Up @@ -133,27 +136,46 @@ public function toArray(): array
return $this->records = $records;
}

public function fetch(): array
public function fetchPaginated(): array
{
// get cache if it exists
$cache = kirby()->cache('bnomei.api-pages')->get($this->cacheKey);
if ($cache) {
return $cache;
}

// run at least once then keep trying with
// GraphQLs Relay PageInfo Connections Specification
$json = [];
do {
$result = $this->fetch(after: $cursor ?? null);
$cursor = A::get($result, $this->recordsDataPageInfo.'.endCursor');
$hasNextPage = A::get($result, $this->recordsDataPageInfo.'.hasNextPage', false);
$json = array_merge_recursive($json, $result);
} while ($hasNextPage);

$expire = $this->recordsCacheExpire;
if (! is_null($expire) && $expire >= 0) {
kirby()->cache('bnomei.api-pages')->set($this->cacheKey, $json, $expire);
}

return [];
}

public function fetch(?string $after = null): array
{
// fetch from remote
$params = $this->endpointParams;
$expire = $this->recordsCacheExpire;
if ($this->recordsDataPageInfo && $after && $data = A::get($params, 'data')) {
// GraphQL PageInfo starting at null will be paginated with after
$params['data'] = str_replace('after: null', 'after: \"'.$after.'\"', $data);
}

$method = strtolower($params['method'] ?? 'GET');
$remote = Remote::$method($this->endpointUrl, $params);

if ($remote->code() >= 200 && $remote->code() <= 300) {
$json = $remote->json() ?? [];
if (! is_null($expire) && $expire >= 0) {
kirby()->cache('bnomei.api-pages')->set($this->cacheKey, $json, $expire);
}

return $json;
return $remote->json() ?? [];
} else {
$ex = option('bnomei.api-pages.exception');
if ($ex instanceof \Closure) {
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "bnomei/kirby-api-pages",
"type": "kirby-plugin",
"version": "5.0.1",
"version": "5.1.0",
"description": "Virtual Pages from APIs",
"license": "MIT",
"authors": [
Expand Down
20 changes: 18 additions & 2 deletions vendor/composer/InstalledVersions.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class InstalledVersions
*/
private static $installed;

/**
* @var bool
*/
private static $installedIsLocalDir;

/**
* @var bool|null
*/
Expand Down Expand Up @@ -309,6 +314,12 @@ public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();

// when using reload, we disable the duplicate protection to ensure that self::$installed data is
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
// so we have to assume it does not, and that may result in duplicate data being returned when listing
// all installed packages for example
self::$installedIsLocalDir = false;
}

/**
Expand All @@ -325,19 +336,24 @@ private static function getInstalled()
$copiedLocalDir = false;

if (self::$canGetVendors) {
$selfDir = strtr(__DIR__, '\\', '/');
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
$vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
self::$installedByVendor[$vendorDir] = $required;
$installed[] = $required;
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
self::$installed = $required;
$copiedLocalDir = true;
self::$installedIsLocalDir = true;
}
}
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
$copiedLocalDir = true;
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions vendor/composer/installed.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php return array(
'root' => array(
'name' => 'bnomei/kirby-api-pages',
'pretty_version' => '5.0.1',
'version' => '5.0.1.0',
'pretty_version' => '5.1.0',
'version' => '5.1.0.0',
'reference' => null,
'type' => 'kirby-plugin',
'install_path' => __DIR__ . '/../../',
Expand All @@ -11,8 +11,8 @@
),
'versions' => array(
'bnomei/kirby-api-pages' => array(
'pretty_version' => '5.0.1',
'version' => '5.0.1.0',
'pretty_version' => '5.1.0',
'version' => '5.1.0.0',
'reference' => null,
'type' => 'kirby-plugin',
'install_path' => __DIR__ . '/../../',
Expand Down

0 comments on commit 0903ab9

Please sign in to comment.