setCurrentPageNumber($currentPageNumber); $this->setItemsPerPage($itemsPerPage); $this->updateInternalState(); } public function getPaginatedItems(): iterable { return $this->paginatedItems; } protected function updatePaginatedItems(int $itemsPerPage, int $offset): void { $paginatedQueryBuilder = clone $this->queryBuilder; $this->paginatedItems = $paginatedQueryBuilder ->setMaxResults($itemsPerPage) ->setFirstResult($offset) ->executeQuery() ->fetchAllAssociative(); } protected function getTotalAmountOfItems(): int { return $this->getTotalItems(); } protected function getAmountOfItemsOnCurrentPage(): int { return count($this->paginatedItems); } private function getTotalItems(): int { if ($this->totalItems === null) { $clonedQueryBuilder = clone $this->queryBuilder; // Remove obsolete query parts. There is no need to enforce any ordering improving // the performance and pagination constraints (LIMIT and OFFSET) are removed because // otherwise we would not get the total items count. $clonedQueryBuilder ->resetOrderBy() ->setMaxResults(null) ->setFirstResult(0); $this->totalItems = (int)$clonedQueryBuilder->getConnection()->createQueryBuilder() // @todo Upstream doctrine/dbal with() is not adopted in the decoration pattern and the reason to use // typo3 internal implementation for the common table expression here. Replace it when upstream // with() support has been integrated into the decoration chain. ->typo3_with('cte_count', $clonedQueryBuilder) ->count('*') ->from('cte_count') ->setParameters($clonedQueryBuilder->getParameters(), $clonedQueryBuilder->getParameterTypes()) ->executeQuery() ->fetchOne(); } return $this->totalItems; } }