entityManager = $this->createMock(EntityManagerInterface::class); $this->pagination = new Pagination(['enabled' => true]); $this->extension1 = $this->createMock(QueryCollectionExtensionInterface::class); $this->extension2 = $this->createMock(QueryCollectionExtensionInterface::class); } private function getProviderUtilsMockForMethod(string $methodName): ProviderUtils|MockObject { $providerUtils = $this ->getMockBuilder(ProviderUtils::class) ->setConstructorArgs([ $this->entityManager, [$this->extension1, $this->extension2], $this->pagination ]) ->setMethodsExcept([$methodName]) ->getMock(); return $providerUtils; } public function testApplyCollectionExtensionsAndPagination(): void { $providerUtils = $this->getProviderUtilsMockForMethod('applyCollectionExtensionsAndPagination'); $entityClass = 'App\Entity\Test\TestEntity'; $operation = $this->createMock(Operation::class); $context = ['filters' => ['name' => 'test']]; $platform = $this->createMock(AbstractPlatform::class); $connection = $this->createMock(Connection::class); $connection->expects(self::any())->method('getDatabasePlatform')->willReturn($platform); $query = $this->createMock(Query::class); $query->method('getEntityManager')->willReturn($this->entityManager); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('getQuery')->willReturn($query); $queryBuilder->method('getEntityManager')->willReturn($this->entityManager); $repository = $this->createMock(EntityRepository::class); $repository ->expects(self::once()) ->method('createQueryBuilder') ->with('o') ->willReturn($queryBuilder); $this->entityManager ->expects(self::once()) ->method('getRepository') ->with($entityClass) ->willReturn($repository); $this->entityManager ->method('getConnection') ->willReturn($connection); // Mock extensions applying to the query $this->extension1 ->expects(self::once()) ->method('applyToCollection') ->with( $queryBuilder, self::isInstanceOf(QueryNameGenerator::class), $entityClass, $operation, $context ); $this->extension2 ->expects(self::once()) ->method('applyToCollection') ->with( $queryBuilder, self::isInstanceOf(QueryNameGenerator::class), $entityClass, $operation, $context ); // Real pagination will be used $result = $providerUtils->applyCollectionExtensionsAndPagination($entityClass, $operation, $context); $this->assertInstanceOf(TraversablePaginator::class, $result); } public function testApplyCollectionExtensionsAndPaginationWithoutContext(): void { $providerUtils = $this->getProviderUtilsMockForMethod('applyCollectionExtensionsAndPagination'); $entityClass = 'App\Entity\Test\TestEntity'; $operation = $this->createMock(Operation::class); $platform = $this->createMock(AbstractPlatform::class); $connection = $this->createMock(Connection::class); $connection->expects(self::any())->method('getDatabasePlatform')->willReturn($platform); $query = $this->createMock(Query::class); $query->method('getEntityManager')->willReturn($this->entityManager); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('getQuery')->willReturn($query); $queryBuilder->method('getEntityManager')->willReturn($this->entityManager); $repository = $this->createMock(EntityRepository::class); $repository ->expects(self::once()) ->method('createQueryBuilder') ->with('o') ->willReturn($queryBuilder); $this->entityManager ->expects(self::once()) ->method('getRepository') ->with($entityClass) ->willReturn($repository); $this->entityManager ->method('getConnection') ->willReturn($connection); // Extensions should still be applied with empty context $this->extension1 ->expects(self::once()) ->method('applyToCollection') ->with( $queryBuilder, self::isInstanceOf(QueryNameGenerator::class), $entityClass, $operation, [] ); $this->extension2 ->expects(self::once()) ->method('applyToCollection') ->with( $queryBuilder, self::isInstanceOf(QueryNameGenerator::class), $entityClass, $operation, [] ); $result = $providerUtils->applyCollectionExtensionsAndPagination($entityClass, $operation); $this->assertInstanceOf(TraversablePaginator::class, $result); } public function testApplyCollectionExtensionsAndPaginationWithNonQueryCollectionExtension(): void { $entityClass = 'App\Entity\Test\TestEntity'; $operation = $this->createMock(Operation::class); $nonQueryExtension = new class {}; $providerUtils = $this ->getMockBuilder(ProviderUtils::class) ->setConstructorArgs([ $this->entityManager, [$this->extension1, $nonQueryExtension, $this->extension2], $this->pagination ]) ->setMethodsExcept(['applyCollectionExtensionsAndPagination']) ->getMock(); $platform = $this->createMock(AbstractPlatform::class); $connection = $this->createMock(Connection::class); $connection->expects(self::any())->method('getDatabasePlatform')->willReturn($platform); $query = $this->createMock(Query::class); $query->method('getEntityManager')->willReturn($this->entityManager); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('getQuery')->willReturn($query); $queryBuilder->method('getEntityManager')->willReturn($this->entityManager); $repository = $this->createMock(EntityRepository::class); $repository ->expects(self::once()) ->method('createQueryBuilder') ->with('o') ->willReturn($queryBuilder); $this->entityManager ->expects(self::once()) ->method('getRepository') ->with($entityClass) ->willReturn($repository); $this->entityManager ->method('getConnection') ->willReturn($connection); $this->extension1 ->expects(self::once()) ->method('applyToCollection'); $this->extension2 ->expects(self::once()) ->method('applyToCollection'); $result = $providerUtils->applyCollectionExtensionsAndPagination($entityClass, $operation); $this->assertInstanceOf(TraversablePaginator::class, $result); } public function testApplyCollectionExtensionsAndPaginationCreatesCorrectDoctrinePaginator(): void { $providerUtils = $this->getProviderUtilsMockForMethod('applyCollectionExtensionsAndPagination'); $entityClass = 'App\Entity\Test\TestEntity'; $operation = $this->createMock(Operation::class); $platform = $this->createMock(AbstractPlatform::class); $connection = $this->createMock(Connection::class); $connection->expects(self::any())->method('getDatabasePlatform')->willReturn($platform); $query = $this->createMock(Query::class); $query->method('getEntityManager')->willReturn($this->entityManager); $queryBuilder = $this->createMock(QueryBuilder::class); $queryBuilder->method('getQuery')->willReturn($query); $queryBuilder->method('getEntityManager')->willReturn($this->entityManager); $repository = $this->createMock(EntityRepository::class); $repository ->expects(self::once()) ->method('createQueryBuilder') ->with('o') ->willReturn($queryBuilder); $this->entityManager ->expects(self::once()) ->method('getRepository') ->with($entityClass) ->willReturn($repository); $this->entityManager ->method('getConnection') ->willReturn($connection); $this->extension1 ->expects(self::once()) ->method('applyToCollection'); $this->extension2 ->expects(self::once()) ->method('applyToCollection'); // Real pagination will be used $result = $providerUtils->applyCollectionExtensionsAndPagination($entityClass, $operation); $this->assertInstanceOf(TraversablePaginator::class, $result); } public function testGetTraversablePaginator(): void { $providerUtils = $this->getProviderUtilsMockForMethod('getTraversablePaginator'); $mappedItems = ['item1', 'item2', 'item3']; $originalPaginator = new TraversablePaginator( new \ArrayIterator(['original1', 'original2']), 2, 10, 50 ); $result = $providerUtils->getTraversablePaginator($mappedItems, $originalPaginator); $this->assertInstanceOf(TraversablePaginator::class, $result); $this->assertEquals(2, $result->getCurrentPage()); $this->assertEquals(10, $result->getItemsPerPage()); $this->assertEquals(50, $result->getTotalItems()); // Test that the iterator contains the mapped items $resultItems = iterator_to_array($result->getIterator()); $this->assertSame($mappedItems, $resultItems); } public function testGetTraversablePaginatorWithEmptyMappedItems(): void { $providerUtils = $this->getProviderUtilsMockForMethod('getTraversablePaginator'); $mappedItems = []; $originalPaginator = new TraversablePaginator( new \ArrayIterator([]), 1, 30, 0 ); $result = $providerUtils->getTraversablePaginator($mappedItems, $originalPaginator); $this->assertInstanceOf(TraversablePaginator::class, $result); $this->assertEquals(1, $result->getCurrentPage()); $this->assertEquals(30, $result->getItemsPerPage()); $this->assertEquals(0, $result->getTotalItems()); $this->assertEmpty(iterator_to_array($result->getIterator())); } public function testGetTraversablePaginatorWithComplexMappedItems(): void { $providerUtils = $this->getProviderUtilsMockForMethod('getTraversablePaginator'); $mappedItems = [ ['id' => 1, 'name' => 'Item 1'], ['id' => 2, 'name' => 'Item 2'], (object)['id' => 3, 'name' => 'Item 3'], ]; $originalPaginator = new TraversablePaginator( new \ArrayIterator(['original1', 'original2', 'original3']), 3, 5, 100 ); $result = $providerUtils->getTraversablePaginator($mappedItems, $originalPaginator); $this->assertInstanceOf(TraversablePaginator::class, $result); $this->assertEquals(3, $result->getCurrentPage()); $this->assertEquals(5, $result->getItemsPerPage()); $this->assertEquals(100, $result->getTotalItems()); $resultItems = iterator_to_array($result->getIterator()); $this->assertCount(3, $resultItems); $this->assertSame($mappedItems, $resultItems); } }