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.