Complex classes like MakeCommand 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 MakeCommand, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Limoncello\Application\Commands; |
||
36 | class MakeCommand implements CommandInterface |
||
37 | { |
||
38 | /** |
||
39 | * Command name. |
||
40 | */ |
||
41 | const NAME = 'l:make'; |
||
42 | |||
43 | /** Argument name */ |
||
44 | const ARG_ITEM = 'item'; |
||
45 | |||
46 | /** Argument name */ |
||
47 | const ARG_SINGULAR = 'singular'; |
||
48 | |||
49 | /** Argument name */ |
||
50 | const ARG_PLURAL = 'plural'; |
||
51 | |||
52 | /** Command action */ |
||
53 | const ITEM_DATA_RESOURCE = 'data-resource'; |
||
54 | |||
55 | /** Command action */ |
||
56 | const ITEM_WEB_RESOURCE = 'web-resource'; |
||
57 | |||
58 | /** Command action */ |
||
59 | const ITEM_JSON_API_RESOURCE = 'json-resource'; |
||
60 | |||
61 | /** Command action */ |
||
62 | const ITEM_FULL_RESOURCE = 'resource'; |
||
63 | |||
64 | /** |
||
65 | * Taken from http://php.net/manual/en/language.oop5.basic.php |
||
66 | */ |
||
67 | protected const VALID_CLASS_NAME_REGEX = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/'; |
||
68 | |||
69 | /** |
||
70 | * @inheritdoc |
||
71 | */ |
||
72 | 1 | public static function getName(): string |
|
76 | |||
77 | /** |
||
78 | * @inheritdoc |
||
79 | */ |
||
80 | 1 | public static function getDescription(): string |
|
84 | |||
85 | /** |
||
86 | * @inheritdoc |
||
87 | */ |
||
88 | 1 | public static function getHelp(): string |
|
92 | |||
93 | /** |
||
94 | * @inheritdoc |
||
95 | */ |
||
96 | 1 | public static function getArguments(): array |
|
121 | |||
122 | /** |
||
123 | * @inheritdoc |
||
124 | */ |
||
125 | 1 | public static function getOptions(): array |
|
129 | |||
130 | /** |
||
131 | * @inheritdoc |
||
132 | */ |
||
133 | 10 | public static function execute(ContainerInterface $container, IoInterface $inOut): void |
|
137 | |||
138 | /** |
||
139 | * @param ContainerInterface $container |
||
140 | * @param IoInterface $inOut |
||
141 | * |
||
142 | * @return void |
||
143 | * |
||
144 | * @throws ContainerExceptionInterface |
||
145 | * @throws NotFoundExceptionInterface |
||
146 | */ |
||
147 | 10 | protected function run(ContainerInterface $container, IoInterface $inOut): void |
|
148 | { |
||
149 | 10 | $item = $inOut->getArguments()[static::ARG_ITEM]; |
|
150 | 10 | $singular = $inOut->getArguments()[static::ARG_SINGULAR]; |
|
151 | 10 | $plural = $inOut->getArguments()[static::ARG_PLURAL]; |
|
152 | |||
153 | 10 | if ($this->isValidShortClassName($singular) === false) { |
|
154 | 1 | throw new InvalidArgumentException("`$singular` is not a valid class name."); |
|
155 | } |
||
156 | 9 | if ($this->isValidShortClassName($plural) === false) { |
|
157 | 1 | throw new InvalidArgumentException("`$plural` is not a valid class name."); |
|
158 | } |
||
159 | |||
160 | /** @var FileSystemInterface $fileSystem */ |
||
161 | 8 | $fileSystem = $container->get(FileSystemInterface::class); |
|
162 | /** @var SettingsProviderInterface $settingsProvider */ |
||
163 | 8 | $settingsProvider = $container->get(SettingsProviderInterface::class); |
|
164 | |||
165 | $dataTemplates = function () use ($settingsProvider, $fileSystem, $singular, $plural) : array { |
||
166 | return [ |
||
167 | 7 | $this->composeMigration($settingsProvider, $fileSystem, $singular, $plural), |
|
168 | 7 | $this->composeSeed($settingsProvider, $fileSystem, $singular, $plural), |
|
169 | 7 | $this->composeModel($settingsProvider, $fileSystem, $singular, $plural), |
|
170 | ]; |
||
171 | 8 | }; |
|
172 | |||
173 | $basicTemplates = function () use ($settingsProvider, $fileSystem, $singular, $plural) : array { |
||
174 | return [ |
||
175 | 3 | $this->composeSchema($settingsProvider, $fileSystem, $singular, $plural), |
|
176 | 3 | $this->composeAuthorization($settingsProvider, $fileSystem, $singular, $plural), |
|
177 | 3 | $this->composeApi($settingsProvider, $fileSystem, $singular, $plural), |
|
178 | 3 | $this->composeValidationRules($settingsProvider, $fileSystem, $singular, $plural), |
|
179 | 3 | $this->composeQueryValidationOnReadRules($settingsProvider, $fileSystem, $singular, $plural), |
|
180 | ]; |
||
181 | 8 | }; |
|
182 | |||
183 | $webTemplates = function () use ($settingsProvider, $fileSystem, $singular, $plural) : array { |
||
184 | return [ |
||
185 | 2 | $this->composeWebValidationOnCreateRules($settingsProvider, $fileSystem, $singular), |
|
186 | 2 | $this->composeWebValidationOnUpdateRules($settingsProvider, $fileSystem, $singular), |
|
187 | 2 | $this->composeWebController($settingsProvider, $fileSystem, $singular, $plural), |
|
188 | 2 | $this->composeWebRoute($settingsProvider, $fileSystem, $singular, $plural), |
|
189 | ]; |
||
190 | 8 | }; |
|
191 | |||
192 | $jsonTemplates = function () use ($settingsProvider, $fileSystem, $singular, $plural) : array { |
||
193 | return [ |
||
194 | 2 | $this->composeJsonValidationOnCreateRules($settingsProvider, $fileSystem, $singular), |
|
195 | 2 | $this->composeJsonValidationOnUpdateRules($settingsProvider, $fileSystem, $singular), |
|
196 | 2 | $this->composeJsonController($settingsProvider, $fileSystem, $singular, $plural), |
|
197 | 2 | $this->composeJsonRoute($settingsProvider, $fileSystem, $singular, $plural), |
|
198 | ]; |
||
199 | 8 | }; |
|
200 | |||
201 | switch ($item) { |
||
202 | 8 | case static::ITEM_DATA_RESOURCE: |
|
203 | 4 | $this->createTemplates($fileSystem, array_merge( |
|
204 | 4 | $dataTemplates() |
|
205 | )); |
||
206 | 1 | break; |
|
207 | 4 | case static::ITEM_WEB_RESOURCE: |
|
208 | 1 | $this->createTemplates($fileSystem, array_merge( |
|
209 | 1 | $dataTemplates(), |
|
210 | 1 | $basicTemplates(), |
|
211 | 1 | $webTemplates() |
|
212 | )); |
||
213 | 1 | break; |
|
214 | 3 | case static::ITEM_JSON_API_RESOURCE: |
|
215 | 1 | $this->createTemplates($fileSystem, array_merge( |
|
216 | 1 | $dataTemplates(), |
|
217 | 1 | $basicTemplates(), |
|
218 | 1 | $jsonTemplates() |
|
219 | )); |
||
220 | 1 | break; |
|
221 | 2 | case static::ITEM_FULL_RESOURCE: |
|
222 | 1 | $this->createTemplates($fileSystem, array_merge( |
|
223 | 1 | $dataTemplates(), |
|
224 | 1 | $basicTemplates(), |
|
225 | 1 | $webTemplates(), |
|
226 | 1 | $jsonTemplates() |
|
227 | )); |
||
228 | 1 | break; |
|
229 | default: |
||
230 | 1 | $inOut->writeError("Unsupported item type `$item`." . PHP_EOL); |
|
231 | 1 | break; |
|
232 | } |
||
233 | } |
||
234 | |||
235 | /** |
||
236 | * @param SettingsProviderInterface $settingsProvider |
||
237 | * @param FileSystemInterface $fileSystem |
||
238 | * @param string $singular |
||
239 | * @param string $plural |
||
240 | * |
||
241 | * @return TemplateOutput |
||
242 | */ |
||
243 | 7 | private function composeMigration( |
|
264 | |||
265 | /** |
||
266 | * @param SettingsProviderInterface $settingsProvider |
||
267 | * @param FileSystemInterface $fileSystem |
||
268 | * @param string $singular |
||
269 | * @param string $plural |
||
270 | * |
||
271 | * @return TemplateOutput |
||
272 | */ |
||
273 | 7 | private function composeSeed( |
|
294 | |||
295 | /** |
||
296 | * @param SettingsProviderInterface $settingsProvider |
||
297 | * @param FileSystemInterface $fileSystem |
||
298 | * @param string $singular |
||
299 | * @param string $plural |
||
300 | * |
||
301 | * @return TemplateOutput |
||
302 | */ |
||
303 | 7 | private function composeModel( |
|
327 | |||
328 | /** |
||
329 | * @param SettingsProviderInterface $settingsProvider |
||
330 | * @param FileSystemInterface $fileSystem |
||
331 | * @param string $singular |
||
332 | * @param string $plural |
||
333 | * |
||
334 | * @return TemplateOutput |
||
335 | */ |
||
336 | 3 | private function composeSchema( |
|
357 | |||
358 | /** |
||
359 | * @param SettingsProviderInterface $settingsProvider |
||
360 | * @param FileSystemInterface $fileSystem |
||
361 | * @param string $singular |
||
362 | * @param string $plural |
||
363 | * |
||
364 | * @return TemplateOutput |
||
365 | */ |
||
366 | 3 | private function composeApi( |
|
389 | |||
390 | /** |
||
391 | * @param SettingsProviderInterface $settingsProvider |
||
392 | * @param FileSystemInterface $fileSystem |
||
393 | * @param string $singular |
||
394 | * @param string $plural |
||
395 | * |
||
396 | * @return TemplateOutput |
||
397 | */ |
||
398 | 3 | private function composeAuthorization( |
|
423 | |||
424 | /** |
||
425 | * @param SettingsProviderInterface $settingsProvider |
||
426 | * @param FileSystemInterface $fileSystem |
||
427 | * @param string $singular |
||
428 | * @param string $plural |
||
429 | * |
||
430 | * @return TemplateOutput |
||
431 | */ |
||
432 | 3 | private function composeValidationRules( |
|
456 | |||
457 | /** |
||
458 | * @param SettingsProviderInterface $settingsProvider |
||
459 | * @param FileSystemInterface $fileSystem |
||
460 | * @param string $singular |
||
461 | * |
||
462 | * @return TemplateOutput |
||
463 | */ |
||
464 | 2 | private function composeJsonValidationOnCreateRules( |
|
485 | |||
486 | /** |
||
487 | * @param SettingsProviderInterface $settingsProvider |
||
488 | * @param FileSystemInterface $fileSystem |
||
489 | * @param string $singular |
||
490 | * |
||
491 | * @return TemplateOutput |
||
492 | */ |
||
493 | 2 | private function composeJsonValidationOnUpdateRules( |
|
514 | |||
515 | /** |
||
516 | * @param SettingsProviderInterface $settingsProvider |
||
517 | * @param FileSystemInterface $fileSystem |
||
518 | * @param string $singular |
||
519 | * @param string $plural |
||
520 | * |
||
521 | * @return TemplateOutput |
||
522 | * |
||
523 | */ |
||
524 | 3 | private function composeQueryValidationOnReadRules( |
|
546 | |||
547 | /** |
||
548 | * @param SettingsProviderInterface $settingsProvider |
||
549 | * @param FileSystemInterface $fileSystem |
||
550 | * @param string $singular |
||
551 | * @param string $plural |
||
552 | * |
||
553 | * @return TemplateOutput |
||
554 | */ |
||
555 | 2 | private function composeJsonController( |
|
577 | |||
578 | /** |
||
579 | * @param SettingsProviderInterface $settingsProvider |
||
580 | * @param FileSystemInterface $fileSystem |
||
581 | * @param string $singular |
||
582 | * @param string $plural |
||
583 | * |
||
584 | * @return TemplateOutput |
||
585 | */ |
||
586 | 2 | private function composeJsonRoute( |
|
607 | |||
608 | /** |
||
609 | * @param SettingsProviderInterface $settingsProvider |
||
610 | * @param FileSystemInterface $fileSystem |
||
611 | * @param string $singular |
||
612 | * |
||
613 | * @return TemplateOutput |
||
614 | */ |
||
615 | 2 | private function composeWebValidationOnCreateRules( |
|
635 | |||
636 | /** |
||
637 | * @param SettingsProviderInterface $settingsProvider |
||
638 | * @param FileSystemInterface $fileSystem |
||
639 | * @param string $singular |
||
640 | * |
||
641 | * @return TemplateOutput |
||
642 | */ |
||
643 | 2 | private function composeWebValidationOnUpdateRules( |
|
663 | |||
664 | /** |
||
665 | * @param SettingsProviderInterface $settingsProvider |
||
666 | * @param FileSystemInterface $fileSystem |
||
667 | * @param string $singular |
||
668 | * @param string $plural |
||
669 | * |
||
670 | * @return TemplateOutput |
||
671 | */ |
||
672 | 2 | private function composeWebController( |
|
696 | |||
697 | /** |
||
698 | * @param SettingsProviderInterface $settingsProvider |
||
699 | * @param FileSystemInterface $fileSystem |
||
700 | * @param string $singular |
||
701 | * @param string $plural |
||
702 | * |
||
703 | * @return TemplateOutput |
||
704 | */ |
||
705 | 2 | private function composeWebRoute( |
|
726 | |||
727 | /** |
||
728 | * @param FileSystemInterface $fileSystem |
||
729 | * @param TemplateOutput[] $templateOutputs |
||
730 | * |
||
731 | * @return void |
||
732 | * |
||
733 | * @SuppressWarnings(PHPMD.ElseExpression) |
||
734 | */ |
||
735 | 7 | private function createTemplates(FileSystemInterface $fileSystem, array $templateOutputs): void |
|
771 | |||
772 | /** |
||
773 | * @param FileSystemInterface $fileSystem |
||
774 | * @param string $templatePath |
||
775 | * @param iterable $templateParams |
||
776 | * |
||
777 | * @return string |
||
778 | */ |
||
779 | 7 | private function composeTemplateContent( |
|
792 | |||
793 | /** |
||
794 | * @param string $name |
||
795 | * |
||
796 | * @return bool |
||
797 | */ |
||
798 | 10 | private function isValidShortClassName(string $name): bool |
|
802 | |||
803 | /** |
||
804 | * @param string $fileName |
||
805 | * |
||
806 | * @return string |
||
807 | */ |
||
808 | 7 | private function getTemplatePath(string $fileName): string |
|
812 | |||
813 | /** |
||
814 | * Folder paths might include masks such as `**`. This function tries to filter them out. |
||
815 | * |
||
816 | * @param string $folder |
||
817 | * |
||
818 | * @return string |
||
819 | */ |
||
820 | 7 | private function filterOutFolderMask(string $folder): string |
|
829 | } |
||
830 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: