Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 30 | class DefaultResolver implements CommandResolver |
||
| 31 | { |
||
| 32 | /** |
||
| 33 | * {@inheritdoc} |
||
| 34 | */ |
||
| 35 | 217 | public function resolveCommand(RawArgs $args, Application $application) |
|
| 36 | { |
||
| 37 | 217 | $tokens = $args->getTokens(); |
|
| 38 | 217 | $namedCommands = $application->getNamedCommands(); |
|
| 39 | |||
| 40 | 217 | $argumentsToTest = $this->getArgumentsToTest($tokens); |
|
| 41 | 217 | $optionsToTest = $this->getOptionsToTest($tokens); |
|
| 42 | |||
| 43 | // Try to find a command for the passed arguments and options. |
||
| 44 | 217 | if ($result = $this->processArguments($args, $namedCommands, $argumentsToTest, $optionsToTest)) { |
|
| 45 | 199 | return $this->createResolvedCommand($result); |
|
| 46 | } |
||
| 47 | |||
| 48 | // If arguments were passed, we did not find the matching command. |
||
| 49 | 18 | if ($argumentsToTest) { |
|
|
|
|||
| 50 | 1 | throw CannotResolveCommandException::nameNotFound(reset($argumentsToTest), $namedCommands); |
|
| 51 | } |
||
| 52 | |||
| 53 | // If no arguments were passed, run the application's default command. |
||
| 54 | 17 | if ($result = $this->processDefaultCommands($args, $application->getDefaultCommands())) { |
|
| 55 | 17 | return $this->createResolvedCommand($result); |
|
| 56 | } |
||
| 57 | |||
| 58 | // No default command is configured. |
||
| 59 | throw CannotResolveCommandException::noDefaultCommand(); |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @param RawArgs $args |
||
| 64 | * @param CommandCollection $namedCommands |
||
| 65 | * @param string[] $argumentsToTest |
||
| 66 | * @param string[] $optionsToTest |
||
| 67 | * |
||
| 68 | * @return ResolveResult |
||
| 69 | */ |
||
| 70 | 217 | private function processArguments(RawArgs $args, CommandCollection $namedCommands, array $argumentsToTest, array $optionsToTest) |
|
| 71 | { |
||
| 72 | 217 | $currentCommand = null; |
|
| 73 | |||
| 74 | // Parse the arguments for command names until we fail to find a |
||
| 75 | // matching command |
||
| 76 | 217 | View Code Duplication | foreach ($argumentsToTest as $name) { |
| 77 | 200 | if (!$namedCommands->contains($name)) { |
|
| 78 | 16 | break; |
|
| 79 | } |
||
| 80 | |||
| 81 | 199 | $nextCommand = $namedCommands->get($name); |
|
| 82 | |||
| 83 | 199 | if ($nextCommand->getConfig() instanceof OptionCommandConfig) { |
|
| 84 | break; |
||
| 85 | } |
||
| 86 | |||
| 87 | 199 | $currentCommand = $nextCommand; |
|
| 88 | 199 | $namedCommands = $currentCommand->getNamedSubCommands(); |
|
| 89 | } |
||
| 90 | |||
| 91 | 217 | if (!$currentCommand) { |
|
| 92 | 18 | return null; |
|
| 93 | } |
||
| 94 | |||
| 95 | 199 | return $this->processOptions($args, $currentCommand, $optionsToTest); |
|
| 96 | } |
||
| 97 | |||
| 98 | /** |
||
| 99 | * @param RawArgs $args |
||
| 100 | * @param Command $currentCommand |
||
| 101 | * @param string[] $optionsToTest |
||
| 102 | * |
||
| 103 | * @return ResolveResult |
||
| 104 | */ |
||
| 105 | 199 | private function processOptions(RawArgs $args, Command $currentCommand, array $optionsToTest) |
|
| 125 | |||
| 126 | /** |
||
| 127 | * @param RawArgs $args |
||
| 128 | * @param Command $currentCommand |
||
| 129 | * |
||
| 130 | * @return ResolveResult |
||
| 131 | */ |
||
| 132 | 199 | private function processDefaultSubCommands(RawArgs $args, Command $currentCommand) |
|
| 133 | { |
||
| 134 | 199 | if ($result = $this->processDefaultCommands($args, $currentCommand->getDefaultSubCommands())) { |
|
| 135 | 42 | return $result; |
|
| 136 | } |
||
| 137 | |||
| 138 | // No default commands, return the current command |
||
| 139 | 157 | return new ResolveResult($currentCommand, $args); |
|
| 140 | } |
||
| 141 | |||
| 142 | /** |
||
| 143 | * @param RawArgs $args |
||
| 144 | * @param CommandCollection $defaultCommands |
||
| 145 | * |
||
| 146 | * @return ResolveResult |
||
| 147 | */ |
||
| 148 | 216 | private function processDefaultCommands(RawArgs $args, CommandCollection $defaultCommands) |
|
| 167 | |||
| 168 | 217 | private function getArgumentsToTest(array &$tokens) |
|
| 169 | { |
||
| 201 | |||
| 202 | 217 | private function getOptionsToTest(array &$tokens) |
|
| 227 | |||
| 228 | 216 | private function createResolvedCommand(ResolveResult $result) |
|
| 236 | } |
||
| 237 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.