Complex classes like MessageController 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 MessageController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class MessageController extends \yii\console\Controller |
||
41 | { |
||
42 | /** |
||
43 | * @var string controller default action ID. |
||
44 | */ |
||
45 | public $defaultAction = 'extract'; |
||
46 | /** |
||
47 | * @var string required, root directory of all source files. |
||
48 | */ |
||
49 | public $sourcePath = '@yii'; |
||
50 | /** |
||
51 | * @var string required, root directory containing message translations. |
||
52 | */ |
||
53 | public $messagePath = '@yii/messages'; |
||
54 | /** |
||
55 | * @var array required, list of language codes that the extracted messages |
||
56 | * should be translated to. For example, ['zh-CN', 'de']. |
||
57 | */ |
||
58 | public $languages = []; |
||
59 | /** |
||
60 | * @var string the name of the function for translating messages. |
||
61 | * Defaults to 'Yii::t'. This is used as a mark to find the messages to be |
||
62 | * translated. You may use a string for single function name or an array for |
||
63 | * multiple function names. |
||
64 | */ |
||
65 | public $translator = 'Yii::t'; |
||
66 | /** |
||
67 | * @var bool whether to sort messages by keys when merging new messages |
||
68 | * with the existing ones. Defaults to false, which means the new (untranslated) |
||
69 | * messages will be separated from the old (translated) ones. |
||
70 | */ |
||
71 | public $sort = false; |
||
72 | /** |
||
73 | * @var bool whether the message file should be overwritten with the merged messages |
||
74 | */ |
||
75 | public $overwrite = true; |
||
76 | /** |
||
77 | * @var bool whether to remove messages that no longer appear in the source code. |
||
78 | * Defaults to false, which means these messages will NOT be removed. |
||
79 | */ |
||
80 | public $removeUnused = false; |
||
81 | /** |
||
82 | * @var bool whether to mark messages that no longer appear in the source code. |
||
83 | * Defaults to true, which means each of these messages will be enclosed with a pair of '@@' marks. |
||
84 | */ |
||
85 | public $markUnused = true; |
||
86 | /** |
||
87 | * @var array list of patterns that specify which files/directories should NOT be processed. |
||
88 | * If empty or not set, all files/directories will be processed. |
||
89 | * See helpers/FileHelper::findFiles() description for pattern matching rules. |
||
90 | * If a file/directory matches both a pattern in "only" and "except", it will NOT be processed. |
||
91 | */ |
||
92 | public $except = [ |
||
93 | '.svn', |
||
94 | '.git', |
||
95 | '.gitignore', |
||
96 | '.gitkeep', |
||
97 | '.hgignore', |
||
98 | '.hgkeep', |
||
99 | '/messages', |
||
100 | '/BaseYii.php', // contains examples about Yii:t() |
||
101 | ]; |
||
102 | /** |
||
103 | * @var array list of patterns that specify which files (not directories) should be processed. |
||
104 | * If empty or not set, all files will be processed. |
||
105 | * See helpers/FileHelper::findFiles() description for pattern matching rules. |
||
106 | * If a file/directory matches both a pattern in "only" and "except", it will NOT be processed. |
||
107 | */ |
||
108 | public $only = ['*.php']; |
||
109 | /** |
||
110 | * @var string generated file format. Can be "php", "db", "po" or "pot". |
||
111 | */ |
||
112 | public $format = 'php'; |
||
113 | /** |
||
114 | * @var string connection component ID for "db" format. |
||
115 | */ |
||
116 | public $db = 'db'; |
||
117 | /** |
||
118 | * @var string custom name for source message table for "db" format. |
||
119 | */ |
||
120 | public $sourceMessageTable = '{{%source_message}}'; |
||
121 | /** |
||
122 | * @var string custom name for translation message table for "db" format. |
||
123 | */ |
||
124 | public $messageTable = '{{%message}}'; |
||
125 | /** |
||
126 | * @var string name of the file that will be used for translations for "po" format. |
||
127 | */ |
||
128 | public $catalog = 'messages'; |
||
129 | /** |
||
130 | * @var array message categories to ignore. For example, 'yii', 'app*', 'widgets/menu', etc. |
||
131 | * @see isCategoryIgnored |
||
132 | */ |
||
133 | public $ignoreCategories = []; |
||
134 | |||
135 | |||
136 | /** |
||
137 | * @inheritdoc |
||
138 | */ |
||
139 | 35 | public function options($actionID) |
|
140 | { |
||
141 | 35 | return array_merge(parent::options($actionID), [ |
|
142 | 35 | 'sourcePath', |
|
143 | 'messagePath', |
||
144 | 'languages', |
||
145 | 'translator', |
||
146 | 'sort', |
||
147 | 'overwrite', |
||
148 | 'removeUnused', |
||
149 | 'markUnused', |
||
150 | 'except', |
||
151 | 'only', |
||
152 | 'format', |
||
153 | 'db', |
||
154 | 'sourceMessageTable', |
||
155 | 'messageTable', |
||
156 | 'catalog', |
||
157 | 'ignoreCategories', |
||
158 | ]); |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * @inheritdoc |
||
163 | * @since 2.0.8 |
||
164 | */ |
||
165 | public function optionAliases() |
||
166 | { |
||
167 | return array_merge(parent::optionAliases(), [ |
||
168 | 'c' => 'catalog', |
||
169 | 'e' => 'except', |
||
170 | 'f' => 'format', |
||
171 | 'i' => 'ignoreCategories', |
||
172 | 'l' => 'languages', |
||
173 | 'u' => 'markUnused', |
||
174 | 'p' => 'messagePath', |
||
175 | 'o' => 'only', |
||
176 | 'w' => 'overwrite', |
||
177 | 'S' => 'sort', |
||
178 | 't' => 'translator', |
||
179 | 'm' => 'sourceMessageTable', |
||
180 | 's' => 'sourcePath', |
||
181 | 'r' => 'removeUnused', |
||
182 | ]); |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Creates a configuration file for the "extract" command using command line options specified |
||
187 | * |
||
188 | * The generated configuration file contains parameters required |
||
189 | * for source code messages extraction. |
||
190 | * You may use this configuration file with the "extract" command. |
||
191 | * |
||
192 | * @param string $filePath output file name or alias. |
||
193 | * @return int CLI exit code |
||
194 | * @throws Exception on failure. |
||
195 | */ |
||
196 | 3 | public function actionConfig($filePath) |
|
197 | { |
||
198 | 3 | $filePath = Yii::getAlias($filePath); |
|
199 | 3 | if (file_exists($filePath)) { |
|
200 | if (!$this->confirm("File '{$filePath}' already exists. Do you wish to overwrite it?")) { |
||
|
|||
201 | return self::EXIT_CODE_NORMAL; |
||
202 | } |
||
203 | } |
||
204 | |||
205 | 3 | $array = VarDumper::export($this->getOptionValues($this->action->id)); |
|
206 | $content = <<<EOD |
||
207 | <?php |
||
208 | /** |
||
209 | 3 | * Configuration file for 'yii {$this->id}/{$this->defaultAction}' command. |
|
210 | * |
||
211 | 3 | * This file is automatically generated by 'yii {$this->id}/{$this->action->id}' command. |
|
212 | * It contains parameters for source code messages extraction. |
||
213 | * You may modify this file to suit your needs. |
||
214 | * |
||
215 | 3 | * You can use 'yii {$this->id}/{$this->action->id}-template' command to create |
|
216 | * template configuration file with detailed description for each parameter. |
||
217 | */ |
||
218 | 3 | return $array; |
|
219 | |||
220 | EOD; |
||
221 | |||
222 | 3 | if (file_put_contents($filePath, $content) === false) { |
|
223 | $this->stdout("Configuration file was NOT created: '{$filePath}'.\n\n", Console::FG_RED); |
||
224 | return self::EXIT_CODE_ERROR; |
||
225 | } |
||
226 | |||
227 | 3 | $this->stdout("Configuration file created: '{$filePath}'.\n\n", Console::FG_GREEN); |
|
228 | 3 | return self::EXIT_CODE_NORMAL; |
|
229 | } |
||
230 | |||
231 | /** |
||
232 | * Creates a configuration file template for the "extract" command. |
||
233 | * |
||
234 | * The created configuration file contains detailed instructions on |
||
235 | * how to customize it to fit for your needs. After customization, |
||
236 | * you may use this configuration file with the "extract" command. |
||
237 | * |
||
238 | * @param string $filePath output file name or alias. |
||
239 | * @return int CLI exit code |
||
240 | * @throws Exception on failure. |
||
241 | */ |
||
242 | public function actionConfigTemplate($filePath) |
||
260 | |||
261 | /** |
||
262 | * Extracts messages to be translated from source code. |
||
263 | * |
||
264 | * This command will search through source code files and extract |
||
265 | * messages that need to be translated in different languages. |
||
266 | * |
||
267 | * @param string $configFile the path or alias of the configuration file. |
||
268 | * You may use the "yii message/config" command to generate |
||
269 | * this file and then customize it for your needs. |
||
270 | * @throws Exception on failure. |
||
271 | */ |
||
272 | 32 | public function actionExtract($configFile = null) |
|
351 | |||
352 | /** |
||
353 | * Saves messages to database |
||
354 | * |
||
355 | * @param array $messages |
||
356 | * @param Connection $db |
||
357 | * @param string $sourceMessageTable |
||
358 | * @param string $messageTable |
||
359 | * @param bool $removeUnused |
||
360 | * @param array $languages |
||
361 | * @param bool $markUnused |
||
362 | */ |
||
363 | 9 | protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages, $markUnused) |
|
473 | |||
474 | /** |
||
475 | * Extracts messages from a file |
||
476 | * |
||
477 | * @param string $fileName name of the file to extract messages from |
||
478 | * @param string $translator name of the function used to translate messages |
||
479 | * @param array $ignoreCategories message categories to ignore. |
||
480 | * This parameter is available since version 2.0.4. |
||
481 | * @return array |
||
482 | */ |
||
483 | 29 | protected function extractMessages($fileName, $translator, $ignoreCategories = []) |
|
502 | |||
503 | /** |
||
504 | * Extracts messages from a parsed PHP tokens list. |
||
505 | * @param array $tokens tokens to be processed. |
||
506 | * @param array $translatorTokens translator tokens. |
||
507 | * @param array $ignoreCategories message categories to ignore. |
||
508 | * @return array messages. |
||
509 | */ |
||
510 | 29 | private function extractMessagesFromTokens(array $tokens, array $translatorTokens, array $ignoreCategories) |
|
581 | |||
582 | /** |
||
583 | * The method checks, whether the $category is ignored according to $ignoreCategories array. |
||
584 | * Examples: |
||
585 | * |
||
586 | * - `myapp` - will be ignored only `myapp` category; |
||
587 | * - `myapp*` - will be ignored by all categories beginning with `myapp` (`myapp`, `myapplication`, `myapprove`, `myapp/widgets`, `myapp.widgets`, etc). |
||
588 | * |
||
589 | * @param string $category category that is checked |
||
590 | * @param array $ignoreCategories message categories to ignore. |
||
591 | * @return bool |
||
592 | * @since 2.0.7 |
||
593 | */ |
||
594 | 29 | protected function isCategoryIgnored($category, array $ignoreCategories) |
|
609 | |||
610 | /** |
||
611 | * Finds out if two PHP tokens are equal |
||
612 | * |
||
613 | * @param array|string $a |
||
614 | * @param array|string $b |
||
615 | * @return bool |
||
616 | * @since 2.0.1 |
||
617 | */ |
||
618 | 29 | protected function tokensEqual($a, $b) |
|
628 | |||
629 | /** |
||
630 | * Finds out a line of the first non-char PHP token found |
||
631 | * |
||
632 | * @param array $tokens |
||
633 | * @return int|string |
||
634 | * @since 2.0.1 |
||
635 | */ |
||
636 | protected function getLine($tokens) |
||
645 | |||
646 | /** |
||
647 | * Writes messages into PHP files |
||
648 | * |
||
649 | * @param array $messages |
||
650 | * @param string $dirName name of the directory to write to |
||
651 | * @param bool $overwrite if existing file should be overwritten without backup |
||
652 | * @param bool $removeUnused if obsolete translations should be removed |
||
653 | * @param bool $sort if translations should be sorted |
||
654 | * @param bool $markUnused if obsolete translations should be marked |
||
655 | */ |
||
656 | 10 | protected function saveMessagesToPHP($messages, $dirName, $overwrite, $removeUnused, $sort, $markUnused) |
|
668 | |||
669 | /** |
||
670 | * Writes category messages into PHP file |
||
671 | * |
||
672 | * @param array $messages |
||
673 | * @param string $fileName name of the file to write to |
||
674 | * @param bool $overwrite if existing file should be overwritten without backup |
||
675 | * @param bool $removeUnused if obsolete translations should be removed |
||
676 | * @param bool $sort if translations should be sorted |
||
677 | * @param string $category message category |
||
678 | * @param bool $markUnused if obsolete translations should be marked |
||
679 | * @return int exit code |
||
680 | */ |
||
681 | 10 | protected function saveMessagesCategoryToPHP($messages, $fileName, $overwrite, $removeUnused, $sort, $category, $markUnused) |
|
766 | |||
767 | /** |
||
768 | * Writes messages into PO file |
||
769 | * |
||
770 | * @param array $messages |
||
771 | * @param string $dirName name of the directory to write to |
||
772 | * @param bool $overwrite if existing file should be overwritten without backup |
||
773 | * @param bool $removeUnused if obsolete translations should be removed |
||
774 | * @param bool $sort if translations should be sorted |
||
775 | * @param string $catalog message catalog |
||
776 | * @param bool $markUnused if obsolete translations should be marked |
||
777 | */ |
||
778 | 10 | protected function saveMessagesToPO($messages, $dirName, $overwrite, $removeUnused, $sort, $catalog, $markUnused) |
|
862 | |||
863 | /** |
||
864 | * Writes messages into POT file |
||
865 | * |
||
866 | * @param array $messages |
||
867 | * @param string $dirName name of the directory to write to |
||
868 | * @param string $catalog message catalog |
||
869 | * @since 2.0.6 |
||
870 | */ |
||
871 | protected function saveMessagesToPOT($messages, $dirName, $catalog) |
||
900 | } |
||
901 |
If an expression can have both
false
, andnull
as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.