Complex classes like Validator 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 Validator, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 49 | class Validator extends Component implements ValidatorInterface, LoggerAwareInterface |
||
| 50 | { |
||
| 51 | use LoggerTrait, TranslatorTrait, SaturateTrait; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Return from validation rule to stop any future field validations. Internal contract. |
||
| 55 | */ |
||
| 56 | const STOP_VALIDATION = -99; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * @invisible |
||
| 60 | * @var ValidatorConfig |
||
| 61 | */ |
||
| 62 | private $config = null; |
||
| 63 | |||
| 64 | /** |
||
| 65 | * @var array|\ArrayAccess |
||
| 66 | */ |
||
| 67 | private $data = []; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * Validation rules, see class title for description. |
||
| 71 | * |
||
| 72 | * @var array |
||
| 73 | */ |
||
| 74 | private $rules = []; |
||
| 75 | |||
| 76 | /** |
||
| 77 | * Error messages raised while validation. |
||
| 78 | * |
||
| 79 | * @var array |
||
| 80 | */ |
||
| 81 | private $errors = []; |
||
| 82 | |||
| 83 | /** |
||
| 84 | * Errors provided from outside. |
||
| 85 | * |
||
| 86 | * @var array |
||
| 87 | */ |
||
| 88 | private $registeredErrors = []; |
||
| 89 | |||
| 90 | /** |
||
| 91 | * If rule has no definer error message this text will be used instead. Localizable. |
||
| 92 | * |
||
| 93 | * @invisible |
||
| 94 | * @var string |
||
| 95 | */ |
||
| 96 | protected $defaultMessage = "[[Condition '{condition}' does not meet.]]"; |
||
| 97 | |||
| 98 | /** |
||
| 99 | * @invisible |
||
| 100 | * @var ContainerInterface |
||
| 101 | */ |
||
| 102 | protected $container = null; |
||
| 103 | |||
| 104 | /** |
||
| 105 | * Validation context. Not validated. |
||
| 106 | * |
||
| 107 | * @var mixed |
||
| 108 | */ |
||
| 109 | protected $context; |
||
| 110 | |||
| 111 | /** |
||
| 112 | * {@inheritdoc} |
||
| 113 | * |
||
| 114 | * @param array $rules Validation rules. |
||
| 115 | * @param array|\ArrayAccess $data Data or model to be validated. |
||
| 116 | * @param ValidatorConfig $config Saturated using shared container |
||
| 117 | * @param ContainerInterface $container Saturated using shared container |
||
| 118 | * |
||
| 119 | * @throws ScopeException |
||
| 120 | */ |
||
| 121 | public function __construct( |
||
| 133 | |||
| 134 | /** |
||
| 135 | * {@inheritdoc} |
||
| 136 | */ |
||
| 137 | public function setRules(array $rules): ValidatorInterface |
||
| 148 | |||
| 149 | /** |
||
| 150 | * {@inheritdoc} |
||
| 151 | */ |
||
| 152 | public function setData($data): ValidatorInterface |
||
| 164 | |||
| 165 | /** |
||
| 166 | * {@inheritdoc} |
||
| 167 | */ |
||
| 168 | public function getData() |
||
| 172 | |||
| 173 | /** |
||
| 174 | * {@inheritdoc} |
||
| 175 | */ |
||
| 176 | public function isValid(): bool |
||
| 182 | |||
| 183 | /** |
||
| 184 | * {@inheritdoc} |
||
| 185 | */ |
||
| 186 | public function registerError(string $field, string $error): ValidatorInterface |
||
| 192 | |||
| 193 | /** |
||
| 194 | * {@inheritdoc} |
||
| 195 | */ |
||
| 196 | public function flushRegistered(): ValidatorInterface |
||
| 202 | |||
| 203 | /** |
||
| 204 | * {@inheritdoc} |
||
| 205 | */ |
||
| 206 | public function hasErrors(): bool |
||
| 210 | |||
| 211 | /** |
||
| 212 | * {@inheritdoc} |
||
| 213 | */ |
||
| 214 | public function getErrors(): array |
||
| 220 | |||
| 221 | /** |
||
| 222 | * {@inheritdoc} |
||
| 223 | */ |
||
| 224 | public function setContext($context) |
||
| 228 | |||
| 229 | /** |
||
| 230 | * {@inheritdoc} |
||
| 231 | */ |
||
| 232 | public function getContext() |
||
| 236 | |||
| 237 | /** |
||
| 238 | * Receive field from context data or return default value. |
||
| 239 | * |
||
| 240 | * @param string $field |
||
| 241 | * @param mixed $default |
||
| 242 | * |
||
| 243 | * @return mixed |
||
| 244 | */ |
||
| 245 | public function getValue(string $field, $default = null) |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Reset validation state. |
||
| 256 | */ |
||
| 257 | public function reset() |
||
| 262 | |||
| 263 | /** |
||
| 264 | * Validate context data with set of validation rules. |
||
| 265 | */ |
||
| 266 | protected function validate() |
||
| 331 | |||
| 332 | /** |
||
| 333 | * Check field with given condition. Can return instance of Checker (data is not valid) to |
||
| 334 | * clarify error. |
||
| 335 | * |
||
| 336 | * @param string $field |
||
| 337 | * @param mixed $value |
||
| 338 | * @param mixed $condition Reference, can be altered if alias exists. |
||
| 339 | * @param array $arguments Rule arguments if any. |
||
| 340 | * |
||
| 341 | * @return bool|CheckerInterface |
||
| 342 | * @throws ValidationException |
||
| 343 | */ |
||
| 344 | protected function check(string $field, $value, &$condition, array $arguments = []) |
||
| 384 | |||
| 385 | /** |
||
| 386 | * Does validation config has alias defined for a given checker name or class exists |
||
| 387 | * |
||
| 388 | * @param string $name |
||
| 389 | * |
||
| 390 | * @return bool |
||
| 391 | */ |
||
| 392 | protected function hasChecker(string $name): bool |
||
| 406 | |||
| 407 | /** |
||
| 408 | * Get or create instance of validation checker. |
||
| 409 | * |
||
| 410 | * @param string $name |
||
| 411 | * |
||
| 412 | * @return CheckerInterface |
||
| 413 | * @throws ValidationException |
||
| 414 | */ |
||
| 415 | protected function getChecker(string $name): CheckerInterface |
||
| 428 | |||
| 429 | /** |
||
| 430 | * Fetch validation rule arguments from rule definition. |
||
| 431 | * |
||
| 432 | * @param array $rule |
||
| 433 | * |
||
| 434 | * @return array |
||
| 435 | */ |
||
| 436 | private function fetchArguments(array $rule): array |
||
| 442 | |||
| 443 | /** |
||
| 444 | * Fetch error message from rule definition or use default message. Method will check "message" |
||
| 445 | * and "error" properties of definition. |
||
| 446 | * |
||
| 447 | * @param array $rule |
||
| 448 | * @param string $message Default message to use. |
||
| 449 | * |
||
| 450 | * @return string |
||
| 451 | */ |
||
| 452 | private function fetchMessage(array $rule, string $message): string |
||
| 464 | |||
| 465 | /** |
||
| 466 | * Register error message for specified field. Rule definition will be interpolated into |
||
| 467 | * message. |
||
| 468 | * |
||
| 469 | * @param string $field |
||
| 470 | * @param string $message |
||
| 471 | * @param mixed $condition |
||
| 472 | * @param array $arguments |
||
| 473 | */ |
||
| 474 | private function addMessage(string $field, string $message, $condition, array $arguments = []) |
||
| 489 | |||
| 490 | /** |
||
| 491 | * @param string $field |
||
| 492 | * @param array $condition |
||
| 493 | * @param \Throwable $e |
||
| 494 | */ |
||
| 495 | protected function logException(string $field, $condition, \Throwable $e) |
||
| 510 | |||
| 511 | /** |
||
| 512 | * @param array|\ArrayAccess|EntityInterface $data |
||
| 513 | * |
||
| 514 | * @return array |
||
| 515 | */ |
||
| 516 | private function extractData($data): array |
||
| 534 | |||
| 535 | /** |
||
| 536 | * Does rule have condition. |
||
| 537 | * |
||
| 538 | * @param $rule |
||
| 539 | * |
||
| 540 | * @return bool |
||
| 541 | */ |
||
| 542 | protected function skipUnderEmptyCondition($rule) |
||
| 553 | |||
| 554 | /** |
||
| 555 | * Does checker condition class exist. |
||
| 556 | * |
||
| 557 | * @param string $name |
||
| 558 | * |
||
| 559 | * @return bool |
||
| 560 | */ |
||
| 561 | protected function hasCondition(string $name): bool |
||
| 571 | |||
| 572 | /** |
||
| 573 | * Get or create instance of validation checker condition. |
||
| 574 | * |
||
| 575 | * @param string $name |
||
| 576 | * |
||
| 577 | * @return CheckerConditionInterface |
||
| 578 | * @throws ValidationException |
||
| 579 | */ |
||
| 580 | protected function getCondition(string $name): CheckerConditionInterface |
||
| 590 | } |
It seems like the method you are trying to call exists only in some of the possible types.
Let’s take a look at an example:
Available Fixes
Add an additional type-check:
Only allow a single type to be passed if the variable comes from a parameter: