Complex classes like GitToolCLI 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 GitToolCLI, and based on these observations, apply Extract Interface, too.
1 | #!/usr/bin/php |
||
16 | class GitToolCLI extends CLI { |
||
17 | |||
18 | /** |
||
19 | * Register options and arguments on the given $options object |
||
20 | * |
||
21 | * @param Options $options |
||
22 | * @return void |
||
23 | */ |
||
24 | protected function setup(Options $options) { |
||
73 | |||
74 | /** |
||
75 | * Your main program |
||
76 | * |
||
77 | * Arguments and options have been parsed when this is run |
||
78 | * |
||
79 | * @param Options $options |
||
80 | * @return void |
||
81 | */ |
||
82 | protected function main(Options $options) { |
||
105 | |||
106 | /** |
||
107 | * Tries to install the given extensions using git clone |
||
108 | * |
||
109 | * @param array $extensions |
||
110 | */ |
||
111 | public function cmdClone($extensions) { |
||
112 | $errors = array(); |
||
113 | $succeeded = array(); |
||
114 | |||
115 | foreach($extensions as $ext) { |
||
116 | $repo = $this->getSourceRepo($ext); |
||
117 | |||
118 | if(!$repo) { |
||
119 | $this->error("could not find a repository for $ext"); |
||
120 | $errors[] = $ext; |
||
121 | } else { |
||
122 | if($this->cloneExtension($ext, $repo)) { |
||
123 | $succeeded[] = $ext; |
||
124 | } else { |
||
125 | $errors[] = $ext; |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | |||
130 | echo "\n"; |
||
131 | if($succeeded) $this->success('successfully cloned the following extensions: ' . join(', ', $succeeded)); |
||
|
|||
132 | if($errors) $this->error('failed to clone the following extensions: ' . join(', ', $errors)); |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Tries to install the given extensions using git clone with fallback to install |
||
137 | * |
||
138 | * @param array $extensions |
||
139 | */ |
||
140 | public function cmdInstall($extensions) { |
||
141 | $errors = array(); |
||
142 | $succeeded = array(); |
||
143 | |||
144 | foreach($extensions as $ext) { |
||
145 | $repo = $this->getSourceRepo($ext); |
||
146 | |||
147 | if(!$repo) { |
||
148 | $this->info("could not find a repository for $ext"); |
||
149 | if($this->downloadExtension($ext)) { |
||
150 | $succeeded[] = $ext; |
||
151 | } else { |
||
152 | $errors[] = $ext; |
||
153 | } |
||
154 | } else { |
||
155 | if($this->cloneExtension($ext, $repo)) { |
||
156 | $succeeded[] = $ext; |
||
157 | } else { |
||
158 | $errors[] = $ext; |
||
159 | } |
||
160 | } |
||
161 | } |
||
162 | |||
163 | echo "\n"; |
||
164 | if($succeeded) $this->success('successfully installed the following extensions: ' . join(', ', $succeeded)); |
||
165 | if($errors) $this->error('failed to install the following extensions: ' . join(', ', $errors)); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Executes the given git command in every repository |
||
170 | * |
||
171 | * @param $cmd |
||
172 | * @param $arg |
||
173 | */ |
||
174 | public function cmdGit($cmd, $arg) { |
||
175 | $repos = $this->findRepos(); |
||
176 | |||
177 | $shell = array_merge(array('git', $cmd), $arg); |
||
178 | $shell = array_map('escapeshellarg', $shell); |
||
179 | $shell = join(' ', $shell); |
||
180 | |||
181 | foreach($repos as $repo) { |
||
182 | if(!@chdir($repo)) { |
||
183 | $this->error("Could not change into $repo"); |
||
184 | continue; |
||
185 | } |
||
186 | |||
187 | $this->info("executing $shell in $repo"); |
||
188 | $ret = 0; |
||
189 | system($shell, $ret); |
||
190 | |||
191 | if($ret == 0) { |
||
192 | $this->success("git succeeded in $repo"); |
||
193 | } else { |
||
194 | $this->error("git failed in $repo"); |
||
195 | } |
||
196 | } |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Simply lists the repositories |
||
201 | */ |
||
202 | public function cmdRepos() { |
||
203 | $repos = $this->findRepos(); |
||
204 | foreach($repos as $repo) { |
||
205 | echo "$repo\n"; |
||
206 | } |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Install extension from the given download URL |
||
211 | * |
||
212 | * @param string $ext |
||
213 | * @return bool|null |
||
214 | */ |
||
215 | private function downloadExtension($ext) { |
||
244 | |||
245 | /** |
||
246 | * Clones the extension from the given repository |
||
247 | * |
||
248 | * @param string $ext |
||
249 | * @param string $repo |
||
250 | * @return bool |
||
251 | */ |
||
252 | private function cloneExtension($ext, $repo) { |
||
270 | |||
271 | /** |
||
272 | * Returns all git repositories in this DokuWiki install |
||
273 | * |
||
274 | * Looks in root, template and plugin directories only. |
||
275 | * |
||
276 | * @return array |
||
277 | */ |
||
278 | private function findRepos() { |
||
294 | |||
295 | /** |
||
296 | * Returns the repository for the given extension |
||
297 | * |
||
298 | * @param $extension |
||
299 | * @return false|string |
||
300 | */ |
||
301 | private function getSourceRepo($extension) { |
||
336 | } |
||
337 | |||
338 | // Main |
||
339 | $cli = new GitToolCLI(); |
||
340 | $cli->run(); |
||
341 |
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.