Skip to content

Commit

Permalink
Added ability to transform result items (#8)
Browse files Browse the repository at this point in the history
Co-authored-by: Antanas Kiselis <a.kiselis@paysera.com>
  • Loading branch information
tonykiselis and Antanas Kiselis authored Sep 22, 2020
1 parent ef2696a commit 0afeede
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 4 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.2.0
### Added
- `ConfiguredQuery` provides new methods: `setItemTransformer`, `getItemTransformer`.
Accepts `callable` type. Receives result item - return value replaces received item in result.

## 1.1.0
### Added
- Support for datetime

## 1.0.0
### Fixed
- support single `group-by` statement in `ResultProvider:findCount` - this enables to properly get count of grouped statements.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Use `ResultProvider` class (service) to provide the result.

To get the result, two arguments are needed:
- `ConfiguredQuery`. This is wrapper around `QueryBuilder` and has configuration for available ordering fields,
maximum offset and whether total count should be calculated;
maximum offset, result item transformation and whether total count should be calculated;
- `Pager`. This holds parameters provided by the user: offset or after/before cursor, limit and ordering directions.

Generally `ConfiguredQuery` holds internals related to `QueryBuilder` so it's recommended to return this from the
Expand All @@ -108,10 +108,10 @@ Generally `ConfiguredQuery` holds internals related to `QueryBuilder` so it's re
Example usage:
```php
<?php
use Paysera\Pagination\Entity\Doctrine\ConfiguredQuery;
use Paysera\Pagination\Service\Doctrine\ResultProvider;
use Paysera\Pagination\Service\CursorBuilder;
use Paysera\Pagination\Service\Doctrine\QueryAnalyser;
use Paysera\Pagination\Entity\Doctrine\ConfiguredQuery;
use Paysera\Pagination\Entity\OrderingConfiguration;
use Paysera\Pagination\Entity\Pager;
use Paysera\Pagination\Entity\OrderingPair;
Expand Down Expand Up @@ -139,6 +139,9 @@ $configuredQuery = (new ConfiguredQuery($queryBuilder))
->addOrderingConfiguration('my_other_name', new OrderingConfiguration('m.otherField', 'otherField'))
->setTotalCountNeeded(true) // total count will be returned only if this is called
->setMaximumOffset(100) // you can optionally limit maximum offset
->setItemTransformer(function ($item) {
// return transformed item if needed
})
;

$pager = (new Pager())
Expand Down
20 changes: 20 additions & 0 deletions src/Entity/Doctrine/ConfiguredQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class ConfiguredQuery
*/
private $maximumOffset;

/**
* @var callable
*/
private $itemTransformer;

public function __construct(QueryBuilder $queryBuilder)
{
$this->queryBuilder = $queryBuilder;
Expand Down Expand Up @@ -124,4 +129,19 @@ public function getMaximumOffset(): int

return $this->maximumOffset;
}

/**
* @return callable|null
*/
public function getItemTransformer()
{
return $this->itemTransformer;
}

public function setItemTransformer(callable $itemTransformer): self
{
$this->itemTransformer = $itemTransformer;

return $this;
}
}
21 changes: 19 additions & 2 deletions src/Service/Doctrine/ResultProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public function getResultForQuery(ConfiguredQuery $configuredQuery, Pager $pager

$result = $this->buildResult($analysedQuery, $pager);

if ($configuredQuery->getItemTransformer() !== null) {
$this->transformResultItems($configuredQuery->getItemTransformer(), $result);
}

if ($configuredQuery->isTotalCountNeeded()) {
$totalCount = $this->calculateTotalCount($pager, count($result->getItems()));
if ($totalCount === null) {
Expand Down Expand Up @@ -246,7 +250,6 @@ private function buildResultForZeroLimit(AnalysedQuery $analysedQuery, Pager $ze
->setHasPrevious($this->existsBeforeCursor($previousCursor, $analysedQuery))
->setHasNext(true)
;

}

private function buildResultForTooLargeOffset(AnalysedQuery $analysedQuery): Result
Expand Down Expand Up @@ -291,6 +294,7 @@ private function existsBeforeCursor(string $previousCursor, AnalysedQuery $analy
->setBefore($previousCursor)
->setLimit(1)
;

return count($this->findItems($analysedQuery, $nextPager)) > 0;
}

Expand All @@ -300,6 +304,7 @@ private function existsAfterCursor(string $nextCursor, AnalysedQuery $analysedQu
->setAfter($nextCursor)
->setLimit(1)
;

return count($this->findItems($analysedQuery, $nextPager)) > 0;
}

Expand Down Expand Up @@ -365,7 +370,9 @@ private function getSingleValidGroupByColumn(QueryBuilder $queryBuilder)

if (count($groupByParts) > 1) {
$groupNames = array_map(
function (GroupBy $groupBy) { return $groupBy->getParts()[0]; },
function (GroupBy $groupBy) {
return $groupBy->getParts()[0];
},
$groupByParts
);
throw new InvalidGroupByException(implode(', ', $groupNames));
Expand All @@ -377,4 +384,14 @@ function (GroupBy $groupBy) { return $groupBy->getParts()[0]; },

return $groupByParts[0]->getParts()[0];
}

private function transformResultItems(callable $transform, Result $result)
{
$transformedItems = [];
foreach ($result->getItems() as $item) {
$transformedItems[] = $transform($item);
}

$result->setItems($transformedItems);
}
}
24 changes: 24 additions & 0 deletions tests/Functional/Service/Doctrine/ResultIteratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,28 @@ public function testIterate()
return $logInfo[0] === 'info';
}));
}

public function testTransformResultItems()
{
$entityManager = $this->createTestEntityManager();
$this->createTestData($entityManager);

$queryBuilder = $entityManager->createQueryBuilder()
->select('p')
->from('PaginationTest:ParentTestEntity', 'p')
;

$configuredQuery = new ConfiguredQuery($queryBuilder);
$configuredQuery->setItemTransformer(function ($item) {
return $item->getName();
});
$resultArray = iterator_to_array($this->resultIterator->iterate($configuredQuery));
list($resultItem) = $resultArray;
$this->assertEquals('P9', $resultItem);

$configuredQuery = new ConfiguredQuery($queryBuilder);
$resultArray = iterator_to_array($this->resultIterator->iterate($configuredQuery));
list($resultItem) = $resultArray;
$this->assertEquals('P9', $resultItem->getName());
}
}

0 comments on commit 0afeede

Please sign in to comment.