Complex classes like CKEditorInstallerCommand 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 CKEditorInstallerCommand, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | class CKEditorInstallerCommand extends Command |
||
29 | { |
||
30 | /** |
||
31 | * @var CKEditorInstaller |
||
32 | */ |
||
33 | private $installer; |
||
34 | |||
35 | /** |
||
36 | * @param CKEditorInstaller|null $installer |
||
37 | */ |
||
38 | 12 | public function __construct(CKEditorInstaller $installer = null) |
|
44 | |||
45 | /** |
||
46 | * {@inheritdoc} |
||
47 | */ |
||
48 | 12 | protected function configure() |
|
98 | |||
99 | /** |
||
100 | * {@inheritdoc} |
||
101 | */ |
||
102 | 12 | protected function execute(InputInterface $input, OutputInterface $output) |
|
114 | |||
115 | /** |
||
116 | * @param InputInterface $input |
||
117 | * @param OutputInterface $output |
||
118 | * |
||
119 | * @return mixed[] |
||
120 | */ |
||
121 | 12 | private function createOptions(InputInterface $input, OutputInterface $output) |
|
147 | |||
148 | /** |
||
149 | * @param InputInterface $input |
||
150 | * @param OutputInterface $output |
||
151 | * |
||
152 | * @return \Closure |
||
153 | */ |
||
154 | 12 | private function createNotifier(InputInterface $input, OutputInterface $output) |
|
155 | { |
||
156 | 12 | $clear = $this->createProgressBar($output); |
|
157 | 12 | $download = $this->createProgressBar($output); |
|
158 | 12 | $extract = $this->createProgressBar($output); |
|
159 | |||
160 | 12 | return function ($type, $data) use ($input, $output, $clear, $download, $extract) { |
|
161 | switch ($type) { |
||
162 | 12 | case CKEditorInstaller::NOTIFY_CLEAR: |
|
163 | 2 | $result = $this->choice( |
|
164 | [ |
||
165 | 2 | sprintf('CKEditor is already installed in "%s"...', $data), |
|
166 | 2 | '', |
|
167 | 2 | 'What do you want to do?', |
|
168 | 2 | ], |
|
169 | $choices = [ |
||
170 | 2 | CKEditorInstaller::CLEAR_DROP => 'Drop the directory & reinstall CKEditor', |
|
171 | 2 | CKEditorInstaller::CLEAR_KEEP => 'Keep the directory & reinstall CKEditor by overriding files', |
|
172 | 2 | CKEditorInstaller::CLEAR_SKIP => 'Skip installation', |
|
173 | 2 | ], |
|
174 | 2 | CKEditorInstaller::CLEAR_DROP, |
|
175 | 2 | $input, |
|
176 | $output |
||
177 | 2 | ); |
|
178 | |||
179 | 2 | if (($key = array_search($result, $choices, true)) !== false) { |
|
180 | $result = $key; |
||
181 | } |
||
182 | |||
183 | 2 | if ($result === CKEditorInstaller::CLEAR_DROP) { |
|
184 | 2 | $this->comment(sprintf('Dropping CKEditor from "%s"', $data), $output); |
|
185 | 2 | } |
|
186 | |||
187 | 2 | return $result; |
|
188 | |||
189 | 12 | case CKEditorInstaller::NOTIFY_CLEAR_ARCHIVE: |
|
190 | 12 | $this->comment(sprintf('Dropping CKEditor ZIP archive "%s"', $data), $output); |
|
191 | 12 | break; |
|
192 | |||
193 | 12 | case CKEditorInstaller::NOTIFY_CLEAR_COMPLETE: |
|
194 | 2 | $this->finishProgressBar($clear, $output); |
|
195 | 2 | break; |
|
196 | |||
197 | 12 | case CKEditorInstaller::NOTIFY_CLEAR_PROGRESS: |
|
198 | 2 | $clear->advance(); |
|
199 | 2 | break; |
|
200 | |||
201 | 12 | case CKEditorInstaller::NOTIFY_CLEAR_SIZE: |
|
202 | 2 | $this->startProgressBar($clear, $output, $data); |
|
203 | 2 | break; |
|
204 | |||
205 | 12 | case CKEditorInstaller::NOTIFY_DOWNLOAD: |
|
206 | 12 | $this->comment(sprintf('Downloading CKEditor ZIP archive from "%s"', $data), $output); |
|
207 | 12 | break; |
|
208 | |||
209 | 12 | case CKEditorInstaller::NOTIFY_DOWNLOAD_COMPLETE: |
|
210 | 12 | $this->finishProgressBar($download, $output); |
|
211 | 12 | break; |
|
212 | |||
213 | 12 | case CKEditorInstaller::NOTIFY_DOWNLOAD_PROGRESS: |
|
214 | 12 | $this->advanceProgressBar($download, $data); |
|
215 | 12 | break; |
|
216 | |||
217 | 12 | case CKEditorInstaller::NOTIFY_DOWNLOAD_SIZE: |
|
218 | 12 | $this->startProgressBar($download, $output, $data); |
|
219 | 12 | break; |
|
220 | |||
221 | 12 | case CKEditorInstaller::NOTIFY_EXTRACT: |
|
222 | 12 | $this->comment(sprintf('Extracting CKEditor ZIP archive to "%s"', $data), $output); |
|
223 | 12 | break; |
|
224 | |||
225 | 12 | case CKEditorInstaller::NOTIFY_EXTRACT_COMPLETE: |
|
226 | 12 | $this->finishProgressBar($extract, $output); |
|
227 | 12 | break; |
|
228 | |||
229 | 12 | case CKEditorInstaller::NOTIFY_EXTRACT_PROGRESS: |
|
230 | 12 | $extract->advance(); |
|
231 | 12 | break; |
|
232 | |||
233 | 12 | case CKEditorInstaller::NOTIFY_EXTRACT_SIZE: |
|
234 | 12 | $this->startProgressBar($extract, $output, $data); |
|
235 | 12 | break; |
|
236 | } |
||
237 | 12 | }; |
|
238 | } |
||
239 | |||
240 | /** |
||
241 | * @param OutputInterface $output |
||
242 | */ |
||
243 | 12 | private function title(OutputInterface $output) |
|
252 | |||
253 | /** |
||
254 | * @param string|string[] $message |
||
255 | * @param OutputInterface $output |
||
256 | */ |
||
257 | 12 | private function comment($message, OutputInterface $output) |
|
262 | |||
263 | /** |
||
264 | * @param string $message |
||
265 | * @param OutputInterface $output |
||
266 | */ |
||
267 | 12 | private function success($message, OutputInterface $output) |
|
271 | |||
272 | /** |
||
273 | * @param string $message |
||
274 | * @param OutputInterface $output |
||
275 | */ |
||
276 | private function info($message, OutputInterface $output) |
||
280 | |||
281 | /** |
||
282 | * @param string $message |
||
283 | * @param OutputInterface $output |
||
284 | * @param string $background |
||
285 | * @param string $font |
||
286 | */ |
||
287 | 12 | private function block($message, OutputInterface $output, $background = null, $font = null) |
|
309 | |||
310 | /** |
||
311 | * @param string|string[] $question |
||
312 | * @param string[] $choices |
||
313 | * @param string $default |
||
314 | * @param InputInterface $input |
||
315 | * @param OutputInterface $output |
||
316 | * |
||
317 | * @return string|null |
||
318 | */ |
||
319 | 2 | private function choice($question, array $choices, $default, InputInterface $input, OutputInterface $output) |
|
333 | |||
334 | /** |
||
335 | * @param OutputInterface $output |
||
336 | * |
||
337 | * @return ProgressBar|ProgressHelper |
||
338 | */ |
||
339 | 12 | private function createProgressBar(OutputInterface $output) |
|
343 | |||
344 | /** |
||
345 | * @param ProgressBar|ProgressHelper $progress |
||
346 | * @param OutputInterface $output |
||
347 | * @param int|null $max |
||
348 | */ |
||
349 | 12 | private function startProgressBar($progress, OutputInterface $output, $max = null) |
|
353 | |||
354 | /** |
||
355 | * @param ProgressBar|ProgressHelper $progress |
||
356 | * @param int $current |
||
357 | */ |
||
358 | 12 | private function advanceProgressBar($progress, $current) |
|
362 | |||
363 | /** |
||
364 | * @param ProgressBar|ProgressHelper $progress |
||
365 | * @param OutputInterface $output |
||
366 | */ |
||
367 | 12 | private function finishProgressBar($progress, OutputInterface $output) |
|
372 | } |
||
373 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.