Skip to content

Commit

Permalink
Fix paginating with multiple initial inputs
Browse files Browse the repository at this point in the history
Reset paginator state after finishing paginating for one base input,
to enable paginating multiple listings of the same structure.

Also fix a warning when running tests, because of a final new line in
a demo cache file and add memory limit option when running phpstan.
  • Loading branch information
otsch committed Dec 19, 2023
1 parent b3d657f commit dd653ee
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ trim_trailing_whitespace = false

[*.yml]
indent_size = 2

[_cachefilecontent]
insert_final_newline = false
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.3.4] - 2023-12-19
### Fixed
* Reset paginator state after finishing paginating for one base input, to enable paginating multiple listings of the same structure.

## [1.3.3] - 2023-12-01
### Fixed
* Add forgotten getter method to get the DOM query that is attached to an `InvalidDomQueryException` instance.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"scripts": {
"test": "pest --exclude-group integration",
"test-integration": "pest --group integration",
"stan": "phpstan analyse",
"stan": "@php -d memory_limit=4G vendor/bin/phpstan analyse",
"cs": "php-cs-fixer fix -v --dry-run",
"cs-fix": "php-cs-fixer fix -v",
"add-git-hooks": "@php bin/add-git-hooks"
Expand Down
19 changes: 19 additions & 0 deletions src/Steps/Loading/Http/AbstractPaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ public function hasFinished(): bool
return $this->hasFinished || $this->maxPagesReached();
}

/**
* When a paginate step is called with multiple inputs, like:
*
* ['https://www.example.com/listing1', 'https://www.example.com/listing2', ...]
*
* it always has to start paginating again for each listing base URL.
* Therefore, we reset the state after finishing paginating one base input.
* Except for $this->found, because if it would be the case that the exact same pages are
* discovered whilst paginating, we don't want to load the exact same pages again and again.
*/
public function resetFinished(): void
{
$this->hasFinished = false;

$this->loadedCount = 0;

$this->latestRequest = null;
}

public function stopWhen(Closure|StopRule $callback): self
{
$this->stopRules[] = $callback;
Expand Down
4 changes: 4 additions & 0 deletions src/Steps/Loading/Http/Paginate.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ protected function invoke(mixed $input): Generator

if ($this->logger) {
$this->paginator->logWhenFinished($this->logger);

if (method_exists($this->paginator, 'resetFinished')) {
$this->paginator->resetFinished();
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Cache/_cachefilecontent
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,4 @@ $query = Query::fromString('foo=1&bar=2&baz=3&quz=4')
<script>hljs.highlightAll();</script>
</body>
</html>
";}
";}
12 changes: 12 additions & 0 deletions tests/_Integration/Http/PaginationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,15 @@ protected function loader(UserAgentInterface $userAgent, LoggerInterface $logger

expect($this->getActualOutputForAssertion())->toContain('Max pages limit reached');
});

it('resets the finished paginating state after each processed (/paginated) input', function () {
$crawler = new PaginationCrawler();

$crawler
->inputs(['http://localhost:8000/paginated-listing', 'http://localhost:8000/paginated-listing?foo=bar'])
->addStep(Http::get()->paginate('#pagination', 2)->outputKey('response'));

$results = helper_generatorToArray($crawler->run());

expect($results)->toHaveCount(4);
});
22 changes: 22 additions & 0 deletions tests/_Integration/Http/QueryParamPaginationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,25 @@ protected function loader(UserAgentInterface $userAgent, LoggerInterface $logger

expect($results)->toHaveCount(2);
});

it('resets the finished paginating state after each processed (/paginated) input', function () {
$crawler = new QueryParamPaginationCrawler();

$crawler
->inputs([
'http://localhost:8000/query-param-pagination?page=1',
'http://localhost:8000/query-param-pagination?page=1&foo=bar',
])
->addStep(
Http::get()
->paginate(
QueryParamsPaginator::paramsInUrl(2)
->increase('page')
->stopWhen(PaginatorStopRules::isEmptyInJson('data.items'))
)->addToResult(['body'])
);

$results = helper_generatorToArray($crawler->run());

expect($results)->toHaveCount(4);
});
9 changes: 7 additions & 2 deletions tests/_Integration/_Server/PaginatedListing.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
<div id="listing">
<?php
$page = $_GET['page'] ?? 1;
$additionalFooQueryParam = '';
$itemsPerPage = 3;

if (!empty($_GET['foo'])) {
$additionalFooQueryParam = '&foo=' . $_GET['foo'];
}

if ($page < 4) {
for ($i = 1; $i < 4; $i++) {
$itemNumber = (($page - 1) * $itemsPerPage) + $i; ?>
Expand All @@ -27,11 +32,11 @@

<div id="pagination">
<?php if ($page > 1) { ?>
<a id="prevPage" href="/paginated-listing?page=<?=($page - 1)?>">&lt;&lt;</a>
<a id="prevPage" href="/paginated-listing?page=<?=($page - 1) . $additionalFooQueryParam?>">&lt;&lt;</a>
<?php } ?>

<?php if ($page < 4) { ?>
<a id="nextPage" href="/paginated-listing?page=<?=($page + 1)?>">&gt;&gt;</a>
<a id="nextPage" href="/paginated-listing?page=<?=($page + 1) . $additionalFooQueryParam?>">&gt;&gt;</a>
<?php } ?>
</div>
</div>
Expand Down

0 comments on commit dd653ee

Please sign in to comment.