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

Feature/better pagination handling: add: better pagination handling #73

Merged
merged 8 commits into from
Jul 11, 2022
14 changes: 13 additions & 1 deletion src/Endpoints/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace FiveamCode\LaravelNotionApi\Endpoints;

use FiveamCode\LaravelNotionApi\Entities\Collections\EntityCollection;
use FiveamCode\LaravelNotionApi\Entities\Collections\PageCollection;
use FiveamCode\LaravelNotionApi\Notion;
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
Expand Down Expand Up @@ -66,7 +67,7 @@ public function query(): PageCollection
} // TODO Compound filters!

if ($this->startCursor !== null) {
$postData['start_cursor'] = $this->startCursor;
$postData['start_cursor'] = $this->startCursor->__toString();
}

if ($this->pageSize !== null) {
Expand Down Expand Up @@ -104,4 +105,15 @@ public function sortBy(Collection $sorts): Database

return $this;
}

/**
* @param EntityCollection $entityCollection
* @return $this
*/
public function offsetByResponse(EntityCollection $entityCollection): Database
{
$this->offset($entityCollection->nextCursor());

return $this;
}
}
51 changes: 51 additions & 0 deletions src/Entities/Collections/EntityCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Query\StartCursor;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

Expand All @@ -25,6 +26,16 @@ class EntityCollection
*/
protected array $rawResults = [];

/**
* @var bool
*/
protected bool $hasMore = false;

/**
* @var string
*/
protected ?string $nextCursor = null;

/**
* @var Collection
*/
Expand Down Expand Up @@ -96,13 +107,24 @@ protected function collectChildren(): void
protected function fillFromRaw()
{
$this->fillResult();
$this->fillCursorInformation();
}

protected function fillResult()
{
$this->rawResults = $this->responseData['results'];
}

protected function fillCursorInformation()
{
if (Arr::exists($this->responseData, 'has_more')) {
$this->hasMore = $this->responseData['has_more'];
}
if (Arr::exists($this->responseData, 'next_cursor')) {
$this->nextCursor = $this->responseData['next_cursor'];
}
}

/**
* @return array
*/
Expand All @@ -111,6 +133,14 @@ public function getRawResponse(): array
return $this->responseData;
}

/**
* @return string
*/
public function getRawNextCursor(): ?string
{
return $this->nextCursor;
}

/**
* @return Collection
*/
Expand All @@ -128,4 +158,25 @@ public function asJson(): string
return $item->toArray();
});
}

/**
* @return bool
*/
public function hasMoreEntries(): bool
{
return $this->hasMore;
}

/**
* @return StartCursor
*/
public function nextCursor(): ?StartCursor
{
$rawNextCursor = $this->getRawNextCursor();
if ($rawNextCursor === null) {
return null;
}

return new StartCursor($rawNextCursor);
}
}
2 changes: 1 addition & 1 deletion src/Query/StartCursor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function __construct(string $cursor)
$this->cursor = $cursor;
}

public function __toString()
public function __toString(): string
{
return $this->cursor;
}
Expand Down
58 changes: 58 additions & 0 deletions tests/EndpointDatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
use FiveamCode\LaravelNotionApi\Query\Sorting;
use FiveamCode\LaravelNotionApi\Query\StartCursor;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Notion;
Expand Down Expand Up @@ -158,6 +159,63 @@ public function it_throws_a_notion_exception_bad_request()
Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')->query();
}

/** @test */
public function it_queries_a_database_with_and_without_offset_and_processes_result()
{
// success /v1/databases/DATABASE_DOES_EXIST/query
Http::fake([
'https://api.notion.com/v1/databases/8284f3ff77e24d4a939d19459e4d6bdc/query*' => Http::sequence()
->push(
json_decode(file_get_contents('tests/stubs/endpoints/databases/response_query_offset_start_200.json'), true),
200,
['Headers']
)
->push(
json_decode(file_get_contents('tests/stubs/endpoints/databases/response_query_offset_end_200.json'), true),
200,
['Headers']
),
]);

$result = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')
->query();

//check instance and offset
$this->assertInstanceOf(PageCollection::class, $result);
$this->assertEquals(true, $result->hasMoreEntries());
$this->assertInstanceOf(StartCursor::class, $result->nextCursor());
$this->assertEquals('1500b7c7-329f-4854-8912-4c6972a8743e', $result->nextCursor());
$this->assertEquals('1500b7c7-329f-4854-8912-4c6972a8743e', $result->getRawNextCursor());

$resultCollection = $result->asCollection();

$this->assertIsIterable($resultCollection);
$this->assertContainsOnly(Page::class, $resultCollection);

// check page object
$page = $resultCollection->first();
$this->assertEquals('Betty Holberton', $page->getTitle());

$resultWithOffset = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc')
->offsetByResponse($result)
->query();

// check instance and offset
$this->assertInstanceOf(PageCollection::class, $resultWithOffset);
$this->assertEquals(false, $resultWithOffset->hasMoreEntries());
$this->assertEquals(null, $resultWithOffset->nextCursor());
$this->assertEquals(null, $resultWithOffset->getRawNextCursor());

$resultWithOffsetCollection = $resultWithOffset->asCollection();

$this->assertIsIterable($resultWithOffsetCollection);
$this->assertContainsOnly(Page::class, $resultWithOffsetCollection);

// check page object
$page = $resultWithOffsetCollection->first();
$this->assertEquals('Betty Holberton', $page->getTitle());
}

/**
* @test
* ! edge-case
Expand Down
163 changes: 163 additions & 0 deletions tests/stubs/endpoints/databases/response_query_offset_end_200.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
{
"object": "list",
"results": [
{
"object": "page",
"id": "1500b7c7-329f-4854-8912-4c6972a8743e",
"created_time": "2021-05-24T11:03:00.000Z",
"last_edited_time": "2021-05-24T11:13:00.000Z",
"parent": {
"type": "database_id",
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
},
"archived": false,
"properties": {
"Birth year": {
"id": "_f<<",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "1917",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "1917",
"href": null
}
]
},
"Known for": {
"id": "aUmo",
"type": "multi_select",
"multi_select": [
{
"id": "f55ee1a3-e67f-4793-ba3f-5dac02938a5f",
"name": "ENIAC",
"color": "purple"
},
{
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
"name": "UNIVAC",
"color": "default"
},
{
"id": "55c46053-f87e-40e9-8070-6c398939fed6",
"name": "Breakpoints",
"color": "red"
}
]
},
"Name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "Betty Holberton",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "Betty Holberton",
"href": null
}
]
}
}
},
{
"object": "page",
"id": "ab2a7a85-08a1-4dfc-be89-0e30aeffc0f6",
"created_time": "2021-05-24T11:03:02.464Z",
"last_edited_time": "2021-05-24T11:12:00.000Z",
"parent": {
"type": "database_id",
"database_id": "8284f3ff-77e2-4d4a-939d-19459e4d6bdc"
},
"archived": false,
"properties": {
"Birth year": {
"id": "_f<<",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "1906",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "1906",
"href": null
}
]
},
"Known for": {
"id": "aUmo",
"type": "multi_select",
"multi_select": [
{
"id": "1ada9715-0139-4c1c-b1af-9d8d2fe80ea2",
"name": "COBOL",
"color": "orange"
},
{
"id": "2016de6e-5325-4549-8e1a-60ee7570382a",
"name": "UNIVAC",
"color": "default"
}
]
},
"Name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "Grace Hopper",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "Grace Hopper",
"href": null
}
]
}
}
}
],
"next_cursor": null,
"has_more": false
}

Loading