Total Complexity | 43 |
Total Lines | 350 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like DefaultConfiguration 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.
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 DefaultConfiguration, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | final class DefaultConfiguration extends AbstractConfiguration |
||
12 | { |
||
13 | |||
14 | private $appEnvironment = 'prod'; |
||
15 | private $keepReleases = 5; |
||
16 | private $repositoryUrl; |
||
17 | private $repositoryBranch = 'master'; |
||
18 | private $remotePhpBinaryPath = 'php'; |
||
19 | private $updateRemoteComposerBinary = false; |
||
20 | private $remoteComposerBinaryPath = '/usr/bin/composer'; |
||
21 | private $composerInstallFlags = '--no-dev --prefer-dist --no-interaction --quiet'; |
||
22 | private $composerOptimizeFlags = '--optimize'; |
||
23 | private $installWebAssets = true; |
||
24 | private $dumpAsseticAssets = false; |
||
25 | private $warmupCache = true; |
||
26 | private $consoleBinaryPath; |
||
27 | private $localProjectDir; |
||
28 | private $configDir; |
||
29 | private $cacheDir; |
||
30 | private $deployDir; |
||
31 | private $logDir; |
||
32 | private $srcDir; |
||
33 | private $templatesDir; |
||
34 | private $webDir; |
||
35 | private $controllersToRemove = []; |
||
36 | private $writableDirs = []; |
||
37 | private $permissionMethod = 'chmod'; |
||
38 | private $permissionMode = '0777'; |
||
39 | private $permissionUser; |
||
40 | private $permissionGroup; |
||
41 | private $sharedFiles; |
||
42 | private $sharedDirs; |
||
43 | private $resetOpCacheFor; |
||
44 | |||
45 | public function __construct(string $localProjectDir) |
||
46 | { |
||
47 | parent::__construct(); |
||
48 | $this->localProjectDir = $localProjectDir; |
||
49 | $this->setDefaultConfiguration(); |
||
50 | } |
||
51 | |||
52 | // this proxy method is needed because the autocompletion breaks |
||
53 | // if the parent method is used directly |
||
54 | public function server(string $sshDsn, array $roles = [Server::ROLE_APP], array $properties = []) : self |
||
55 | { |
||
56 | parent::server($sshDsn, $roles, $properties); |
||
57 | |||
58 | return $this; |
||
59 | } |
||
60 | |||
61 | // this proxy method is needed because the autocompletion breaks |
||
62 | // if the parent method is used directly |
||
63 | public function useSshAgentForwarding(bool $useIt) : self |
||
64 | { |
||
65 | parent::useSshAgentForwarding($useIt); |
||
66 | |||
67 | return $this; |
||
68 | } |
||
69 | |||
70 | public function appEnvironment(string $name) : self |
||
71 | { |
||
72 | $this->appEnvironment = $name; |
||
73 | |||
74 | return $this; |
||
75 | } |
||
76 | |||
77 | public function keepReleases(int $numReleases) : self |
||
78 | { |
||
79 | $this->keepReleases = $numReleases; |
||
80 | |||
81 | return $this; |
||
82 | } |
||
83 | |||
84 | public function repositoryUrl(string $url) : self |
||
85 | { |
||
86 | // SSH agent forwarding only works when using SSH URLs, not https URLs. Check these URLs: |
||
87 | // https://github.com/<user>/<repo> |
||
88 | // https://bitbucket.org/<user>/<repo> |
||
89 | // https://gitlab.com/<user>/<repo>.git |
||
90 | if (Str::startsWith($url, 'https://')) { |
||
91 | $sshUrl = str_replace('https://', 'git@', $url); |
||
92 | if (!Str::endsWith($sshUrl, '.git')) { |
||
93 | $sshUrl .= '.git'; |
||
94 | } |
||
95 | |||
96 | throw new InvalidConfigurationException(sprintf('The repository URL must use the SSH syntax instead of the HTTPs syntax to make it work on any remote server. Replace "%s" by "%s"', $url, $sshUrl)); |
||
97 | } |
||
98 | |||
99 | $this->repositoryUrl = $url; |
||
100 | |||
101 | return $this; |
||
102 | } |
||
103 | |||
104 | public function repositoryBranch(string $branchName) : self |
||
105 | { |
||
106 | $this->repositoryBranch = $branchName; |
||
107 | |||
108 | return $this; |
||
109 | } |
||
110 | |||
111 | public function remotePhpBinaryPath(string $path) : self |
||
112 | { |
||
113 | $this->remotePhpBinaryPath = $path; |
||
114 | |||
115 | return $this; |
||
116 | } |
||
117 | |||
118 | public function updateRemoteComposerBinary(bool $updateBeforeInstall) : self |
||
119 | { |
||
120 | $this->updateRemoteComposerBinary = $updateBeforeInstall; |
||
121 | |||
122 | return $this; |
||
123 | } |
||
124 | |||
125 | public function remoteComposerBinaryPath(string $path) : self |
||
126 | { |
||
127 | $this->remoteComposerBinaryPath = $path; |
||
128 | |||
129 | return $this; |
||
130 | } |
||
131 | |||
132 | public function composerInstallFlags(string $flags) : self |
||
133 | { |
||
134 | $this->composerInstallFlags = $flags; |
||
135 | |||
136 | return $this; |
||
137 | } |
||
138 | |||
139 | public function composerOptimizeFlags(string $flags) : self |
||
140 | { |
||
141 | $this->composerOptimizeFlags = $flags; |
||
142 | |||
143 | return $this; |
||
144 | } |
||
145 | |||
146 | public function installWebAssets(bool $install) : self |
||
147 | { |
||
148 | $this->installWebAssets = $install; |
||
149 | |||
150 | return $this; |
||
151 | } |
||
152 | |||
153 | public function dumpAsseticAssets(bool $dump) : self |
||
154 | { |
||
155 | $this->dumpAsseticAssets = $dump; |
||
156 | |||
157 | return $this; |
||
158 | } |
||
159 | |||
160 | public function warmupCache(bool $warmUp) : self |
||
161 | { |
||
162 | $this->warmupCache = $warmUp; |
||
163 | |||
164 | return $this; |
||
165 | } |
||
166 | |||
167 | public function consoleBinaryPath(string $path) : self |
||
168 | { |
||
169 | $this->consoleBinaryPath = $path; |
||
170 | |||
171 | return $this; |
||
172 | } |
||
173 | |||
174 | |||
175 | // Relative to the project root directory |
||
176 | public function configDir(string $path) : self |
||
177 | { |
||
178 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
179 | $this->configDir = rtrim($path, '/'); |
||
180 | |||
181 | return $this; |
||
182 | } |
||
183 | |||
184 | // Relative to the project root directory |
||
185 | public function cacheDir(string $path) : self |
||
186 | { |
||
187 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
188 | $this->cacheDir = rtrim($path, '/'); |
||
189 | |||
190 | return $this; |
||
191 | } |
||
192 | |||
193 | public function deployDir(string $path) : self |
||
194 | { |
||
195 | $this->deployDir = rtrim($path, '/'); |
||
196 | |||
197 | return $this; |
||
198 | } |
||
199 | |||
200 | // Relative to the project root directory |
||
201 | public function logDir(string $path) : self |
||
202 | { |
||
203 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
204 | $this->logDir = rtrim($path, '/'); |
||
205 | |||
206 | return $this; |
||
207 | } |
||
208 | |||
209 | // Relative to the project root directory |
||
210 | public function srcDir(string $path) : self |
||
211 | { |
||
212 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
213 | $this->srcDir = rtrim($path, '/'); |
||
214 | |||
215 | return $this; |
||
216 | } |
||
217 | |||
218 | // Relative to the project root directory |
||
219 | public function templatesDir(string $path) : self |
||
220 | { |
||
221 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
222 | $this->templatesDir = rtrim($path, '/'); |
||
223 | |||
224 | return $this; |
||
225 | } |
||
226 | |||
227 | // Relative to the project root directory |
||
228 | public function webDir(string $path) : self |
||
229 | { |
||
230 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
231 | $this->webDir = rtrim($path, '/'); |
||
232 | |||
233 | return $this; |
||
234 | } |
||
235 | |||
236 | // Relative to the project root directory |
||
237 | // the $paths can be glob() patterns, so this method needs to resolve them |
||
238 | public function controllersToRemove(array $paths) : self |
||
239 | { |
||
240 | $absoluteGlobPaths = array_map(function ($globPath) { |
||
241 | return $this->localProjectDir.DIRECTORY_SEPARATOR.$globPath; |
||
242 | }, $paths); |
||
243 | |||
244 | $localAbsolutePaths = []; |
||
245 | foreach ($absoluteGlobPaths as $path) { |
||
246 | $localAbsolutePaths = array_merge($localAbsolutePaths, glob($path)); |
||
247 | } |
||
248 | |||
249 | $localRelativePaths = array_map(function ($absolutePath) { |
||
250 | $relativePath = str_replace($this->localProjectDir, '', $absolutePath); |
||
251 | $this->validatePathIsRelativeToProject($relativePath, 'controllersToRemove'); |
||
252 | |||
253 | return trim($relativePath, DIRECTORY_SEPARATOR); |
||
254 | }, $localAbsolutePaths); |
||
255 | |||
256 | $this->controllersToRemove = $localRelativePaths; |
||
257 | |||
258 | return $this; |
||
259 | } |
||
260 | |||
261 | // Relative to the project root directory |
||
262 | public function writableDirs(array $paths) : self |
||
263 | { |
||
264 | foreach ($paths as $path) { |
||
265 | $this->validatePathIsRelativeToProject($path, __METHOD__); |
||
266 | } |
||
267 | $this->writableDirs = $paths; |
||
268 | |||
269 | return $this; |
||
270 | } |
||
271 | |||
272 | public function fixPermissionsWithChmod(string $mode = '0777') : self |
||
273 | { |
||
274 | $this->permissionMethod = 'chmod'; |
||
275 | $this->permissionMode = $mode; |
||
276 | |||
277 | return $this; |
||
278 | } |
||
279 | |||
280 | public function fixPermissionsWithChown(string $webServerUser) : self |
||
281 | { |
||
282 | $this->permissionMethod = 'chown'; |
||
283 | $this->permissionUser = $webServerUser; |
||
284 | |||
285 | return $this; |
||
286 | } |
||
287 | |||
288 | public function fixPermissionsWithChgrp(string $webServerGroup) : self |
||
289 | { |
||
290 | $this->permissionMethod = 'chgrp'; |
||
291 | $this->permissionGroup = $webServerGroup; |
||
292 | |||
293 | return $this; |
||
294 | } |
||
295 | |||
296 | public function fixPermissionsWithAcl(string $webServerUser) : self |
||
297 | { |
||
298 | $this->permissionMethod = 'acl'; |
||
299 | $this->permissionUser = $webServerUser; |
||
300 | |||
301 | return $this; |
||
302 | } |
||
303 | |||
304 | // Relative to the project root directory |
||
305 | public function sharedFilesAndDirs(array $paths) : self |
||
320 | } |
||
321 | |||
322 | |||
323 | public function resetOpCacheFor(string $homepageUrl) : self |
||
324 | { |
||
325 | if (!Str::startsWith($homepageUrl, 'http')) { |
||
326 | throw new InvalidConfigurationException(sprintf('The value of %s option must be the valid URL of your homepage (it must start with http:// or https://).', Option::resetOpCacheFor)); |
||
327 | } |
||
328 | |||
329 | $this->resetOpCacheFor = rtrim($homepageUrl, '/'); |
||
330 | |||
331 | return $this; |
||
332 | } |
||
333 | |||
334 | protected function getReservedServerProperties() : array |
||
335 | { |
||
336 | return [Property::bin_dir, Property::config_dir, Property::console_bin, Property::cache_dir, Property::deploy_dir, Property::log_dir, Property::src_dir, Property::templates_dir, Property::web_dir]; |
||
337 | } |
||
338 | |||
339 | private function setDefaultConfiguration() : void |
||
340 | { |
||
341 | $this->setDirs('config', 'storage/framework/cache', 'storage/logs', 'src', 'templates', 'public'); |
||
342 | $this->controllersToRemove([]); |
||
343 | $this->sharedDirs = ['storage/logs']; |
||
344 | $this->writableDirs = ['storage/framework/cache/', 'storage/logs/']; |
||
345 | } |
||
346 | |||
347 | private function setDirs(string $configDir, string $cacheDir, string $logDir, string $srcDir, string $templatesDir, string $webDir) : void |
||
355 | } |
||
356 | |||
357 | private function validatePathIsRelativeToProject($path, $methodName) : void |
||
361 | } |
||
362 | } |
||
363 | } |
||
364 |