| Total Complexity | 52 | 
| Total Lines | 359 | 
| Duplicated Lines | 0 % | 
| Changes | 0 | ||
Complex classes like PaginationExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use PaginationExtension, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 37 | final class PaginationExtension implements ContextAwareQueryResultCollectionExtensionInterface | ||
| 38 | { | ||
| 39 | private $managerRegistry; | ||
| 40 | private $requestStack; | ||
| 41 | /** | ||
| 42 | * @var ResourceMetadataFactoryInterface | ||
| 43 | */ | ||
| 44 | private $resourceMetadataFactory; | ||
| 45 | private $enabled; | ||
| 46 | private $clientEnabled; | ||
| 47 | private $clientItemsPerPage; | ||
| 48 | private $itemsPerPage; | ||
| 49 | private $pageParameterName; | ||
| 50 | private $enabledParameterName; | ||
| 51 | private $itemsPerPageParameterName; | ||
| 52 | private $maximumItemPerPage; | ||
| 53 | private $partial; | ||
| 54 | private $clientPartial; | ||
| 55 | private $partialParameterName; | ||
| 56 | /** | ||
| 57 | * @var Pagination|null | ||
| 58 | */ | ||
| 59 | private $pagination; | ||
| 60 | |||
| 61 | /** | ||
| 62 | * @param ResourceMetadataFactoryInterface|RequestStack $resourceMetadataFactory | ||
| 63 | * @param Pagination|ResourceMetadataFactoryInterface $pagination | ||
| 64 | */ | ||
| 65 | public function __construct(ManagerRegistry $managerRegistry, /* ResourceMetadataFactoryInterface */ $resourceMetadataFactory, /* Pagination */ $pagination) | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 |      * {@inheritdoc} | ||
| 118 | */ | ||
| 119 | public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = []) | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 |      * {@inheritdoc} | ||
| 134 | */ | ||
| 135 | public function supportsResult(string $resourceClass, string $operationName = null, array $context = []): bool | ||
| 136 |     { | ||
| 137 |         if ($context['graphql_operation_name'] ?? false) { | ||
| 138 | return $this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context); | ||
|  | |||
| 139 | } | ||
| 140 | |||
| 141 |         if (null === $this->requestStack) { | ||
| 142 | return $this->pagination->isEnabled($resourceClass, $operationName, $context); | ||
| 143 | } | ||
| 144 | |||
| 145 |         if (null === $request = $this->requestStack->getCurrentRequest()) { | ||
| 146 | return false; | ||
| 147 | } | ||
| 148 | |||
| 149 | return $this->isPaginationEnabled($request, $this->resourceMetadataFactory->create($resourceClass), $operationName); | ||
| 150 | } | ||
| 151 | |||
| 152 | /** | ||
| 153 |      * {@inheritdoc} | ||
| 154 | */ | ||
| 155 | public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = []) | ||
| 183 | } | ||
| 184 | |||
| 185 | /** | ||
| 186 | * @throws InvalidArgumentException | ||
| 187 | */ | ||
| 188 | private function getPagination(QueryBuilder $queryBuilder, string $resourceClass, ?string $operationName, array $context): ?array | ||
| 189 |     { | ||
| 190 | $request = null; | ||
| 191 |         if (null !== $this->requestStack && null === $request = $this->requestStack->getCurrentRequest()) { | ||
| 192 | return null; | ||
| 193 | } | ||
| 194 | |||
| 195 |         if (null === $request) { | ||
| 196 |             if (!$this->pagination->isEnabled($resourceClass, $operationName, $context)) { | ||
| 197 | return null; | ||
| 198 | } | ||
| 199 | |||
| 200 |             if (($context['graphql_operation_name'] ?? false) && !$this->pagination->isGraphQlEnabled($resourceClass, $operationName, $context)) { | ||
| 201 | return null; | ||
| 202 | } | ||
| 203 | |||
| 204 | $context = $this->addCountToContext($queryBuilder, $context); | ||
| 205 | |||
| 206 | return \array_slice($this->pagination->getPagination($resourceClass, $operationName, $context), 1); | ||
| 207 | } | ||
| 208 | |||
| 209 | $resourceMetadata = $this->resourceMetadataFactory->create($resourceClass); | ||
| 210 |         if (!$this->isPaginationEnabled($request, $resourceMetadata, $operationName)) { | ||
| 211 | return null; | ||
| 212 | } | ||
| 213 | |||
| 214 | $itemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_items_per_page', $this->itemsPerPage, true); | ||
| 215 |         if ($request->attributes->getBoolean('_graphql', false)) { | ||
| 216 |             $collectionArgs = $request->attributes->get('_graphql_collections_args', []); | ||
| 217 | $itemsPerPage = $collectionArgs[$resourceClass]['first'] ?? $itemsPerPage; | ||
| 218 | } | ||
| 219 | |||
| 220 |         if ($resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_client_items_per_page', $this->clientItemsPerPage, true)) { | ||
| 221 | $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'maximum_items_per_page', null, true); | ||
| 222 | |||
| 223 |             if (null !== $maxItemsPerPage) { | ||
| 224 |                 @trigger_error('The "maximum_items_per_page" option has been deprecated since API Platform 2.5 in favor of "pagination_maximum_items_per_page" and will be removed in API Platform 3.', E_USER_DEPRECATED); | ||
| 225 | } | ||
| 226 | |||
| 227 | $maxItemsPerPage = $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_maximum_items_per_page', $maxItemsPerPage ?? $this->maximumItemPerPage, true); | ||
| 228 | |||
| 229 | $itemsPerPage = (int) $this->getPaginationParameter($request, $this->itemsPerPageParameterName, $itemsPerPage); | ||
| 230 | $itemsPerPage = (null !== $maxItemsPerPage && $itemsPerPage >= $maxItemsPerPage ? $maxItemsPerPage : $itemsPerPage); | ||
| 231 | } | ||
| 232 | |||
| 233 |         if (0 > $itemsPerPage) { | ||
| 234 |             throw new InvalidArgumentException('Item per page parameter should not be less than 0'); | ||
| 235 | } | ||
| 236 | |||
| 237 | $page = (int) $this->getPaginationParameter($request, $this->pageParameterName, 1); | ||
| 238 | |||
| 239 |         if (1 > $page) { | ||
| 240 |             throw new InvalidArgumentException('Page should not be less than 1'); | ||
| 241 | } | ||
| 242 | |||
| 243 |         if (0 === $itemsPerPage && 1 < $page) { | ||
| 244 |             throw new InvalidArgumentException('Page should not be greater than 1 if itemsPerPage is equal to 0'); | ||
| 245 | } | ||
| 246 | |||
| 247 | $firstResult = ($page - 1) * $itemsPerPage; | ||
| 248 |         if ($request->attributes->getBoolean('_graphql', false)) { | ||
| 249 |             $collectionArgs = $request->attributes->get('_graphql_collections_args', []); | ||
| 250 |             if (isset($collectionArgs[$resourceClass]['after'])) { | ||
| 251 | $after = base64_decode($collectionArgs[$resourceClass]['after'], true); | ||
| 252 | $firstResult = (int) $after; | ||
| 253 | $firstResult = false === $after ? $firstResult : ++$firstResult; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | return [$firstResult, $itemsPerPage]; | ||
| 258 | } | ||
| 259 | |||
| 260 | private function isPartialPaginationEnabled(Request $request = null, ResourceMetadata $resourceMetadata = null, string $operationName = null): bool | ||
| 278 | } | ||
| 279 | |||
| 280 | private function isPaginationEnabled(Request $request, ResourceMetadata $resourceMetadata, string $operationName = null): bool | ||
| 290 | } | ||
| 291 | |||
| 292 | private function getPaginationParameter(Request $request, string $parameterName, $default = null) | ||
| 293 |     { | ||
| 294 |         if (null !== $paginationAttribute = $request->attributes->get('_api_pagination')) { | ||
| 295 | return \array_key_exists($parameterName, $paginationAttribute) ? $paginationAttribute[$parameterName] : $default; | ||
| 296 | } | ||
| 297 | |||
| 298 | return $request->query->get($parameterName, $default); | ||
| 299 | } | ||
| 300 | |||
| 301 | private function addCountToContext(QueryBuilder $queryBuilder, array $context): array | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * Determines the value of the $fetchJoinCollection argument passed to the Doctrine ORM Paginator. | ||
| 316 | */ | ||
| 317 | private function shouldDoctrinePaginatorFetchJoinCollection(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null): bool | ||
| 343 | } | ||
| 344 | |||
| 345 | /** | ||
| 346 | * Determines whether the Doctrine ORM Paginator should use output walkers. | ||
| 347 | */ | ||
| 348 | private function shouldDoctrinePaginatorUseOutputWalkers(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null): bool | ||
| 396 | } | ||
| 397 | } | ||
| 398 | 
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.