Complex classes like QuestionHelper 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 QuestionHelper, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 27 | class QuestionHelper extends Helper |
||
| 28 | { |
||
| 29 | private $inputStream; |
||
| 30 | private static $shell; |
||
| 31 | private static $stty; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Asks a question to the user. |
||
| 35 | * |
||
| 36 | * @param InputInterface $input An InputInterface instance |
||
| 37 | * @param OutputInterface $output An OutputInterface instance |
||
| 38 | * @param Question $question The question to ask |
||
| 39 | * |
||
| 40 | * @return string The user answer |
||
| 41 | * |
||
| 42 | * @throws RuntimeException If there is no data to read in the input stream |
||
| 43 | */ |
||
| 44 | public function ask(InputInterface $input, OutputInterface $output, Question $question) |
||
| 66 | |||
| 67 | /** |
||
| 68 | * Sets the input stream to read from when interacting with the user. |
||
| 69 | * |
||
| 70 | * This is mainly useful for testing purpose. |
||
| 71 | * |
||
| 72 | * @param resource $stream The input stream |
||
| 73 | * |
||
| 74 | * @throws InvalidArgumentException In case the stream is not a resource |
||
| 75 | */ |
||
| 76 | public function setInputStream($stream) |
||
| 84 | |||
| 85 | /** |
||
| 86 | * Returns the helper's input stream. |
||
| 87 | * |
||
| 88 | * @return resource |
||
| 89 | */ |
||
| 90 | public function getInputStream() |
||
| 94 | |||
| 95 | /** |
||
| 96 | * {@inheritdoc} |
||
| 97 | */ |
||
| 98 | public function getName() |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Asks the question to the user. |
||
| 105 | * |
||
| 106 | * This method is public for PHP 5.3 compatibility, it should be private. |
||
| 107 | * |
||
| 108 | * @param OutputInterface $output |
||
| 109 | * @param Question $question |
||
| 110 | * |
||
| 111 | * @return bool|mixed|null|string |
||
| 112 | * |
||
| 113 | * @throws \Exception |
||
| 114 | * @throws \RuntimeException |
||
| 115 | */ |
||
| 116 | public function doAsk(OutputInterface $output, Question $question) |
||
| 150 | |||
| 151 | /** |
||
| 152 | * Outputs the question prompt. |
||
| 153 | * |
||
| 154 | * @param OutputInterface $output |
||
| 155 | * @param Question $question |
||
| 156 | */ |
||
| 157 | protected function writePrompt(OutputInterface $output, Question $question) |
||
| 176 | |||
| 177 | /** |
||
| 178 | * Outputs an error message. |
||
| 179 | * |
||
| 180 | * @param OutputInterface $output |
||
| 181 | * @param \Exception $error |
||
| 182 | */ |
||
| 183 | protected function writeError(OutputInterface $output, \Exception $error) |
||
| 193 | |||
| 194 | /** |
||
| 195 | * Autocompletes a question. |
||
| 196 | * |
||
| 197 | * @param OutputInterface $output |
||
| 198 | * @param Question $question |
||
| 199 | * |
||
| 200 | * @return string |
||
| 201 | */ |
||
| 202 | private function autocomplete(OutputInterface $output, Question $question, $inputStream) |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Gets a hidden response from user. |
||
| 314 | * |
||
| 315 | * @param OutputInterface $output An Output instance |
||
| 316 | * |
||
| 317 | * @return string The answer |
||
| 318 | * |
||
| 319 | * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden |
||
| 320 | */ |
||
| 321 | private function getHiddenResponse(OutputInterface $output, $inputStream) |
||
| 371 | |||
| 372 | /** |
||
| 373 | * Validates an attempt. |
||
| 374 | * |
||
| 375 | * @param callable $interviewer A callable that will ask for a question and return the result |
||
| 376 | * @param OutputInterface $output An Output instance |
||
| 377 | * @param Question $question A Question instance |
||
| 378 | * |
||
| 379 | * @return string The validated response |
||
| 380 | * |
||
| 381 | * @throws \Exception In case the max number of attempts has been reached and no valid response has been given |
||
| 382 | */ |
||
| 383 | private function validateAttempts($interviewer, OutputInterface $output, Question $question) |
||
| 400 | |||
| 401 | /** |
||
| 402 | * Returns a valid unix shell. |
||
| 403 | * |
||
| 404 | * @return string|bool The valid shell name, false in case no valid shell is found |
||
| 405 | */ |
||
| 406 | private function getShell() |
||
| 427 | |||
| 428 | /** |
||
| 429 | * Reads user input. |
||
| 430 | * |
||
| 431 | * @param resource $stream The input stream |
||
| 432 | * |
||
| 433 | * @return string User input |
||
| 434 | * |
||
| 435 | * @throws RuntimeException |
||
| 436 | */ |
||
| 437 | private function readFromInput($stream) |
||
| 451 | |||
| 452 | /** |
||
| 453 | * Returns whether Stty is available or not. |
||
| 454 | * |
||
| 455 | * @return bool |
||
| 456 | */ |
||
| 457 | private function hasSttyAvailable() |
||
| 467 | } |
||
| 468 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.