diff --git a/CHANGELOG.md b/CHANGELOG.md index 31c0777..e66c37d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/README.md b/README.md index cf40fba..cab6416 100644 --- a/README.md +++ b/README.md @@ -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 @@ -108,10 +108,10 @@ Generally `ConfiguredQuery` holds internals related to `QueryBuilder` so it's re Example usage: ```php 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()) diff --git a/src/Entity/Doctrine/ConfiguredQuery.php b/src/Entity/Doctrine/ConfiguredQuery.php index 7a74277..c39a6c6 100644 --- a/src/Entity/Doctrine/ConfiguredQuery.php +++ b/src/Entity/Doctrine/ConfiguredQuery.php @@ -31,6 +31,11 @@ class ConfiguredQuery */ private $maximumOffset; + /** + * @var callable + */ + private $itemTransformer; + public function __construct(QueryBuilder $queryBuilder) { $this->queryBuilder = $queryBuilder; @@ -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; + } } diff --git a/src/Service/Doctrine/ResultProvider.php b/src/Service/Doctrine/ResultProvider.php index 024e460..e135117 100644 --- a/src/Service/Doctrine/ResultProvider.php +++ b/src/Service/Doctrine/ResultProvider.php @@ -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) { @@ -246,7 +250,6 @@ private function buildResultForZeroLimit(AnalysedQuery $analysedQuery, Pager $ze ->setHasPrevious($this->existsBeforeCursor($previousCursor, $analysedQuery)) ->setHasNext(true) ; - } private function buildResultForTooLargeOffset(AnalysedQuery $analysedQuery): Result @@ -291,6 +294,7 @@ private function existsBeforeCursor(string $previousCursor, AnalysedQuery $analy ->setBefore($previousCursor) ->setLimit(1) ; + return count($this->findItems($analysedQuery, $nextPager)) > 0; } @@ -300,6 +304,7 @@ private function existsAfterCursor(string $nextCursor, AnalysedQuery $analysedQu ->setAfter($nextCursor) ->setLimit(1) ; + return count($this->findItems($analysedQuery, $nextPager)) > 0; } @@ -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)); @@ -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); + } } diff --git a/tests/Functional/Service/Doctrine/ResultIteratorTest.php b/tests/Functional/Service/Doctrine/ResultIteratorTest.php index 8e73487..dbf1306 100644 --- a/tests/Functional/Service/Doctrine/ResultIteratorTest.php +++ b/tests/Functional/Service/Doctrine/ResultIteratorTest.php @@ -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()); + } }