Total Complexity | 45 |
Total Lines | 484 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like StubGenerator 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 StubGenerator, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
26 | class StubGenerator |
||
27 | { |
||
28 | /** |
||
29 | * The list of server variables that are allowed to be modified. |
||
30 | * |
||
31 | * @var array |
||
32 | */ |
||
33 | private static $allowedMung = [ |
||
34 | 'PHP_SELF', |
||
35 | 'REQUEST_URI', |
||
36 | 'SCRIPT_FILENAME', |
||
37 | 'SCRIPT_NAME', |
||
38 | ]; |
||
39 | |||
40 | /** |
||
41 | * The alias to be used in "phar://" URLs. |
||
42 | * |
||
43 | * @var string |
||
44 | */ |
||
45 | private $alias = ''; |
||
46 | |||
47 | /** |
||
48 | * The top header comment banner text. |
||
49 | * |
||
50 | * @var string |
||
51 | */ |
||
52 | private $banner = 'Generated by Box. |
||
53 | |||
54 | @link https://github.com/herrera-io/php-box/'; |
||
55 | |||
56 | /** |
||
57 | * Embed the Extract class in the stub? |
||
58 | * |
||
59 | * @var bool |
||
60 | */ |
||
61 | private $extract = false; |
||
62 | |||
63 | /** |
||
64 | * The processed extract code. |
||
65 | * |
||
66 | * @var array |
||
67 | */ |
||
68 | private $extractCode = []; |
||
69 | |||
70 | /** |
||
71 | * Force the use of the Extract class? |
||
72 | * |
||
73 | * @var bool |
||
74 | */ |
||
75 | private $extractForce = false; |
||
76 | |||
77 | /** |
||
78 | * The location within the Phar of index script. |
||
79 | * |
||
80 | * @var string |
||
81 | */ |
||
82 | private $index; |
||
83 | |||
84 | /** |
||
85 | * Use the Phar::interceptFileFuncs() method? |
||
86 | * |
||
87 | * @var bool |
||
88 | */ |
||
89 | private $intercept = false; |
||
90 | |||
91 | /** |
||
92 | * The map for file extensions and their mimetypes. |
||
93 | * |
||
94 | * @var array |
||
95 | */ |
||
96 | private $mimetypes = []; |
||
97 | |||
98 | /** |
||
99 | * The list of server variables to modify. |
||
100 | * |
||
101 | * @var array |
||
102 | */ |
||
103 | private $mung = []; |
||
104 | |||
105 | /** |
||
106 | * The location of the script to run when a file is not found. |
||
107 | * |
||
108 | * @var string |
||
109 | */ |
||
110 | private $notFound; |
||
111 | |||
112 | /** |
||
113 | * The rewrite function. |
||
114 | * |
||
115 | * @var string |
||
116 | */ |
||
117 | private $rewrite; |
||
118 | |||
119 | /** |
||
120 | * The shebang line. |
||
121 | * |
||
122 | * @var string |
||
123 | */ |
||
124 | private $shebang = '#!/usr/bin/env php'; |
||
125 | |||
126 | /** |
||
127 | * Use Phar::webPhar() instead of Phar::mapPhar()? |
||
128 | * |
||
129 | * @var bool |
||
130 | */ |
||
131 | private $web = false; |
||
132 | |||
133 | /** |
||
134 | * Sets the alias to be used in "phar://" URLs. |
||
135 | * |
||
136 | * @param string $alias the alias |
||
137 | * |
||
138 | * @return StubGenerator the stub generator |
||
139 | */ |
||
140 | public function alias($alias) |
||
141 | { |
||
142 | $this->alias = $alias; |
||
143 | |||
144 | return $this; |
||
145 | } |
||
146 | |||
147 | /** |
||
148 | * Sets the top header comment banner text. |
||
149 | * |
||
150 | * @param string $banner the banner text |
||
151 | * |
||
152 | * @return StubGenerator the stub generator |
||
153 | */ |
||
154 | public function banner($banner) |
||
155 | { |
||
156 | $this->banner = $banner; |
||
157 | |||
158 | return $this; |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Creates a new instance of the stub generator. |
||
163 | * |
||
164 | * @return StubGenerator the stub generator |
||
165 | */ |
||
166 | public static function create() |
||
167 | { |
||
168 | return new static(); |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Embed the Extract class in the stub? |
||
173 | * |
||
174 | * @param bool $extract Embed the class? |
||
175 | * @param bool $force Force the use of the class? |
||
176 | * |
||
177 | * @return StubGenerator the stub generator |
||
178 | */ |
||
179 | public function extract($extract, $force = false) |
||
180 | { |
||
181 | $this->extract = $extract; |
||
182 | $this->extractForce = $force; |
||
183 | |||
184 | if ($extract) { |
||
185 | $this->extractCode = [ |
||
186 | 'constants' => [], |
||
187 | 'class' => [], |
||
188 | ]; |
||
189 | |||
190 | $compactor = new Php(new Tokenizer()); |
||
191 | $code = file_get_contents(__DIR__.'/Extract.php'); |
||
192 | $code = $compactor->compact($code); |
||
|
|||
193 | $code = preg_replace('/\n+/', "\n", $code); |
||
194 | $code = explode("\n", $code); |
||
195 | $code = array_slice($code, 2); |
||
196 | |||
197 | foreach ($code as $i => $line) { |
||
198 | if ((0 === strpos($line, 'use')) |
||
199 | && (false === strpos($line, '\\')) |
||
200 | ) { |
||
201 | unset($code[$i]); |
||
202 | } elseif (0 === strpos($line, 'define')) { |
||
203 | $this->extractCode['constants'][] = $line; |
||
204 | } else { |
||
205 | $this->extractCode['class'][] = $line; |
||
206 | } |
||
207 | } |
||
208 | } |
||
209 | |||
210 | return $this; |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Sets location within the Phar of index script. |
||
215 | * |
||
216 | * @param string $index the index file |
||
217 | * |
||
218 | * @return StubGenerator the stub generator |
||
219 | */ |
||
220 | public function index($index) |
||
221 | { |
||
222 | $this->index = $index; |
||
223 | |||
224 | return $this; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Use the Phar::interceptFileFuncs() method in the stub? |
||
229 | * |
||
230 | * @param bool $intercept Use interceptFileFuncs()? |
||
231 | * |
||
232 | * @return StubGenerator the stub generator |
||
233 | */ |
||
234 | public function intercept($intercept) |
||
235 | { |
||
236 | $this->intercept = $intercept; |
||
237 | |||
238 | return $this; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Generates the stub. |
||
243 | * |
||
244 | * @return string the stub |
||
245 | */ |
||
246 | public function generate() |
||
247 | { |
||
248 | $stub = []; |
||
249 | |||
250 | if ('' !== $this->shebang) { |
||
251 | $stub[] = $this->shebang; |
||
252 | } |
||
253 | |||
254 | $stub[] = '<?php'; |
||
255 | |||
256 | if (null !== $this->banner) { |
||
257 | $stub[] = $this->getBanner(); |
||
258 | } |
||
259 | |||
260 | if ($this->extract) { |
||
261 | $stub[] = implode("\n", $this->extractCode['constants']); |
||
262 | |||
263 | if ($this->extractForce) { |
||
264 | $stub = array_merge($stub, $this->getExtractSections()); |
||
265 | } |
||
266 | } |
||
267 | |||
268 | $stub = array_merge($stub, $this->getPharSections()); |
||
269 | |||
270 | if ($this->extract) { |
||
271 | if ($this->extractForce) { |
||
272 | if ($this->index && !$this->web) { |
||
273 | $stub[] = "require \"\$dir/{$this->index}\";"; |
||
274 | } |
||
275 | } else { |
||
276 | end($stub); |
||
277 | |||
278 | $stub[key($stub)] .= ' else {'; |
||
279 | |||
280 | $stub = array_merge($stub, $this->getExtractSections()); |
||
281 | |||
282 | if ($this->index) { |
||
283 | $stub[] = "require \"\$dir/{$this->index}\";"; |
||
284 | } |
||
285 | |||
286 | $stub[] = '}'; |
||
287 | } |
||
288 | |||
289 | $stub[] = implode("\n", $this->extractCode['class']); |
||
290 | } |
||
291 | |||
292 | $stub[] = '__HALT_COMPILER();'; |
||
293 | |||
294 | return implode("\n", $stub); |
||
295 | } |
||
296 | |||
297 | /** |
||
298 | * Sets the map for file extensions and their mimetypes. |
||
299 | * |
||
300 | * @param array $mimetypes the map |
||
301 | * |
||
302 | * @return StubGenerator the stub generator |
||
303 | */ |
||
304 | public function mimetypes(array $mimetypes) |
||
305 | { |
||
306 | $this->mimetypes = $mimetypes; |
||
307 | |||
308 | return $this; |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Sets the list of server variables to modify. |
||
313 | * |
||
314 | * @param array $list the list |
||
315 | * |
||
316 | * @throws Exception\Exception |
||
317 | * @throws InvalidArgumentException if the list contains an invalid value |
||
318 | * |
||
319 | * @return StubGenerator the stub generator |
||
320 | */ |
||
321 | public function mung(array $list) |
||
322 | { |
||
323 | foreach ($list as $value) { |
||
324 | if (false === in_array($value, self::$allowedMung, true)) { |
||
325 | throw InvalidArgumentException::create( |
||
326 | 'The $_SERVER variable "%s" is not allowed.', |
||
327 | $value |
||
328 | ); |
||
329 | } |
||
330 | } |
||
331 | |||
332 | $this->mung = $list; |
||
333 | |||
334 | return $this; |
||
335 | } |
||
336 | |||
337 | /** |
||
338 | * Sets the location of the script to run when a file is not found. |
||
339 | * |
||
340 | * @param string $script the script |
||
341 | * |
||
342 | * @return StubGenerator the stub generator |
||
343 | */ |
||
344 | public function notFound($script) |
||
345 | { |
||
346 | $this->notFound = $script; |
||
347 | |||
348 | return $this; |
||
349 | } |
||
350 | |||
351 | /** |
||
352 | * Sets the rewrite function. |
||
353 | * |
||
354 | * @param string $function the function |
||
355 | * |
||
356 | * @return StubGenerator the stub generator |
||
357 | */ |
||
358 | public function rewrite($function) |
||
359 | { |
||
360 | $this->rewrite = $function; |
||
361 | |||
362 | return $this; |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Sets the shebang line. |
||
367 | * |
||
368 | * @param string $shebang the shebang line |
||
369 | * |
||
370 | * @return StubGenerator the stub generator |
||
371 | */ |
||
372 | public function shebang($shebang) |
||
373 | { |
||
374 | $this->shebang = $shebang; |
||
375 | |||
376 | return $this; |
||
377 | } |
||
378 | |||
379 | /** |
||
380 | * Use Phar::webPhar() instead of Phar::mapPhar()? |
||
381 | * |
||
382 | * @param bool $web Use Phar::webPhar()? |
||
383 | * |
||
384 | * @return StubGenerator the stub generator |
||
385 | */ |
||
386 | public function web($web) |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Escapes an argument so it can be written as a string in a call. |
||
395 | * |
||
396 | * @param string $arg the argument |
||
397 | * @param string $quote the quote |
||
398 | * |
||
399 | * @return string the escaped argument |
||
400 | */ |
||
401 | private function arg($arg, $quote = "'") |
||
402 | { |
||
403 | return $quote.addcslashes($arg, $quote).$quote; |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * Returns the alias map. |
||
408 | * |
||
409 | * @return string the alias map |
||
410 | */ |
||
411 | private function getAlias() |
||
412 | { |
||
413 | $stub = ''; |
||
414 | $prefix = ''; |
||
415 | |||
416 | if ($this->extractForce) { |
||
417 | $prefix = '$dir/'; |
||
418 | } |
||
419 | |||
420 | if ($this->web) { |
||
421 | $stub .= 'Phar::webPhar('.$this->arg($this->alias); |
||
422 | |||
423 | if ($this->index) { |
||
424 | $stub .= ', '.$this->arg($prefix.$this->index, '"'); |
||
425 | |||
426 | if ($this->notFound) { |
||
427 | $stub .= ', '.$this->arg($prefix.$this->notFound, '"'); |
||
428 | |||
429 | if ($this->mimetypes) { |
||
430 | $stub .= ', '.var_export( |
||
431 | $this->mimetypes, |
||
432 | true |
||
433 | ); |
||
434 | |||
435 | if ($this->rewrite) { |
||
436 | $stub .= ', '.$this->arg($this->rewrite); |
||
437 | } |
||
438 | } |
||
439 | } |
||
440 | } |
||
441 | |||
442 | $stub .= ');'; |
||
443 | } else { |
||
444 | $stub .= 'Phar::mapPhar('.$this->arg($this->alias).');'; |
||
445 | } |
||
446 | |||
447 | return $stub; |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * Returns the banner after it has been processed. |
||
452 | * |
||
453 | * @return string the processed banner |
||
454 | */ |
||
455 | private function getBanner() |
||
467 | } |
||
468 | |||
469 | /** |
||
470 | * Returns the self extracting sections of the stub. |
||
471 | * |
||
472 | * @return array the stub sections |
||
473 | */ |
||
474 | private function getExtractSections() |
||
475 | { |
||
476 | return [ |
||
477 | '$extract = new Extract(__FILE__, Extract::findStubLength(__FILE__));', |
||
478 | '$dir = $extract->go();', |
||
479 | 'set_include_path($dir . PATH_SEPARATOR . get_include_path());', |
||
480 | ]; |
||
481 | } |
||
482 | |||
483 | /** |
||
484 | * Returns the sections of the stub that use the Phar class. |
||
485 | * |
||
486 | * @return array the stub sections |
||
487 | */ |
||
488 | private function getPharSections() |
||
510 | } |
||
511 | } |
||
512 |