2020use ApiPlatform \Metadata \Util \IriHelper ;
2121use ApiPlatform \State \Pagination \PaginatorInterface ;
2222use ApiPlatform \State \Pagination \PartialPaginatorInterface ;
23+ use ApiPlatform \Hydra \State \Util \PaginationHelperTrait ;
24+ use ApiPlatform \Hydra \PartialCollectionView ;
2325use Symfony \Component \PropertyAccess \PropertyAccess ;
2426use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
2527use Symfony \Component \Serializer \Exception \UnexpectedValueException ;
3537final class PartialCollectionViewNormalizer implements NormalizerInterface, NormalizerAwareInterface
3638{
3739 use HydraPrefixTrait;
40+ use PaginationHelperTrait;
3841 private readonly PropertyAccessorInterface $ propertyAccessor ;
3942
4043 /**
@@ -60,21 +63,11 @@ public function normalize(mixed $object, ?string $format = null, array $context
6063 throw new UnexpectedValueException ('Expected data to be an array ' );
6164 }
6265
63- $ currentPage = $ lastPage = $ itemsPerPage = $ pageTotalItems = null ;
64- if ($ paginated = ($ object instanceof PartialPaginatorInterface)) {
65- if ($ object instanceof PaginatorInterface) {
66- $ paginated = 1. !== $ lastPage = $ object ->getLastPage ();
67- } else {
68- $ itemsPerPage = $ object ->getItemsPerPage ();
69- $ pageTotalItems = (float ) \count ($ object );
70- }
71-
72- $ currentPage = $ object ->getCurrentPage ();
66+ $ paginated = ($ object instanceof PartialPaginatorInterface);
67+ if ($ paginated && $ object instanceof PaginatorInterface) {
68+ $ paginated = 1. !== $ object ->getLastPage ();
7369 }
7470
75- // TODO: This needs to be changed as well as I wrote in the CollectionFiltersNormalizer
76- // We should not rely on the request_uri but instead rely on the UriTemplate
77- // This needs that we implement the RFC and that we do more parsing before calling the serialization (MainController)
7871 $ parsed = IriHelper::parseIri ($ context ['uri ' ] ?? $ context ['request_uri ' ] ?? '/ ' , $ this ->pageParameterName );
7972 $ appliedFilters = $ parsed ['parameters ' ];
8073 unset($ appliedFilters [$ this ->enabledParameterName ]);
@@ -94,18 +87,35 @@ public function normalize(mixed $object, ?string $format = null, array $context
9487 $ isPaginatedWithCursor = (bool ) $ cursorPaginationAttribute ;
9588
9689 $ hydraPrefix = $ this ->getHydraPrefix ($ context + $ this ->defaultContext );
97- $ data [$ hydraPrefix .'view ' ] = ['@id ' => null , '@type ' => $ hydraPrefix .'PartialCollectionView ' ];
9890
9991 if ($ isPaginatedWithCursor ) {
92+ $ data [$ hydraPrefix .'view ' ] = ['@id ' => null , '@type ' => $ hydraPrefix .'PartialCollectionView ' ];
93+
10094 return $ this ->populateDataWithCursorBasedPagination ($ data , $ parsed , $ object , $ cursorPaginationAttribute , $ operation ?->getUrlGenerationStrategy() ?? $ this ->urlGenerationStrategy , $ hydraPrefix );
10195 }
10296
103- $ data [$ hydraPrefix .'view ' ]['@id ' ] = IriHelper::createIri ($ parsed ['parts ' ], $ parsed ['parameters ' ], $ this ->pageParameterName , $ paginated ? $ currentPage : null , $ operation ?->getUrlGenerationStrategy() ?? $ this ->urlGenerationStrategy );
97+ $ partialCollectionView = $ this ->getPartialCollectionView ($ object , $ context ['uri ' ] ?? $ context ['request_uri ' ] ?? '/ ' , $ this ->pageParameterName , $ this ->enabledParameterName , $ operation ?->getUrlGenerationStrategy() ?? $ this ->urlGenerationStrategy );
98+
99+ $ view = [
100+ '@id ' => $ partialCollectionView ->id ,
101+ '@type ' => $ hydraPrefix .'PartialCollectionView ' ,
102+ ];
103+
104+ if (null !== $ partialCollectionView ->first ) {
105+ $ view [$ hydraPrefix .'first ' ] = $ partialCollectionView ->first ;
106+ $ view [$ hydraPrefix .'last ' ] = $ partialCollectionView ->last ;
107+ }
104108
105- if ($ paginated ) {
106- return $ this -> populateDataWithPagination ( $ data , $ parsed , $ currentPage , $ lastPage , $ itemsPerPage , $ pageTotalItems , $ operation ?->getUrlGenerationStrategy() ?? $ this -> urlGenerationStrategy , $ hydraPrefix ) ;
109+ if (null !== $ partialCollectionView -> previous ) {
110+ $ view [ $ hydraPrefix . ' previous ' ] = $ partialCollectionView -> previous ;
107111 }
108112
113+ if (null !== $ partialCollectionView ->next ) {
114+ $ view [$ hydraPrefix .'next ' ] = $ partialCollectionView ->next ;
115+ }
116+
117+ $ data [$ hydraPrefix .'view ' ] = $ view ;
118+
109119 return $ data ;
110120 }
111121
@@ -168,22 +178,4 @@ private function populateDataWithCursorBasedPagination(array $data, array $parse
168178
169179 return $ data ;
170180 }
171-
172- private function populateDataWithPagination (array $ data , array $ parsed , ?float $ currentPage , ?float $ lastPage , ?float $ itemsPerPage , ?float $ pageTotalItems , ?int $ urlGenerationStrategy , string $ hydraPrefix ): array
173- {
174- if (null !== $ lastPage ) {
175- $ data [$ hydraPrefix .'view ' ][$ hydraPrefix .'first ' ] = IriHelper::createIri ($ parsed ['parts ' ], $ parsed ['parameters ' ], $ this ->pageParameterName , 1. , $ urlGenerationStrategy );
176- $ data [$ hydraPrefix .'view ' ][$ hydraPrefix .'last ' ] = IriHelper::createIri ($ parsed ['parts ' ], $ parsed ['parameters ' ], $ this ->pageParameterName , $ lastPage , $ urlGenerationStrategy );
177- }
178-
179- if (1. !== $ currentPage ) {
180- $ data [$ hydraPrefix .'view ' ][$ hydraPrefix .'previous ' ] = IriHelper::createIri ($ parsed ['parts ' ], $ parsed ['parameters ' ], $ this ->pageParameterName , $ currentPage - 1. , $ urlGenerationStrategy );
181- }
182-
183- if ((null !== $ lastPage && $ currentPage < $ lastPage ) || (null === $ lastPage && $ pageTotalItems >= $ itemsPerPage )) {
184- $ data [$ hydraPrefix .'view ' ][$ hydraPrefix .'next ' ] = IriHelper::createIri ($ parsed ['parts ' ], $ parsed ['parameters ' ], $ this ->pageParameterName , $ currentPage + 1. , $ urlGenerationStrategy );
185- }
186-
187- return $ data ;
188- }
189181}
0 commit comments