Complex classes like QueryValidator 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 QueryValidator, and based on these observations, apply Extract Interface, too.
| 1 | <?php namespace Limoncello\Flute\Http\Query; |
||
| 41 | class QueryValidator extends QueryParser implements QueryValidatorInterface |
||
| 42 | { |
||
| 43 | use HasContainerTrait; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @var ContextStorageInterface |
||
| 47 | */ |
||
| 48 | private $contextStorage; |
||
| 49 | |||
| 50 | /** |
||
| 51 | * @var CaptureAggregatorInterface |
||
| 52 | */ |
||
| 53 | private $captureAggregator; |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @var ErrorAggregatorInterface |
||
| 57 | */ |
||
| 58 | private $errorAggregator; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @var array |
||
| 62 | */ |
||
| 63 | private $rulesData; |
||
| 64 | |||
| 65 | /** |
||
| 66 | * @var array |
||
| 67 | */ |
||
| 68 | private $blocks; |
||
| 69 | |||
| 70 | /** |
||
| 71 | * @var int[] |
||
| 72 | */ |
||
| 73 | private $attributeRules; |
||
| 74 | |||
| 75 | /** |
||
| 76 | * @var array |
||
| 77 | */ |
||
| 78 | private $attributeRulesIdx; |
||
| 79 | |||
| 80 | /** |
||
| 81 | * @param array $data |
||
| 82 | * @param ContainerInterface $container |
||
| 83 | * @param PaginationStrategyInterface $paginationStrategy |
||
| 84 | * @param string[]|null $messages |
||
| 85 | * |
||
| 86 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 87 | */ |
||
| 88 | 5 | public function __construct( |
|
| 104 | |||
| 105 | /** |
||
| 106 | * @inheritdoc |
||
| 107 | */ |
||
| 108 | 4 | public function withAllAllowedFilterFields(): QueryParserInterface |
|
| 116 | |||
| 117 | /** |
||
| 118 | * @inheritdoc |
||
| 119 | */ |
||
| 120 | 5 | public function withNoAllowedFilterFields(): QueryParserInterface |
|
| 128 | |||
| 129 | /** |
||
| 130 | * @inheritdoc |
||
| 131 | */ |
||
| 132 | 1 | public function withAllowedFilterFields(array $fields): QueryParserInterface |
|
| 140 | |||
| 141 | /** |
||
| 142 | * @inheritdoc |
||
| 143 | * |
||
| 144 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 145 | */ |
||
| 146 | 4 | public function withValidatedFilterFields(string $rulesSetClass): QueryValidatorInterface |
|
| 152 | |||
| 153 | /** |
||
| 154 | * @inheritdoc |
||
| 155 | * |
||
| 156 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 157 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
| 158 | */ |
||
| 159 | 4 | public function getFilters(): iterable |
|
| 191 | |||
| 192 | /** |
||
| 193 | * @return ContextStorageInterface |
||
| 194 | */ |
||
| 195 | 5 | protected function createContextStorage(): ContextStorageInterface |
|
| 199 | |||
| 200 | /** |
||
| 201 | * @return CaptureAggregatorInterface |
||
| 202 | */ |
||
| 203 | 5 | protected function createCaptureAggregator(): CaptureAggregatorInterface |
|
| 207 | |||
| 208 | /** |
||
| 209 | * @return ErrorAggregatorInterface |
||
| 210 | */ |
||
| 211 | 5 | protected function createErrorAggregator(): ErrorAggregatorInterface |
|
| 215 | |||
| 216 | /** |
||
| 217 | * @param ContextStorageInterface $contextStorage |
||
| 218 | * |
||
| 219 | * @return self |
||
| 220 | */ |
||
| 221 | 5 | private function setContextStorage(ContextStorageInterface $contextStorage): self |
|
| 227 | |||
| 228 | /** |
||
| 229 | * @return CaptureAggregatorInterface |
||
| 230 | */ |
||
| 231 | 2 | private function getCaptureAggregator(): CaptureAggregatorInterface |
|
| 235 | |||
| 236 | /** |
||
| 237 | * @param CaptureAggregatorInterface $captureAggregator |
||
| 238 | * |
||
| 239 | * @return self |
||
| 240 | */ |
||
| 241 | 5 | private function setCaptureAggregator(CaptureAggregatorInterface $captureAggregator): self |
|
| 247 | |||
| 248 | /** |
||
| 249 | * @return ErrorAggregatorInterface |
||
| 250 | */ |
||
| 251 | 3 | private function getErrorAggregator(): ErrorAggregatorInterface |
|
| 255 | |||
| 256 | /** |
||
| 257 | * @param ErrorAggregatorInterface $errorAggregator |
||
| 258 | * |
||
| 259 | * @return self |
||
| 260 | */ |
||
| 261 | 5 | private function setErrorAggregator(ErrorAggregatorInterface $errorAggregator): self |
|
| 267 | |||
| 268 | /** |
||
| 269 | * @param int $blockIndex |
||
| 270 | * @param string $name |
||
| 271 | * @param iterable $operationsAndArgs |
||
| 272 | * |
||
| 273 | * @return iterable |
||
| 274 | */ |
||
| 275 | 2 | private function getValidatedOperationsAndArguments( |
|
| 284 | |||
| 285 | /** |
||
| 286 | * @param int $blockIndex |
||
| 287 | * @param string $name |
||
| 288 | * @param iterable $arguments |
||
| 289 | * |
||
| 290 | * @return iterable |
||
| 291 | */ |
||
| 292 | 2 | private function getValidatedArguments(int $blockIndex, string $name, iterable $arguments): iterable |
|
| 301 | |||
| 302 | /** |
||
| 303 | * @return ContextStorageInterface |
||
| 304 | */ |
||
| 305 | 3 | private function getContextStorage(): ContextStorageInterface |
|
| 309 | |||
| 310 | /** |
||
| 311 | * @return array |
||
| 312 | */ |
||
| 313 | 5 | private function getRulesData(): array |
|
| 317 | |||
| 318 | /** |
||
| 319 | * @param array $rulesData |
||
| 320 | * |
||
| 321 | * @return self |
||
| 322 | */ |
||
| 323 | 5 | private function setRulesData(array $rulesData): self |
|
| 329 | |||
| 330 | /** |
||
| 331 | * @return array |
||
| 332 | */ |
||
| 333 | 5 | private function getBlocks(): array |
|
| 337 | |||
| 338 | /** |
||
| 339 | * @param array $blocks |
||
| 340 | * |
||
| 341 | * @return self |
||
| 342 | */ |
||
| 343 | 5 | private function setBlocks(array $blocks): self |
|
| 349 | |||
| 350 | /** |
||
| 351 | * @param array $rules |
||
| 352 | * |
||
| 353 | * @return self |
||
| 354 | * |
||
| 355 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 356 | */ |
||
| 357 | 4 | private function setAttributeRules(array $rules): self |
|
| 366 | |||
| 367 | /** |
||
| 368 | * @return self |
||
| 369 | */ |
||
| 370 | 5 | private function unsetAttributeRules(): self |
|
| 377 | |||
| 378 | /** |
||
| 379 | * @return int[]|null |
||
| 380 | */ |
||
| 381 | 4 | private function getAttributeRules(): ?array |
|
| 385 | |||
| 386 | /** |
||
| 387 | * @param string $name |
||
| 388 | * |
||
| 389 | * @return int|null |
||
| 390 | * |
||
| 391 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 392 | */ |
||
| 393 | 3 | private function getAttributeIndex(string $name): ?int |
|
| 399 | |||
| 400 | /** |
||
| 401 | * @param array $indexes |
||
| 402 | * |
||
| 403 | * @return bool |
||
| 404 | * |
||
| 405 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 406 | */ |
||
| 407 | 3 | private function executeStarts(array $indexes): bool |
|
| 416 | |||
| 417 | /** |
||
| 418 | * @param array $indexes |
||
| 419 | * |
||
| 420 | * @return bool |
||
| 421 | * |
||
| 422 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 423 | */ |
||
| 424 | 3 | private function executeEnds(array $indexes): bool |
|
| 433 | |||
| 434 | /** |
||
| 435 | * @param mixed $input |
||
| 436 | * @param int $index |
||
| 437 | * |
||
| 438 | * @return bool |
||
| 439 | * |
||
| 440 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 441 | */ |
||
| 442 | 2 | private function executeBlock($input, int $index): bool |
|
| 453 | |||
| 454 | /** |
||
| 455 | * @param array $rules |
||
| 456 | * |
||
| 457 | * @return bool |
||
| 458 | * |
||
| 459 | * @SuppressWarnings(PHPMD.StaticAccess) |
||
| 460 | */ |
||
| 461 | 4 | private function debugCheckIndexesExist(array $rules): bool |
|
| 477 | } |
||
| 478 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.