Complex classes like StartController 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 StartController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class StartController extends CommonController |
||
24 | { |
||
25 | /** |
||
26 | * @var string absolute path to the project root directory |
||
27 | */ |
||
28 | protected $_rootDir; |
||
29 | |||
30 | /** |
||
31 | * @var bool hidev already started flag |
||
32 | */ |
||
33 | public static $started = false; |
||
34 | |||
35 | /** |
||
36 | * Make action. |
||
37 | */ |
||
38 | 2 | public function actionMake() |
|
39 | { |
||
40 | $this->getRootDir(); |
||
41 | $this->takeConfig()->includeConfig('.hidev/config.yml'); |
||
42 | if (file_exists('.hidev/config-local.yml')) { |
||
43 | $this->takeConfig()->includeConfig('.hidev/config-local.yml'); |
||
44 | } |
||
45 | $this->addAliases(); |
||
46 | $this->addAutoloader(); |
||
47 | $this->requireAll(); |
||
48 | $this->includeAll(); |
||
49 | $this->loadConfig(); |
||
50 | 2 | self::$started = true; |
|
51 | 2 | } |
|
52 | |||
53 | 2 | public function addAutoloader() |
|
54 | { |
||
55 | $autoloader = Yii::getAlias('@root/vendor/autoload.php'); |
||
56 | if (file_exists($autoloader)) { |
||
57 | spl_autoload_unregister(['Yii', 'autoload']); |
||
58 | require $autoloader; |
||
59 | spl_autoload_register(['Yii', 'autoload'], true, true); |
||
60 | } |
||
61 | 2 | } |
|
62 | |||
63 | /** |
||
64 | * Update action. |
||
65 | * @return int exit code |
||
66 | */ |
||
67 | public function actionUpdate() |
||
71 | |||
72 | /** |
||
73 | * Adds aliases: |
||
74 | * - @root alias to current project root dir |
||
75 | * - current package namespace for it could be used from hidev. |
||
76 | */ |
||
77 | 2 | public function addAliases() |
|
78 | { |
||
79 | Yii::setAlias('@root', $this->getRootDir()); |
||
80 | $config = $this->takeConfig()->rawItem('package'); |
||
81 | $alias = strtr($config['namespace'], '\\', '/'); |
||
82 | 2 | if ($alias && !Yii::getAlias('@' . $alias, false)) { |
|
83 | $srcdir = Yii::getAlias('@root/' . ($config['src'] ?: 'src')); |
||
84 | Yii::setAlias($alias, $srcdir); |
||
|
|||
85 | } |
||
86 | $aliases = $this->takeConfig()->rawItem('aliases'); |
||
87 | if (!empty($aliases) && is_array($aliases)) { |
||
88 | foreach ($aliases as $alias => $path) { |
||
89 | if (!$this->hasAlias($alias)) { |
||
90 | Yii::setAlias($alias, $path); |
||
91 | } |
||
92 | } |
||
93 | } |
||
94 | 2 | } |
|
95 | |||
96 | 2 | public function hasAlias($alias, $exact = true) |
|
97 | { |
||
98 | $pos = strpos($alias, '/'); |
||
99 | |||
100 | return $pos === false ? isset(Yii::$aliases[$alias]) : isset(Yii::$aliases[substr($alias, 0, $pos)][$alias]); |
||
101 | 2 | } |
|
102 | |||
103 | /** |
||
104 | * Require all configured requires. |
||
105 | */ |
||
106 | 2 | protected function requireAll() |
|
131 | |||
132 | 2 | public function needsComposerInstall() |
|
133 | { |
||
134 | if (file_exists('vendor')) { |
||
135 | return false; |
||
136 | } |
||
137 | if (!file_exists('composer.json')) { |
||
138 | 2 | return false; |
|
139 | } |
||
140 | $data = File::create('composer.json')->load(); |
||
141 | foreach (['require', 'require-dev'] as $key) { |
||
142 | if (isset($data[$key])) { |
||
143 | foreach ($data[$key] as $package => $version) { |
||
144 | list(, $name) = explode('/', $package); |
||
145 | if (strncmp($name, 'hidev-', 6) === 0) { |
||
146 | return true; |
||
147 | } |
||
148 | } |
||
149 | } |
||
150 | } |
||
151 | |||
152 | return false; |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Include all configs. |
||
157 | */ |
||
158 | 2 | public function includeAll() |
|
159 | { |
||
160 | 2 | $still = true; |
|
161 | while ($still) { |
||
162 | 2 | $still = false; |
|
163 | $include = $this->takeConfig()->rawItem('include'); |
||
164 | 2 | if ($include) { |
|
165 | foreach ($include as $path) { |
||
166 | $still = $still || $this->takeConfig()->includeConfig($path); |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | 2 | } |
|
171 | |||
172 | /** |
||
173 | * Load project's config if configured. |
||
174 | */ |
||
175 | 2 | public function loadConfig() |
|
176 | { |
||
177 | $path = $this->takeConfig()->rawItem('config'); |
||
178 | 2 | if ($path) { |
|
179 | $this->module->loadExtraConfig($path); |
||
180 | } |
||
181 | 2 | } |
|
182 | |||
183 | public function setRootDir($value) |
||
184 | { |
||
185 | $this->_rootDir = $value; |
||
186 | } |
||
187 | |||
188 | public function getRootDir() |
||
189 | { |
||
190 | if ($this->_rootDir === null) { |
||
191 | $this->_rootDir = $this->findRootDir(); |
||
192 | } |
||
193 | |||
194 | return $this->_rootDir; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Chdirs to project's root by looking for config file in the current directory and up. |
||
199 | * @throws InvalidParamException when failed to find |
||
200 | * @return string path to the root directory of hidev project |
||
201 | */ |
||
202 | 2 | protected function findRootDir() |
|
203 | { |
||
204 | 2 | $configDir = '.hidev'; |
|
205 | for ($i = 0;$i < 9;++$i) { |
||
206 | if (is_dir($configDir)) { |
||
207 | return getcwd(); |
||
208 | } |
||
209 | chdir('..'); |
||
210 | 2 | } |
|
211 | throw new InvalidParamException("Not a hidev project (or any of the parent directories).\nUse `hidev init` to initialize hidev project."); |
||
212 | } |
||
213 | |||
214 | public function buildRootPath($subpath) |
||
218 | } |
||
219 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.